HarmonyOS 开发-PixelMap深拷贝案例

news2024/11/27 6:20:02

介绍

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

效果图预览

使用说明

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

实现思路

  1. PixelMap深拷贝方法。通过readPixelsToBuffer读取图片资源的PixelMap到ArrayBuffer,再通过createPixelMap得到目标PixelMap。
   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。
   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。
    ...
    // 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。
   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.鸿蒙南向开发方向

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1579812.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

首发!澳门地区OSGB数据V0.2版免费分享

之前分享了澳门OSGB V0.1版数据(独家&#xff0c;澳门地区OSGB数据免费分享&#xff01;)&#xff0c;得到了众多读者的认同&#xff0c;也有读者在数据使用过程中发现的问题&#xff0c;向我进行了反馈与交流&#xff0c;基于此&#xff0c;我在V0.1版本的基础上进行了修正与更…

vue3+Ts+Ant Design Vue +天地图组件封装

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来Vue3TsAntDesign-Vue组件天地图组件的封装 示例图 首先,在index.html引入天地图资源,vue3选择v4版本 <script src"http://api.tianditu.gov.cn/api?…

JVM 内存溢出排查

说明&#xff1a;记录一次JVM内存溢出的排查过程&#xff1b; 场景 项目开发完成后&#xff0c;首次提交到测试环境。测试、产品同事反馈页面先是操作响应慢&#xff0c;抛出超时异常&#xff0c;最后直接无法使用。查看日志后得知是内存溢出。 重启服务后&#xff0c;我对前…

2024,还没掌握 JS 发布者、订阅者模式吗

面试中经常出现问到如何实现JS 发布者、订阅者模式。下面是ES5实现发布订阅模式。 1、直接上代码。 function EventEmitter() {this.events {}; }; // 订阅者 EventEmitter.prototype.on function(ename, callback) {if (!this.events[ename]) {// 初始化创建订阅&#xff…

算法训练营第二十一天(二叉树part7)

算法训练营第二十一天&#xff08;二叉树part7&#xff09; 530.二叉搜索树的最小绝对差 力扣题目链接(opens new window) 题目 给你一棵所有节点为非负值的二叉搜索树&#xff0c;请你计算树中任意两节点的差的绝对值的最小值。 示例&#xff1a; 提示&#xff1a;树中至…

9.枚举类与注解

文章目录 1. 枚举类1.1 自定义枚举类1.2 enum关键字定义枚举类1.3 Enum类主要方法 2. 注解2.1 注解作用2.1.1 生成文档相关注解2.1.2 JDK内置基本注解-在编译时进行格式检查2.1.3 跟踪代码依赖性&#xff0c;实现替代配置文件功能 2.2 自定义Annotation2.3 JDK中的元注解2.3.1 …

Python零基础从小白打怪升级中~~~~~~~流程控制语句

第三节&#xff1a;Python的流程控制语法 一、Python条件语句的语法 if 条件1:条件1成立执⾏的代码一条件1成⽴执⾏的代码二...... elif 条件2&#xff1a;条件2成立执⾏的代码三条件2成立执⾏的代码四...... ...... else:以上条件都不成⽴&#xff0c;执行的代码五以上条件都…

海外盲盒系统开发,盲盒出口成为企业新机遇

随着盲盒的兴起&#xff0c;国内消费市场形成了万物皆可盲盒的态势。并且&#xff0c;盲盒自带社交属性&#xff0c;也成为了年轻人的社交神器。 除了在国内&#xff0c;盲盒在海外也掀起了一股热潮&#xff0c;呈现出了爆发式增长形势&#xff0c;国内热门盲盒企业也出口到了…

Redis的三种部署方案

文章目录 单机模式主从复制哨兵模式分片集群 在Redis中提供的集群方案总共有三种&#xff1a;单机模式&#xff0c;主从复制集群、哨兵模式&#xff0c;Redis分片集群 单机模式 Redis 只运行在一台服务器上&#xff0c;并且所有的数据都存储在这一台服务器的内存中。 主从复制…

小程序商城免费搭建之java商城 电子商务Spring Cloud+Spring Boot+二次开发+mybatis+MQ+VR全景

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

黄金白银价格上涨是投资机会吗?

黄金和白银&#xff0c;作为历史悠久的贵重金属&#xff0c;一直以来都被投资者视为避险资产。近年来&#xff0c;随着全球经济环境的变动&#xff0c;我们观察到黄金与白银的价格不断攀升&#xff0c;这是否预示着投资机会的到来&#xff1f;今天&#xff0c;就让我们来深度探…

【保姆级讲解SQL Server的详细使用教程】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

ATG-2021B功率信号源可以应用在哪些方面

功率信号源是一种能够产生一定功率的信号源&#xff0c;广泛应用于各个领域。下面将介绍功率信号源在电子、通信、工业和科研等方面的应用。 在电子行业中&#xff0c;功率信号源是一种重要的测试工具。它可以产生各种波形的信号&#xff0c;如正弦波、方波、脉冲波等&#xff…

vue中实现表格的局部刷新

背景&#xff1a; 列表中展示所有审核任务信息&#xff0c;包括审核状态、审核进度等&#xff0c;原来的实现是【查询】按钮绑定了一个定时器&#xff0c;定时查询整个列表&#xff0c;但是需要用户手动开启 领导觉得这种方式用户体验不好&#xff0c;希望能够实现【审核进度…

Golang | Leetcode Golang题解之第16题最接近的三数之和

题目&#xff1a; 题解&#xff1a; func threeSumClosest(nums []int, target int) int {sort.Ints(nums)var (n len(nums)best math.MaxInt32)// 根据差值的绝对值来更新答案update : func(cur int) {if abs(cur - target) < abs(best - target) {best cur}}// 枚举 a…

人工智能支持节能的七种方式

2024年2月&#xff0c;OpenAI公布了名为“Sora”的人工智能模型。从去年的chatgpt到今天Sora发布&#xff0c;OpenAI的每⼀次重要的动作和发布&#xff0c;都伴随着⼀场场精妙绝伦精巧的事件营销&#xff0c;它的设置议题的能⼒&#xff0c;节奏控制&#xff0c;公众引导堪称创…

P1731 [NOI1999] 生日蛋糕——典型的回溯和剪枝题目,值得一看

今天尝试了一下md的编辑器&#xff0c;不知道有没有什么改变 [NOI1999] 生日蛋糕 题目背景 数据加强版 link 题目描述 7 月 17 日是 Mr.W 的生日&#xff0c;ACM-THU 为此要制作一个体积为 N π N\pi Nπ 的 M M M 层生日蛋糕&#xff0c;每层都是一个圆柱体。 设从下往…

node后端上传文件到本地指定文件夹

实现 第一步&#xff0c;引入依赖 const fs require(fs) const multer require(multer) 第二步&#xff0c;先设置一个上传守卫&#xff0c;用于初步拦截异常请求 /*** 上传守卫* param req* param res* param next*/ function uploadFile (req, res, next) {// dest 值…

GD32F470_(4线制)火光/火焰传感器模块火源探测 红外接收传感器 智能车配件

2.16 火焰传感器 红外火焰传感器可以用来探测火源或其它一些波长在700纳米~1000纳米范围内的热源&#xff0c;在机器人比赛中&#xff0c;远红外火焰探头起到非常重要的作用&#xff0c;它可以用作机器人的眼睛来寻找火源或足球。利用它可以制作灭火机器人等。 红外火焰传感器…

10-热点文章-定时计算

xxl-Job分布式任务调度 1 今日内容 1.1 需求分析 目前实现的思路&#xff1a;从数据库直接按照发布时间倒序查询 问题1&#xff1a; 如何访问量较大&#xff0c;直接查询数据库&#xff0c;压力较大 问题2&#xff1a; 新发布的文章会展示在前面&#xff0c;并不是热点文章 …