HarmonyOS colorFilter 图片滤镜实战:从颜色矩阵到混合模式完整方案
本文介绍了ArkUI Image组件的colorFilter属性实现常见图片滤镜效果,包括复古灰度、反色、饱和度增强和美白。通过4×5 RGBA颜色矩阵或颜色滤波器对像素进行线性变换,colorFilter能在渲染管线中修改图片颜色输出。详细解析了颜色矩阵的参数含义和计算原理,并对比了矩阵与滤波器两种实现方式的适用场景。最后展示了不同滤镜的具体实现代码和效果示例,帮助开发者快速掌握图片色彩处理技术
一、colorFilter 能干啥
美颜类应用里,图片处理和美化功能很关键。通过对原始图像做色彩滤镜调整,能创造出各种美图滤镜效果。
ArkUI 的 Image 组件有 colorFilter 属性,这是实现图片滤镜的核心。它允许通过数学矩阵或底层图形对象操纵像素颜色通道。
本文讲几个常见滤镜效果:
- 复古灰度
- 反色
- 饱和度增强
- 美白
同时解析 colorFilter 的两种使用方式:4×5 RGBA 转换矩阵和颜色滤波器。
二、实现原理:RGBA 通道线性变换
colorFilter 本质是对像素 RGBA 通道做线性变换,在渲染管线的片元着色阶段执行,最终影响渲染输出颜色。
ArkUI 提供两种方式实现这种变换:
- 4×5 颜色矩阵(用 number[] 数组传入)
- 颜色滤波器(用 BlendMode 混合模式)
4×5 颜色矩阵详解
颜色矩阵是业界通用方法,通过 colorFilter 传入 4×5 的 RGBA 转换矩阵。数学原理上这是 4×5 二维矩阵,但在 ArkTS 里要按行优先展开,封装成 20 个数值的一维数组。
前 5 个元素对应第一行(R 通道变换),接下来 5 个对应第二行(G 通道变换),以此类推。
颜色转换公式:

其中:
- R, G, B, A:原始像素分量,取值 [0,255]
- R’, G’, B’, A’:变换后颜色分量
- mxy:颜色通道间转换系数
- mx4:颜色偏移量(乘 255 得实际偏移值)
矩阵参数详解:
每行决定输出的通道:
- Row 0 → 红色(Red’):R’ = m00_R + m01_G + m02_B + m03_A + m04*255
- Row 1 → 绿色(Green’):G’ = m10_R + m11_G + m12_B + m13_A + m14*255
- Row 2 → 蓝色(Blue’):B’ = m20_R + m21_G + m22_B + m23_A + m24*255
- Row 3 → 透明度(Alpha’):A’ = m30_R + m31_G + m32_B + m33_A + m34*255
对角线元素(m00, m11, m22, m33):控制对应通道缩放
- 等于 1:保持原色
- 大于 1:增强该通道
- 小于 1:减弱该通道
- 等于 0:完全移除该通道
比如 m00 控制红色通道:
- m00 = 0:移除红色(图片变蓝绿)
- m00 = 0.5:减弱红色
- m00 = 1:保持原色
- m00 = 2:红色加倍
非对角线元素:控制通道混合,实现色相偏移、去色等
- 正值:增加其他通道对当前通道贡献
- 负值:反向混合
比如黑白胶片滤镜,RGB 三通道用相同权重系数(0.213, 0.715, 0.072),这是 BT.709 标准的灰度转换系数,把 RGB 混合消除色相只保留亮度。
第 5 列元素(mx4):控制色彩偏移,整体提亮、压暗、色调偏移
- 范围 [0,1],实际偏移 = 该值 × 255
- 比如 0.1 表示增加 25.5 亮度值
颜色滤波器(API 12+)
从 API 12 起,ArkUI 开放 @ohos.graphics.drawing 模块的颜色滤波器(DrawingColorFilter)。这方式更高级、语义化、简便。
接口:createBlendModeColorFilter(color: common2D.Color | number, mode: BlendMode) : ColorFilter
参数:
- color:目标颜色(ARGB 格式)
- mode:混合模式算法
BlendMode.SRC_IN:改变图标颜色(保留透明度)BlendMode.DST_OVER:在图片下方绘制背景色BlendMode.MODULATE:颜色相乘,使图片变暗或着色BlendMode.PLUS:颜色叠加,提亮效果
两种方式对比:
| 对比维度 | 颜色矩阵 | 颜色滤波器 |
|---|---|---|
| 核心原理 | 4×5矩阵线性变换像素RGB/Alpha值 | 源图与目标图按混合规则融合 |
| 使用场景 | 精细参数控制(亮度、饱和度等),灵活可控 | 简单UI染色、叠加、蒙版等 |
三、滤镜实现
原图显示:单位矩阵
滤镜列表第一个选项是"原图",用单位矩阵实现:
/**
* Original color matrix
*/
export const ORIGINAL_MATRIX: number[] = [
1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0
];
这是标准单位矩阵,不改变任何 RGBA 值,保持原图效果或重置。

