目录

如何解决创建PixelMap出现Create PixelMap error错误

问题现象

使用readPixelsToBuffer将PixelMap转换成buffer后,再将buffer转回PixelMap时出现报错,报错和代码如下:

this.pixel = await imageSource.createPixelMap(opts);
 let readBuffer: ArrayBuffer = new ArrayBuffer(this.pixel.getPixelBytesNumber());
 this.pixel.readPixelsToBuffer(readBuffer).then(() => {
   const pImgBigImageSource = image.createImageSource(readBuffer);
   pImgBigImageSource.createPixelMap().then((pixMap: image.PixelMap) => { 
     console.info('createPixelMap success');  
   }).catch((err: BusinessError) => { 
     console.error('createPixelMap error: ', err.toString());
   }) 
 })

背景知识

readPixelsToBuffer读取图像像素数据,并按照PixelMap的像素格式写入缓冲区中。createImageSource用来创建图片源实例对象,可支持uri、文件描述符、图像资源文件的RawFileDescriptor、缓冲区等参数来创建。

问题定位

检查readPixelsToBuffer和createImageSource对传入参数及写入类型的要求,发现尽管createImageSource支持传入ArrayBuffer的类型,但要求入参必须是未解码的数据,不能是类似于RBGA,YUV的像素buffer数据,而readPixelsToBuffer写入缓冲区的是像素数据,不符合createImageSource的参数要求。

分析结论

对于已解码获取的图像像素数据,不能在创建ImageSource后创建PixelMap,而是要调用image.createPixelMap直接创建。

修改建议

对于图像像素buffer直接调用image.createPixelMap来创建PixelMap。

import { image } from '@kit.ImageKit';


@Entry
@Component
struct PixelBufferToAnotherPixel {
  @State targetPixel: PixelMap | undefined = undefined;
  private context = this.getUIContext();


  async creatPixel() {
    const resourceManager = this.context.getHostContext()?.resourceManager;
    const imageData = await resourceManager!.getMediaContent($r('app.media.startIcon').id);
    let arrayBuffer = imageData.buffer;
    const imageSource = image.createImageSource(arrayBuffer);
    let imageInfo = imageSource.getImageInfoSync(0);
    let width = imageInfo.size.width;
    let height = imageInfo.size.height;
    let format = imageInfo.pixelFormat;
    const opts: image.DecodingOptions = {
      editable: true,
      desiredPixelFormat : image.PixelMapFormat.BGRA_8888
    };
    let pixel = await imageSource.createPixelMap(opts);
    try {
      let readBuffer: ArrayBuffer = new ArrayBuffer(pixel.getPixelBytesNumber());
      pixel.readPixelsToBuffer(readBuffer).then(() => {
        let opts: image.InitializationOptions = {
          editable: true,
          pixelFormat: format,
          size: { height: height, width: width },
        };
        // 直接调用
        image.createPixelMap(readBuffer, opts).then((value) => {
          return this.targetPixel = value;
        });
        console.info("createPixelMap success");
      });
    } catch (error) {
      console.error("createPixelMap error", error.toString());
    }
  }


  build() {
    Column() {
      Button('创建PixelMap')
        .onClick(()=>{
          this.creatPixel();
        })
      Image(this.targetPixel)
        .objectFit(ImageFit.Contain)
        .height('50%')
    }
    .height('100%')
    .width('100%')
  }
}

总结

readPixelsToBuffer读取后的buffer里存放的是像素数据,而当createImageSource传入数据类型是ArrayBuffer时,buffer数据应该是未解码的数据,不能是类似于RBGA,YUV的像素buffer数据,如果想通过像素buffer数据创建PixelMap,可以调用image.createPixelMap接口。