鸿蒙开发之PixelMap介绍与实现图片变换

简介: PixelMap你会用了吗?

本文所学技术可以用在哪

很多读者一看这个文章标题,可能根本不知道能干嘛,且不感兴趣。所以咱们先说说,今天写的这个技术有没有用。

首先,猫林老师即将给大家写的《原生AI之文字识别》就得用到这个知识。如果不学,等这篇文章面世时,各位可能有些代码看不懂。

其次,这个技术是实现一切图片处理的基石,比如你的App有个功能需要修改用户头像,而用户上传的图片可能会过大,那我们就需要对图片进行处理,例如裁剪,缩放,那必不可少的要用到这个技术。

最后,有些游戏的实现也依赖了这个技术,例如下图这种拼图游戏,就要用到本文的技术

image-20241217225531483

(如上图所示,这游戏的核心技术就是:将一张完整大图裁剪打散变成多张小图,再通过玩家进行移动摆放拼成原图)

P.S:若本文阅读量过万。猫林老师就出一篇文章或视频教大家如何开发这种游戏。(顺便,走过路过亲爱的读者们,麻烦点个关注点个赞点个收藏)

好了,言归正传,咱们本篇内容,正式开始!

PixelMap是什么

在回答这个问题之前,大家有必要理解一些基础知识:

  1. 任何文件,包括图片和你电脑中的小电影,本质上都是二进制数据。
  2. 图片有多种格式,例如png、jpg、gif等
  3. 每种图片格式都有其独特优势和用途,例
    • png一般是对原图无损压缩,文件体积会大一点
    • jpg是有损压缩算法,文件体积会小一点
    • gif是支持简单调色板和动画帧,所以可以动起来
  4. 根据以上信息可得,每种格式的图片,虽然展示的图像可能差别不是很大,但是因为他们的压缩算法和添加的内容有出入,每张图片的二进制表示形式排列规则绝对不一样
  5. 既然二进制排列不一样,各有各的规则,那么就意味着打开png格式的图片,要按照png的二进制规则去读取,电脑才能展现,同样打开jpg就要按照jpg的规则去读取去展现。以此类推
  6. 按不同的规则去打开对应格式图片的东西,可以叫图片解码器,所以不同格式图片有不同图片解码器。

根据以上结论,不知道有没有同学遇到过有些特定格式的图片系统默认情况下是打不开的。但是你装了某个软件后,他能打开了?现在能不能思考出原因?

没错,就因为系统默认只有一些常见的图片解码器,所以对于不常见或者某些企业自研图片格式就打不开。装完对应软件就能打开了是因为装的这个软件就是它对应的解码器。

tips:我有个朋友,真的是我朋友啊。就是他有的时候半夜三更睡不着嘛,就会去下载些爱情片学习别人怎么谈恋爱的,但是下载下来的有些电影文件的格式后缀奇奇怪怪的,他的播放器默认打不开。但是他播放器有在线更新功能,在打开这个电影时,虽然第一次打不开,但是也提示了正在下载某某格式解码器。等这个解码器下载完安装好,爱情片就能播放了。现在,聪明的你知道什么原因了吗?

对了!这真的是我朋友啊!!

好了,以上说了一大坨,回归我们的主题:PixelMap到底是个啥?跟上面说的有啥关系?

上面我们已经知道,不同格式的图片要想能打开就要用不同的规则去加载。那同样的道理,如果现在你要做图片裁剪功能,就意味着不同格式的图片得用不同的裁剪方式。这样就大大不利于开发。

正因此,需要一种统一的方式才好处理图片。而PixelMap正是提供了这种统一的方式,将这些不同格式的图像转换成一个可以直接操作的数据结构。也就相当于PixelMap是一种统一规则的像素结构,它内部根据一系列操作,把不同格式的图片还原成每个像素点的颜色和位置信息,并存在内存中。

