[HarmonyOS Next]初探EffectKit,改变图片亮度

165 阅读1分钟

大家好,这里是程序员阿山哥🤓


今天研究一下怎么可以像平常在图片编辑里,拉动滑块,就可以改变图片亮度的效果。
先介绍一下现在我的编译环境

系统:macOS 12.7.5
开发环境:DevEcoStudio 5.0.3.700

第一步,先实现点击按钮,拉起图片选择,返回图片URI,将图片显示出来

image.png

Button('选择图片').onClick(async () => {
// 异步获取图片
  let value = await this.getUriFromPhotoPicker()
  this.photoUri = value

  try {
// 处理图片,将图片通过fileIo打开(只读),再转成pixelMap,方便后续操作
    let file = fileIo.openSync(this.photoUri, fileIo.OpenMode.READ_ONLY);
    console.info('file fd: ' + file.fd);
    const imageSource: image.ImageSource = image.createImageSource(file.fd);
    const pixelMap: image.PixelMap = await imageSource.createPixelMap();

    this.imagePixelMap = pixelMap
  } catch (e) {
    console.log(`Bright: ${e}`)
  }
  
  console.log("图片URI:" + value)
})
// 选择图片并返回图片对应的URI
  async getUriFromPhotoPicker(): Promise<string> {
    //picker的选项配置
    let PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions()
    PhotoSelectOptions.maxSelectNumber = 1 //最大可选数
    // 创建图片选择器
    let photoPicker = new photoAccessHelper.PhotoViewPicker()

    try {
      let result = await photoPicker.select(PhotoSelectOptions) // 拉起图片选择器
      console.info('选择结果 uri: ' + JSON.stringify(result))
      let photosUris = result.photoUris
      return Promise.resolve(photosUris[0].toString())
    } catch (e) {
      console.error('出错: ' + JSON.stringify(e))
    }
    return Promise.reject()
  }

一顿操作,就完成了图片选择和显示了(背后还处理了图片转成PixelMap,Image组件可以直接显示PixelMap),而且用PhotoViewPicker,不需要做图片库授权配置,适合只读图片数据的场景

第二步,通过滑块改变图片的亮度*

这一步就需要用到EffectKit了(参考文档:developer.huawei.com/consumer/cn…

这个功能属于ArkGraphics 2D的内容,有点难度,我折腾了好久才成功将图片转成PixelMap。转成PixelMap之后,后面的操作就容易很多了。

image.png

Slider({
        value: 0,
        step:0.1,
        min: 0,
        max: 1,
        style: SliderStyle.InSet
      })
        .enabled(this.imagePixelMap != undefined)
        .onChange(async (value: number, mode: SliderChangeMode) => {
          if (mode === SliderChangeMode.Moving) { //在滑动d的时候修改亮度
            try {

              let file = fileIo.openSync(this.photoUri, fileIo.OpenMode.READ_ONLY);
              console.info('file fd: ' + file.fd);
              const imageSource: image.ImageSource = image.createImageSource(file.fd);
              const pixelMap: image.PixelMap = await imageSource.createPixelMap();

              let bright = value;
              let headFilter = effectKit.createEffect(pixelMap);
              if (headFilter != null) {
                headFilter.brightness(bright);
                this.imagePixelMap = await headFilter.getEffectPixelMap()
              }
            } catch (e) {
              console.log(`Bright: ${e}`)
            }
          }
        })

以此文章抛砖引玉,让大家举一反三,EffectKit除了可以修改亮度外,还可以做如灰度、动态模糊等效果,留给大家自己研究了
今天的分享到此结束了,大家学废了吗😉
参考文档:

图像效果:developer.huawei.com/consumer/cn…

使用ImageSource完成图片解码:developer.huawei.com/consumer/cn…

附上完整Index.ets代码

import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { image } from '@kit.ImageKit';
import { effectKit } from "@kit.ArkGraphics2D";
import { fileIo } from '@kit.CoreFileKit';

@Entry
@Component
struct Index {
  @State photoUri: string = ''
  @State imagePixelMap?: image.PixelMap = undefined

  build() {
    Column({ space: 8 }) {

      Button('选择图片').onClick(async () => {

        let value = await this.getUriFromPhotoPicker()
        this.photoUri = value

        try {

          let file = fileIo.openSync(this.photoUri, fileIo.OpenMode.READ_ONLY);
          console.info('file fd: ' + file.fd);
          const imageSource: image.ImageSource = image.createImageSource(file.fd);
          const pixelMap: image.PixelMap = await imageSource.createPixelMap();

          this.imagePixelMap = pixelMap
        } catch (e) {
          console.log(`Bright: ${e}`)
        }

        console.log("图片URI:" + value)

      })
        .margin({ top: 20 })

      Slider({
        value: 0,
        step:0.1,
        min: 0,
        max: 1,
        style: SliderStyle.InSet
      })
        .enabled(this.imagePixelMap != undefined)
        .onChange(async (value: number, mode: SliderChangeMode) => {
          if (mode === SliderChangeMode.Moving) { //
            try {

              let file = fileIo.openSync(this.photoUri, fileIo.OpenMode.READ_ONLY);
              console.info('file fd: ' + file.fd);
              const imageSource: image.ImageSource = image.createImageSource(file.fd);
              const pixelMap: image.PixelMap = await imageSource.createPixelMap();

              let bright = value;
              let headFilter = effectKit.createEffect(pixelMap);
              if (headFilter != null) {
                headFilter.brightness(bright);
                this.imagePixelMap = await headFilter.getEffectPixelMap()
              }
            } catch (e) {
              console.log(`Bright: ${e}`)
            }
          }
        })
        .width('90%')

      if (this.imagePixelMap === undefined) {
        Image($r('app.media.ic_picture_default'))
          .objectFit(ImageFit.Contain)
          .width('90%')
      } else {
        Image(this.imagePixelMap)
          .objectFit(ImageFit.Contain)
          .width('90%')
      }
    }
    .width('100%')
    .height('80%')
  }

  // 选择图片并返回图片对应的URI
  async getUriFromPhotoPicker(): Promise<string> {
    //picker的选项配置
    let PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions()
    PhotoSelectOptions.maxSelectNumber = 1 //最大可选数
    // 创建图片选择器
    let photoPicker = new photoAccessHelper.PhotoViewPicker()

    try {
      let result = await photoPicker.select(PhotoSelectOptions) // 拉起图片选择器
      console.info('选择结果 uri: ' + JSON.stringify(result))
      let photosUris = result.photoUris
      return Promise.resolve(photosUris[0].toString())
    } catch (e) {
      console.error('出错: ' + JSON.stringify(e))
    }
    return Promise.reject()
  }
}