鸿蒙开发之PixelMap介绍与实现图片变换
本文所学技术可以用在哪
很多读者一看这个文章标题,可能根本不知道能干嘛,且不感兴趣。所以咱们先说说,今天写的这个技术有没有用。
首先,猫林老师即将给大家写的《原生AI之文字识别》就得用到这个知识。如果不学,等这篇文章面世时,各位可能有些代码看不懂。
其次,这个技术是实现一切图片处理的基石,比如你的App有个功能需要修改用户头像,而用户上传的图片可能会过大,那我们就需要对图片进行处理,例如裁剪,缩放,那必不可少的要用到这个技术。
最后,有些游戏的实现也依赖了这个技术,例如下图这种拼图游戏,就要用到本文的技术

(如上图所示,这游戏的核心技术就是:将一张完整大图裁剪打散变成多张小图,再通过玩家进行移动摆放拼成原图)
P.S:若本文阅读量过万。猫林老师就出一篇文章或视频教大家如何开发这种游戏。(顺便,走过路过亲爱的读者们,麻烦点个关注点个赞点个收藏)
好了,言归正传,咱们本篇内容,正式开始!
PixelMap是什么
在回答这个问题之前,大家有必要理解一些基础知识:
- 任何文件,包括图片和你电脑中的小电影,本质上都是二进制数据。
- 图片有多种格式,例如png、jpg、gif等
- 每种图片格式都有其独特优势和用途,例
- png一般是对原图无损压缩,文件体积会大一点
- jpg是有损压缩算法,文件体积会小一点
- gif是支持简单调色板和动画帧,所以可以动起来
- 根据以上信息可得,每种格式的图片,虽然展示的图像可能差别不是很大,但是因为他们的压缩算法和添加的内容有出入,每张图片的二进制表示形式排列规则绝对不一样
- 既然二进制排列不一样,各有各的规则,那么就意味着打开png格式的图片,要按照png的二进制规则去读取,电脑才能展现,同样打开jpg就要按照jpg的规则去读取去展现。以此类推
- 按不同的规则去打开对应格式图片的东西,可以叫图片解码器,所以不同格式图片有不同图片解码器。
根据以上结论,不知道有没有同学遇到过有些特定格式的图片系统默认情况下是打不开的。但是你装了某个软件后,他能打开了?现在能不能思考出原因?
没错,就因为系统默认只有一些常见的图片解码器,所以对于不常见或者某些企业自研图片格式就打不开。装完对应软件就能打开了是因为装的这个软件就是它对应的解码器。
tips:我有个朋友,真的是我朋友啊。就是他有的时候半夜三更睡不着嘛,就会去下载些爱情片学习别人怎么谈恋爱的,但是下载下来的有些电影文件的格式后缀奇奇怪怪的,他的播放器默认打不开。但是他播放器有在线更新功能,在打开这个电影时,虽然第一次打不开,但是也提示了正在下载某某格式解码器。等这个解码器下载完安装好,爱情片就能播放了。现在,聪明的你知道什么原因了吗?
对了!这真的是我朋友啊!!
好了,以上说了一大坨,回归我们的主题:PixelMap到底是个啥?跟上面说的有啥关系?
上面我们已经知道,不同格式的图片要想能打开就要用不同的规则去加载。那同样的道理,如果现在你要做图片裁剪功能,就意味着不同格式的图片得用不同的裁剪方式。这样就大大不利于开发。
正因此,需要一种统一的方式才好处理图片。而PixelMap正是提供了这种统一的方式,将这些不同格式的图像转换成一个可以直接操作的数据结构。也就相当于PixelMap是一种统一规则的像素结构,它内部根据一系列操作,把不同格式的图片还原成每个像素点的颜色和位置信息,并存在内存中。
所以PixelMap可以简单粗暴的理解为图片还原成像素后的一种数据,有了这种数据后不用再关心这张图片之前是什么格式什么规则。我们只需要对像素数据进行处理即可实现裁剪、缩放等功能!
好了,概念到此结束,以上听懂了是我讲得好。没听懂?那也没关系,不懂也完全不影响我们用。
如何把图片转为PixelMap
我们看看在HarmonyOS Next中如何通过代码来转换。
首先需要导入image模块
import { image } from '@kit.ImageKit';
获取图片,我们以获取相册里的图片为例(上上篇文章讲过,不会可以去翻看)
const picker = new photoAccessHelper.PhotoViewPicker() // 异步的,记得给所在函数加async
const res = await picker.select({
MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE,
maxSelectNumber: 1
})
先用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)
把解码后的图片调用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'
@Entry
@Component
struct Index {
// 声明个全局状态变量,保存PixelMap并交给
@State 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组件显示
效果如下图

如何用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
可观察到下图效果

PixelMap其他操作方法
- scale
- 缩放,传入x、y方向倍数
- translate
- 偏移,传入x、y方向偏移值
- rotate
- 旋转,传入旋转角度(无需加单位)
- flip(false, true)
- 垂直翻转
- flip(true, false)
- 水平翻转
- opacity
- 透明度(1-0之间)
总结
- PixelMap是将图片解码后得到的像素数据,方便对图片进行操作
- 本篇是其他文章的基石,例如拼图游戏。
- 最后,都看到这了,给个关注、点赞、收藏不过分吧?
鸿蒙开发之PixelMap介绍与实现图片变换的更多相关文章
- Android开发之WebService介绍
经常有网友问:“在Android平台如何调用WebService”?经过沟通我发现,甚至有些朋友连什么是WebSerivce都不知道就在问怎么使用,更别说和WebService有关的SOAP.WSDL ...
- 李洪强iOS开发之-Swift_00_介绍
SWIFT (计算机编程语言) Swift,苹果于2014年WWDC(苹果开发者大会)发布的新开发语言,可与Objective-C*共同运行于Mac OS和iOS平台,用于搭建基于苹果平台的应用程序. ...
- Android开发之OkHttp介绍
要论时下最火的网络请求框架,当属OkHttp了.自从Android4.4开始,google已经开始将源码中的HttpURLConnection替换为OkHttp,而在Android6.0之后的SDK中 ...
- 安卓开发之cache 的使用(图片查看器案例)
package com.lidaochen.test; import android.graphics.Bitmap; import android.graphics.BitmapFactory; i ...
- 基于xmpp openfire smack开发之openfire介绍和部署[1]
前言 http://blog.csdn.net/shimiso/article/details/8816558 Java领域的即时通信的解决方案可以考虑openfire+spark+smack.当然也 ...
- 深入浅出Android开发之Surface介绍
一 目的 本节的目的就是为了讲清楚Android中的Surface系统,大家耳熟能详的SurfaceFlinger到底是个什么东西,它的工作流程又是怎样的.当然,鉴于SurfaceFlinger的复杂 ...
- 基于xmpp openfire smack开发之Android客户端开发[3]
在上两篇文章中,我们依次介绍openfire部署以及smack常用API的使用,这一节中我们着力介绍如何基于asmack开发一个Android的客户端,本篇的重点在实践,讲解和原理环节,大家可以参考前 ...
- 高效开发之SASS篇 灵异留白事件——图片下方无故留白 你会用::before、::after吗 link 与 @import之对比 学习前端前必知的——HTTP协议详解 深入了解——CSS3新增属性 菜鸟进阶——grunt $(#form :input)与$(#form input)的区别
高效开发之SASS篇 作为通往前端大神之路的普通的一只学鸟,最近接触了一样稍微高逼格一点的神器,特与大家分享~ 他是谁? 作为前端开发人员,你肯定对css很熟悉,但是你知道css可以自定义吗?大家 ...
- iOS-iPad开发之popoverController使用介绍
iOS-iPad开发之popoverController使用介绍 iOS开发UI篇-popoverController使用注意 iOS SDK:自定义Popover(弹出窗口) 实现的简单例子: // ...
- iOS-iPad开发之SplitViewController简单介绍
iOS-iPad开发之SplitViewController简单介绍 SplitViewController图形化创建 SplitViewController可以并列显示两个view,适用于基于nav ...
随机推荐
- Rust字符串类型全解析
字符串是每种编程语言都绕不开的类型, 不过,在Rust中,你会看到远比其他语言更加丰富多样的字符串类型. 如下图: 为什么Rust中需要这么多种表示字符串的类型呢? 初学Rust时,可能无法理解为什么 ...
- C# WebSocket Servers -- Fleck、SuperSocket、TouchSocke
最近在维护老项目,感觉内存一直都有问题,定位到问题是WebSocketServer的问题,了解了 Fleck.SuperSocket.TouchSocke 等开源项目,这里记录一下. .net5..n ...
- python处理nii文件
第一步安装nibabel,可以使用命令:pip install nibabel 之后: from nibabel.viewers import OrthoSlicer3D as osdimport n ...
- kotlin更多语言结构——>相等性
Kotlin 中有两种类型的相等性: - 结构相等(用 equals() 检测); - 引用相等(两个引用指向同一对象). 结构相等 结构相等由 ==(以及其否定形式 !=)操作判断.按照惯例,像 ...
- IHostedService(BackgroundService)的启动和停止顺序
一句话总结: 按照Add顺序启动, 先启动, 后停止. Host 源代码 public async Task StartAsync(CancellationToken cancellationToke ...
- appium-解决uiautomatorviewer不能定位android7以上版本元素的方法
上图是android10模拟器,发现我们是无法连接模拟器识别的 解决方法: 在模拟器内打开指定页面然后截图,最后保存为uix文件,然后用adb拉到本地,一共四个命令,可以保存为.bat文件快捷执行(这 ...
- 【JVM第3课】运行时数据区
运行时数据区结构图如下: 可分为 5 个区域,分别是方法区.堆区.虚拟机栈.本地方法栈.程序计数器.这里大概介绍一下各个模块的作用,会在后面的文章展开讲. 类加载子系统会把类信息加载到方法区,程序运行 ...
- 如何在HarmonyOS Next中编译React-Native包
一.创作背景 鸿蒙既出,万众瞩目.作为国内操作系统自力更生的代表,它承载着十四亿中国人民的强烈期望,系国家安全和国运于一身.就算抛开爱国情怀不谈,作为一名软件开发人员,偌大的就业市场,海量的翻身机会就 ...
- GIt分布式管理工具
Git(分布式版本控制工具) Git的学习是不依赖我们前面学习的知识,就算没有学习java也可以学习 Git就是一个类似于百度云盘的仓库 重点是要掌握使用idea操作Git,企业用的最多,一般不会去使 ...
- Air780EP之RC522开发板,你了解吗?
本文讲解合宙Air780EP开发板RC522实例. 本文档适用于Air780EP开发板: 关联文档和使用工具: rc522 - rc522 非接触式读写卡驱动 - LuatOS 文档: LuatO ...