复古灰度滤镜
/**
* Retro/Vintage matrix
*/
const RETRO_COLOR_MATRIX: number[] = [
0.213, 0.715, 0.072, 0, 0, // R' = Sepia calculation for Red
0.213, 0.715, 0.072, 0, 0, // G' = Sepia calculation for Green
0.213, 0.715, 0.072, 0, 0, // B' = Sepia calculation for Blue
0, 0, 0, 1, 0 // Alpha unchanged
];
RGB 三通道用相同权重系数(0.213, 0.715, 0.072),这是 ITU-R BT.709 标准的亮度计算公式:


灰度图特点是每个像素的 R、G、B 值相等。通过转换矩阵使 R’ = G’ = B’,图片失去色相只保留亮度。
实际计算举例:
假设原始 RGBA 为 (255, 255, 0, 255),即黄色:
- R’ = 0.213×255 + 0.715×255 + 0.072×0 = 236.64
- G’ = 0.213×255 + 0.715×255 + 0.072×0 = 236.64
- B’ = 0.213×255 + 0.715×255 + 0.072×0 = 236.64
- A’ = 255
转换后变成 (237, 237, 237, 255),灰色。
反色滤镜
/**
* Invert/Reverse color matrix
*/
const REVERSE_COLOR_MATRIX: number[] = [
-1, 0, 0, 0, 1, // R' = -1*R + 255
0, -1, 0, 0, 1, // G' = -1*G + 255
0, 0, -1, 0, 1, // B' = -1*B + 255
0, 0, 0, 1, 0 // Alpha unchanged
];
原理:
- 每个颜色通道系数为 -1,实现颜色取反
- 第 5 列偏移量为 1(即 255),补偿负值使结果在 [0,255] 范围内
- 数学公式:新颜色 = 255 - 原颜色
比如原色 (100, 150, 200) 反色后变成 (155, 105, 55)。

饱和度增强滤镜
/**
* Saturation Enhancement matrix (Approx 1.8x saturation)
*/
const ENHANCE_COLOR_MATRIX: number[] = [
1.63, -0.5723, -0.0577, 0, 0, // R' = High weight Red
-0.17, 1.2277, -0.0577, 0, 0, // G' = High weight Green
-0.17, -0.5723, 1.7423, 0, 0, // B' = High weight Blue
0, 0, 0, 1, 0 // Alpha unchanged
];
原理:
- 对角线元素增大(1.63, 1.2277, 1.7423),增强各通道颜色强度
- 非对角线负值减少其他通道干扰,使颜色更纯净
- 整体饱和度提升约 1.8 倍,色彩更鲜艳
基于线性插值原理,在"灰度图像"与"原图"间加权混合:
- S ≈ 1.8,提升饱和度约 80%
- Gray 表示像素亮度值(BT.709 标准)