所以PixelMap可以简单粗暴的理解为图片还原成像素后的一种数据,有了这种数据后不用再关心这张图片之前是什么格式什么规则。我们只需要对像素数据进行处理即可实现裁剪、缩放等功能!

好了,概念到此结束,以上听懂了是我讲得好。没听懂?那也没关系,不懂也完全不影响我们用。

如何把图片转为PixelMap

我们看看在HarmonyOS Next中如何通过代码来转换。

  1. 首先需要导入image模块

    import {
          image } from '@kit.ImageKit';
    
  2. 获取图片,我们以获取相册里的图片为例(上上篇文章讲过,不会可以去翻看)

    const picker = new photoAccessHelper.PhotoViewPicker()
    
    // 异步的,记得给所在函数加async
    const res = await picker.select({
         
         MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE,
         maxSelectNumber: 1
    })
    
  3. 先用fileIo文件流打开图片,得到文件描述符(因为解码图片需要用文件描述符),并使用image模块里的createImageSource方法,传入读取到的图片文件描述符,得到解码后的图片,完了后记得关闭io流

    const imgFile = fileIo.openSync(res.photoUris[0], fileIo.OpenMode.READ_ONLY)
    const imageSource : image.ImageSource = image.createImageSource(imgFile.fd)
    fileIo.close(imgFile)
    
  4. 把解码后的图片调用createPixelMap方法转成PixelMap格式,异步的,记得加await,以及所在函数加async

    const pixelMap = await imageSource.createPixelMap()
    

经过这五步,我们就得到了一个图片所对应的PixelMap,我们可以用如下代码测试:

import {
    photoAccessHelper } from '@kit.MediaLibraryKit'
import {
    image } from '@kit.ImageKit'
import {
    fileIo } from '@kit.CoreFileKit'



struct Index {
   
  // 声明个全局状态变量,保存PixelMap并交给
   image:PixelMap | null = null
  build() {
   
    Column(){
   

      Image(this.image)
        .objectFit(ImageFit.Contain)
        .width('80%')
      Button('点我')
        .width('80%')
        .onClick(async () => {
   

          const picker = new photoAccessHelper.PhotoViewPicker()

          const res = await picker.select({
   
            MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE,
            maxSelectNumber: 1
          })

          const imgFile = fileIo.openSync(res.photoUris[0], fileIo.OpenMode.READ_ONLY)
          const imageSource : image.ImageSource = image.createImageSource(imgFile.fd)
          fileIo.close(imgFile)

          const pixelMap = await imageSource.createPixelMap()
          this.image = pixelMap
        })
    }
    .width('100%')
    .height('100%')
  }
}

说明:

  • 因为PixelMap本身就是表示像素信息的,因此也可以给Image组件显示

效果如下图

image-20241218000635770

如何用PixelMap对图片进行裁剪

PixelMap图片数据。具有crop方法,即可进行裁剪,用法

pixelMap.crop({
   x: 0, y: 0, size: {
    height: 400, width: 400 } });
  • x与y代表一个以左上角为原点的坐标,设置一个裁剪起点
  • size代表从上面这个起点开始,裁剪多大的区域

如再上例代码得到PixelMap后我们加一句代码,即

const pixelMap = await imageSource.createPixelMap()
pixelMap.cropSync({
   
   x: 300,
   y: 300,
   size: {
    width: 240, height: 240 }
})
this.image = pixelMap

可观察到下图效果

image-20241218003153874

PixelMap其他操作方法

  • scale
    • 缩放,传入x、y方向倍数
  • translate
    • 偏移,传入x、y方向偏移值
  • rotate
    • 旋转,传入旋转角度(无需加单位)
  • flip(false, true)
    • 垂直翻转
  • flip(true, false)
    • 水平翻转
  • opacity
    • 透明度(1-0之间)

总结

  • PixelMap是将图片解码后得到的像素数据,方便对图片进行操作
  • 本篇是其他文章的基石,例如拼图游戏。
  • 最后,都看到这了,给个关注、点赞、收藏不过分吧?
