HarmonyOS 鸿蒙Next 编辑图片裁剪图片的能力

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

HarmonyOS 鸿蒙Next 编辑图片裁剪图片的能力

需要一个编辑图片裁剪图片的能力 类似于系统相册编辑图片的功能,可以提供下吗?

3 回复

可以通过图片处理模块的pixelMap方法对图片进行编辑裁剪。

包括但不限于:

pixelMap.crop方法,可以根据输入的尺寸对图片进行裁剪。

pixelMap.opacity方法,可以通过设置透明比率对图片设置透明效果。

pixelMap.scale方法,可以根据输入的宽高对图片进行缩放。

pixelMap.rotate方法,可以根据输入的角度对图片进行旋转。

pixelMap.flip方法,可以根据输入的条件对图片进行翻转。

下面的demo是从图库中选取图片裁剪的:

import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { image } from '@kit.ImageKit';
import { picker } from '@kit.CoreFileKit';
import { fileIo } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';
import { dataSharePredicates } from '@kit.ArkData';

const context = getContext(this) as common.UIAbilityContext;
@Entry
@Component
struct PhotoSelect {
  @State pixelMap?: image.PixelMap = undefined;
  private regionItem:RegionItem = new RegionItem(0,0);
  @State isPixelMapChange: boolean = false;
  build() {
    Column() {
      Column() {
        if(this.isPixelMapChange){
          Image(this.pixelMap)
            .objectFit(ImageFit.Auto)
            .width(300)
            .height(500)
        } else {
          Image(this.pixelMap)
            .objectFit(ImageFit.Auto)
            .width(300)
            .height(500)
        }
      }
      .width('100%')
      .height('70%')
      Button('选择图片').onClick(() => {
        try {
          let uris: Array<string> = [];
          let PhotoSelectOptions = new picker.PhotoSelectOptions();
          PhotoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
          PhotoSelectOptions.maxSelectNumber = 1;
          let photoPicker = new picker.PhotoViewPicker();
          photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult: photoAccessHelper.PhotoSelectResult) => {
            uris = PhotoSelectResult.photoUris;
            this.testMethod(uris[0])
            let file = fileIo.openSync(uris[0], fileIo.OpenMode.READ_ONLY);
            console.info('file fd: ' + file.fd);
            let buffer = new ArrayBuffer(4096);
            let readLen = fileIo.readSync(file.fd, buffer);
            console.info('readSync data to file succeed and buffer size is:' + readLen);
            const imageSource: image.ImageSource = image.createImageSource(file.fd);
            let decodingOptions: image.DecodingOptions = {
              editable: true,
              desiredPixelFormat: 3,
            }
            imageSource.createPixelMap(decodingOptions, (err: BusinessError, pixelMap: image.PixelMap) => {
              if (err !== undefined) {
                console.error(`Failed to create pixelMap.code is ${err.code},message is ${err.message}`);
              } else {
                this.pixelMap = pixelMap
                console.info('Succeeded in creating pixelMap object.');
              }
            })
          }).catch((err: BusinessError) => {
            console.error(`Invoke photoPicker.select failed, code is ${err.code}, message is ${err.message}`);
          })
        } catch (error) {
          let err: BusinessError = error as BusinessError;
          console.error('photoPicker failed with err: ' + JSON.stringify(err));
        }
      })
      if(this.pixelMap){
        Button('裁剪').onClick(() => {
          banner(this.pixelMap!, this.regionItem.x, this.regionItem.y).then(() => {
            this.flushPixelMapChange();
          });
        })
      }
    }
    .alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
  }

  flushPixelMapChange() {
    this.isPixelMapChange = !this.isPixelMapChange;
  }

  async testMethod(uri: string) {
    let predicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates();
    predicates.equalTo(photoAccessHelper.PhotoKeys.URI, uri);
    let fetchOptions: photoAccessHelper.FetchOptions = {
      fetchColumns: [
        "title",
        photoAccessHelper.PhotoKeys.WIDTH,
        photoAccessHelper.PhotoKeys.HEIGHT,
        photoAccessHelper.PhotoKeys.DURATION,
        photoAccessHelper.PhotoKeys.SIZE,
        photoAccessHelper.PhotoKeys.DISPLAY_NAME,
        photoAccessHelper.PhotoKeys.ORIENTATION,//旋转
        photoAccessHelper.PhotoKeys.PHOTO_SUBTYPE],
      predicates: predicates
    };//"--"+"ORIENTATION: "+photoAsset.get("orientation")
    try {
      let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(getContext(this));
      let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset> =
        await phAccessHelper.getAssets(fetchOptions);
      let photoAsset: photoAccessHelper.PhotoAsset = await fetchResult.getFirstObject();
      let title :photoAccessHelper.PhotoKeys = photoAccessHelper.PhotoKeys.TITLE;
      let paTitle = photoAsset.get(title.toString())
      let orientation = photoAsset.get("orientation") as number
      this.regionItem = new RegionItem(photoAsset.get("width") as number,photoAsset.get("height") as number);
      console.debug("ccTestShow","title: "+paTitle.toString()+"-width:"+photoAsset.get("height")+"-height:"+photoAsset.get("width")+"--"+"ORIENTATION: "+photoAsset.get("orientation"))
      fetchResult.close();
      return photoAsset
    } catch (err) {
      console.error('getAssets failed with err: ' + err);
    }
    return
  }
}

