HarmonyOS 相册多选场景pixelMap转ArrayBuffer只有异步方法导致只有一张图片生效

在cordova插件中实现相册多选功能,目前发现图片对应的pixelMap转ArrayBuffer时,如果使用pixelMap.readPixelsToBufferSync()方法,最后生成的base64不对;如果使用imagePackageApi.packing,最后生成的base64是对的,但是这个方法目前只有一个异步方法,我只能在异步回调处理方法中返回结果,导致用户选多张图片的情况下,最终实际只返回了第一张。具体代码如下:

private getPicture(params: object, callbackContext: CallbackContext) {
  let imgBase64Arr: string[] = []
  const factory: ImageSelectorFactory = new DefaultImageSelectorFactory();
  const selector: ImageSelector = factory.create({ maxSelectNumber: params[0] });
  selector.openSelectPhoto().then((uris: string[]) => {
    //调用成功
    forEach(uris, async (item: string, index: number) => {
      const file : fileIo.File = fileIo.openSync(item, fileIo.OpenMode.READ_WRITE);
      const fd : number = file?.fd;
      const ims: image.ImageSource = image.createImageSource(fd);
      let pixelMap = ims.createPixelMapSync()
      let imgInfo: image.ImageInfo = pixelMap.getImageInfoSync()
      let width = imgInfo.size.width
      let height = imgInfo.size.height
      const imagePackageApi: image.ImagePacker = image.createImagePacker()
      let packOpts: image.PackingOption = {
        format: 'image/jpeg',
        quality: 100,
      }
      const readBuffer = await imagePackageApi.packing(pixelMap, packOpts)
      let base64Helper = new util.Base64Helper()
      let uint8Arr = new Uint8Array(readBuffer)
      let base64Str = base64Helper.encodeToStringSync(uint8Arr)
      //console.info(`base64Str: ${base64Str}}`)
      imgBase64Arr.push(base64Str)
      //目前测试发现只能在这里返回,但是这里只返回了一张图片的base64
      callbackContext.successByJson(imgBase64Arr)
    })
    //实际相册多选时希望能在这里统一返回所有图片的base64
  }).catch((err: BusinessError) => {
    //调用失败,拒绝权限信息'Permission denied'
    console.error(`调用相册,异常. message is ${JSON.stringify(err)}`)
  })
}
HarmonyOS
2天前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
FengTianYa

这边提供有批量选择相册图片,并且将图片压缩,转成base64格式的demo:

页面:

import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { buffer } from '@kit.ArkTS';
import { PictureUtils } from '../utils/PictureUtils';

@Entry
@Component
struct Index {
  @State pictures: Array<string> = [];

  @Styles
  butStyle(){
    .width(200)
    .height(50)
    .margin({ top: 30 })
  }

  async selectAndCompressPicture() {
    this.pictures = [];
    let selectResult: photoAccessHelper.PhotoSelectResult = await PictureUtils.selectPicture(2);
    let pictureUriArr: Array<string> = selectResult.photoUris;
    pictureUriArr.forEach(uri => {
      PictureUtils.compressPicture(uri, "image/jpeg", 20).then((data: ArrayBuffer) => {
        // 将图片转成base64
        let base64Str = buffer.from(data).toString('base64')
        let resultBase64Str = "data:image/png;base64," + base64Str
        this.pictures.push(resultBase64Str)

      })
    });
  }

  build() {
    Column() {
      ForEach(this.pictures, (uri: string) => {
        Image(uri)
          .width(200)
          .height(200)
          .padding({ top: 30 })
      }, (item: string) => item)

      Button("选择图片并压缩", { type: ButtonType.Capsule, stateEffect: false })
        .fontSize('15fp')
        .fontColor('#ffffff')
        .butStyle()
        .onClick(() => {
          this.selectAndCompressPicture()
        })
    }
    .width('100%')
    .height('100%')
    .alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
  }
}

util:

import { photoAccessHelper } from '@kit.MediaLibraryKit';
import fs from '@ohos.file.fs';
import { image } from '@kit.ImageKit';

export class PictureUtils {
  /**
   * 选择图片
   *
   * @param selectNumber 选择图片的最大数量
   * @returns PhotoSelectResult
   */
  static async selectPicture(selectNumber: number): Promise<photoAccessHelper.PhotoSelectResult> {
    let photoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
    // 设置要选择的媒体文件类型
    photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
    // 设置选择文件最大数量
    photoSelectOptions.maxSelectNumber = selectNumber;
    let photoPicker = new photoAccessHelper.PhotoViewPicker();
    return await photoPicker.select(photoSelectOptions)
  }

  /**
   * 图片压缩
   *
   * @param pictureUri 图片uri
   * @param format 压缩后的目标格式,支持jpg、webp和png
   * @param quality 压缩质量,取值范围0-100,压缩质量数字越大,图片越大
   * @returns ArrayBuffer
   */
  static async compressPicture(pictureUri: string, format: string, quality: number): Promise<ArrayBuffer> {
    let file = fs.openSync(pictureUri, fs.OpenMode.READ_ONLY);
    let size = fs.statSync(file.fd).size;
    let buf = new ArrayBuffer(size);
    fs.readSync(file.fd, buf);
    fs.closeSync(file);
    let imageSource = image.createImageSource(buf);

    const imagePackerApi: image.ImagePacker = image.createImagePacker();
    let packOpts: image.PackingOption = { format: format, quality: quality };
    return await imagePackerApi.packing(imageSource, packOpts)
  }
}
分享
微博
QQ
微信
回复
2天前
相关问题
如何保存一张PNG图片相册
2120浏览 • 1回复 待解决
HarmonyOS 多张图片拼接为一张
178浏览 • 1回复 待解决
如何吸取一张图片的色值?
553浏览 • 1回复 待解决
HarmonyOS 多张画布横向合成一张图片
131浏览 • 1回复 待解决
HarmonyOS 多张string图片合并成一张
124浏览 • 1回复 待解决
HarmonyOS 获取手机最新的一张图片
155浏览 • 1回复 待解决
如何将一张图片转化为PixelMapElement
10171浏览 • 1回复 待解决