HarmonyOS 鸿蒙Next 读取PixelMap的ArrayBuffer再创建PixelMap展示图片变黑白 丢失了颜色?

发布于 1周前 作者 nodeper 最后一次编辑是 5天前 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 读取PixelMap的ArrayBuffer再创建PixelMap展示图片变黑白 丢失了颜色?

HarmonyOS 读取PixelMap的ArrayBuffer,再使用读取的数据创建PixelMap展示,图片变成了黑白,丢失了颜色。?

2 回复

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()

在HarmonyOS鸿蒙系统中,如果你遇到读取PixelMap的ArrayBuffer后再创建PixelMap展示图片变为黑白、丢失颜色的问题,这通常与像素数据格式处理或颜色空间转换有关。

首先,确认在读取ArrayBuffer时,像素数据的格式(如RGBA、ARGB等)与创建PixelMap时指定的格式一致。如果格式不匹配,可能会导致颜色信息丢失或错误解析。

其次,检查是否在处理像素数据时,不小心对颜色通道进行了操作,如只保留了灰度信息而忽略了其他颜色通道。这通常发生在手动处理像素数据的场景中。

此外,还需要确认是否在处理过程中涉及了颜色空间的转换。不同的颜色空间(如sRGB、Linear RGB等)在转换时,如果没有正确处理,也可能导致颜色丢失或变化。

最后,检查你的代码逻辑,确保在创建和展示PixelMap的过程中,没有额外的处理步骤导致颜色信息被覆盖或修改。

如果以上步骤都确认无误,但问题依旧存在,那么可能是系统或API层面的bug。此时,建议直接联系官网客服以获取更专业的帮助。官网地址是:https://www.itying.com/category-93-b0.html。

回到顶部