OpenHarmony图片转Base64编码开发流程

前言

随着生态扩展,许多开发者都有对图片进行各种数据处理、转换、编码的需求。下文会为大家介绍如何去进行Base64编码以及在调研过程中遇到的一些重要问题。

开发环境

系统版本: 4.0-Release

DevEco Studio版本: 4.0 Release (build:4.0.0.600)

SDK版本: 4.0.10.13(及以上)

流程

通过图片选择器选择图片,拿到图片pixelMap

import picker from '@ohos.file.picker';
import image from '@ohos.multimedia.image';
import dataSharePredicates from '@ohos.data.dataSharePredicates';
import photoAccessHelper from '@ohos.file.photoAccessHelper';

let PhotoSelectOptions = new picker.PhotoSelectOptions();
PhotoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE;
PhotoSelectOptions.maxSelectNumber = 1;
let photoPicker = new picker.PhotoViewPicker();
photoPicker.select(PhotoSelectOptions).then(async (PhotoSelectResult: picker.PhotoSelectResult) => {
WinsleiLogManager.hilogIWithTag(TAG, `selectPhoto select, PhotoSelectResult: ${JSON.stringify(PhotoSelectResult)}`)
    let uris = PhotoSelectResult.photoUris;
    try {
        for (let index = 0; index < uris.length; index++) {
            let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(getContext(this));
            let predicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates();
            // 配置查询条件,使用PhotoViewPicker选择图片返回的uri进行查询
            predicates.equalTo('uri', uris[index]);
            let fetchOption: photoAccessHelper.FetchOptions = {
                fetchColumns: [],
                predicates: predicates
            };
            WinsleiLogManager.hilogIWithTag(TAG, `selectPhoto select, getAssets start`)
            let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset> = await phAccessHelper.getAssets(fetchOption);
            // 得到uri对应的PhotoAsset对象,读取文件的部分信息
            WinsleiLogManager.hilogIWithTag(TAG, `selectPhoto select, getFirstObject start`)
            let asset: photoAccessHelper.PhotoAsset = await fetchResult.getFirstObject();
            WinsleiLogManager.hilogIWithTag(TAG, 'selectPhoto asset displayName: ' + asset.displayName);
            WinsleiLogManager.hilogIWithTag(TAG, 'selectPhoto asset uri: ' + asset.uri);
            WinsleiLogManager.hilogIWithTag(TAG, 'selectPhoto asset photoType: ' + asset.photoType);

            // 获取缩略图
            let pixelMap = await asset.getThumbnail();
            WinsleiLogManager.hilogIWithTag(TAG, 'selectPhoto getThumbnail, pixelMap: ' + JSON.stringify(pixelMap));
    }).catch((err: base.BusinessError) => {
        WinsleiLogManager.hilogIWithTag(TAG, `selectPhoto select, err: ${JSON.stringify(err)}`)
    });

将pixelMap打包(重要步骤!!!)

const imagePackageApi: image.ImagePacker = image.createImagePacker()
let packOpts: image.PackingOption = {
    format: 'image/jpeg',
    quality: 100,
}
const readBuffer = await imagePackageApi.packing(pixelMap, packOpts)

将打包后的ArrayBuffer进行Base64编码

在OpenHarmony中,Base64编码有3种方式:

系统Api

https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkts/js-apis-util.md#base64helper9

三方库

https://ohpm.openharmony.cn/#/cn/detail/@ohos%2Fbase64

手动转换

arrayBufferToBase64(array: Uint8Array): string {
    let length = array.byteLength;
    let table = ['A','B','C','D','E','F','G','H',
      'I','J','K','L','M','N','O','P',
      'Q','R','S','T','U','V','W','X',
      'Y','Z','a','b','c','d','e','f',
      'g','h','i','j','k','l','m','n',
      'o','p','q','r','s','t','u','v',
      'w','x','y','z','0','1','2','3',
      '4','5','6','7','8','9','+','/'];
    let base64Str = '';
    for(let i = 0; length - i >= 3; i += 3) {
      let num1 = array[i];
      let num2 = array[i + 1];
      let num3 = array[i + 2];
      base64Str += table[num1 >>> 2]
        + table[((num1 & 0b11) << 4) | (num2 >>> 4)]
        + table[((num2 & 0b1111) << 2) | (num3 >>> 6)]
        + table[num3 & 0b111111];

      let lastByte = length - i;
      if(lastByte === 1) {
        let lastNum1 = array[i];
        base64Str += table[lastNum1 >>> 2] + table[((lastNum1 & 0b11) << 4)] + '==';
      } else if(lastByte === 2){
        let lastNum1 = array[i];
        let lastNum2 = array[i + 1];
        base64Str += table[lastNum1 >>> 2]
          + table[((lastNum1 & 0b11) << 4) | (lastNum2 >>> 4)]
          + table[(lastNum2 & 0b1111) << 2]
          + '=';
      }
    }

    return base64Str;
  }

这里以系统Api为例

import util from '@ohos.util';

// base64
let base64Helper = new util.Base64Helper()
let uint8Arr = new Uint8Array(readBuffer)
WinsleiLogManager.hilogIWithTag(TAG, 'selectPhoto Uint8Array, uint8Arr: ' + JSON.stringify(uint8Arr));
let pixelStr = base64Helper.encodeToStringSync(uint8Arr)
// let pixelStr = this.arrayBufferToBase64(uint8Arr)
this.base64Str = 'data:image/jpg;base64,' + pixelStr
WinsleiLogManager.hilogIWithTag(TAG, 'selectPhoto base64, base64Str: ' + this.base64Str);

即可正常加载Base64编码后的图片了。

注意事项

在上述流程中,可以看到其中一步操作将pixelMap打包。为什么说这一步是重要步骤,因为很多开发者(包括作者)在研究Base64编码过程中,会直接将PixelMap直接转换为Uint8Array再转换为base64。反面示例:

// 获取pixelMap总字节数
let pixelBytesNumber: number = pixelMap.getPixelBytesNumber();
WinsleiLogManager.hilogIWithTag(TAG, 'selectPhoto getPixelBytesNumber, pixelBytesNumber: ' + JSON.stringify(pixelBytesNumber));
// 将读取的整张图像像素数据结果写入ArrayBuffer中
const readBuffer = new ArrayBuffer(pixelBytesNumber);
await pixelMap.readPixelsToBuffer(readBuffer)
WinsleiLogManager.hilogIWithTag(TAG, 'selectPhoto ArrayBuffer, readBuffer: ' + JSON.stringify(readBuffer));

这么处理无法得到正确的Uint8Array

参考文献

Image Kit: https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-image-kit/image.md

FilePicker: https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-core-file-kit/js-apis-file-picker.md

Base64Helper: https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkts/js-apis-util.md#base64helper9

DataSharePredicates: https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkdata/js-apis-data-dataSharePredicates.md

PhotoAccessHelper: https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-media-library-kit/js-apis-photoAccessHelper.md#photoviewpicker

示例Demo

https://gitee.com/winslei/open-harmony_-winsleikit/commit/7b0a1e49ad2c6193ad9605683160cc097c9a3b1b

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值