HarmonyOS鸿蒙Next图片编辑解决方案

HarmonyOS鸿蒙Next图片编辑解决方案

图片编辑库

一、环境准备

需满足以下基础条件:

  • DevEco Studio 3.1+
  • HarmonyOS SDK API 9+
  • 目标设备:支持ArkUI开发框架的设备
  • 读写权限限制:
    • 在图片处理中,可能需要使用用户图片,应用需要向用户申请对应的读写操作权限才能保证功能的正常运行。
    • 申请受限权限 ohos.permission.READ_IMAGEVIDEOohos.permission.WRITE_IMAGEVIDEO 读取媒体库的图片与视频。

二、安装方法

  1. 通过ohpm安装基础组件

    # 终端执行以下命令安装核心模块
    ohpm install [@ohos](/user/ohos).multimedia.image
    ohpm install [@ohos](/user/ohos).effectKit
    
  2. 配置模块依赖

    在模块级oh-package.json5中添加:

    "dependencies": {
        "[@ohos](/user/ohos).multimedia.image": "^3.2.1",
        "[@ohos](/user/ohos).effectKit": "^3.1.0",
        "[@ohos](/user/ohos).mediaLibrary": "^1.0.0" // 媒体库访问支持
    }
    

优点:

  • 功能全面:支持基础旋转、裁剪、滤镜、元数据处理、格式转换等编辑功能。
  • 系统原生支持:集成度高,无需依赖第三方库。

缺点:

  • 设备兼容性:可能受限于HarmonyOS版本或设备型号,旧版本可能不支持某些功能。

三、使用ImageSource完成图片解码

概述

图片解码指将所支持格式的存档图片解码成统一的 PixelMap,以便在应用或系统中进行图片显示或处理。当前支持的存档图片格式包括JPEG、PNG、GIF、WebP、BMP、SVG、ICO、DNG、HEIF(不同硬件设备支持情况不同)。图片解码相关API的详细介绍请参见:图片解码接口说明。

开发思路

  • 全局导入Image、fileIo模块,获取沙箱路径;
  • 通过沙箱路径获取图片的文件描述符,该方法需要先导入@kit.CoreFileKit模块,然后调用fs.openSync()获取文件描述符;使用资源管理器获取资源文件的ArrayBuffer。
  • 通过资源管理器获取资源文件的RawFileDescriptor。具体请参考获取应用文件路径,应用沙箱的介绍及如何向应用沙箱推送文件,ResourceManager API参考文档。

代码实现

import { image } from '[@kit](/user/kit).ImageKit';
import { fileIo as fs } from '[@kit](/user/kit).CoreFileKit';

// 导入resourceManager资源管理器。
import { resourceManager } from '[@kit](/user/kit).LocalizationKit';
import { BusinessError } from '[@kit](/user/kit).BasicServicesKit';

const context : Context = getContext(this);
const filePath : string = context.cacheDir + '/test.jpg';
const file : fs.File = fs.openSync(filePath, fs.OpenMode.READ_WRITE);
const fd : number = file?.fd;

const resourceMgr : resourceManager.ResourceManager = context.resourceManager;
resourceMgr.getRawFileContent('test.jpg').then((fileData : Uint8Array) => {
    console.log("Succeeded in getting RawFileContent")
    // 获取图片的ArrayBuffer。
    const buffer = fileData.buffer.slice(0);
}).catch((err : BusinessError) => {
    console.error("Failed to get RawFileContent")
});

resourceMgr.getRawFd('test.jpg').then((rawFileDescriptor : resourceManager.RawFileDescriptor) => {
    console.log("Succeeded in getting RawFileDescriptor")
}).catch((err : BusinessError) => {
    console.error("Failed to get RawFileDescriptor")
});

通过沙箱路径创建ImageSource,文件描述符fd创建ImageSource实例;

通过缓冲区数组创建ImageSource,创建资源文件RawFileDescriptor的ImageSource;

