当前位置: 首页 > news >正文

【共创季稿事节】鸿蒙ArkTS颜色滤镜实战

鸿蒙 ArkTS 实战:ColorFilter 颜色矩阵滤镜——从原理到 7 种经典效果完整实现

一、为什么需要 ColorFilter?

图像滤镜是移动应用的常见需求——从社交 App 的美化功能、电商的商品展示,到工具 App 的禁用灰度状态,都需要动态改变图像的色彩表现。

传统做法是编写 GPU 着色器,这对 ArkTS 开发者过于底层。HarmonyOS NEXT 的Image组件直接提供了colorFilter属性,允许传入一个4×5 的颜色变换矩阵,在 GPU 层面并行计算每个像素的 RGBA 变换。一行.colorFilter(matrix)即可生效,零额外依赖。


二、颜色矩阵原理 | 4×5 矩阵的数学本质

2.1 矩阵结构(行主序)

索引 0 1 2 3 4 → R 通道变换系数 5 6 7 8 9 → G 通道变换系数 10 11 12 13 14 → B 通道变换系数 15 16 17 18 19 → A 通道变换系数

2.2 数学公式

新 R = m[0]×R + m[1]×G + m[2]×B + m[3]×A + m[4] 新 G = m[5]×R + m[6]×G + m[7]×B + m[8]×A + m[9] 新 B = m[10]×R + m[11]×G + m[12]×B + m[13]×A + m[14] 新 A = m[15]×R + m[16]×G + m[17]×B + m[18]×A + m[19]

前 4 列是缩放系数,决定当前输出通道受 R、G、B、A 输入的影响权重;第 5 列是偏移量,与输入像素值无关。例如反色中偏移设为 +1,结合 -1 系数,实现新值 = 1 - 原值

2.3 单位矩阵(原图效果)

