当前位置: 首页 > 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.jsqmd.com/news/1012532/

相关文章:

  • Kubernetes GPU 调度:拓扑感知与多租户隔离
  • MPC8309 eSDHC控制器:命令响应、状态监控与中断处理实战解析
  • 2026年6月福建知名的无人机服务中心哪家专业,无人机驾照培训/无人机培训就业/无人机飞行执照培训,无人机服务品牌哪家好 - 品牌推荐师
  • 如何快速掌握BepInEx:终极Unity游戏插件框架完全指南
  • 深入解析MPC7450异常处理:从原理到实战的嵌入式系统核心机制
  • eTSEC控制器实战解析:从硬件接口到驱动配置的嵌入式网络开发指南
  • 终极指南:使用Dism++免费完成Windows系统维护与优化
  • MAA明日方舟助手:开源智能自动化工具完全指南
  • Awesome-Dify-Workflow:无需代码,轻松构建AI工作流的终极指南
  • 暗黑破坏神2存档编辑器:10分钟掌握免费修改神器的完整使用教程
  • 选择合适的后端技术栈:项目需求与技术匹配策略
  • TensorFlow原生PSO:GPU加速的粒子群优化实现
  • AI 推理服务冷启动优化:轻量化容器镜像构建与按需分层加载实践
  • AI一键多发真的靠谱吗_CSDN_AI数字营销完整试用记录
  • 2026年众智商学院官网怎么找、400电话怎么拨打、冯老师微信怎么加、课程怎么报名 - 众智商学院职业教育
  • 从平面到立体:5分钟免费解锁你的3D打印创意之旅
  • D3KeyHelper暗黑3技能连点器:彻底告别手酸,轻松实现自动化战斗
  • FanControl终极指南:Windows平台免费风扇控制软件完全掌控你的电脑散热
  • 专业级开源工具:WuMgr如何解决Windows 10更新管理难题
  • UCC BISYNC模式错误处理:从硬件原理到工程实践
  • Ryujinx Switch模拟器终极指南:在PC上完美运行Switch游戏的实战解决方案
  • 怎样高效批量下载抖音视频:5个实用技巧实现自动去水印
  • UI-TARS桌面版终极指南:5分钟快速上手,用自然语言彻底解放你的重复GUI操作
  • Path of Building PoE2:终极流放之路2角色构建指南,轻松打造百万DPS角色!
  • 2026 奢侈品包包回收避坑调研报告,五大商户真实交易测评汇总 - 讯息早知道
  • 3步掌握UI-TARS桌面版:用自然语言实现GUI自动化的实用指南
  • 3步完成AutoHotkey v1到v2脚本转换的完整解决方案
  • 200+插件一键安装:Koikatu HF Patch终极增强补丁完全指南
  • 终极指南:如何在电脑上使用Citra模拟器重温任天堂3DS经典游戏
  • 江门名酒回收指南,江门名酒礼品回收实测好评榜 - 爱吃西瓜的西高地