设置解码参数DecodingOptions,解码获取pixelMap图片对象。设置期望的format进行解码:HDR图片解码;解码完成,获取到pixelMap对象后,可以进行后续图片处理。

const imageSource : image.ImageSource = image.createImageSource(filePath);
const imageSource : image.ImageSource = image.createImageSource(fd);
const imageSource : image.ImageSource = image.createImageSource(buffer);
const imageSource : image.ImageSource = image.createImageSource(rawFileDescriptor);

let img = await getContext(this).resourceManager.getMediaContent($r('app.media.image'));
let imageSource:image.ImageSource = image.createImageSource(img.buffer.slice(0));

let decodingOptions : image.DecodingOptions = {
    editable: true,
    desiredPixelFormat: 3,
}

imageSource.createPixelMap(decodingOptions).then((pixelMap : image.PixelMap) => {
    console.log("Succeeded in creating PixelMap")
}).catch((err : BusinessError) => {
    console.error("Failed to create PixelMap")
});

let img = await getContext(this).resourceManager.getMediaContent($r('app.media.CUVAHdr'));
let imageSource:image.ImageSource = image.createImageSource(img.buffer.slice(0));

let decodingOptions : image.DecodingOptions = {
    //设置为AUTO会根据图片资源格式解码,如果图片资源为HDR资源则会解码为HDR的pixelmap。
    desiredDynamicRange: image.DecodingDynamicRange.AUTO,
}

imageSource.createPixelMap(decodingOptions).then((pixelMap : image.PixelMap) => {
    console.log("Succeeded in creating PixelMap")
    // 判断pixelmap是否为hdr内容。
    let info = pixelMap.getImageInfoSync();
    console.log("pixelmap isHdr:" + info.isHdr);
}).catch((err : BusinessError) => {
    console.error("Failed to create PixelMap")
});

释放pixelMap和imageSource,需确认pixelMap和imageSource异步方法已经执行完成,不再使用该变量后可按需手动调用下面方法释放。

pixelMap.release();
imageSource.release();

注意:选择合适的C API接口:

  • 图片框架当前提供了两套C API接口,分别为依赖于JS对象的C API和不依赖于JS对象的C API。

依赖于JS对象的C接口,这类接口可以完成图片编解码,图片接收器,处理图像数据等功能,相关示例代码可以参考图片开发指导(依赖JS对象)(C/C++)节点下的内容。开发者可查看Image模块下的C API,确认API范围。这部分API在API 11之前发布,在后续的版本不再增加新功能。

不依赖于JS对象的C接口,这类接口除了提供上述图片框架基础功能,还可以完成多图编解码等新特性,相关开发指导请参考图片开发指导(C/C++)节点下的内容。开发者可查看Image_NativeModule模块下的C API,确认API范围。这部分API从API 12开始支持,并将持续演进,推荐开发者使用。

注意:两套C API不建议同时使用,在部分场景下存在不兼容的问题。

二、使用ImagePacker完成图片编码

概述

图片编码指将PixelMap编码成不同格式的存档图片,当前支持打包为JPEG、WebP、png和HEIF(不同硬件设备支持情况不同)格式,用于后续处理,如保存、传输等。图片编码相关API的详细介绍请参见:图片编码接口说明。

开发思路

  • 创建图像编码ImagePacker或PixelMap对象,设置编码输出流和编码参数,format为图像的编码格式;quality为图像质量,范围从0-100,100为最佳质量,编码为hdr内容(需要资源本身为hdr,支持jpeg格式)。进行图片编码,并保存编码后的图片。
  • 图片编码进文件流,图片编码进文件,在编码时,开发者可以传入对应的文件路径,编码后的内存数据将直接写入文件。

代码实现

import { image } from '[@kit](/user/kit).ImageKit';
import { BusinessError } from '[@kit](/user/kit).BasicServicesKit';
import { fileIo as fs } from '[@kit](/user/kit).CoreFileKit';

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);

