HarmonyOS 相机 + 文字识别实现拍照识字 27 ImageKit 图像处理能力概述
·
27 ImageKit 图像处理能力概述
引言
HarmonyOS 5.0.5 SDK 将系统能力按 Kit 化拆包,图像处理相关能力集中在 ImageKit(对应 @kit.ImageKit,底层是 image 命名空间)。无论是相册选图、相机拍照,还是本工程"拍照识别文字"中的 JPEG 解码链路,都离不开 ImageKit。本文以工程实际用法为线索(源码参考:entry/src/main/ets/common/utils/Camera.ets),梳理 ImageKit 的能力全景、典型使用流程,以及它与相机、OCR 的结合点,帮助开发者建立"解码 → 像素图 → 处理 → 编码"的整体认知。

正文知识点
1. image 命名空间的核心对象
ImageKit 的核心类都挂在 image 命名空间下,按职责可分为四组:
| 对象 | 职责 | 典型用途 |
image.ImageSource |
图像解码源,把磁盘/内存中的图像解码成像素数据 | image.createImageSource(buffer) 后 createPixelMap() |
image.PixelMap |
像素图,可直接用于显示、裁剪、缩放、OCR 等 | 传给 textRecognition.recognizeText 的 pixelMap 字段 |
image.ImageReceiver |
图像接收器,内部持有 Surface,可接收相机/编码器输出 | createImageReceiver(宽,高,格式,容量),getReceivingSurfaceId() |
image.ImagePacker |
图像编码打包,把 PixelMap 编码为 JPEG/PNG 字节流 | createImagePacker().packing(pixelMap, { format: 'image/jpeg' }) |
image.Component |
相机 Photo 的组件(如主图的 JPEG 数据) | photo.main.getComponent(image.ComponentType.JPEG, cb) |
image.DecodingOptions / image.ImageInfo |
解码参数 / 图像信息描述 | 指定目标尺寸、像素格式;查询宽高、格式 |
2. 典型使用流程:解码 → 像素图 → 处理 → 编码
ImageKit 的标准流水线是单向的:
- 解码:
createImageSource(入参可以是路径、fd、ArrayBuffer)→createPixelMap得到可操作像素图; - 处理:对 PixelMap 做缩放、裁剪、旋转、水印、滤镜(PixelMap 提供
scale、crop、rotate等接口),或用DecodingOptions.desiredSize在解码阶段直接降采样; - 编码:
createImagePacker().packing(pixelMap, packOpts)输出字节流,可落盘或上传。
3. 与相机 / OCR 的结合点
本工程恰好串起了这三者:
- 相机侧:
photoOutput.on('photoAvailable')回调解出photo.main,再getComponent(JPEG)拿到 JPEG 原始字节; - ImageKit 侧:
image.createImageSource(buffer)+createPixelMap()把字节解码成 PixelMap; - OCR 侧:
textRecognition.recognizeText({ pixelMap })消费像素图,返回识别文本。
entry/src/main/ets/common/utils/Camera.ets):
import { image } from '@kit.ImageKit';
// 字段:图像接收器(作为拍照输出的目标 Surface 之一)
private receiver: image.ImageReceiver | undefined = undefined;
// 获取接收器 SurfaceId,可交给 camera.createPhotoOutput 作为输出目标
async getImageReceiverSurfaceId(receiver: image.ImageReceiver): Promise<string | undefined> {
let photoSurfaceId: string | undefined = undefined;
if (receiver !== undefined) {
photoSurfaceId = await receiver.getReceivingSurfaceId();
Logger.info(TAG, `getReceivingSurfaceId success`);
}
return photoSurfaceId;
}
代码示例
一个"解码 → 降采样 → 编码 → 落盘"的完整示例,可用于相册图片压缩场景:
import { image } from '@kit.ImageKit';
import { BusinessError } from '@kit.BasicServicesKit';
async function compressImage(srcPath: string, dstPath: string): Promise<void> {
const imageSource: image.ImageSource = image.createImageSource(srcPath);
const packer: image.ImagePacker = image.createImagePacker();
try {
// 解码阶段直接降到目标分辨率,省内存
const decodingOptions: image.DecodingOptions = {
desiredSize: { width: 1080, height: 1920 },
desiredPixelFormat: image.PixelMapFormat.RGBA_8888
};
const pixelMap: image.PixelMap = await imageSource.createPixelMap(decodingOptions);
// 获取图像信息(宽高、像素格式等)
const info: image.ImageInfo = pixelMap.getImageInfoSync();
console.info(`size=${info.size.width}x${info.size.height}, format=${info.pixelFormat}`);
// 编码为 JPEG
const packOpts: image.PackingOption = { format: 'image/jpeg', quality: 85 };
const data: ArrayBuffer = await packer.packing(pixelMap, packOpts);
// 落盘:fileIo 写入(此处略去 open/close)
// await fileIo.write(fd, data);
pixelMap.release();
} catch (error) {
const err = error as BusinessError;
console.error(`compressImage failed. code=${err.code}, message=${err.message}`);
} finally {
await packer.release();
await imageSource.release();
}
}
运行效果与注意事项
createImageSource是同步创建解码源,createPixelMap是异步接口,必须await;解码失败会抛异常(如62980096参数错误),务必 try-catch。- 解码参数里的
desiredSize是"不超过"目标尺寸的降采样提示,不保证精确等于该值;精确尺寸用 PixelMap 的scale或crop再处理。 ImageSource、PixelMap、ImagePacker都占用底层资源,用完要release()(工程recognizeImage里识别完成后即pixelMapInstance.release()与imageResource.release())。- 本项目"拍照识别"链路可以抽象为:相机给字节(CameraKit)→ ImageKit 解码成像素图 → CoreVisionKit 识别,三者通过
pixelMap这个中间产物衔接,理解这条链路对排查"识别失败/内存上涨"非常有帮助。
总结
ImageKit 是 HarmonyOS 图像处理的"总入口":ImageSource 管解码、PixelMap 管像素操作、ImageReceiver 管 Surface 接收、ImagePacker 管编码。典型流程"解码 → 像素图 → 处理 → 编码"可以覆盖相册压缩、拍照、水印、OCR 预处理等绝大多数需求。本工程通过 image.createImageSource(buffer) 把相机 JPEG 转成 PixelMap 再交给 OCR,正是 ImageKit 与相机、AI 能力协作的标准范式,值得作为后续图像类应用的通用底座。
更多推荐



所有评论(0)