美白滤镜(颜色滤波器)
美白效果用颜色滤波器实现:
/**
* Whitening color configurations
*/
const WHITENING_COLOR_CONFIG: common2D.Color = {
alpha: 30, // Low opacity for the blend (≈12%)
red: 255,
green: 255,
blue: 255
};
/**
* Creates a color filter for whitening effect
*/
const WHITENING_COLOR_FILTER =
drawing.ColorFilter.createBlendModeColorFilter(WHITENING_COLOR_CONFIG, drawing.BlendMode.PLUS);
原理:
- 用
createBlendModeColorFilter创建混合模式滤镜 - 颜色配置为低透明度白色(alpha = 30,约 12%)
- 采用
BlendMode.PLUS混合模式,将白色叠加到原图 - 整体提亮,肤色显白皙,保留细节

四、开发步骤
步骤一:定义滤镜数据结构
/**
* Interface definition for Filter Options
*/
export interface FilterOption {
label: string; // Display text for the UI
value: string; // Unique identifier for logic
filter: ColorFilter | number[]; // The actual Matrix or Drawing Object
}
步骤二:初始化滤镜配置
/**
* List of available filter options
*/
export const FILTER_OPTIONS: FilterOption[] = [
{ label: 'Original', value: 'original', filter: ORIGINAL_MATRIX },
{ label: 'Retro', value: 'retro', filter: RETRO_COLOR_MATRIX },
{ label: 'Invert', value: 'invert', filter: REVERSE_COLOR_MATRIX },
{ label: 'Enhance', value: 'enhance', filter: ENHANCE_COLOR_MATRIX },
{ label: 'Whiten', value: 'whitening', filter: WHITENING_COLOR_FILTER }
];
步骤三:初始化滤镜状态
aboutToAppear(): void {
// Initialize all images to 'original' filter
this.imageFilterTags = new Array<string>(CAROUSEL_DATA_SOURCE.length).fill('original');
}
步骤四:应用滤镜
在 Image 组件用 colorFilter 属性:
Image(imgRes)
.width('100%')
.height('100%')
.objectFit(ImageFit.Contain)
.borderRadius(16)
.colorFilter(this.getFilterByTag(this.imageFilterTags[index]))
辅助方法获取滤镜对象:
// Helper: Retrieves the actual filter object based on the tag string
private getFilterByTag(tag: string): ColorFilter | number[] {
const option = FILTER_OPTIONS.find(opt => opt.value === tag);
return option ? option.filter : ORIGINAL_MATRIX;
}
五、踩坑总结
坑一:SVG 图片 colorFilter 不生效
PNG、JPG 正常,SVG 不起作用。
原因:API 版本及 SVG 内部结构有关
- API 11 及之前:SVG 不支持 colorFilter
- API 12+:支持 DrawingColorFilter,但只在 SVG 设置 stroke 属性时生效
- API 21+:当
supportSvg2(true)时,colorFilter 才对整个 SVG 起作用
解决:低版本把 SVG 转 PNG 或 PixelMap 再应用 colorFilter,或用 fillColor 属性(单色图标)。
坑二:colorFilter 和 renderMode 混用失效
设置 renderMode: ImageRenderMode.Template 把图标染黑色,后来加了 colorFilter,Template 效果消失。
原因:系统规格指出:设置 colorFilter 时,renderMode 不生效。
解决:不要混用。要染色直接用 colorFilter 模拟 Template 模式(忽略原图像素颜色,只保留 Alpha 通道)。比如染红色:
[
0, 0, 0, 0, 1, // Max out red channel (Offset)
0, 0, 0, 0, 0, // Zero out green channel
0, 0, 0, 0, 0, // Zero out blue channel
0, 0, 0, 1, 0 // Preserve original alpha channel
]
六、使用建议
- 精细参数控制(亮度、饱和度)→ 用颜色矩阵
- 简单染色、叠加、蒙版 → 用颜色滤波器
- 需要动态调整效果 → 颜色矩阵更灵活
- 固定效果一键应用 → 颜色滤波器更简单
记住:颜色矩阵是 number[] 数组,20 个元素。颜色滤波器是 DrawingColorFilter 对象,用 BlendMode 创建。两者不混用。
更多推荐

所有评论(0)