HarmonyOS 开发-PixelMap深拷贝案例

介绍

在图片开发过程中经常会涉及到PixelMap的深拷贝,本例通过使用PixelMap的readPixelsToBuffer方法来实现深拷贝。在创建源PixelMap的时候,需要将解码参数设置为BGRA_8888,而在深拷贝创建目标PixelMap的时候需要将解码参数设置为RGBA_8888。

效果图预览

使用说明

  1. 进入页面,显示的即为rawfile中图片的PixelMap经过深拷贝过后的PixelMap对象。点击底部的按钮,对原始PixelMap进行深拷贝后再根据相应的比例进行裁剪。点击顶部的保存图标,可以保存当前图片。

实现思路

  1. PixelMap深拷贝方法。通过readPixelsToBuffer读取图片资源的PixelMap到ArrayBuffer,再通过createPixelMap得到目标PixelMap。
typescript 复制代码
   async function copyPixelMap(pm: PixelMap): Promise<PixelMap> {
     const imageInfo: image.ImageInfo = await pm.getImageInfo();
     const buffer: ArrayBuffer = new ArrayBuffer(pm.getPixelBytesNumber());
     // TODO 知识点:通过readPixelsToBuffer实现PixelMap的深拷贝,其中readPixelsToBuffer输出为BGRA_8888
     await pm.readPixelsToBuffer(buffer);
     // TODO 知识点:readPixelsToBuffer输出为BGRA_8888,此处createPixelMap需转为RGBA_8888
     const opts: image.InitializationOptions = {
       editable: true,
       pixelFormat: image.PixelMapFormat.RGBA_8888,
       size: { height: imageInfo.size.height, width: imageInfo.size.width }
     };
     return await image.createPixelMap(buffer, opts);
   }
  1. 初始化时,通过深拷贝从原始PixelMap创建目标PixelMap。源码参考ImageDepthCopy.ets
typescript 复制代码
   async aboutToAppear(): Promise<void> {
     const context: Context = getContext(this);
     // 获取resourceManager资源管理
     const resourceMgr: resourceManager.ResourceManager = context.resourceManager;
     // 获取rawfile中的图片资源
     const fileData: Uint8Array = await resourceMgr.getRawFileContent(ImageCropConstants.RAWFILE_PICPATH);
     // 获取图片的ArrayBuffer
     const buffer = fileData.buffer.slice(fileData.byteOffset, fileData.byteLength + fileData.byteOffset);
     // 保存用于恢复原图的imageSource
     this.imageSource = image.createImageSource(buffer);
     // TODO 知识点: 创建源图片的用于深拷贝的PixelMap,因readPixelsToBuffer输出为BGRA_8888。故此处desiredPixelFormat需为BGRA_8888
     const decodingOptions: image.DecodingOptions = {
       editable: false, // 是否可编辑。当取值为false时,图片不可二次编辑。
       desiredPixelFormat: image.PixelMapFormat.BGRA_8888,
     }
     // 保存用于深拷贝的pixelMap
     this.pixelMapSrc = await this.imageSource.createPixelMap(decodingOptions);
     // TODO 知识点: 通过readPixelsToBuffer进行深拷贝
     this.pixelMapDst = await copyPixelMap(this.pixelMapSrc!);
   }
  1. 图片裁剪。源码参考ImageDepthCopy.ets
typescript 复制代码
    ...
    // TODO 知识点:通过readPixelsToBuffer拷贝到PixelMap对象
    const pixelMapTemp = await copyPixelMap(this.pixelMapSrc);
    const imageInfo: image.ImageInfo = await pixelMapTemp.getImageInfo();
    if (!imageInfo) {
      logger.error(TAG, `imageInfo is null`);
      return;
    }
    let imageHeight: number = imageInfo.size.height;
    let imageWith: number = imageInfo.size.width;
    if (proportion === ImageCropConstants.ONE_ONE) {
      if (imageHeight > imageWith) {
        imageHeight = imageWith;
      } else {
        imageWith = imageHeight;
      }
    }
    try {
      logger.info(TAG, `imageInfo imageHeight = ${JSON.stringify(imageHeight / proportion)}, imageWith = ${JSON.stringify(imageWith)}`);
      // PixelMap按比例裁剪
      await pixelMapTemp.crop({
        size: { height: imageHeight / proportion, width: imageWith },
        x: 0,
        y: 0
      });
      this.pixelMapDst = pixelMapTemp;
    } catch (error) {
      logger.error(TAG, `imageInfo crop error = ${JSON.stringify(error)}`);
    }
  1. 保存图片。将裁剪后的图片保存。源码参考FileUtil.ets
typescript 复制代码
   export async function savePixelMap(context: Context, pm: PixelMap): Promise<string> {
     if (pm === null) {
       logger.error(TAG, '传入的pm为空');
       return '';
     }
     const imagePackerApi: image.ImagePacker = image.createImagePacker();
     const packOpts: image.PackingOption = { format: 'image/jpeg', quality: 30 };
     try {
       packToFile(context, pm);
       const data: ArrayBuffer = await imagePackerApi.packing(pm, packOpts);
       return await saveFile(context, data);
     } catch (err) {
       logger.error(TAG, '保存文件失败,err=' + JSON.stringify(err));
       return '';
     }
   }
   
   async function saveFile(context: Context, data: ArrayBuffer): Promise<string> {
     let uri: string = context.filesDir + '/' + getTimeStr() + '.jpg';
     const file: fileIo.File = fs.openSync(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
     fs.writeSync(file.fd, data);
     fs.closeSync(file);
     // 加上file://前缀
     uri = 'file:/' + uri;
     return uri;
   }

工程结构&模块类型

复制代码
   imagedepthcopy                               // har类型
   |---view
   |   |---ImageDepthCopy.ets                   // 视图层-图片深拷贝页面
   |---constants
   |   |---ImageCropConstants.ets               // 常量
   |---model
   |   |---AdjustData.ets                       // 裁剪选项资源
   |---util
   |   |---CopyObj.ets                          // 业务层-图片深拷贝处理
   |   |---FileUtil.ets                         // 业务层-图片保存

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ......

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ......

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ......

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题

2.性能优化方向

3.架构方向

4.鸿蒙开发系统底层方向

5.鸿蒙音视频开发方向

6.鸿蒙车载开发方向

7.鸿蒙南向开发方向

相关推荐
遇见尚硅谷1 分钟前
C语言:20250728学习(指针)
c语言·开发语言·数据结构·c++·笔记·学习·算法
yanchao_hu3 小时前
数据结构基础内容(第二篇:线性结构)
数据结构·windows
拳里剑气3 小时前
C语言:顺序表(上)
c语言·开发语言·数据结构·学习方法
积极向上的zzz4 小时前
java中一些数据结构的转换
java·开发语言·数据结构
每天都在想吃啥5 小时前
day22 哈希表和二叉树
数据结构·哈希算法·散列表
Das15 小时前
【初识数据结构】CS61B 中的归并排序和选择排序
数据结构·算法·排序算法
baobao熊5 小时前
HarmonyOS 6 云开发-用户头像上传云存储
华为·数据挖掘·harmonyos
优测云服务平台5 小时前
优测推出HarmonyOS全场景测试服务,解锁分布式场景应用卓越品质!
分布式·harmonyos
HarmonyOS小助手7 小时前
【宝藏贴】HarmonyOS官方模板优秀案例 · 第1期:便捷生活-购物中心
harmonyos·鸿蒙·鸿蒙生态
yanchao_hu8 小时前
数据结构基本内容(第四篇:队列)
数据结构