相关文章
|
5天前
|
调度 云计算 芯片
云超算技术跃进,阿里云牵头制定我国首个云超算国家标准
近日,由阿里云联合中国电子技术标准化研究院主导制定的首个云超算国家标准已完成报批,不久后将正式批准发布。标准规定了云超算服务涉及的云计算基础资源、资源管理、运行和调度等方面的技术要求,为云超算服务产品的设计、实现、应用和选型提供指导,为云超算在HPC应用和用户的大范围采用奠定了基础。
179571 18
|
12天前
|
存储 运维 安全
云上金融量化策略回测方案与最佳实践
2024年11月29日,阿里云在上海举办金融量化策略回测Workshop,汇聚多位行业专家,围绕量化投资的最佳实践、数据隐私安全、量化策略回测方案等议题进行深入探讨。活动特别设计了动手实践环节,帮助参会者亲身体验阿里云产品功能,涵盖EHPC量化回测和Argo Workflows量化回测两大主题,旨在提升量化投研效率与安全性。
云上金融量化策略回测方案与最佳实践
|
14天前
|
人工智能 自然语言处理 前端开发
从0开始打造一款APP:前端+搭建本机服务,定制暖冬卫衣先到先得
通义灵码携手科技博主@玺哥超carry 打造全网第一个完整的、面向普通人的自然语言编程教程。完全使用 AI,再配合简单易懂的方法,只要你会打字,就能真正做出一个完整的应用。
9198 23
|
18天前
|
Cloud Native Apache 流计算
资料合集|Flink Forward Asia 2024 上海站
Apache Flink 年度技术盛会聚焦“回顾过去,展望未来”,涵盖流式湖仓、流批一体、Data+AI 等八大核心议题,近百家厂商参与,深入探讨前沿技术发展。小松鼠为大家整理了 FFA 2024 演讲 PPT ,可在线阅读和下载。
4885 12
资料合集|Flink Forward Asia 2024 上海站
|
18天前
|
自然语言处理 数据可视化 API
Qwen系列模型+GraphRAG/LightRAG/Kotaemon从0开始构建中医方剂大模型知识图谱问答
本文详细记录了作者在短时间内尝试构建中医药知识图谱的过程,涵盖了GraphRAG、LightRAG和Kotaemon三种图RAG架构的对比与应用。通过实际操作,作者不仅展示了如何利用这些工具构建知识图谱,还指出了每种工具的优势和局限性。尽管初步构建的知识图谱在数据处理、实体识别和关系抽取等方面存在不足,但为后续的优化和改进提供了宝贵的经验和方向。此外,文章强调了知识图谱构建不仅仅是技术问题,还需要深入整合领域知识和满足用户需求,体现了跨学科合作的重要性。
|
26天前
|
人工智能 自动驾驶 大数据
预告 | 阿里云邀您参加2024中国生成式AI大会上海站,马上报名
大会以“智能跃进 创造无限”为主题,设置主会场峰会、分会场研讨会及展览区,聚焦大模型、AI Infra等热点议题。阿里云智算集群产品解决方案负责人丛培岩将出席并发表《高性能智算集群设计思考与实践》主题演讲。观众报名现已开放。
|
14天前
|
人工智能 容器
三句话开发一个刮刮乐小游戏!暖ta一整个冬天!
本文介绍了如何利用千问开发一款情侣刮刮乐小游戏,通过三步简单指令实现从单个功能到整体框架,再到多端优化的过程,旨在为生活增添乐趣,促进情感交流。在线体验地址已提供,鼓励读者动手尝试,探索编程与AI结合的无限可能。
三句话开发一个刮刮乐小游戏!暖ta一整个冬天!
|
13天前
|
消息中间件 人工智能 运维
12月更文特别场——寻找用云高手,分享云&AI实践
我们寻找你,用云高手,欢迎分享你的真知灼见!
1025 68