HarmonyOS鸿蒙Next中“仿抖音快手”App开发技术分享(十二)把位图数据转存为图片文件

HarmonyOS鸿蒙Next中“仿抖音快手”App开发技术分享(十二)把位图数据转存为图片文件

上一节我们利用Scroller实现了列表项的自动滚动功能,对于图像列表来说,被选做封面的图像需要保存为图片文件,以便向服务器上传封面图片。

由于avImageGenerator从视频提取的图像帧数据为image.PixelMap(位图格式),因此前面的图像转存操作就变成了把位图数据写入图片文件。那么根据沙箱文件的操作规范,可将完整的图片转存过程划分为下列三个步骤:

一、在沙箱目录下创建新文件并打开该文件

鸿蒙把文件操作能力封装到了Core File Kit(文件基础服务),并通过fileIo工具来调用文件操作函数。为此要在代码开头添加下面的导包语句,表示引入文件操作工具fileIo:

import { fileIo } from '@kit.CoreFileKit';

鸿蒙把创建文件和打开文件合并到了一起,调用open函数或者openSync函数,即可实现创建并打开文件的功能。注意,在调用open或者openSync的时候,模式参数要填“fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE”,表示指定路径若不存在文件就创建新文件,若已存在文件就打开原文件。示例代码如下:

let dstFile = fileIo.openSync(this.imagePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);

二、把位图数据打包写入第一步骤的新文件

鸿蒙把图片处理能力封装到了Image Kit(图片处理服务),并通过image工具来调用图片处理函数。image工具又包含下列常见的子工具:

  • ImageSource类,提供获取图片信息、将图片解码为PixelMap或Picture、读取和修改图片属性的能力。支持解码的图片格式包括png、jpeg、bmp、gif、webp、dng、heic。
  • ImagePacker类,提供将图片编码为压缩后的数据流或文件的能力。编码前需获取图片的ImageSource、PixelMap或Picture作为输入。支持编码的图片格式包括jpeg、webp、png、heic、gif。
  • PixelMap类,位图对象,包含像素数据以及图片信息。可用于读取或写入像素数据,进行裁剪、缩放、平移、旋转、镜像等操作,并可直接传给Image组件用于显示。

可见位图数据属于PixelMap类,而位图数据的转存功能则由ImagePacker类实现,调用image工具的createImagePacker方法,即可获得ImagePacker类的对象实例。接着调用ImagePacker实例的packToFile,即可将位图数据写入指定句柄的文件中。示例代码如下:

imagePackerApi.packToFile(this.pixelMap, dstFile.fd, packOpts, (err: BusinessError) => {
  /* 这里可补充位图转存完成之后的其他操作 */
  if (err) { /* 打印失败日志 */ } else { /* 打印成功日志 */ }
})

三、写入完毕,关闭第一步打开的图片文件

调用fileIo工具的close函数或者closeSync函数,即可实现关闭文件的功能。示例代码如下:

fileIo.closeSync(dstFile);

综合上述三个步骤,可编写位图数据转存为图片文件的代码框架如下所示:

// 保存封面图片
saveCover() {
  let videoFileName = this.videoPath.toString().split('/').pop() as string
  let imageFileName = (videoFileName.split('.'))[0] + '_' + this.coverPos + '.jpeg'
  this.imagePath = `${this.context.cacheDir}/${imageFileName}`

  let dstFile = fileIo.openSync(this.imagePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);

  // 转存为图片
  let imagePackerApi: image.ImagePacker = image.createImagePacker();
  let packOpts: image.PackingOption = { format: 'image/jpeg', quality: 90 };

  imagePackerApi.packToFile(this.pixelMap, dstFile.fd, packOpts, (err: BusinessError) => {
    fileIo.closeSync(dstFile);
    if (err) { /* 打印失败日志 */ } else { /* 打印成功日志 */ }
  })
}

下一篇文章会介绍如何把相册中的视频复制到沙箱目录。


更多关于HarmonyOS鸿蒙Next中“仿抖音快手”App开发技术分享(十二)把位图数据转存为图片文件的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

在HarmonyOS Next中,将位图数据转存为图片文件可使用ImagePacker API。首先获取位图的PixelMap对象,然后创建ImagePacker实例并设置输出格式(如JPEG/PNG)。调用packing()方法将PixelMap写入指定路径的OutputStream。示例代码片段:

import image from '@ohos.multimedia.image';
import fileio from '@ohos.fileio';

let packer = image.createImagePacker();
let pixelMap: image.PixelMap; // 获取到的位图数据
let filePath = 'xxx.jpg'; 
let outputStream = fileio.createStream(filePath, 'w+');
packer.packing(pixelMap, outputStream); 

需提前申请ohos.permission.WRITE_MEDIA存储权限。输出文件格式由ImagePacker的初始化参数决定。

更多关于HarmonyOS鸿蒙Next中“仿抖音快手”App开发技术分享(十二)把位图数据转存为图片文件的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中实现位图转存为图片文件的过程确实如您所述,主要分为三个关键步骤:

  1. 文件创建与打开: 使用fileIo.openSync()方法时,建议添加错误处理逻辑,特别是在生产环境中。模式参数READ_WRITE | CREATE的组合使用是正确的,这确保了文件不存在时创建,存在时打开。

  2. 位图编码与写入: ImagePacker的使用需要注意:

  • 编码格式支持通过PackingOption指定,JPEG是推荐的通用格式
  • 质量参数(quality)建议根据实际需求调整,90是个不错的平衡点
  • 异步回调中建议添加资源释放逻辑
  1. 文件关闭: 务必在操作完成后调用closeSync,特别是在频繁文件操作的场景中,避免文件描述符泄漏。

您的代码示例很好地展示了完整流程。在实际开发中,可以进一步优化:

  • 添加更完善的错误处理
  • 考虑大文件情况下的内存管理
  • 对于频繁操作,可以考虑使用文件池管理

这些技术点对于短视频类App的封面处理非常重要,特别是需要处理大量视频帧的场景。

回到顶部