给灭霸点颜色看看

·  阅读 9913
给灭霸点颜色看看

前言

继续我们 Flutter 绘图相关的介绍,本篇我们引入一位重量级主角 —— 灭霸。通过绘图的颜色过滤器,我们要给灭霸点颜色看看。通过本篇,你会了解到如下内容:

  • ColorFilter 颜色过滤器的介绍;
  • 彩色图片转换为灰度图;
  • 通过矩阵运算构建自定义的颜色过滤器。

ColorFilter 颜色过滤器

其实我们之前在给小姐姐的照片调个颜色滤镜有介绍过颜色滤镜,在 Flutter 中提供了一个 ColorFiltered 的组件,可以将颜色过滤器应用到其子组件上。实际上,颜色过滤器就是对一个图层的每个像素的颜色(包括透明度)进行数学运算,改变像素的颜色来实现特定的效果。数学公式如下:

颜色变换矩阵

在 Flutter 中,ColorFilter 类的继承自 ImageFilter,像 ImageFilter 一样,也只提供了命名构造函数,一共有四个命名构造函数,分别如下:

  • ColorFilter.mode(Color color, BlendMode mode):按制定的混合模式(blend mode),将颜色混入到绘制的目标中。可以理解为图像的色值调整,我们可以用一个指定的颜色调整原图,调整的模式有很多种,具体可以查看 BlendMode 枚举。
  • ColorFilter.linearToSrgbGamma():将一个 SRGB 的 gamma 曲线应用到 RGB 颜色通道中。
  • ColorFilter.srgbToLinearGamma()ColorFilter.linearToSrgbGamma()的反向过程。
  • ColorFilter.matrix(List<double> matrix):应用一个矩阵做颜色变换,也就是我们上面说的矩阵,这是最通用的版本,要什么效果可以自己构建对应的矩阵。

这里说一下 SRGB 的 gamma 曲线的用途。我们人眼在显示屏中对图片进行调色等操作时,是按照线性空间的角度进行的,但显示器是在gamma空间中的,那么图像在计算机中的存储一般都应该是在 gamma 空间下了。也就是计算机存储的是非线性的,但是给我们展示的时候要转为线性的。因此,对于一张图像,可能是线性的也可能是 gamma 空间的,这个时候为了统一可能就需要进行转换,那就会用到linearToSrgbGammasrgbToLinearGamma两个颜色过滤器。

彩色图片转成灰色图片

彩色图片转变为灰色图片有2种方法,最简单的方法是使用ColorFilter.mode,第一个参数颜色选择灰色或黑色,然后 第二个参数选择 BlendMode.color 或者接近的效果(比如 huesaturation)。BlendMode.color 是取源图的色调和饱和度,然后取目标(即要改变的图片)的亮度。因此,如果我们想更改一张图片的色调,用这种方式最好了。下面是对应的实现代码和变换前后的对比图。

var paint = Paint();
paint.colorFilter = ColorFilter.mode(Colors.grey, BlendMode.color);

canvas.drawImageRect(
  bgImage,
  Rect.fromLTRB(0, 0, bgImage.width.toDouble(), bgImage.height.toDouble()),
  Offset.zero & size,
  paint,
);
复制代码

灰度图.jpg 使用ColorFilter.mode另一个用途就是简单的“修图”了,比如我们可以将一张蓝天白云图修成夕阳西下的效果。

夕阳效果.jpg

当然,转换为灰度图我们也可以通过矩阵实现。

矩阵运算改变颜色

如果要想任意调换颜色,那么使用矩阵运算更合适。在 Flutter 中,ColorFilter.matrix 多增加了一行,这一行主要是在构建一些特殊的矩阵运算更方便,比如反转色的时候。

Matrix 构建公式

比如我们要让变换后的图像实现反转:

  • 红色色值=255-原红色色值
  • 绿色色值=255-原绿色色值
  • 蓝色色值=255-原蓝色色值

那么构建如下矩阵就可以了。

反转色变换矩阵

由于最后一行数值对实际变化没影响,因此实际构建 ColorFilter.matrix 的时候,只需要传入20个参数就可以了。下面是应用了反转效果后的灭霸图,灭霸看起来像一个雕塑了。

下面我们先来看一下使用矩阵实现彩色图变灰度图,用下面的矩阵就能实现,最终得到变换后的 R、G、B值是相等的,而且三个色值的系数相加等于1(保证数值不会超出255)。这个矩阵是官方提供的,实际上也是经过图像学研究推导得到的。

灰度变换公式

对应灰度变换的 ColorFilter 的构造代码如下:

const greyScale = ColorFilter.matrix(<double>[
  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,
]);
复制代码

最后,我们来看看颜色循环变换的效果,颜色循环变换就是红色部分变为原先像素的绿色值,绿色部分变到原先像素的蓝色值,然后蓝色部分变到原先像素的红色值,对应的 ColorFilter 构造代码如下:

var colorRotation = ColorFilter.matrix(<double>[
  0, 1, 0, 0, 0,
  0, 0, 1, 0, 0,
  1, 0, 0, 0, 0,
  0, 0, 0, 1, 0
]);
复制代码

有了这个我们其实就可以做一些动效了,比如我们把变化过程由动画值控制,得到下面的矩阵。

var colorRotation = ColorFilter.matrix(<double>[
  animationValue, 1-animationValue, 0, 0, 0,
  0, animationValue, 1-animationValue, 0, 0,
  1-animationValue, 0, animationValue, 0, 0,
  0, 0, 0, 1, 0
]);
复制代码

我们看看灭霸图片颜色变化的动画效果,整个画面的色调在不断的变化,感觉像灭霸要开始“打响指”了。

颜色变化动画.gif

ColorFilter 的应用

ColorFilter 的最佳应用场景应该是图片滤镜,我们在图片类应用经常会看到各种滤镜效果(取得名字都很好听,比如什么“清纯”、“蓝调”,“怀旧”等等),实际上这种效果就是将一个颜色预置的变换矩阵应用到图片上。

总结

本篇介绍了颜色过滤器 ColorFilter 的应用以及原理,我们绘图的时候可以使用 ColorFilter 处理图片,实现类似滤镜的效果。如果考虑简单使用,也可以直接使用 ColorFiltered 组件。


本篇源码已上传至:绘图相关源码,文件名为:color_filter_demo.dart

我是岛上码农,微信公众号同名,这是Flutter 入门与实战的专栏文章,提供体系化的 Flutter 学习文章。对应源码请看这里:Flutter 入门与实战专栏源码。如有问题可以加本人微信交流,微信号:island-coder

👍🏻:觉得有收获请点个赞鼓励一下!

🌟:收藏文章,方便回看哦!

💬:评论交流,互相进步!

我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿

分类:
Android
收藏成功!
已添加到「」, 点击更改