HarmonyOS 图片怎么调用系统的裁剪功能?

HarmonyOS
5h前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
Heiang

图片裁剪需要对PixelMap进行相关的操作。参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/image-arkts-dev-V5

Button('图像裁剪').fancy()
  .onClick(() => {
    let region: image.Region = { x: 300, y: 0, size: { height: 500, width: 700 } };
    if (this.imagePixelMap != undefined) {
      this.imagePixelMap.crop(region).then(async () => {
        if (this.imagePixelMap != undefined) {
          let pixel = await copyPixelMap(this.imagePixelMap);
          this.imagePixelMap.release();
          this.imagePixelMap = pixel;
          console.info('Sucessed in setting crop.');
        }
      }).catch((err: BusinessError) => {
        console.error('Failed to crop pixelmap.');
      })
    }
  })

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;
}

简易示例参考如下。第三方库的图片裁剪可以参考ImageKnife,里面提供裁剪接口request.crop(),文档:https://gitee.com/openharmony-tpc/ImageKnife

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

@Entry
@Component
struct Index {
  @State origin: PixelMap | undefined = undefined
  @State origin2: 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
    }
  }
  build() {
    Column() {
      Button('添加照片')
        .onClick(async () => {
          let uris = await selectPhoto({
            MIMEType: picker.PhotoViewMIMETypes.IMAGE_TYPE,
            maxSelectNumber: 1,
            isPhotoTakingSupported: false,
            recommendationOptions: {
              recommendationType: photoAccessHelper.RecommendationType.PROFILE_PICTURE,
            }
          })
          if (uris.length == 0) {
            return
          }
          this.uri = uris[0];
          this.origin = await this.decodeImage(uris[0])

        })
      Image(this.origin)
        .width('100%')
        .height('100%')
        .layoutWeight(1)
        .objectFit(ImageFit.Contain)


      Button('裁剪照片')
        .onClick(async () => {
          this.origin2 = await this.decodeImage(this.uri)
          if (this.origin2) {
            let info = await this.origin2.getImageInfo()
            this.origin2.crop({
              x: 0, y: 0,
              size: {
                width: info.size.width,
                height: info.size.height / 2
              }
            })
            let pixel = await copyPixelMap(this.origin2);
            this.origin2.release();
            this.origin2 = pixel;
          }
        })

      Image(this.origin2)
        .width('100%')
        .height('100%')
        .layoutWeight(1)
        .objectFit(ImageFit.Contain)
    }
    .width(`100%`)
  }
}


const PHOTO_DEFAULT_SELECT_NUMBER: number = 9; //数量

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;
}

/**

 通过选择模式拉起photoPicker界面,用户可以选择一个或多个图片/视频。
 @param options
 @returns

 */
async function selectPhoto(options?: PhotoSelectOptions): Promise<Array<string>> {
  try {
    if (!options) {
      options = new PhotoSelectOptions();
    }
    if (!options.MIMEType) { //可选择的媒体文件类型,若无此参数,则默认为图片和视频类型。
      options.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
    }
    if (!options.maxSelectNumber) { //选择媒体文件数量的最大值,默认9
      options.maxSelectNumber = PHOTO_DEFAULT_SELECT_NUMBER;
    }
    if (options.isPhotoTakingSupported == undefined) {
      options.isPhotoTakingSupported = true; //支持拍照。
    }
    if (options.isEditSupported == undefined) {
      options.isEditSupported = true; //支持编辑照片。
    }
    if (options.isSearchSupported == undefined) {
      options.isSearchSupported = true; //支持编辑照片。
    }
    let photoSelectOptions: photoAccessHelper.PhotoSelectOptions = {
      MIMEType: options.MIMEType,
      maxSelectNumber: options.maxSelectNumber,
      isPhotoTakingSupported: options.isPhotoTakingSupported,
      isEditSupported: options.isEditSupported,
      isSearchSupported: options.isSearchSupported,
      recommendationOptions: options.recommendationOptions,
      preselectedUris: options.preselectedUris
    }
    let photoPicker = new photoAccessHelper.PhotoViewPicker();
    let photoSelectResult: photoAccessHelper.PhotoSelectResult = await photoPicker.select(photoSelectOptions)
    if (photoSelectResult && photoSelectResult.photoUris && photoSelectResult.photoUris.length > 0) {
      return photoSelectResult.photoUris
    } else {
      return [];
    }
  } catch (err) {
    console.error(err)
    return [];
  }
}
class PhotoSelectOptions {
  MIMEType?: photoAccessHelper.PhotoViewMIMETypes = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE; //可选择的媒体文件类型,若无此参数,则默认为图片和视频类型。
  maxSelectNumber?: number = PHOTO_DEFAULT_SELECT_NUMBER; //选择媒体文件数量的最大值(默认值为50,最大值为500)。
  isPhotoTakingSupported?: boolean = true; //支持拍照。
  isEditSupported?: boolean = true; //支持编辑照片。
  isSearchSupported?: boolean = true; //支持搜索。
  recommendationOptions?: photoAccessHelper.RecommendationOptions; //支持照片推荐。
  preselectedUris?: Array<string>; //预选择图片的uri数据。
}

可以使用gesture实现放大缩小图片,参考demo:https://developer.huawei.com/consumer/cn/codelabsPortal/carddetails/tutorials_NEXT-ElectronicAlbum

结合ImageKnife实现图片裁剪:https://gitee.com/openharmony-tpc/ImageKnife

分享
微博
QQ
微信
回复
2h前
相关问题
想要实现一个图片裁剪功能
374浏览 • 1回复 待解决
HarmonyOS 有没有图片裁剪控件?
55浏览 • 1回复 待解决
如何编辑裁剪相册中图片
547浏览 • 1回复 待解决
如何实现图片裁剪、旋转
462浏览 • 1回复 待解决
如何调用系统拍照并获取图片
665浏览 • 1回复 待解决
如何对相册图片进行编辑裁剪
1788浏览 • 1回复 待解决
当前有没有图片裁剪相关demo
424浏览 • 1回复 待解决
HarmonyOS 图像裁剪demo
306浏览 • 1回复 待解决
怎么实现保存网络图片到相册功能
331浏览 • 1回复 待解决