[1,0,0,0,0,// 新 R = R0,1,0,0,0,// 新 G = G0,0,1,0,0,// 新 B = B0,0,0,1,0]// 新 A = A

对角为 1、其余为 0、偏移为 0,就是"原图"。


三、API 24 下的 colorFilter 属性

3.1 属性签名

// 方式一:直接传入 20 个 number 的数组(推荐,0 依赖,兼容性最好)Image(src).colorFilter([r0,r1,r2,r3,r4,g0,g1,g2,g3,g4,b0,b1,b2,b3,b4,a0,a1,a2,a3,a4])// 方式二:使用 ColorFilter 对象(API 24 从 @kit.ArkGraphics2D 导入)import{ColorFilter}from'@kit.ArkGraphics2D';Image(src).colorFilter(newColorFilter(matrix))

⚠️ API 24 中ColorFilter/ColorMatrix不在@kit.ArkUI中,推荐直接用数组传参,省去 import 烦恼。

3.2 与简化属性对比

属性等价效果示例
.grayscale(v)灰度,v∈[0,1].grayscale(0.8)
.sepia(v)怀旧,v∈[0,1].sepia(0.6)
.invert(v)反色,v∈[0,1].invert(0.5)
.saturate(v)饱和度,v≥0.saturate(2.0)
.hueRotate(deg)色相旋转.hueRotate(90)
.brightness(v)亮度.brightness(1.2)
.contrast(v)对比度.contrast(1.5)
.colorFilter(matrix)通用矩阵核心 API

简化属性适合单一效果,colorFilter适合多通道混合变换。


四、7 种滤镜矩阵逐行解读

4.1 原图

对角全 1,不做变换,作为对比基准。

4.2 灰度(Grayscale)

[0.2126,0.7152,0.0722,0,0,0.2126,0.7152,0.0722,0,0,0.2126,0.7152,0.0722,0,0,0,0,0,1,0]

三行系数相同,输出R=G=B = 0.2126R + 0.7152G + 0.0722B。权重来自ITU-R BT.709亮度标准:人眼对绿色最敏感(0.7152),对蓝色最不敏感(0.0722)。若均分 0.333,灰度图会偏暗。

4.3 怀旧/复古(Sepia)

[0.393,0.769,0.189,0,0,0.349,0.686,0.168,0,0,0.272,0.534,0.131,0,0,0,0,0,1,0]

R 行和 G 行从其他通道"借"来大量能量,B 通道被大幅削弱,产生暖黄褐色的老照片效果。三行系数相加均大于 1,整体亮度提升约 35%。

4.4 反色(Invert)

[-1,0,0,0,1,0,-1,0,0,1,0,0,-1,0,1,0,0,0,1,0]

对角线 -1 + 偏移 +1 =新值 = 1 - 原值。黑变白、白变黑,完美反转。

4.5 高饱和度

[1.438,-0.122,-0.016,0,-0.03,-0.062,1.378,-0.016,0,-0.05,-0.062,-0.122,1.483,0,-0.02,0,0,0,1,0]

对角系数 > 1 增强本色,负的非对角系数削弱串扰。红更红、绿更绿、蓝更蓝。

4.6 冷色调

[1,0,0,0,0,0,0.9,0,0,0,0,0,1.2,0,0,0,0,0,1,0]

R 不变、G 略降(0.9)、B 提升(1.2),模拟色温降低时蓝光增多的效果。适合科技感 UI。

4.7 黑白高对比

[1.5,1.5,1.5,0,-1,1.5,1.5,1.5,0,-1,1.5,1.5,1.5,0,-1,0,0,0,1,0]

放大灰度增益至 1.5 倍,引入 -1 偏移,将中间色调"撕裂"成近乎二值化的黑白分明的效果。RGB 均值低于 0.67 的像素压至 0,高于的被裁剪到 1。


五、完整代码实现

5.1 接口定义与状态声明

interfaceFilterOption{label:string;matrix:number[];}@Entry@Componentstruct Index{@StatecurrentFilterIndex:number=0;@StateshowMatrixDebug:boolean=false;privatereadonlyfilters:FilterOption[]=[{label:'原图',matrix:[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0]},{label:'灰度',matrix:[0.2126,0.7152,0.0722,0,0,0.2126,0.7152,0.0722,0,0,0.2126,0.7152,0.0722,0,0,0,0,0,1,0]},{label:'怀旧/复古',matrix:[0.393,0.769,0.189,0,0,0.349,0.686,0.168,0,0,0.272,0.534,0.131,0,0,0,0,0,1,0]},{label:'反色',matrix:[-1,0,0,0,1,0,-1,0,0,1,0,0,-1,0,1,0,0,0,1,0]},{label:'高饱和度',matrix:[1.438,-0.122,-0.016,0,-0.03,-0.062,1.378,-0.016,0,-0.05,-0.062,-0.122,1.483,0,-0.02,0,0,0,1,0]},{label:'冷色调',matrix:[1,0,0,0,0,0,0.9,0,0,0,0,0,1.2,0,0,0,0,0,1,0]},{label:'黑白高对比',matrix:[1.5,1.5,1.5,0,-1,1.5,1.5,1.5,0,-1,1.5,1.5,1.5,0,-1,0,0,0,1,0]}];getcurrentMatrix():number[]{returnthis.filters[this.currentFilterIndex].matrix;}getcurrentLabel():string{returnthis.filters[this.currentFilterIndex].label;}

5.2 build() 布局

build(){Scroll(){// ★ Scroll 实现页面滚动Column(){// ---- 标题 ----Text('🎨 ColorFilter 颜色滤镜演示').fontSize(22).fontWeight(FontWeight.Bold).width('100%').padding({top:16,bottom:8})Text('通过 4×5 RGBA 颜色矩阵实现图像滤镜效果').fontSize(13).fontColor('#888888').width('100%').padding({bottom:12})// ---- 当前滤镜名 ----Text(this.currentLabel).fontSize(18).fontWeight(FontWeight.Medium).fontColor('#ff6600').width('100%').padding({bottom:8})// ---- 图片展示区(核心) ----Stack(){Image($r('app.media.background')).width('95%').aspectRatio(1.6).objectFit(ImageFit.Cover).borderRadius(16)// ★★★ 核心:colorFilter ★★★.colorFilter(this.currentMatrix).animation({duration:400,curve:Curve.EaseInOut})}.width('100%').padding({bottom:16})// ---- 滤镜按钮(Flex + wrap 流式布局) ----Flex({direction:FlexDirection.Row,wrap:FlexWrap.Wrap,justifyContent:FlexAlign.Center}){ForEach(this.filters,(item,index)=>{Button(item.label).height(40).fontSize(14).borderRadius(20).margin(6).backgroundColor(this.currentFilterIndex===index?'#ff6600':'#f0f0f0').fontColor(this.currentFilterIndex===index?'#ffffff':'#333333').onClick(()=>{this.currentFilterIndex=index;})},(_,i)=>i.toString())}.width('100%').padding({left:12,right:12,bottom:12})// ---- 矩阵调试面板 ----Button(this.showMatrixDebug?'收起 ▲':'展开 ▼').fontSize(12).height(32).borderRadius(12).onClick(()=>{this.showMatrixDebug=!this.showMatrixDebug;})if(this.showMatrixDebug){Scroll(){Column(){Text('🎯 4×5 颜色矩阵').fontSize(13).fontColor('#666')this.MatrixRow('R 通道',0)this.MatrixRow('G 通道',5)this.MatrixRow('B 通道',10)this.MatrixRow('A 通道',15)}.padding(16)}.height(160).backgroundColor('#fafafa').borderRadius(12).padding(8)}// ---- 底部说明 ----Text('布局要点说明').fontSize(14).fontWeight(FontWeight.Bold).padding({top:16,bottom:4})Column(){Text('① .colorFilter() 传入 20 个数值的数组,无需 import').fontSize(12).fontColor('#666')Text('② 每行 5 值:4 个通道系数 + 1 个偏移量').fontSize(12).fontColor('#666')Text('③ 灰度:R_out = G_out = B_out = 0.2126R + 0.7152G + 0.0722B').fontSize(12).fontColor('#666')Text('④ 反色利用 -1 对角系数 + 偏移 +1 实现').fontSize(12).fontColor('#666')Text('⑤ 也可从 @kit.ArkGraphics2D 导入 ColorFilter 类').fontSize(12).fontColor('#666')}.alignItems(HorizontalAlign.Start).width('90%').padding({bottom:20})}.width('100%').padding(8)}.scrollable(ScrollDirection.Vertical)}

5.3 @Builder 矩阵行

@BuilderMatrixRow(label:string,offset:number){Row(){Text(label).fontSize(12).width(55).textAlign(TextAlign.End)Text(this.currentMatrix[offset].toFixed(3)).fontSize(12).width(50)Text(this.currentMatrix[offset+1].toFixed(3)).fontSize(12).width(50)Text(this.currentMatrix[offset+2].toFixed(3)).fontSize(12).width(50)Text(this.currentMatrix[offset+3].toFixed(3)).fontSize(12).width(50)Text(this.currentMatrix[offset+4].toFixed(3)).fontSize(12).width(50).fontColor('#cc5500')// 偏移量橙色高亮}.justifyContent(FlexAlign.Center).padding({top:4,bottom:4})}}

六、避坑指南:API 24 常见编译错误

6.1 ColorFilter/ColorMatrix 未导出

Module '"@kit.ArkUI"' has no exported member 'ColorFilter'

修复:用数组传参代替类实例。或从@kit.ArkGraphics2D导入。

6.2 Curve.FadeIn 不存在

Curve枚举没有FadeIn。用Curve.EaseIn/Curve.EaseOut/Curve.EaseInOut

6.3 自定义组件 6 个参数

ArkTS@Component不支持位置参数传值。改用@Builder函数传参:

// ✅ 用 @Builder@BuilderMatrixRow(label:string,offset:number){...}this.MatrixRow('R 通道',0)// ❌ 不行MatrixRow('R 通道',0.1,0.2,0.3,0.4,0.5)

6.4 Column 没有 scrollable()

Scroll包裹Columnscrollable()设置方向。

6.5 build() 内不能声明变量

build()中不允许let/const。变量提取为get计算属性:

getcurrentMatrix():number[]{returnthis.filters[idx].matrix;}

七、性能优化

  • GPU 管线colorFilter在片段着色器阶段完成,1920×1080 图片处理 < 1ms
  • 矩阵复用:将矩阵定义为private readonly常量,避免每次 re-render 重建
  • 动画开销.animation({ duration: 400 })会触发属性插值,列表场景建议减少动画组件数
  • 列表场景:配合LazyForEach+.syncLoad(true)获得流畅滚动体验

八、总结

本文从颜色矩阵的数学原理出发,用 7 个具体滤镜(原图、灰度、怀旧、反色、高饱和、冷色调、黑白高对比)展示了 HarmonyOS NEXT API 24 中Image.colorFilter()的完整用法,并附带了可运行的 ArkTS 代码和常见编译错误的解决方案。

颜色矩阵的核心规律可概括为:

  • 对角 > 1→ 增强该通道
  • 对角 < 1→ 减弱该通道
  • 对角为负→ 反相
  • 非对角非零→ 颜色串扰 / 混合
  • 第 5 列→ 整体偏移

掌握了这五条规律,任何色彩变换需求你都能写出对应的矩阵。下一步可以尝试滑块实时调节矩阵参数、多层滤镜叠加、AI 自动推荐滤镜等进阶功能。


API 参考:

  • Image 组件 colorFilter 属性
  • ArkTS 声明式语法



http://www.cnnetsun.cn/news/2920245.html

相关文章:

  • 113.低配GPU友好!DDPM显存溢出解决+混合精度训练优化方案
  • MPC8272硬件安全引擎:数据包描述符驱动与硬件加速实战解析
  • 语义打标:让非结构化文本进入业务决策的翻译器
  • Notepad--:为什么这款国产跨平台文本编辑器值得你立刻尝试?
  • 在 macOS 上享受完美歌词同步体验:LyricsX 终极指南
  • SAP成本估算CK11N自动化实战:BAPI与BDC两种方案对比与避坑指南
  • MPC7450 AltiVec向量指令与缓存架构深度解析及性能优化实战
  • MPC8544E LBC核心寄存器深度解析:从时序陷阱到性能优化实战
  • 制造业运维AI Agent:基于大模型的设备故障自动排查实战
  • 如何快速掌握Mi-Create:小米智能手表表盘设计的完整指南
  • S8.1价值感知设计——让用户觉得每一分钱都花得值
  • MPC8309 I/O Sequencer与PCI接口:地址转换与事务转发机制详解
  • 深入解析EHCI数据结构:USB主机控制器调度原理与嵌入式实践
  • 终极指南:3分钟免费激活IDM,永久解锁完整版下载功能
  • WhatsApp 400亿消息背后的高并发IM工程实践
  • 你的电脑太吵了?试试这款免费风扇控制神器,让电脑瞬间安静下来!
  • 免费CAD绘图工具终极指南:10分钟掌握LitCAD二维设计
  • 【趣解】看门狗定时器:防止系统“死机“的秘密武器
  • PowerPC条件寄存器与分支控制:嵌入式底层编程核心机制解析
  • Platinum-MD:3步让经典MiniDisc设备在现代电脑上重获新生
  • MPC8323E电源管理与总线仲裁:嵌入式系统低功耗与性能优化实战
  • 如何在Mac上快速配置桌面歌词:LyricsX的完整免费指南
  • 开源大模型微调实现高精度Text-to-SQL实战指南
  • SpaceX 首次 IPO,埃隆·马斯克净资产突破万亿美元大关
  • Box64架构深度解析:ARM64平台x86_64模拟器实战部署与性能优化指南
  • MPC8309 DMA控制器:直接与链式模式实战及性能调优
  • Android 16终极保活方案:基于Linux特性的进程永生技术深度解析
  • LizzieYzy:围棋AI分析软件让你的棋艺提升事半功倍
  • 深入解析MPC8272 ATM控制器:数据转发机制与内存结构设计
  • 终极指南:LyricsX macOS歌词工具完整配置与使用教程