嚴華 发表于 2024-11-14 05:39:17

鸿蒙HarmonyOS (开辟进阶)图像含糊动效优化

鸿蒙NEXT开辟实战往期必看文章:
一分钟相识”纯血版!鸿蒙HarmonyOS Next应用开辟!
“非常详细的” 鸿蒙HarmonyOS Next应用开辟学习路线!(从零根本入门到精通)
HarmonyOS NEXT应用开辟案例实践总结合(持续更新......)
HarmonyOS NEXT应用开辟性能优化实践总结(持续更新......)
概述

含糊效果是一种常见的图像处置惩罚技术,它通过削弱图像细节,去除干扰,使核心更加光显。如下图所示,含糊效果不但能加强界面空间感,还能清晰区分元素层级,是图像处置惩罚范畴中一项常用且紧张的技术本事。但当这一效果融入动态变化,便催生了含糊动效。含糊动效被广泛应用于页面之间的转场、图像元素的缩放等需要突出内容或改变用户关注点的场景中。
由于含糊算法需要对组件进行精细的像素级处置惩罚,当组件需要及时刷新时,这要求在极短的单个视频帧周期内完成含糊化处置惩罚。若组件同时还负担着繁重的动画渲染任务,则会进一步加剧计算资源的消耗,轻易导致含糊效果处置惩罚时间不足,无法按时完成含糊动效,最终引发卡顿、丢帧等不良现象。
因此,随着应用的广泛普及,含糊动效的性能优化愈发显得至关紧张。鉴于体系为开辟者提供的静态含糊和动态含糊两种动效本领,本文将对比静态与动态含糊在“转场结合图片含糊”的应用场景下的性能差别,发起开辟者在组件背景和内容无需及时更新的场景中,推荐利用静态含糊,可以淘汰应用卡顿与丢帧,提升用户体验。

https://img-blog.csdnimg.cn/img_convert/9498a038d917cd170daa9f78139cc63d.png
利用场景

在介绍静态含糊和动态含糊之前,需要分析动态含糊和静态含糊的区别在于要含糊的内容是不是动态更新的,如对视频做含糊就是动态含糊,对图片做含糊就是静态含糊。


[*]静态含糊:静态含糊是指对输入的静态内容进行含糊处置惩罚并获取一张含糊后的图像的含糊。适用于需要为静态图像提供含糊化效果的场景。Effect Kit在Filter图像效果类中提供了blur接口,可用于定义含糊半径,数值越大含糊效果越明显。


[*]动态含糊:动态含糊是指含糊效果会随着每帧含糊内容和含糊半径的变化,进行及时变化的含糊。适用于含糊内容需要及时刷新和更改的场景。体系针对组件内容、背景的动态含糊提供了两种实现动态含糊的方法:backgroundBlurStyle和foregroundBlurStyle。这两个方法不能指定含糊半径、提亮、饱和度、蒙版颜色等具体参数,只能调用底层将这些参数封装好的含糊样式来实现不同风格的含糊效果。同时体系也为开辟者提供了能够自定义参数的backgroundEffect,可以对组件背景实现自定义含糊动效。如果只需要对组件进行简单的含糊处置惩罚,体系还提供了与静态含糊类似的简单方法blur和backdropBlur,只需要定义含糊半径即可。
场景示例

下面将在常见的“转场结合图片含糊”的应用场景下(全屏模态转场拉起一个图片设置含糊的模态页面),分别采用动态含糊和静态含糊,进行性能分析对比。需要分析,由于静态含糊和动态含糊底层采用的算法不同,动态含糊blur和静态含糊blur设置的含糊半径数值并不等效。为了从效果一致性的维度来更准确的比力两者的性能差别,这里将动态含糊和静态含糊场景的含糊半径的数值尽大概的调解到类似的含糊效果来进行对比。动态含糊blur设置13,静态含糊blur设置3的图片含糊效果较为靠近,作为本例中效果一致性较为近似的等效条件。
下面是利用动态含糊对图片进行含糊处置惩罚的场景示例。通过直接对Image组件设置blur,为Image添加含糊效果。
@Entry
@Component
struct Index {
@State isShowMotionBlur: boolean = false; // 是否显示全屏模态页面

// 图片设置动态模糊的模态页面
@Builder
motionBlurBuilder() {
    Stack({ alignContent: Alignment.Bottom }) {
      Image($r('app.media.test'))
      .width('100%')
      .height('100%')
      .objectFit(ImageFit.Fill)
      .blur(13) // 添加动态模糊效果
      Button('close')
      .fontSize(20)
      .margin(10)
      .onClick(() => {
          this.isShowMotionBlur = false;
      })
    }
    .width('100%')
    .height('100%')
}

build() {
    Column({ space: 10 }) {
      Button('动态模糊')
      .margin(10)
      .onClick(() => {
          this.isShowMotionBlur = true;
      })
      .bindContentCover(this.isShowMotionBlur, this.motionBlurBuilder(), {
          modalTransition: ModalTransition.DEFAULT // 全屏模态转场类型。DEFAULT表示上下切换动画
      })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.End)
}
}
https://img-blog.csdnimg.cn/img_convert/b2ddde4e5611d288aa6bfcc93bcd6fc7.gif
下面是利用静态含糊对图片进行含糊处置惩罚的场景示例。主要步骤如下:

