HarmonyOS鸿蒙Next中pickerResult.resultUri返回的照片如何裁剪大小并转base64数据?

发布于 1周前 作者 bupafengyu 来自 鸿蒙OS

HarmonyOS鸿蒙Next中pickerResult.resultUri返回的照片如何裁剪大小并转base64数据?

let pickerResult: cameraPicker.PickerResult = await cameraPicker.pick(getContext(this),
[this.mediaType[0]], pickerProfile);
// Get video URI
this.uri = pickerResult.resultUri;
3 回复

在worker线程中不支持直接使用getContext接口获取主线程的context信息。主线程和worker线程的上下文不一致。需要子线程中获取Context时,需要将主线程的context发送消息的方式传输到worker线程中。

主要业务代码:主线程:

import { fileIo, picker } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { image } from '@kit.ImageKit';
import { util } from '@kit.ArkTS';

@Entry
@Component
struct Index {
  @State selectedUri: string = ''
  @State cropped: PixelMap | undefined = undefined
  private uri: string = ''

  private async decodeImage(uri: string) {
    try {
      let file = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY)
      const imageSourceApi = image.createImageSource(file.fd)
      imageSourceApi.getImageInfo(0, (error: BusinessError, imageInfo) => {
        if (imageInfo == undefined) {
          // log.e(error)
        }
        console.log(`imageInfo: ${JSON.stringify(imageInfo)}`)
      })
      return await imageSourceApi.createPixelMap()
    } catch (error) {
      // log.e(error)
      return undefined
    }
  }

  selectPhoto() {
    const photoSelectOptions = new picker.PhotoSelectOptions();
    const photoViewPicker = new picker.PhotoViewPicker();
    photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; // 过滤选择媒体文件类型为IMAGE
    photoSelectOptions.maxSelectNumber = 1; // 选择媒体文件的最大数目
    photoViewPicker.select(photoSelectOptions).then((photoSelectResult: picker.PhotoSelectResult) => {
      this.selectedUri = photoSelectResult.photoUris[0]
      //裁剪
      this.crop()
      //转base64
      this.loadImage()
    })
  }

  async crop() {
    let origin = await this.decodeImage(this.selectedUri)
    if (origin != undefined) {
      let info = await origin.getImageInfo()
      //根据自己要求填写尺寸
      let region: image.Region = { x: 0, y: 0, size: { height: info.size.height / 2, width: info.size.width } };
      origin.crop(region).then(() => {
        if (origin != undefined) {
          let pixel = await copyPixelMap(origin);
          origin.release();
          this.cropped = pixel;
          console.info('Sucessed in setting crop.');
        }
      }).catch((err: BusinessError) => {
        console.error('Failed to crop pixelmap.');
      })
    }
  }

  //通过图片uri转为ArrayBuff
  async loadImage() {
    let f = await fileIo.open(this.selectedUri, fileIo.OpenMode.READ_ONLY);
    let photoSize = fileIo.statSync(f.fd).size;
    console.info('Photo Size: ' + photoSize);
    let buffer = new ArrayBuffer(photoSize);
    fileIo.readSync(f.fd, buffer);
    fileIo.closeSync(f);
    let base64 = new util.Base64Helper(); // 实例化Base64Helper
    let unit8data = base64.encodeSync(new Uint8Array(buffer.slice(0, buffer.byteLength))) // 转换成Uint8Array
    console.info(`data长度:${unit8data.length}`)
    let textDecoder = util.TextDecoder.create('utf-8', { ignoreBOM : true })
    let retStr = textDecoder.decodeWithStream(unit8data , {stream: false}); // 可以把Uint8Array转码成base64
    console.log('imageSource: ' + retStr);
  }

  build() {
    Column() {
      Button('选择图片')
        .onClick(async () => {
          this.selectPhoto()
        })
      Image(this.selectedUri)
        .width('100%')
        .height('100%')
        .layoutWeight(1)
        .objectFit(ImageFit.Contain)
      Image(this.cropped)
        .width('100%')
        .height('100%')
        .layoutWeight(1)
        .objectFit(ImageFit.Contain)
    }
    .width(`100%`)
  }
}

async function copyPixelMap(imagePixel: PixelMap): Promise<image.PixelMap> {
  let imageInfo: image.ImageInfo = await imagePixel.getImageInfo();
  console.info(`copyPixelMapSize: width:${imageInfo?.size.width} height:${imageInfo?.size.height}`);
  let newRegion: image.Region = {
    size: { height: imageInfo.size.height, width: imageInfo.size.width },
    x: 0,
    y: 0
  }
  let newArea: image.PositionArea = {
    pixels: new ArrayBuffer(imageInfo.size.height * imageInfo.size.width * 4),
    offset: 0,
    stride: imageInfo.stride,
    region: newRegion
  }
  await imagePixel.readPixels(newArea);
  let opts: image.InitializationOptions = { editable: true, pixelFormat: 4, size: imageInfo.size };
  let imagePixelCache = await image.createPixelMap(newArea.pixels, opts);
  return imagePixelCache;
}

更多关于HarmonyOS鸿蒙Next中pickerResult.resultUri返回的照片如何裁剪大小并转base64数据?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,pickerResult.resultUri返回的照片可以通过以下步骤裁剪大小并转换为base64数据:

  1. 获取照片路径:首先,使用Uri获取照片的路径。

    const filePath = await uriToFilePath(pickerResult.resultUri);
  2. 裁剪照片:使用Image模块的createPixelMap方法加载图片,并通过ImageSource进行裁剪。

    const imageSource = image.createImageSource(filePath);
    const pixelMap = await imageSource.createPixelMap();
    const options = {
        desiredSize: { width: 200, height: 200 } // 设置裁剪后的尺寸
    };
    const croppedPixelMap = await pixelMap.createPixelMap(options);
  3. 转换为base64:使用ArrayBufferBase64模块将裁剪后的图片转换为base64数据。

    const arrayBuffer = await croppedPixelMap.getImageInfo();
    const base64Data = Base64.encode(arrayBuffer);

完成以上步骤后,base64Data即为裁剪后的base64数据。

在HarmonyOS鸿蒙Next中,可以通过Image组件获取pickerResult.resultUri的图片资源,然后使用ImageSource进行裁剪。首先,创建ImageSource对象并加载图片,接着使用createPixelMap方法进行裁剪。裁剪后,将像素数据转换为ArrayBuffer,再通过Base64编码转为base64数据。具体代码示例如下:

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

let imageSource = image.createImageSource(pickerResult.resultUri);
let options = {
    desiredSize: { width: 100, height: 100 } // 设置裁剪大小
};
imageSource.createPixelMap(options).then(pixelMap => {
    let arrayBuffer = pixelMap.getImageInfo().data;
    let base64 = arrayBufferToString(arrayBuffer);
    console.log(base64);
});

function arrayBufferToString(buffer) {
    return btoa(String.fromCharCode(...new Uint8Array(buffer)));
}
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!