鸿蒙开发-想给图片加特效?ColorFilter和ImageFilter怎么用
想给画面加滤镜ColorFilter 和 ImageFilter 怎么用上一篇我们提到了 Brush 和 Pen 可以设置setColorFilter和setImageFilter但没有展开讲。今天我们专门来看看这两个滤波器能做什么。ColorFilter 和 ImageFilter 的关系和定位如下绘制时的滤波器ColorFilter: 颜色变换ImageFilter: 图像变换混合模式滤波颜色矩阵滤波色彩空间转换组合滤波器模糊效果偏移效果图片叠加从 ColorFilter 创建ColorFilter颜色变换器ColorFilter 的作用是变换颜色。不管你在画布上画了什么颜色经过 ColorFilter 处理后输出的颜色会发生变化。打个比方你用红色的笔画画但 ColorFilter 把所有红色都变成了蓝色——这就是颜色滤波。创建方式一混合模式颜色滤波器import{common2D,drawing}fromkit.ArkGraphics2D;constcolor:common2D.Color{alpha:255,red:255,green:0,blue:0};letcolorFilterdrawing.ColorFilter.createBlendModeColorFilter(color,drawing.BlendMode.SRC);这个方法创建一个用指定颜色和混合模式来变换的滤波器。它把你的绘制颜色和指定的颜色按混合模式混合。比如BlendMode.SRC意思是只用源色——如果你传入红色那所有绘制内容都会变成红色。如果你想做色调叠加效果可以用MULTIPLY或SCREEN等混合模式。从 API 18 开始color参数也支持直接传数字letcolorFilterdrawing.ColorFilter.createBlendModeColorFilter(0xFFFF0000,drawing.BlendMode.SRC);创建方式二颜色矩阵滤波器这个是真正的自定义颜色变换利器// 灰度矩阵letmatrix[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];letcolorFilterdrawing.ColorFilter.createMatrixColorFilter(matrix);这是一个 4x5 的矩阵长度为 20 的数组和 effectKit 里的setColorMatrix原理一样。每一行对应一个输出通道R、G、B、A每一列对应一个输入通道R、G、B、A、常量偏移。几个常用的矩阵灰度和上面一样[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]反色[-1,0,0,0,1,0,-1,0,0,1,0,0,-1,0,1,0,0,0,1,0]增强红色把红色通道的权重加大[1.5,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0]降低饱和度向灰度靠拢letsat0.5;// 0完全灰度, 1原始[0.21260.7874*sat,0.7152-0.7152*sat,0.0722-0.0722*sat,0,0,0.2126-0.2126*sat,0.71520.2848*sat,0.0722-0.0722*sat,0,0,0.2126-0.2126*sat,0.7152-0.7152*sat,0.07220.9278*sat,0,0,0,0,0,1,0]创建方式三色彩空间转换// sRGB gamma 转线性letcolorFilterdrawing.ColorFilter.createSRGBGammaToLinear();// 线性转 sRGB gammaletcolorFilterdrawing.ColorFilter.createLinearToSRGBGamma();这两个是色彩空间转换用的一般在做颜色精确计算时使用。如果你不做色彩管理可能用不到。创建方式四组合滤波器你可以把两个 ColorFilter 组合成一个letouterdrawing.ColorFilter.createSRGBGammaToLinear();letinnerdrawing.ColorFilter.createBlendModeColorFilter({alpha:255,red:255,green:0,blue:0},drawing.BlendMode.SRC);letcomposeddrawing.ColorFilter.createComposeColorFilter(outer,inner);组合的顺序是先应用inner再应用outer。就像流水线一样颜色先经过 inner 处理输出的结果再经过 outer 处理。把 ColorFilter 用在 Brush 和 Pen 上constbrushnewdrawing.Brush();brush.setColorFilter(colorFilter);canvas.attachBrush(brush);// 所有用这个 Brush 画的图形都会被 ColorFilter 处理canvas.drawRect(0,0,200,200);canvas.detachBrush();constpennewdrawing.Pen();pen.setColorFilter(colorFilter);canvas.attachPen(pen);// 所有用这个 Pen 画的描边都会被 ColorFilter 处理canvas.drawLine(0,0,200,200);canvas.detachPen();传null可以清除滤波器brush.setColorFilter(null);ImageFilter图像滤波器如果说 ColorFilter 是变换颜色那 ImageFilter 就是变换整个图像。它可以做模糊、偏移、混合等操作作用范围比 ColorFilter 更大。模糊效果最常用的 ImageFilter 就是模糊import{drawing}fromkit.ArkGraphics2D;letimgFilterdrawing.ImageFilter.createBlurImageFilter(5,10,drawing.TileMode.CLAMP);参数说明sigmaXx 方向的高斯模糊标准差必须大于 0sigmaYy 方向的高斯模糊标准差必须大于 0tileMode边缘处理模式CLAMP/REPEAT/MIRROR/DECALsigma 值越大模糊效果越明显。x 和 y 可以设不同的值做出单方向模糊的效果——比如sigmaX10, sigmaY0就是水平方向模糊像运动模糊一样。从 ColorFilter 创建 ImageFilter你可以把 ColorFilter 包装成 ImageFilterletcolorFilterdrawing.ColorFilter.createSRGBGammaToLinear();letimgFilterdrawing.ImageFilter.createFromColorFilter(colorFilter);这样就可以在 Pen 上使用 ColorFilter 了Pen 的setImageFilter接收 ImageFilterletcolorFilterdrawing.ColorFilter.createSRGBGammaToLinear();letimgFilterdrawing.ImageFilter.createFromColorFilter(colorFilter);letpennewdrawing.Pen();pen.setImageFilter(imgFilter);从图片创建 ImageFilterAPI 20letimgFilterdrawing.ImageFilter.createFromImage(pixelMap,srcRect,dstRect);这个方法把一张 PixelMap 变成一个 ImageFilter可以用来做图片叠加效果。srcRect指定图片的哪个区域被使用dstRect指定渲染到画布的哪个位置。偏移效果letoffsetFilterdrawing.ImageFilter.createOffsetImageFilter(10,20,null);把绘制内容向右偏移 10 像素、向下偏移 20 像素。第三个参数是输入的 ImageFilter可以链式叠加null表示直接作用于原始图像。组合 ImageFilterletblurFilterdrawing.ImageFilter.createBlurImageFilter(5,5,drawing.TileMode.CLAMP);letoffsetFilterdrawing.ImageFilter.createOffsetImageFilter(10,10,blurFilter);这样就把模糊和偏移组合在一起了——先模糊再偏移。链式调用很像 effectKit 的 Filter 链。也可以用createComposeImageFilter来组合letcomposeddrawing.ImageFilter.createComposeImageFilter(outerFilter,innerFilter);在 Brush 和 Pen 上使用// Brush 上使用模糊constbrushnewdrawing.Brush();brush.setImageFilter(imgFilter);canvas.attachBrush(brush);canvas.drawRect(0,0,200,200);canvas.detachBrush();// Pen 上使用模糊constpennewdrawing.Pen();pen.setImageFilter(imgFilter);canvas.attachPen(pen);canvas.drawLine(0,0,200,200);canvas.detachPen();传null清除brush.setImageFilter(null);pen.setImageFilter(null);完整示例带模糊效果的卡片来做一张毛玻璃风格的卡片import{RenderNode}fromkit.ArkUI;import{common2D,drawing}fromkit.ArkGraphics2D;classBlurCardRenderNodeextendsRenderNode{draw(context:DrawContext){constcanvascontext.canvas;// 先画一个渐变背景模拟背景图constbgBrushnewdrawing.Brush();constgradientdrawing.ShaderEffect.createLinearGradient({x:0,y:0},{x:400,y:400},[0xFF6200EE,0xFF03DAC6],drawing.TileMode.CLAMP);bgBrush.setShaderEffect(gradient);canvas.attachBrush(bgBrush);canvas.drawRect(0,0,400,400);canvas.detachBrush();// 毛玻璃卡片constblurBrushnewdrawing.Brush();blurBrush.setColor(255,255,255,255);// 白色底blurBrush.setAlpha(80);// 半透明letblurFilterdrawing.ImageFilter.createBlurImageFilter(10,10,drawing.TileMode.CLAMP);blurBrush.setImageFilter(blurFilter);canvas.attachBrush(blurBrush);constroundRectnewdrawing.RoundRect({left:40,top:40,right:360,bottom:200},16,16);canvas.drawRoundRect(roundRect);canvas.detachBrush();}}当两者需要配合使用时可以参考下面的组合流程变换颜色值模糊/偏移等图像效果先调色再加模糊需要对绘制内容加滤镜需求是什么?使用 ColorFilter使用 ImageFilterColorFilter ImageFilter 组合设到 Brush 或 Pen 上设到 Brush 或 Pen 上ColorFilter 调色ImageFilter.createFromColorFilter 包装设到 Pen 上使用ColorFilter vs ImageFilter什么时候用哪个特性ColorFilterImageFilter作用变换颜色值变换整个图像能做模糊不能能能做颜色变换能间接能通过 ColorFilter 包装能做偏移不能能适用场景色调调整、反色、灰度模糊、阴影、图片叠加简单记改颜色用 ColorFilter改形状/效果用 ImageFilter。两者可以组合使用——先用 ColorFilter 调色再用 ImageFilter 加模糊效果叠加。小结ColorFilter颜色变换支持混合模式、颜色矩阵、色彩空间转换可以组合。ImageFilter图像变换支持模糊、偏移、图片叠加可以链式组合。两者都可以设在 Brush 和 Pen 上传null清除。ColorFilter 可以包装成 ImageFiltercreateFromColorFilter反过来不行。下一篇我们来看 Path路径——怎么画直线、曲线、贝塞尔曲线做出各种复杂的形状。