本文同步发表于微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

   在上一篇文章中介绍了Image Kit的整体能力。今天来聊聊其中的核心功能——使用ImageSource完成图片解码

图片解码是将图片文件转换成PixelMap位图对象的过程,是图片显示和处理的基础。

一、图片解码

将所支持格式的图片文件解码成PixelMap(位图对象),以便在应用或系统中显示或处理图片。

支持的图片格式

格式 说明
JPEG 常见图片格式
PNG 支持透明通道
GIF 支持动图
WebP Google推出的现代图片格式
BMP 位图格式
SVG 矢量图格式
ICO 图标格式
DNG 数码相机原始图像格式
HEIC 高效率图像文件格式

注意:不同硬件设备的支持情况可能不同。

RAW格式预览图解码(API 22+)

从API version 22开始,支持对专业相机拍摄的RAW格式图片内嵌的预览图(通常为JPEG格式)进行解码:

RAW格式 文件扩展名
CR2/CR3 Canon
ARW Sony
NEF/NRW Nikon
RAF Fujifilm
ORF Olympus
RW2 Panasonic
PEF Pentax
SRW Samsung

说明:该解码能力不受运行设备类型限制。

二、导入模块

import { image } from '@kit.ImageKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
import { fileIo as fs } from '@kit.CoreFileKit';
import { resourceManager } from '@kit.LocalizationKit';

三、获取图片(四种方式)

3.1 方式一:通过沙箱路径直接获取

适用于应用沙箱中的图片。

function getFilePath(context: Context, fileName: string): string {
    const filePath: string = context.cacheDir + '/' + fileName;
    return filePath;
}

3.2 方式二:通过文件描述符fd获取

通过沙箱路径获取图片的文件描述符。

function getFileFd(context: Context, fileName: string): number | undefined {
    const filePath: string = context.cacheDir + '/' + fileName;
    const file: fs.File = fs.openSync(filePath, fs.OpenMode.READ_ONLY);
    const fd: number = file?.fd;
    return fd;
}

3.3 方式三:通过资源管理器获取ArrayBuffer

通过资源管理器获取资源文件的ArrayBuffer。

async function getFileBuffer(context: Context, fileName: string): Promise<ArrayBuffer | undefined> {
    try {
        const resourceMgr: resourceManager.ResourceManager = context.resourceManager;
        // 获取资源文件内容,返回Uint8Array
        const fileData: Uint8Array = await resourceMgr.getRawFileContent(fileName);
        console.info('Successfully get the RawFileContent.');
        // 转为ArrayBuffer并返回
        const buffer: ArrayBuffer = fileData.buffer.slice(0);
        return buffer;
    } catch (error) {
        console.error(`Failed to get the RawFileContent with error: ${error}.`);
        return undefined;
    }
}

3.4 方式四:通过资源管理器获取RawFileDescriptor

通过资源管理器获取资源文件的RawFileDescriptor。

async function getRawFd(context: Context, fileName: string): Promise<resourceManager.RawFileDescriptor | undefined> {
    try {
        const resourceMgr: resourceManager.ResourceManager = context.resourceManager;
        const rawFileDescriptor: resourceManager.RawFileDescriptor = await resourceMgr.getRawFd(fileName);
        console.info('Successfully get the RawFileDescriptor.');
        return rawFileDescriptor;
    } catch (error) {
        console.error(`Failed to get the RawFileDescriptor with error: ${error}.`);
        return undefined;
    }
}

四、创建ImageSource实例

创建方式 数据来源 方法
方式一 沙箱路径 image.createImageSource(filePath)
方式二 文件描述符fd image.createImageSource(fd)
方式三 缓冲区ArrayBuffer image.createImageSource(buffer)
方式四 RawFileDescriptor image.createImageSource(rawFileDescriptor)

4.1 通过沙箱路径创建

// path为已获得的沙箱路径
const imageSource: image.ImageSource = image.createImageSource(filePath);

4.2 通过文件描述符fd创建

// fd为已获得的文件描述符
const imageSource: image.ImageSource = image.createImageSource(fd);

4.3 通过缓冲区数组创建

// buffer为已获得的ArrayBuffer
const imageSource: image.ImageSource = image.createImageSource(buffer);

4.4 通过RawFileDescriptor创建

// rawFileDescriptor为已获得的RawFileDescriptor
const imageSource: image.ImageSource = image.createImageSource(rawFileDescriptor);

五、解码获取PixelMap

5.1 DecodingOptions参数

参数 类型 说明
editable boolean 是否可编辑
desiredPixelFormat PixelMapFormat 目标像素格式(如RGBA_8888)
desiredDynamicRange DecodingDynamicRange 动态范围(AUTO/HDR等)

5.2 解码代码示例

async function createPixelMap(imageSource: image.ImageSource | undefined): Promise<image.PixelMap | undefined> {
    if (!imageSource) {
        console.error('imageSource is undefined.');
        return undefined;
    }

    // 配置解码选项参数
    let decodingOptions: image.DecodingOptions = {
        editable: true,                                    // 可编辑
        desiredPixelFormat: image.PixelMapFormat.RGBA_8888, // RGBA格式
        // AUTO:根据图片资源格式和设备支持情况进行解码
        // 如果图片资源为HDR资源且设备支持HDR解码,则会解码为HDR的pixelMap
        desiredDynamicRange: image.DecodingDynamicRange.HDR,
    };

    try {
        // 生成 pixelMap 并返回
        const pixelMap = await imageSource.createPixelMap(decodingOptions);
        
        if (pixelMap) {
            console.info('Create PixelMap successfully.');
            
            // 判断pixelMap是否为hdr内容
            let imageInfo = await pixelMap.getImageInfo();
            console.info(`Create PixelMap successfully with imageInfo.isHdr: ${imageInfo.isHdr}.`);
            
            return pixelMap;
        } else {
            console.info('Create PixelMap failed.');
            return undefined;
        }
    } catch (error) {
        console.error(`Failed to create PixelMap: ${error}.`);
        return undefined;
    }
}

六、释放资源

6.1 释放时机

资源 释放时机
ImageSource createPixelMap执行完成,成功获取pixelMap后,如果确定不再使用imageSource的其他方法,可以手动释放
PixelMap 页面切换、应用退后台、内存紧张时释放除当前页面外其他不可见页面的PixelMap

6.2 释放代码

async function release(pixelMap: image.PixelMap | undefined, imageSource: image.ImageSource | undefined) {
    pixelMap?.release();
    pixelMap = undefined;
    
    imageSource?.release();
    imageSource = undefined;
}

6.3 说明

  • imageSource与pixelMap独立:解码得到的pixelMap是一个独立的实例,imageSource的释放不会导致pixelMap不可用

  • Image组件自动管理:如果使用系统的Image组件进行图片显示,无需手动释放,Image组件会自动管理传递给它的pixelMap

  • 手动释放场景:应用自行处理pixelMap时,推荐在页面切换、应用退后台等场景下手动释放

流程

获取图片数据
    ↓
创建ImageSource实例
    ↓
配置DecodingOptions解码参数
    ↓
调用createPixelMap解码
    ↓
获取PixelMap进行显示/处理
    ↓
释放资源(imageSource、pixelMap)

   鸿蒙图片解码通过ImageSource将图片文件转换为PixelMap位图对象,支持四种数据来源(沙箱路径、文件描述符、ArrayBuffer、RawFileDescriptor),可通过DecodingOptions配置可编辑性、像素格式和动态范围,解码后的PixelMap可用于Image组件显示或后续处理。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