[*]通过createPixelMap创建图片的PixelMap。
[*]通过createEffect创建Filter实例。
[*]通过Filter图像效果类中的blur,为Image添加含糊效果。
import { image } from '@kit.ImageKit'; // 导入图片处理模块
import { effectKit } from '@kit.ArkGraphics2D'; // 导入图像效果模块

@Entry
@Component
struct Index {
@State isShowStaticBlur: boolean = false; // 是否显示全屏模态页面
@State pixelMap: image.PixelMap | undefined = undefined; // PixelMap实例
@State imgSource: image.ImageSource | undefined = undefined; // ImageSource实例

// 静态模糊
async staticBlur() {
    let context = getContext(this); // 获得当前Ability的Context
    let resourceMgr = context.resourceManager; // 获取resourceManager对象
    const fileData = await resourceMgr.getRawFileContent('test.png'); // 获取rawfile目录下的图片
    let buffer: ArrayBuffer = fileData.buffer.slice(0); // 创建ArrayBuffer实例
    this.imgSource = image.createImageSource(buffer); // 创建图片源实例
    // 创建像素的属性
    let opts: image.InitializationOptions = {
      editable: true, // 是否可编辑
      pixelFormat: 3, // 像素格式。3表示RGBA_8888
      size: {
      // 创建图片大小
      height: 4,
      width: 6
      }
    };
    // 创建PixelMap
    await this.imgSource.createPixelMap(opts).then((pixelMap: image.PixelMap) => {
      const blurRadius = 3; // 模糊半径
      let headFilter = effectKit.createEffect(pixelMap); // 创建Filter实例
      if (headFilter !== null) {
      headFilter.blur(blurRadius); // 设置静态模糊。将模糊效果添加到效果链表中
      // 获取已添加链表效果的源图像的image.PixelMap
      headFilter.getEffectPixelMap().then((pixelMap: image.PixelMap) => {
          this.pixelMap = pixelMap;
      });
      }
    })
}

// 图片设置静态模糊的模态页面
@Builder
staticBlurBuilder() {
    Stack({ alignContent: Alignment.Bottom }) {
      Image(this.pixelMap)
      .width('100%')
      .height('100%')
      .objectFit(ImageFit.Fill)
      Button('close')
      .fontSize(20)
      .margin(10)
      .onClick(() => {
          this.isShowStaticBlur = false;
      })
    }
    .width('100%')
    .height('100%')
}

build() {
    Column({ space: 10 }) {
      Button('静态模糊')
      .margin(10)
      .onClick(() => {
          this.isShowStaticBlur = true;
          // 设置静态模糊
          this.staticBlur();
      })
      .bindContentCover(this.isShowStaticBlur, this.staticBlurBuilder(), {
          modalTransition: ModalTransition.DEFAULT // 全屏模态转场类型。DEFAULT表示上下切换动画
      })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.End)
}
}
https://img-blog.csdnimg.cn/img_convert/cfc077a904902fbe6edfe0ae7843dc9b.gif
效果对比

下面利用DevEco Studio内置的Profiler中的帧率分析工具Frame抓取点击按钮触发转场过程的trace来分析静态含糊和动态含糊场景下的性能差别。需要分析,由于场景示例通过点击按钮触发转场,以是可以通过User Events(用户输入变乱)的Click标签定位到转场过程的起点为Click标签竣事位置。转场过程的终点为连续的RenderFrame(实行GPU绘制)标签不再连续的位置。

https://img-blog.csdnimg.cn/img_convert/c16fa341310196eab08aa1cd01daf534.png
如上图所示,通过RenderFrame(实行GPU绘制)标签可以看出,动态含糊转场匀称渲染耗时为6.113ms。同时从Present Fence(图形上屏信号)标签可以看出动态含糊转场匀称帧率为108.0fps。

https://img-blog.csdnimg.cn/img_convert/e0f93dd4b526a16cbcec0782bce183d9.png
如上图所示,通过RenderFrame标签可以看出,静态含糊转场匀称渲染耗时为3.357ms。同时从Present Fence标签可以看出静态含糊转场匀称帧率为119.9fps。和动态含糊转场相比匀称渲染耗时淘汰了约45%(性能耗时数据因应用场景、装备型号版本而异,以实测为准)。
由此可见,在含糊效果类似的条件下,静态含糊的性能要优于动态含糊。这源于底层实现机制的差别:静态含糊只需完成一次性的含糊处置惩罚,有效减轻了及时渲染的负担;而动态含糊则需要对每一帧进行连续的含糊计算,尽管在抱负环境下能够营造出更为平滑和连贯的视觉过渡效果,但同时也明显增加了渲染的复杂度和资源消耗,若页面过于复杂,反而大概导致卡顿或丢帧现象的发生。
https://i-blog.csdnimg.cn/direct/61f09d9f29a74f4e9c1fcaab6e81392a.png

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 鸿蒙HarmonyOS (开辟进阶)图像含糊动效优化