本文正在参与优质创作者激励
目录
HarmonyOS Sample 之 PixelMap 图像功能开发
1.介绍
HarmonyOS图像模块支持图像业务的开发,常见功能如图像解码、图像编码、基本的位图操作、图像编辑等。当然,也支持通过接口组合来实现更复杂的图像处理逻辑。
那么什么叫图像解码,什么叫图像编码,什么叫位图?
PixelMap是图像解码后无压缩的位图格式
图像解码就是不同的存档格式图片(如JPEG、PNG等)解码为无压缩的位图格式
图像编码就是将无压缩的位图格式,编码成不同格式的存档格式图片(JPEG、PNG等)
不管是编码还是解码的目的是方便在应用或者系统中进行相应的处理。
本文正在参与优质创作者激励
2.搭建环境
安装DevEco Studio,详情请参考DevEco Studio下载。
设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:
如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。
如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。
下载源码后,使用DevEco Studio 打开项目,模拟器运行即可。
真机运行需要将config.json中的bundleName修改为自己的,如果没有请到AGC上进行配置,参见 使用模拟器进行调试 。
3.代码结构

4.实例讲解
4.1.界面布局
布局只有几个操作按钮,见后面的效果图,不是本文的重点。
4.2.后台代码
4.2.1 图像解码功能
图像解码就是将所支持格式的存档图片解码成统一的PixelMap图像,用于后续图像显示或其他处理,比如旋转、缩放、裁剪等。当前支持格式包括JPEG、PNG、GIF、HEIF、WebP、BMP。
主要用到 ImageSource等
ImageSource.SourceOptions 指定数据源的格式信息,非必填
ImageSource.DecodingOptions 用来支持在解码过程中的图像处理操作,例如缩放、裁剪、旋转,非必填。
接下来看个最简单的图像解码的例子:
效果:

还有一个渐进式解码,
官方文档的描述:在未获取到全部图像时,支持先更新部分数据来尝试解码,调用updateData更新数据,将参数isFinal设置为false;当获取到全部数据后,最后一次更新数据时设置isFinal为true,表示数据更新完毕。
又去网上搜索了一下关于渐进式解码的内容,是这么说的
“渐进式解码提供在整个图像完成下载之前以增量方式解码和呈现图像部分的能力。 此功能极大地改进了从 Internet 查看图像时用户的体验,因为用户无需等待整个图像下载,就可以开始解码。 在下载整个映像之前,用户可以查看包含可用数据的映像预览。 此功能对于用于从 Internet 或带宽有限的数据源查看图像的任何应用程序都至关重要。”
“渐进式解码是一种从不完整的图像文件中以增量方式解码图像部分的能力。 传统解码需要完整的图像文件才能开始解码。 渐进式解码在图像的渐进式级别完成下载后开始。 解码器对图像的当前渐进式级别执行解码传递。 然后,它会在下载每个渐进式级别时对图像执行多个解码传递。 每次解码传递都显示更多图像,直到完全下载并解码图像。 解码完整图像所需的传递数取决于图像文件格式和用于创建图像的编码过程。
使用渐进式解码的要求:
1.图像文件必须支持渐进式解码。 大多数图像格式不支持渐进式解码,尽管常用图像格式为 JPEG、PNG 和 GIF。
2.图像文件必须编码为渐进式图像。 未使用渐进式图像编码创建的图像文件无法实现渐进式解码,即使文件格式会支持渐进式解码。
3.支持渐进式解码的编解码器必须可用。 如果编解码器不支持渐进式解码,则编码为渐进式图像的图像将被解码为传统图像。”
一起看个渐进式解码的例子,
点击 “渐进式解码” 按钮,执行一次imageSource.updateData
效果:

4.2.2 图像编码功能
图像编码主要用到ImagePacker
ImagePacker.PackingOptions 设置编码选项,目前没有太多可选。
4.2.3 编辑位图功能
a.通过imageSource创建缩略图,createThumbnailPixelmap
b.读写位图像素数据,画个像素小人
private void edit(Component component) {
cleanComponents();
int colorsWidth = 552;
int colorsHeight = 310;
PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
initializationOptions.size = new Size(colorsWidth, colorsHeight);
initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
initializationOptions.editable = true;
int[] colors = new int[colorsWidth * colorsHeight];
Arrays.fill(colors, Color.RED.getValue());
PixelMap pixelMap = PixelMap.create(colors, initializationOptions);
showFirstImage.setPixelMap(pixelMap);
PixelMap pixelMap2 = PixelMap.create(pixelMap, initializationOptions);
int color = pixelMap2.readPixel(new Position(1, 1));
HiLog.info(LABEL_LOG, "%{public}s", "pixelMapEdit readPixel color :" + color);
for(int i=130;i<180 ;i++){
pixelMap2.writePixel(new Position(i, i), 0xFF112233);
}
int[] pixelArray = new int[1024*1024];
Arrays.fill(pixelArray, Color.BLACK.getValue());
Rect region = new Rect(160, 110, 50, 50);
pixelMap2.writePixels(pixelArray, 0, 100, region);
Arrays.fill(pixelArray, Color.GREEN.getValue());
Rect region2= new Rect(150, 160, 70, 60);
pixelMap2.writePixels(pixelArray, 0, 100, region2);
Arrays.fill(pixelArray, Color.YELLOW.getValue());
Rect region3= new Rect(130, 160, 20, 70);
pixelMap2.writePixels(pixelArray, 0, 100, region3);
Rect region4= new Rect(220, 160, 20, 70);
pixelMap2.writePixels(pixelArray, 0, 100, region4);
Arrays.fill(pixelArray, Color.GRAY.getValue());
Rect region5= new Rect(160, 200, 20, 70);
pixelMap2.writePixels(pixelArray, 0, 100, region5);
Rect region6= new Rect(190, 200, 20, 70);
pixelMap2.writePixels(pixelArray, 0, 100, region6);
showSecondImage.setPixelMap(pixelMap2);
long capacity = pixelMap.getPixelBytesCapacity();
long bytesNumber = pixelMap.getPixelBytesNumber();
int rowBytes = pixelMap.getBytesNumberPerRow();
byte[] ninePatchData = pixelMap.getNinePatchChunk();
showResultText.setText(
"This pixelMap detail info :" + System.lineSeparator() + "capacity = " + capacity + System.lineSeparator()
+ "bytesNumber = " + bytesNumber + System.lineSeparator() + "rowBytes = " + rowBytes
+ System.lineSeparator() + "ninePatchData = " + Arrays.toString(ninePatchData) + System.lineSeparator());
pixelMap.release();
pixelMap2.release();
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
效果是这样的

4.2.4 获取图像属性
图像属性解码就是获取图像中包含的属性信息,PropertyKey 存储了常用的属性KEY信息。
看代码:
效果:

5.思考总结
通过这次实践,可以学到的内容:
1.位图的概念,如何进行图像的编码、解码、编辑。
2.渐进式解码的概念,如何生成缩略图,获取其他图像属性等。
6.完整代码
附件直接下载
本文正在参与优质创作者激励
这才是真正的技术分享,官网那个简陋的文档,看了蛋疼。
详细,注释太好了
hhh,确实