实战:HarmonyOS 中 HEIF 图像开发全流程(转码篇 兼容场景)
紧接着上篇文章。我们继续HarmonyOS 中 HEIF 图像开发全流程。这篇主要记录如何进行图转码。
实战 :HEIF 图像自定义处理(进阶场景)
这里还是说一下环境吧。
环境要求
- HarmonyOS 版本:需基于 HarmonyOS 5.0 及以上(HEIF 解码性能优化、硬件编码支持均从 5.0 开始)。
- 开发工具:DevEco Studio 5.0 及以上(确保 ArkUI 组件与 Image Kit API 兼容)。
- 测试设备:搭载 HarmonyOS 5.x 的真机或模拟器(部分硬件解码能力需真机支持)。
- 图像资源:准备 1-2 张 HEIF 格式图片(后缀通常为
.heif
或.heic
,可通过手机拍摄或在线工具转换获取),并放入项目的main_pages/images
目录下(需在module.json5
中配置资源路径)。
部分旧应用或第三方接口可能仅支持 JPEG 格式,此时需将 HEIF 转码为 JPEG 并保存到本地。本实战将实现 “加载 HEIF 图片→转码为 JPEG→保存到应用沙箱目录” 的全流程。
1. 场景需求
加载 scenery.heic
图片,将其转码为质量 95 的 JPEG 格式,保存到应用的沙箱目录(/data/storage/el2/base/haps/应用包名/files/
),并输出保存路径。
2. 操作步骤
步骤 1:申请文件读写权限
转码后需保存文件到本地,需在 module.json5
中申请 ohos.permission.WRITE_USER_STORAGE
权限:
{"module": {"abilities": [{"permissions": [{"name": "ohos.permission.WRITE_USER_STORAGE","reason": "需要保存转码后的JPEG图片","usedScene": { "when": "always" }}]}]}
}
步骤 2:编写转码代码
通过 image.createImagePacker()
创建编码器,配置 JPEG 编码参数(质量、是否保留 EXIF 信息),最后将转码后的文件保存到沙箱目录:
import image from '@ohos.multimedia.image';
import fs from '@ohos.file.fs';
import { Column, Button, Text, FlexAlign, AlertDialog } from '@ohos/ui';
import permission from '@ohos.permission';@Entry
@Component
struct HEIFTranscodePage {private jpegSavePath: string = ''; // 存储 JPEG 保存路径// 申请文件读写权限async requestStoragePermission() {const result = await permission.requestPermissions(['ohos.permission.WRITE_USER_STORAGE']);return result[0].grantStatus === permission.GrantStatus.PERMISSION_GRANTED;}// 核心方法:HEIF 转码为 JPEG 并保存async transcodeHEIFToJPEG() {// 1. 先申请权限const hasPermission = await this.requestStoragePermission();if (!hasPermission) {AlertDialog.show({ message: '请授予文件读写权限,否则无法保存图片' });return;}try {// 2. 创建 HEIF 图像源const imageSource = image.createImageSource($r('app.image.scenery').uri);// 3. 创建图像编码器(用于转码)const imagePacker = image.createImagePacker();// 4. 配置 JPEG 编码选项const packOpts: image.PackingOption = {format: 'image/jpeg', // 目标格式为 JPEGquality: 95, // 质量(0-100,95 为高质量)needsPackProperties: true // 保留原图片的 EXIF 信息(如拍摄时间、分辨率)};// 5. 定义 JPEG 保存路径(应用沙箱的 files 目录)const appFilesDir = fs.getAppFilesDir(); // 获取应用沙箱目录this.jpegSavePath = `${appFilesDir}/transcoded_scenery.jpg`;// 6. 打开文件流,准备保存const file = await fs.open(this.jpegSavePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);// 7. 执行转码并保存到文件await imagePacker.packToFile(imageSource, file.fd, packOpts);// 8. 关闭文件流、释放资源await fs.close(file.fd);imagePacker.release();imageSource.release();// 9. 提示转码成功并输出路径AlertDialog.show({title: '转码成功',message: `JPEG 保存路径:${this.jpegSavePath}`,confirm: { text: '确定' }});} catch (err) {console.error('HEIF 转码失败:', err);AlertDialog.show({ message: '转码失败,请检查图片格式或权限' });}}build() {Column({ space: 30, alignItems: FlexAlign.Center }) {Text('HEIF 转码为 JPEG').fontSize(24).fontWeight(FontWeight.Bold);// 触发转码的按钮Button('开始 HEIF 转码为 JPEG').width(300).height(50).fontSize(16).onClick(() => {this.transcodeHEIFToJPEG();});// 显示保存路径if (this.jpegSavePath) {Text(`JPEG 已保存至:\n${this.jpegSavePath}`).fontSize(14).width('90%').textAlign(TextAlign.Center);}}.padding(20).width('100%').height('100%');}
}
步骤 3:验证转码结果
- 运行应用,点击 “开始 HEIF 转码为 JPEG” 按钮,授予权限后,会弹出 “转码成功” 提示。
- 通过 DevEco Studio 的 “Device File Explorer”(设备文件浏览器),导航到提示的
jpegSavePath
目录,下载transcoded_scenery.jpg
到本地,用图片查看器确认:- 格式为 JPEG(后缀
.jpg
)。 - 图像质量无明显损失(因质量设为 95)。
- EXIF 信息保留(可通过图片属性查看拍摄时间等)。
- 格式为 JPEG(后缀
3. 关键注意点
- 权限申请:HarmonyOS 6.0 及以上需动态申请
WRITE_USER_STORAGE
权限,静态配置后需通过permission.requestPermissions()
触发用户授权。 - 编码质量:
quality
设为 95 时,可在 “体积” 与 “质量” 间取得平衡;若需更小体积,可降至 80-90。 - 文件覆盖:若目标路径已存在同名文件,需先删除或重命名,避免转码失败(可通过
fs.access()
判断文件是否存在)。