image.createPixelMap 描述可知通过属性创建PixelMap,默认采用BGRA_8888格式处理数据,通过Promise返回结果,即使创建pixelMap时的buffer和options 都是rgba格式的,当前接口只能处理BGRA流,建议尝试统一更改为BGRA_8888。
import { image } from '@kit.ImageKit';
import fs from '@ohos.file.fs';
class JoinPicture {
/**
* RGBA与BGRA编码互换,前后统一编码后,就不需要转换了
* @param data
* @returns
*/
rgba2BGRA(data: ArrayBuffer): ArrayBuffer {
let length: number = data.byteLength;
let tempBuffer: ArrayBuffer = new ArrayBuffer(length);
let rgbaData = new DataView(data);
let bgraData = new DataView(tempBuffer);
for (let i = 0; i < length; i += 4) {
bgraData.setUint8(i, rgbaData.getUint8(i + 2));
bgraData.setUint8(i + 1, rgbaData.getUint8(i + 1));
bgraData.setUint8(i + 2, rgbaData.getUint8(i));
bgraData.setUint8(i + 3, rgbaData.getUint8(i + 3));
}
return bgraData.buffer
}
//1、读取PixelMap的ArrayBuffer
async pixelMapToArray(pixelMap:PixelMap){
//size为需要创建的像素buffer大小,取值为:height * width *4
let size = pixelMap.getPixelBytesNumber();
const readBuffer: ArrayBuffer = new ArrayBuffer(size);
if (pixelMap) {
await pixelMap.readPixelsToBuffer(readBuffer);
let bufferSize = readBuffer.byteLength;
return readBuffer;
}
return readBuffer;
}
//2、使用读取的数据创建PixelMap
arrayToPixelMap(readBuffer: ArrayBuffer | null, w:number, h:number, callback:(pixelMap:PixelMap)=>void){
let opts: image.InitializationOptions = { editable: true, pixelFormat: image.PixelMapFormat.BGRA_8888,
size: { height: h, width: w } }
image.createPixelMap(readBuffer, opts).then((pixelMap)=>{
callback(pixelMap);
});
}
// 这里只考虑横向排列拼接,且每张小图的高度一致
async join(picturePaths: Array<string>, joinPath: string, callback: Function) {
try {
if (picturePaths.length < 2) {
console.info('PictureJoinTogether 需要拼接的图片数量不足')
return;
}
const tempPath = picturePaths[0];
const imageSource = image.createImageSource(tempPath);
const imageInfo = await imageSource.getImageInfo();
const singleWidth = imageInfo.size.width;
const singleHeight = imageInfo.size.height;
const combineOpts: image.InitializationOptions = {
alphaType: 0,
editable: true,
// 注意上下格式统一
pixelFormat: image.PixelMapFormat.BGRA_8888,
//pixelFormat: image.PixelMapFormat.RGBA_8888,
size: { width: singleWidth * picturePaths.length, height: singleHeight }
}
const singleOpts: image.DecodingOptions = {
editable: true,
desiredPixelFormat: image.PixelMapFormat.BGRA_8888,
//desiredPixelFormat: image.PixelMapFormat.RGBA_8888,
desiredSize: { width: singleWidth, height: singleHeight }
};
const combineColor = new ArrayBuffer(combineOpts.size.width * combineOpts.size.height * 4);
let singleColor = new ArrayBuffer(singleOpts.desiredSize!.width * singleOpts.desiredSize!.height * 4);
const newPixelMap = await image.createPixelMap(combineColor, combineOpts);
let newPixelMap2 =newPixelMap;
this.pixelMapToArray(newPixelMap).then((buffer)=>{
let imageInfo = newPixelMap.getImageInfoSync();
let w = imageInfo.size.width;
let h = imageInfo.size.height;
this.arrayToPixelMap(buffer, w, h, (pixelMaps)=>{
newPixelMap2 = pixelMaps;
} )
})
for (let x = 0; x < picturePaths.length; x++) {
//读取小图
//图片应用沙箱路径
let singlePath = picturePaths[x];
let imageSource = image.createImageSource(singlePath);
const singlePixelMap = await imageSource.createPixelMap(singleOpts);
await singlePixelMap.readPixelsToBuffer(singleColor);
//写入大图
let area: image.PositionArea = {
pixels: singleColor,
offset: 0,
stride: singleWidth * 4,
region: {
size: { height: singleHeight, width: singleWidth },
x: singleWidth * x,
y: 0
}
}
await newPixelMap2.writePixels(area);
}
let combinePixelMap = newPixelMap2;
//保存大图
const saveResult = await this.save(combinePixelMap, joinPath)
saveResult && callback();
} catch (err) {
console.error('PictureJoinTogether join error: ' + JSON.stringify(err))
}
}
async save(pixelMap: image.PixelMap | undefined, path: string) {
if (pixelMap === undefined) {
return false;
}
const imagePackerApi: image.ImagePacker = image.createImagePacker();
let packOpts: image.PackingOption = { format: "image/jpeg", quality: 100 };
const packingArrayBuffer = await imagePackerApi.packing(pixelMap, packOpts);
console.info('packing succeeded.');
let file = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
fs.writeSync(file.fd, packingArrayBuffer, { offset: 0 })
fs.closeSync(file.fd)
return true
}
}
export const joinPicture = new JoinPicture()