class RegionItem {
  /**
   * width coordinate.
   */
  x: number;

  /**
   * height coordinate.
   */
  y: number;

  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
}

export async function cropCommon(pixelMap: PixelMap, cropWidth: number, cropHeight: number, cropPosition: RegionItem) {
  pixelMap.crop({
    size: {
      width: cropWidth,
      height: cropHeight
    },
    x: cropPosition.x,
    y: cropPosition.y
  });
}

// 传入image.PixelMap、图片width、图片height三个参数,获取到裁剪后的图片宽度和高度后将参数传入cropCommon方法
export async function banner(pixelMap: PixelMap, width: number, height: number) {
  if (width <= height) {
    const cropWidth = width;
    const cropHeight = Math.floor(width * 0.75);
    const cropPosition = new RegionItem(0, Math.floor((height - cropHeight) / 2));
    cropCommon(pixelMap, cropWidth, cropHeight, cropPosition);
    return;
  }
  if (width * 0.75 >= height) {
    const cropWidth = Math.floor(height / 0.75);
    const cropHeight = height;
    const cropPosition = new RegionItem(Math.floor((width - cropWidth) / 2), 0);
    cropCommon(pixelMap, cropWidth, cropHeight, cropPosition);
    return;
  }
  const cropWidth = width;
  const cropHeight = Math.floor(width * 0.75);
  const cropPosition = new RegionItem(0, Math.floor((height - cropHeight) / 2));
  cropCommon(pixelMap, cropWidth, cropHeight, cropPosition);
}

pixelMap的相关文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-image-V5#pixelmap7

更多关于HarmonyOS 鸿蒙Next 编辑图片裁剪图片的能力的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


HarmonyOS 鸿蒙Next在编辑图片和裁剪图片方面提供了强大的功能。

鸿蒙Next系统内置了图片编辑工具,用户可以直接在相册或文件管理应用中打开图片进行编辑。在编辑界面,用户会看到一个裁剪工具选项,点击进入后,系统会显示一个可调整的裁剪框。用户可以通过拖动裁剪框的边角或边缘来调整裁剪区域的大小和位置,以满足不同的裁剪需求。

此外,鸿蒙Next还提供了多种裁剪比例供用户选择,如1:1(正方形)、3:2、4:3、16:9等,用户可以根据实际需要选择合适的比例。在裁剪完成后,用户还可以对图片进行其他编辑操作,如旋转、翻转、添加滤镜、调整亮度、对比度等。

值得注意的是,鸿蒙Next的图片编辑工具支持实时预览功能,用户在调整裁剪区域或进行其他编辑操作时,可以实时看到图片的变化效果,从而更准确地完成编辑任务。

总的来说,HarmonyOS 鸿蒙Next在编辑图片和裁剪图片方面提供了丰富的功能和便捷的操作方式,能够满足用户多样化的图片编辑需求。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部