1 简介
应用开发中的图片开发
是对图片像素数据进行解析
、处理
、构造
的过程,达到目标图片效果,主要涉及图片解码
、图片处理
、图片编码
等。
-
图片解码
指将所支持格式的存档图片解码成统一的PixelMap
,以便在应用或系统中进行图片显示或图片处理。当前支持的存档图片格式包括JPEG
、PNG
、GIF
、RAW
、WebP
、BMP
、SVG
、ICO
。 -
PixelMap
指图片解码后无压缩的位图,用于图片显示或图片处理。 -
图片处理
指对PixelMap
进行相关的操作,如旋转、缩放、设置透明度、获取图片信息、读写像素数据等。 -
图片编码
指将PixelMap
编码成不同格式的存档图片(当前仅支持JPEG
、WebP
和PNG
),用于后续处理,如保存、传输等。
- 获取图片:通过应用沙箱等方式获取原始图片。
- 创建
ImageSource
实例:ImageSource
是图片解码出来的图片源类,用于获取或修改图片相关信息。 - 图片解码:通过
ImageSource
解码生成PixelMap
。 - 图片处理:对
PixelMap
进行处理,更改图片属性实现图片的旋转、缩放、裁剪等效果。然后通过Image
组件显示图片。 - 图片编码:使用图片打包器类
ImagePacker
,将PixelMap
或ImageSource
进行压缩编码,生成一张新的图片。
除上述基本图片开发能力外,OpenHarmony
还提供常用图片工具,供开发者选择使用。编解码支持多种图片格式,并采用了高效的算法和优化策略,提高了图片处理的速度和效率。在图片处理中,可能需要使用用户图片,应用需要向用户申请对应的读写操作权限才能保证功能的正常运行。图片框架提供图片编解码能力,为Image
组件及图库等应用提供支撑,其解码结果可以传给Image组件
显示。
下面我们来学习ArkTS相关的图片解码、编码。
2 图片解码(ArkTS)
图片解码
指将所支持格式的存档图片解码成统一的PixelMap
,以便在应用或系统中进行图片显示或图片处理。当前支持的存档图片格式包括JPEG
、PNG
、GIF
、RAW
、WebP
、BMP
、SVG
、ICO
。
2.1 开发步骤
- 全局导入
Image
模块
import image from '@ohos.multimedia.image';
- 获取图片
- 方法一:获取沙箱路径。具体请参考获取应用文件路径。应用沙箱的介绍及如何向应用沙箱推送文件,请参考文件管理。
// Stage模型参考如下代码
const context : Context = getContext(this);
const filePath : string = context.cacheDir + '/test.jpg';
// FA模型参考如下代码
import featureAbility from '@ohos.ability.featureAbility';const context = featureAbility.getContext();
const filePath = context.getCacheDir() + "/test.jpg";
- 方法二:通过沙箱路径获取图片的文件描述符。具体请参考
file.fs API
参考文档。 该方法需要先导入@ohos.file.fs
模块。
import fs from '@ohos.file.fs';
然后调用fs.openSync()
获取文件描述符。
// Stage模型参考如下代码
const context = getContext(this);
const filePath = context.cacheDir + '/test.jpg';
const file : fs.File = fs.openSync(filePath, fs.OpenMode.READ_WRITE);
const fd : number = file?.fd;
// FA模型参考如下代码
import featureAbility from '@ohos.ability.featureAbility';const context = featureAbility.getContext();
const filePath = context.getCacheDir() + "/test.jpg";
const file : fs.File = fs.openSync(filePath, fs.OpenMode.READ_WRITE);
const fd : number = file?.fd;
- 方法三:通过资源管理器获取资源文件的
ArrayBuffer
。
// Stage模型
const context : Context = getContext(this);
// 获取resourceManager资源管理器
const resourceMgr : resourceManager.ResourceManager = context.resourceManager;
// FA模型
// 导入resourceManager资源管理器
import resourceManager from '@ohos.resourceManager';
import {BusinessError} from '@ohos.base';
resourceManager.getResourceManager().then((resourceMgr : resourceManager.ResourceManager) => {console.log("Succeeded in getting resourceManager")
}).catch((err : BusinessError) => {console.error("Failed to get resourceManager")
});
不同模型获取资源管理器的方式不同,获取资源管理器后,再调用resourceMgr.getRawFileContent()
获取资源文件的ArrayBuffer
。
resourceMgr.getRawFileContent('test.jpg').then((fileData : Uint8Array) => {console.log("Succeeded in getting RawFileContent")// 获取图片的ArrayBufferconst buffer = fileData.buffer.slice(0);
}).catch((err : BusinessError) => {console.error("Failed to get RawFileContent")
});
- 方法四:通过资源管理器获取资源文件的
RawFileDescriptor
。
// Stage模型
const context : Context = getContext(this);
// 获取resourceManager资源管理器
const resourceMgr : resourceManager.ResourceManager = context.resourceManager;
// FA模型
// 导入resourceManager资源管理器
import resourceManager from '@ohos.resourceManager';
import {BusinessError} from '@ohos.base';
resourceManager.getResourceManager().then((resourceMgr : resourceManager.ResourceManager) => {console.log("Succeeded in getting resourceManager")
}).catch((err : BusinessError) => {console.error("Failed to get resourceManager")
});
不同模型获取资源管理器的方式不同,获取资源管理器后,再调用resourceMgr.getRawFd()
获取资源文件的RawFileDescriptor
。
resourceMgr.getRawFd('test.jpg').then((rawFileDescriptor : resourceManager.RawFileDescriptor) => {console.log("Succeeded in getting resourceManager")
}).catch((err : BusinessError) => {console.error("Failed to get resourceManager")
});
- 创建
ImageSource
实例。
- 方法一:通过沙箱路径创建
ImageSource
。沙箱路径可以通过步骤2的方法一获取。
// path为已获得的沙箱路径
const imageSource : image.ImageSource = image.createImageSource(filePath);
- 方法二:通过文件描述符
fd
创建ImageSource
。文件描述符可以通过步骤2的方法二获取。
// fd为已获得的文件描述符
const imageSource : image.ImageSource = image.createImageSource(fd);
- 方法三:通过缓冲区数组创建
ImageSource
。缓冲区数组可以通过步骤2的方法三获取。
const imageSource : image.ImageSource = image.createImageSource(buffer);
- 方法四:通过资源文件的
RawFileDescriptor
创建ImageSource
。RawFileDescriptor
可以通过步骤2的方案四获取。
const imageSource : image.ImageSource = image.createImageSource(rawFileDescriptor);
设置解码参数DecodingOptions
,解码获取PixelMap
图片对象。
import {BusinessError} from '@ohos.base';
let decodingOptions : image.DecodingOptions = {editable: true,desiredPixelFormat: 3,
}
// 创建pixelMap并进行简单的旋转和缩放
imageSource.createPixelMap(decodingOptions).then((pixelMap : image.PixelMap) => {console.log("Succeeded in creating PixelMap")
}).catch((err : BusinessError) => {console.error("Failed to create PixelMap")
});
解码完成,获取到PixelMap
对象后,可以进行后续图片处理。释放pixelMap
。
pixelMap.release();
2.2 示例
// 1. 获取resourceManager资源管理
const context : Context = getContext(this);
const resourceMgr : resourceManager.ResourceManager = context.resourceManager;// 2. 创建ImageSource。
// 通过rawfile文件夹下test.jpg的ArrayBuffer创建。resourceMgr.getRawFileContent('test.jpg').then((fileData : Uint8Array) => {console.log("Succeeded in getting RawFileContent")// 获取图片的ArrayBufferconst buffer = fileData.buffer.slice(0);const imageSource : image.ImageSource = image.createImageSource(buffer);}).catch((err : BusinessError) => {console.error("Failed to get RawFileContent")});// 通过rawfile文件夹下test.jpg的RawFileDescriptor创建。
resourceMgr.getRawFd('test.jpg').then((rawFileDescriptor : resourceManager.RawFileDescriptor) => {console.log("Succeeded in getting RawFd")const imageSource : image.ImageSource = image.createImageSource(rawFileDescriptor);}).catch((err : BusinessError) => {console.error("Failed to get RawFd")});// 3. 创建PixelMap。
imageSource.createPixelMap().then((pixelMap: image.PixelMap) => {console.log("Succeeded in creating PixelMap")
}).catch((err : BusinessError) => {console.error("Failed to creating PixelMap")
});// 4. 释放pixelMap。
pixelMap.release();
3 图片编码(ArkTS)
图片编码
指将PixelMap
编码成不同格式的存档图片(当前仅支持打包为JPEG
、WebP
和 png
格式),用于后续处理,如保存、传输等。
3.1 图片编码进文件流
- 创建图像编码
ImagePacker
对象。
// 导入相关模块包
import image from '@ohos.multimedia.image';const imagePackerApi = image.createImagePacker();
- 设置编码输出流和编码参数。
format
为图像的编码格式;quality
为图像质量,范围从0-100,100为最佳质量。
let packOpts : image.PackingOption = { format:"image/jpeg", quality:98 };
- 创建
PixelMap
对象或创建ImageSource
对象。进行图片编码,并保存编码后的图片。
- 方法一:通过
PixelMap
进行编码。
import {BusinessError} from '@ohos.base'
imagePackerApi.packing(pixelMap, packOpts).then( (data : ArrayBuffer) => {// data 为打包获取到的文件流,写入文件保存即可得到一张图片
}).catch((error : BusinessError) => { console.error('Failed to pack the image. And the error is: ' + error);
})
- 方法二:通过
imageSource
进行编码。
import {BusinessError} from '@ohos.base'
imagePackerApi.packing(imageSource, packOpts).then( (data : ArrayBuffer) => {// data 为打包获取到的文件流,写入文件保存即可得到一张图片
}).catch((error : BusinessError) => { console.error('Failed to pack the image. And the error is: ' + error);
})
3.2 图片编码进文件
在编码时,开发者可以传入对应的文件路径,编码后的内存数据将直接写入文件。
- 方法一:通过
PixelMap
编码进文件。
import {BusinessError} from '@ohos.base'
import fs from '@ohos.file.fs'
const context : Context = getContext(this);
const path : string = context.cacheDir + "/pixel_map.jpg";
let file = fs.openSync(path, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
imagePackerApi.packToFile(pixelMap, file.fd, packOpts).then(() => {// 直接打包进文件
}).catch((error : BusinessError) => { console.error('Failed to pack the image. And the error is: ' + error);
})
- 方法二:通过
imageSource
编码进文件。
import {BusinessError} from '@ohos.base'
import fs from '@ohos.file.fs'
const context : Context = getContext(this);
const filePath : string = context.cacheDir + "/image_source.jpg";
let file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
imagePackerApi.packToFile(imageSource, file.fd, packOpts).then(() => {// 直接打包进文件
}).catch((error : BusinessError) => { console.error('Failed to pack the image. And the error is: ' + error);
})
4 图片工具
图片工具当前主要提供图片EXIF信息的读取与编辑能力。
EXIF(Exchangeable image file format)
是专门为数码相机的照片设定的文件格式,可以记录数码照片的属性信息和拍摄数据。当前仅支持JPEG格式图片
。
在图库等应用中,需要查看或修改数码照片的EXIF
信息。由于摄像机的手动镜头的参数无法自动写入到EXIF
信息中或者因为相机断电等原因经常会导致拍摄时间出错,这时候就需要手动修改错误的EXIF
数据,即可使用本功能。
OpenHarmony
目前仅支持对部分EXIF
信息的查看和修改
- 获取图片,创建图片源
ImageSource
。
// 导入相关模块包
import image from '@ohos.multimedia.image';// 获取沙箱路径创建ImageSource
const fd : number = ...; // 获取需要被处理的图片的fd
const imageSource : image.ImageSource = image.createImageSource(fd);
- 读取、编辑
EXIF
信息。
import {BusinessError} from '@ohos.base';
// 读取EXIF信息,BitsPerSample为每个像素比特数
let options : image.ImagePropertyOptions = { index: 0, defaultValue: '9999' }
imageSourceApi.getImageProperty(image.PropertyKey.BITS_PER_SAMPLE, options).then((data : string) => {console.log('Succeeded in getting the value of the specified attribute key of the image.');
}).catch((error : BusinessError) => {console.error('Failed to get the value of the specified attribute key of the image.');
})// 编辑EXIF信息
imageSourceApi.modifyImageProperty(image.PropertyKey.IMAGE_WIDTH, "120").then(() => {imageSourceApi.getImageProperty(image.PropertyKey.IMAGE_WIDTH).then((width : string) => {console.info('The new imageWidth is ' + width);}).catch((error : BusinessError) => {console.error('Failed to get the Image Width.');})
}).catch((error : BusinessError) => {console.error('Failed to modify the Image Width');
})
参考文献:
[1]OpenHarmoney应用开发文档