let imagePackerApi = image.createImagePacker();
let packOpts : image.PackingOption = {
    format:"image/jpeg", 
    quality:98 
};
packOpts.desiredDynamicRange = image.PackingDynamicRange.AUTO;

imagePackerApi.packing(pixelMap, packOpts).then( (data : ArrayBuffer) => {
    // data 为打包获取到的文件流,写入文件保存即可得到一张图片。
}).catch((error : BusinessError) => { 
    console.error('Failed to pack the image. And the error is: ' + error); 
});

imagePackerApi.packing(imageSource, packOpts).then( (data : ArrayBuffer) => {
    // data 为打包获取到的文件流,写入文件保存即可得到一张图片。
}).catch((error : BusinessError) => { 
    console.error('Failed to pack the image. And the error is: ' + error); 
});

imagePackerApi.packToFile(pixelMap, file.fd, packOpts).then(() => {
    // 直接打包进文件。
}).catch((error : BusinessError) => { 
    console.error('Failed to pack the image. And the error is: ' + error); 
}).finally(()=>{
    fs.closeSync(file.fd);
});

imagePackerApi.packToFile(imageSource, file.fd, packOpts).then(() => {
    // 直接打包进文件。
}).catch((error : BusinessError) => { 
    console.error('Failed to pack the image. And the error is: ' + error); 
}).finally(()=>{
    fs.closeSync(file.fd);
});

图片编码保存进图库,可以将图片编码保存到应用沙箱,然后使用媒体文件管理相关接口保存媒体库资源。

注意:

  • 根据MIME标准,标准编码格式为image/jpeg。当使用image编码时,PackingOption.format设置为image/jpeg,image编码后的文件扩展名可设为.jpg或.jpeg,可在支持image/jpeg解码的平台上使用。

官方地址

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/image-overview


更多关于HarmonyOS鸿蒙Next图片编辑解决方案的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

鸿蒙Next图片编辑可使用ArkUI的Image组件结合PixelMap API实现基础操作。系统提供native image processing接口支持旋转、裁剪、滤镜等处理,通过@ohos.multimedia.image库调用。关键类包括ImageSource(解码)、ImagePacker(编码)、EffectKit(特效)。开发者可调用createPixelMap()获取位图数据,使用Matrix4对象实现2D变换。对于AI修图功能,需调用@ohos.ai.imageProcessing模块的智能抠图、超分等算法。性能优化建议使用native buffer和硬件加速渲染。

更多关于HarmonyOS鸿蒙Next图片编辑解决方案的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


HarmonyOS Next的图片编辑解决方案主要基于Image Kit能力,提供了完整的图片处理功能链。以下是关键点总结:

  1. 核心能力:
  • 支持解码JPEG/PNG/GIF/WebP/BMP/SVG等格式
  • 提供PixelMap对象进行像素级操作
  • 支持编码为JPEG/WebP/PNG/HEIF格式
  1. 开发准备:
  • 需要配置DevEco Studio 3.1+和API 9+环境
  • 申请ohos.permission.READ/WRITE_IMAGEVIDEO权限
  • 安装@ohos.multimedia.image等核心模块
  1. 典型流程: a) 解码:
  • 通过createImageSource()创建图像源
  • 使用createPixelMap()获取可编辑的PixelMap
  • 设置decodingOptions控制解码参数

b) 编码:

  • 通过createImagePacker()创建编码器
  • 设置packingOptions指定格式和质量
  • 支持输出到内存或直接写入文件
  1. 注意事项:
  • 及时释放PixelMap和ImageSource资源
  • HDR图片需要特殊处理
  • 两套C API接口不要混用

该方案优点是系统原生集成,功能全面,适合需要深度图片处理的场景。开发者可根据具体需求选择不同的编解码参数和输出方式。

回到顶部