针对前端合并多张图片的情况大概分为2种方法:
1、第一种方法,下载多张图片后,将多张图片绘制到一个canvas中,并记录每个区域的大小和范围,同时还要记录空闲空间,缺点是维护繁琐,同时会产生空闲空间碎片,优点是绘制方便。
2、第二种方法,下载多张图像后,提取图片纹素,将每张图片的纹素按照顺序排列到图片的空闲位置上,也就是按照像素排列,而不是按照图片排列,将原来的图片打散,同时记录每个图片的宽度、高度,按照图像宽度*高度*4采样图像就可以了。
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
function imageToUint8Array(image, context) {
context.width = image.width;
context.height = image.height;
context.drawImage(image, 10, 10);
return new Uint8Array(context.getImageData(0, 0, image.width, image.height).data.buffer);
}
const imageUrls = ["./texture/4.png", "./texture/5.png"];
const urlResources = [];
imageUrls.forEach((url) => {
const urlResource = new Resource({
//url: buildModuleUrl(url),
url: url,
});
urlResources.push(urlResource.fetchImage());
});
Promise.all(urlResources).then(function(images){
// 转换数据到内存
const datas = [];
images.forEach(image=>{
canvas.width = image.width;
canvas.height = image.height;
const data = imageToUint8Array(image, context);
datas.push({data: data, width: image.width, height: image.height});
});
// 计算总长度
let allLenght = 0;
datas.forEach(element => {
allLenght += element.data.length;
});
// 合并数据
const arr = new Uint8ClampedArray(775*1024*4);
let index = 0;
datas.forEach(element => {
let data = element.data;
for (let i = 0; i < data.length; i += 4) {
arr[index + i + 0] = data[i + 0]; // R value
arr[index + i + 1] = data[i + 1]; // G value
arr[index + i + 2] = data[i + 2]; // B value
arr[index + i + 3] = data[i + 3]; // A value
}
index += element.data.length;
});
// Initialize a new ImageData object
let imageData = new ImageData(arr, 775, 1024);
// 绘制数据
// Draw image data to the canvas
const imageCanvas = document.getElementById('my-img');
const ctx = imageCanvas.getContext('2d');
ctx.putImageData(imageData, 0, 0);
return datas;
}).catch(function(error) {
console.log(error);
});;
注意事项:
1、每张图像下载后需要修改canvas的大小,否则只显示部分,其他部分会丢失
canvas.width = image.width;
canvas.height = image.height;
2、每个像素占4个字节,例如图像是10*20时,申请的内存是10*20*4,并且需要存储在Uint8ClampedArray类型的内存中
3、ImageData(arr, 775, 1024)的大小与Uint8ClampedArray(775*1024*4)要匹配,不然会报错