【鸿蒙开发】第十九章 Image图片处理

24 篇文章 4 订阅
24 篇文章 2 订阅

1 简介

应用开发中的图片开发是对图片像素数据进行解析处理构造的过程,达到目标图片效果,主要涉及图片解码图片处理图片编码等。

  • 图片解码
    指将所支持格式的存档图片解码成统一的PixelMap,以便在应用或系统中进行图片显示或图片处理。当前支持的存档图片格式包括JPEGPNGGIFRAWWebPBMPSVGICO

  • PixelMap
    指图片解码后无压缩的位图,用于图片显示或图片处理。

  • 图片处理
    指对PixelMap进行相关的操作,如旋转、缩放、设置透明度、获取图片信息、读写像素数据等。

  • 图片编码
    指将PixelMap编码成不同格式的存档图片(当前仅支持JPEGWebPPNG),用于后续处理,如保存、传输等。

在这里插入图片描述

  1. 获取图片:通过应用沙箱等方式获取原始图片。
  2. 创建ImageSource实例:ImageSource是图片解码出来的图片源类,用于获取或修改图片相关信息。
  3. 图片解码:通过ImageSource解码生成PixelMap
  4. 图片处理:对PixelMap进行处理,更改图片属性实现图片的旋转、缩放、裁剪等效果。然后通过Image组件显示图片。
  5. 图片编码:使用图片打包器类ImagePacker,将PixelMapImageSource进行压缩编码,生成一张新的图片。

除上述基本图片开发能力外,OpenHarmony还提供常用图片工具,供开发者选择使用。编解码支持多种图片格式,并采用了高效的算法和优化策略,提高了图片处理的速度和效率。在图片处理中,可能需要使用用户图片,应用需要向用户申请对应的读写操作权限才能保证功能的正常运行。图片框架提供图片编解码能力,为Image组件及图库等应用提供支撑,其解码结果可以传给Image组件显示。

下面我们来学习ArkTS相关的图片解码、编码。

2 图片解码(ArkTS)

图片解码指将所支持格式的存档图片解码成统一的PixelMap,以便在应用或系统中进行图片显示或图片处理。当前支持的存档图片格式包括JPEGPNGGIFRAWWebPBMPSVGICO

2.1 开发步骤

  1. 全局导入Image模块
import image from '@ohos.multimedia.image';
  1. 获取图片
  • 方法一:获取沙箱路径。具体请参考获取应用文件路径。应用沙箱的介绍及如何向应用沙箱推送文件,请参考文件管理。
// 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")
   // 获取图片的ArrayBuffer
   const 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")
});
  1. 创建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创建ImageSourceRawFileDescriptor可以通过步骤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")
    // 获取图片的ArrayBuffer
    const 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编码成不同格式的存档图片(当前仅支持打包为JPEGWebPpng 格式),用于后续处理,如保存、传输等。

3.1 图片编码进文件流

  1. 创建图像编码ImagePacker对象。
// 导入相关模块包
import image from '@ohos.multimedia.image';

const imagePackerApi = image.createImagePacker();
  1. 设置编码输出流和编码参数。format为图像的编码格式;quality为图像质量,范围从0-100,100为最佳质量。
let packOpts : image.PackingOption = { format:"image/jpeg", quality:98 };
  1. 创建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信息的查看和修改

  1. 获取图片,创建图片源ImageSource
// 导入相关模块包
import image from '@ohos.multimedia.image';

// 获取沙箱路径创建ImageSource
const fd : number = ...; // 获取需要被处理的图片的fd
const imageSource : image.ImageSource = image.createImageSource(fd);
  1. 读取、编辑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应用开发文档

  • 23
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__Yvan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值