HarmonyOS 鸿蒙Next 拉起相册后选中的照片jpeg格式如何转换成nv21数据

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

HarmonyOS 鸿蒙Next 拉起相册后选中的照片jpeg格式如何转换成nv21数据

// 拉起相册,选择图片
let PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
PhotoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
PhotoSelectOptions.maxSelectNumber = 1;
let photoPicker = new photoAccessHelper.PhotoViewPicker();
let photoSelectResult: photoAccessHelper.PhotoSelectResult = await photoPicker.select(PhotoSelectOptions);
let albumPath = photoSelectResult.photoUris[0];

通过convertPixelFormat转换了一下像素格式,但是打印出来readBuffer每个字节都是0,如何能把读到的这张jpeg转换成nv21数据,并保存到应用沙箱/本地相册呢?


更多关于HarmonyOS 鸿蒙Next 拉起相册后选中的照片jpeg格式如何转换成nv21数据的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

楼主你的demo感觉有点问题,这边基于你的demo修改了下,可以参考注释内容

async convert() {
   // 拉起相册,选择图片
   try {
     // 1. 拉起相册,选择图片
     let PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
     PhotoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
     PhotoSelectOptions.maxSelectNumber = 1; // 选择一张图片
     let photoPicker = new photoAccessHelper.PhotoViewPicker();
     let photoSelectResult: photoAccessHelper.PhotoSelectResult = await photoPicker.select(PhotoSelectOptions);

     if (!photoSelectResult || photoSelectResult.photoUris.length === 0) {
       console.error("No image selected");
       return;
     }

     let url = photoSelectResult.photoUris[0]; // 获取选中图片的URI

     // 2. 读取图片为buffer
     const file = fs.openSync(url, fs.OpenMode.READ_ONLY);
     const photoSize = fs.statSync(file.fd).size;
     let buffer = new ArrayBuffer(photoSize);
     fs.readSync(file.fd, buffer);
     fs.closeSync(file);

     // 3. 创建ImageSource并生成PixelMap
     const imageSource = image.createImageSource(buffer);
     const pixelMap = await imageSource.createPixelMap();

     // 4. 转换为NV21格式
     let targetPixelFormat = image.PixelMapFormat.NV21;
     await pixelMap.convertPixelFormat(targetPixelFormat);

     // 5. 读取转换后的像素数据
     const imageInfo = await pixelMap.getImageInfo();
     const readBuffer = new ArrayBuffer(imageInfo.size.width * imageInfo.size.height * 3 / 2); // NV21格式的大小
     await pixelMap.readPixelsToBuffer(readBuffer);

     // 6. 将NV21数据保存到沙箱
     const sandboxDir = getContext().filesDir; // 沙箱目录
     const filePath = `${sandboxDir}/image_nv21.bin`; // 保存路径
     let file1 = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
     fs.writeSync(file1.fd, readBuffer);

     console.log("NV21 image saved to:", filePath);
   } catch (error) {
     console.error("Error occurred:", error);
   }
 }
 aboutToAppear(): void {
   this.convert()
 }
 

 沙箱文件

cke_7443.png

更多关于HarmonyOS 鸿蒙Next 拉起相册后选中的照片jpeg格式如何转换成nv21数据的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


谢谢,我试了可以成功保存nv21,我想问下用media文件夹里面的图去生成PixelMap是不是同样的方式?目前图片又保存失败了let media = await this.context.resourceManager.getMediaContent($r(‘app.media.faces’).id); // 3. 创建ImageSource并生成PixelMap const imageSource = image.createImageSource(media.buffer); const pixelMap = await imageSource.createPixelMap();

在HarmonyOS鸿蒙Next系统中,将拉起相册后选中的JPEG格式照片转换成NV21数据,可以通过以下步骤实现:

  1. 读取JPEG数据: 使用系统API读取选中的JPEG照片,获取其字节数组。

  2. 解码JPEG数据: 利用BitmapFactory类将JPEG字节数组解码成Bitmap对象。

  3. 创建NV21缓冲区: 根据Bitmap的宽度和高度,计算NV21数据所需的缓冲区大小,并创建相应的byte数组。

  4. 转换Bitmap到NV21: 遍历Bitmap的像素数据,按照NV21的格式(YUV420SP)填充缓冲区。注意,NV21格式中,Y分量在前,UV分量交错在后。

  5. 处理边缘情况: 对于Bitmap的宽高不是16的倍数的情况,需要进行适当填充或裁剪,以保证NV21数据的正确性。

具体代码实现如下(伪代码):

Bitmap bitmap = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
byte[] nv21Data = new byte[width * height * 3 / 2];
// 填充nv21Data...
// 此处省略具体转换逻辑,需按NV21格式手动填充

// 返回nv21Data

注意:上述代码省略了具体的转换逻辑,需根据NV21格式手动实现。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部