HarmonyOS之深入解析图像的编码和解码
Posted Forever_wj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HarmonyOS之深入解析图像的编码和解码相关的知识,希望对你有一定的参考价值。
一、基本概念
- HarmonyOS 图像模块支持图像业务的开发,常见功能如图像解码、图像编码、基本的位图操作、图像编辑等。当然,也支持通过接口组合来实现更复杂的图像处理逻辑。
- 图像解码:图像解码就是不同的存档格式图片(如 JPEG、PNG 等)解码为无压缩的位图格式,以方便在应用或者系统中进行相应的处理。
- PixelMap:PixelMap 是图像解码后无压缩的位图格式,用于图像显示或者进一步的处理。
- 渐进式解码:渐进式解码是在无法一次性提供完整图像文件数据的场景下,随着图像文件数据的逐步增加,通过多次增量解码逐步完成图像解码的模式。
- 预乘:预乘时,RGB 各通道的值被替换为原始值乘以 Alpha 通道不透明的比例(0~1)后的值,方便后期直接合成叠加;不预乘指 RGB 各通道的数值是图像的原始值,与 Alpha 通道的值无关。
- 图像编码:图像编码就是将无压缩的位图格式,编码成不同格式的存档格式图片( JPEG、PNG 等),以方便在应用或者系统中进行相应的处理。
- 为及时释放本地资源,建议在图像解码的 ImageSource 对象、位图图像 PixelMap 对象或图像编码的 ImagePacker 对象使用完成后,主动调用 ImageSource、PixelMap 和 ImagePacker 的 release() 方法。
二、图像解码
① 应用场景
- 图像解码就是将所支持格式的存档图片解码成统一的 PixelMap 图像,用于后续图像显示或其他处理,比如旋转、缩放、裁剪等。当前支持格式包括 JPEG、PNG、GIF、HEIF、WebP、BMP。
② 解码 API
- mageSource 主要用于图像解码:
接口名 | 描述 |
---|---|
create(String pathName, SourceOptions opts) | 从图像文件路径创建图像数据源 |
create(InputStream is, SourceOptions opts) | 从输入流创建图像数据源 |
create(byte[] data, SourceOptions opts) | 从字节数组创建图像源 |
create(byte[] data, int offset, int length, SourceOptions opts) | 从字节数组指定范围创建图像源 |
create(File file, SourceOptions opts) | 从文件描述符创建图像数据源 |
create(FileDescriptor fd, SourceOptions opts) | 创建渐进式图像数据源 |
createIncrementalSource(SourceOptions opts) | 创建渐进式图像数据源,支持设置渐进式数据更新模式 |
createIncrementalSource(IncrementalSourceOptions opts) | 从图像数据源解码并创建PixelMap图像 |
createPixelmap(DecodingOptions opts) | 从图像数据源解码并创建PixelMap图像,如果图像数据源支持多张图片的话,支持指定图像索引 |
createPixelmap(int index, DecodingOptions opts) | 更新渐进式图像源数据 |
updateData(byte[] data, boolean isFinal) | 更新渐进式图像源数据,支持设置输入数据的有效数据范围 |
updateData(byte[] data, int offset, int length, boolean isFinal) | |
getImageInfo() | 获取图像基本信息 |
getImageInfo(int index) | 根据特定的索引获取图像基本信息 |
getSourceInfo() | 获取图像源信息 |
release() | 释放对象关联的本地资源 |
③ 普通解码
- 创建图像数据源 ImageSource 对象,可以通过 SourceOptions 指定数据源的格式信息,此格式信息仅为给解码器的提示,正确提供能帮助提高解码效率,如果不设置或设置不正确,会自动检测正确的图像格式。不使用该选项时,可以将 create 接口传入的 SourceOptions 设置为 null。
ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
srcOpts.formatHint = "image/png";
String pathName = "/sdcard/image.png";
ImageSource imageSource = ImageSource.create(pathName, srcOpts);
// 不通过SourceOptions指定数据源格式信息
ImageSource imageSourceNoOptions = ImageSource.create(pathName, null);
- 设置解码参数,解码获取 PixelMap 图像对象,解码过程中同时支持图像处理操作。
-
- 设置 desiredSize 支持按尺寸缩放,如果设置为全 0,则不进行缩放。
-
- 设置 desiredRegion 支持按矩形区域裁剪,如果设置为全 0,则不进行裁剪。
-
- 设置 rotateDegrees 支持旋转角度,以图像中心点顺时针旋转。
- 如果只需要解码原始图像,不使用该选项时,可将给 createPixelMap 传入的 DecodingOptions 设置为 null。
// 普通解码叠加缩放、裁剪、旋转
ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
decodingOpts.desiredSize = new Size(100, 2000);
decodingOpts.desiredRegion = new Rect(0, 0, 100, 100);
decodingOpts.rotateDegrees = 90;
PixelMap pixelMap = imageSource.createPixelmap(decodingOpts);
// 普通解码
PixelMap pixelMapNoOptions = imageSource.createPixelmap(null);
- 解码完成获取到 PixelMap 对象后,可以进行后续处理,比如渲染显示等。
④ 渐进式解码
- 创建渐进式图像数据源 ImageSource 对象:可以通过 SourceOptions 指定数据源的格式信息,此格式信息仅为提示,如果填写不正确,会自动检测正确的图像格式。使用 IncrementalSourceOptions 指定图像数据的更新方式为渐进式更新。
ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
srcOpts.formatHint = "image/jpeg";
ImageSource.IncrementalSourceOptions incOpts = new ImageSource.IncrementalSourceOptions();
incOpts.opts = srcOpts;
incOpts.mode = ImageSource.UpdateMode.INCREMENTAL_DATA;
imageSource = ImageSource.createIncrementalSource(incOpts);
- 渐进式更新数据,在未获取到全部图像时,支持先更新部分数据来尝试解码,调用 updateData 更新数据,将参数 isFinal 设置为 false;当获取到全部数据后,最后一次更新数据时设置 isFinal为true,表示数据更新完毕,设置解码参数同普通解码。
// 获取到一定的数据时尝试解码
imageSource.updateData(data, 0, bytes, false);
ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
PixelMap pixelMap = imageSource.createPixelmap(decodingOpts);
// 更新数据再次解码,重复调用直到数据全部更新完成
imageSource.updateData(data, 0, bytes, false);
PixelMap pixelMap = imageSource.createPixelmap(decodingOpts);
// 数据全部更新完成时需要传入isFinal为true
imageSource.updateData(data, 0, bytes, true);
PixelMap pixelMap = imageSource.createPixelmap(decodingOpts);
- 解码完成获取到 PixelMap 对象后,可以进行后续处理,比如渲染显示等。
三、图像编码
① 应用场景
- 图像编码就是将 PixelMap 图像编码成不同存档格式图片,用于后续其他处理,比如保存、传输等。当前仅支持 JPEG 格式。
② 编码 API
- ImagePacker 主要用于图像编码:
接口名 | 描述 |
---|---|
create() | 创建图像打包器实例 |
initializePacking(byte[] data, PackingOptions opts) | 初始化打包任务,将字节数组设置为打包后输出目的 |
initializePacking(byte[] data, int offset, PackingOptions opts) | 初始化打包任务,将带偏移量的字节数组设置为打包后输出目的 |
initializePacking(OutputStream outputStream, PackingOptions opts) | 初始化打包任务,将输出流设置为打包后输出目的 |
addImage(PixelMap pixelmap) | 将PixelMap对象添加到图像打包器中 |
addImage(ImageSource source) | 将图像数据源ImageSource中图像添加到图像打包器中 |
addImage(ImageSource source, int index) | 将图像数据源ImageSource中指定图像添加到图像打包器中 |
finalizePacking() | 完成图像打包任务 |
release() | 释放对象关联的本地资源 |
③ 图像编码流程
- 创建图像编码 ImagePacker 对象:
ImagePacker imagePacker = ImagePacker.create();
- 设置编码输出流和编码参数。设置 format 为编码的图像格式,当前支持 jpeg 格式。设置 quality 为图像质量,范围从0-100,100为最佳质量。
FileOutputStream outputStream = new FileOutputStream("/path/to/packed.file");
ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions();
packingOptions.format = "image/jpeg";
packingOptions.quality = 90;
boolean result = imagePacker.initializePacking(outputStream, packingOptions);
- 添加需要编码的 PixelMap 对象,进行编码操作。
result = imagePacker.addImage(myPixelMap);
long dataSize = imagePacker.finalizePacking();
- 编码输出完成后,可以进行后续处理,比如保存、传输等。
以上是关于HarmonyOS之深入解析图像的编码和解码的主要内容,如果未能解决你的问题,请参考以下文章