HarmonyOS鸿蒙Next中Uint8Array转换成PixelMap失败,求助

HarmonyOS鸿蒙Next中Uint8Array转换成PixelMap失败,求助 从另一个进程传过来的base64格式图片流(图片为PNG),拿到后进行base64解码,解码后的byteLength和base64编码前一致。创建ImageResource后创建PixalMap,得到如下报错

图片代码如下

Log.i(TAG, 'vcode base64=' + base64Buffer)
let base64Helper = new util.Base64Helper()
let uint8Array: Uint8Array = base64Helper.decodeSync(base64Buffer)
Log.i(TAG, 'vcode buffer len=' + uint8Array.byteLength)
let imageSource = image.createImageSource(uint8Array.buffer)
Log.i(TAG, 'createImageSource finished')

let options: image.InitializationOptions = {
  'alphaType': 0, // 透明度
  'editable': false, // 是否可编辑
  'pixelFormat': 3, // 像素格式
  'scaleMode': 1, // 缩略值
  'size': { height: 40, width: 80 } // 创建图片大小
}
// 生成 PixelMap
imageSource.createPixelMap(options).then((pixelMap: image.PixelMap) => {
  Log.i(TAG, 'createPixelMap finished')
  AppStorage.setOrCreate(AppStorageKey.GRAPHIC_VCODE, pixelMap)
}).catch((e: BusinessError) => {
  Log.i(TAG, 'createPixelMap failed, ' + JSON.stringify(e))
})

更多关于HarmonyOS鸿蒙Next中Uint8Array转换成PixelMap失败,求助的实战教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

从打印结果看,输出了:

'createPixelMap finished'

这应该说明转换是成功的。 报错的信息,很可能是这一句:

    AppStorage.setOrCreate(AppStorageKey.GRAPHIC_VCODE, pixelMap)

从API version 12开始,AppStorage支持MapSetDate类型,支持null、undefined以及联合类型

不应该用 AppStorage 去存储 PixelMap 类型的对象。

更多关于HarmonyOS鸿蒙Next中Uint8Array转换成PixelMap失败,求助的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


建议楼主将 PixelMap 保存为图片放在沙箱中使用,PixelMap存储在内存中占用存储过大,出现过多的PixelMap存储在内存中会导致UI卡顿

const resourceMgr: resourceManager.ResourceManager = this.context.resourceManager;
// beer.jpeg为rawfile文件下的图片名,可根据自身需求修改使用。
const fileData: Uint8Array = await resourceMgr.getRawFileContent('beer.jpeg');
let buffer = new Uint8Array(fileData).buffer as object as ArrayBuffer;
let imageResource = image.createImageSource(buffer);
let opts: image.DecodingOptions = { editable: true };
this.pixel = await imageResource.createPixelMap(opts);
AppStorage.setOrCreate(AppStorageKey.GRAPHIC_VCODE, pixelMap)

AppStorage.setOrCreate方法无法直接存储PixelMap对象

可以将PixelMap保存为本地文件后,存储文件路径到AppStorage

感谢您的提问,这边复现了下并没有出现pixmapNapi unwrapped is nullptr问题,为了更快解决您的问题,麻烦请补充以下信息:

复现代码(如最小复现demo);

版本信息(如:开发工具、手机系统版本信息);

从代码和错误信息来看,核心问题在于createPixelMap时指定的size与原始图片的实际尺寸不匹配。

错误码401通常表示参数错误。在你的代码中,InitializationOptions里设置的size是固定的{ height: 40, width: 80 }createPixelMap方法会尝试将图片解码并缩放到这个指定尺寸。如果传入的PNG图片流的实际尺寸与这个{40, 80}的宽高比差异巨大,或者图片本身无法正确解码到这个尺寸,就会抛出这个异常。

解决方案是使用图片解码后的自然尺寸,或者先获取图片信息再决定缩放尺寸。建议修改如下:

  1. 先获取图片尺寸:使用createImageSource后,先调用getImageInfo()获取图片的原始宽高。
  2. 动态计算目标尺寸或使用原始尺寸:根据获取到的imageInfo来设置options中的size,或者使用imageInfo.size直接作为目标尺寸,避免宽高比不匹配导致的解码失败。

修改后的核心代码段示例:

let imageSource = image.createImageSource(uint8Array.buffer);
// 首先获取图片信息
imageSource.getImageInfo().then((imageInfo: image.ImageInfo) => {
  Log.i(TAG, `Original image size: width=${imageInfo.size.width}, height=${imageInfo.size.height}`);

  let options: image.InitializationOptions = {
    'alphaType': 0,
    'editable': false,
    'pixelFormat': 3,
    'scaleMode': 1,
    // 使用获取到的原始尺寸,或基于此计算你的目标尺寸(如按比例缩放)
    'size': imageInfo.size // 直接使用原始尺寸通常是最安全的
    // 或者按需缩放: 'size': { height: yourTargetHeight, width: yourTargetWidth }
  };

  // 生成 PixelMap
  return imageSource.createPixelMap(options);
}).then((pixelMap: image.PixelMap) => {
  Log.i(TAG, 'createPixelMap finished');
  AppStorage.setOrCreate(AppStorageKey.GRAPHIC_VCODE, pixelMap);
}).catch((e: BusinessError) => {
  Log.i(TAG, 'Error: ' + JSON.stringify(e));
});

关键点:确保createPixelMapsize参数与图片内容兼容。对于来自网络或进程间通信的图片,其尺寸是未知的,直接指定一个固定尺寸风险很高。先通过getImageInfo()探明尺寸是标准做法。

另外,检查uint8Array.buffer包含的数据是否是完整的、未损坏的PNG文件数据。你已确认byteLength一致,这步通常是正确的。问题焦点应放在尺寸参数的处理上。

回到顶部