github地址
本文主要介绍 colorMatrixFilter.js
* filter.js //主文件
* preloadImage.js //图片加载处理
* colorMatrixFilter.js //颜色矩阵滤镜
* convolutionMatrixFilter.js //卷积矩阵滤镜
colorMatrixFilter.js
颜色矩阵滤镜原理介绍
学习参考
as 颜色矩阵滤镜使用示例
as 颜色矩阵滤镜API
blog 里面有很多示例
矩阵乘法的原理介绍
CSDN博客-颜色空间总结 RGB、HSV、YUV
百度百科-色彩空间
知乎-色彩空间与色彩模型的本质区别是什么
用一句话介绍就是:把位图中的每一个颜色值与一个4行5列的多维矩阵(20个元素的数组)相乘,得出新图像的颜色数据。即公式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| RGBA = [ R, G, B, A ] matrix =[ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0 ] 新的颜色信息 = RGBA * matrix = [ matrix[0]*R + matrix[1]*G + matrix[2]*B + matrix[3]*A + matrix[4] // R通道 matrix[5]*R + matrix[6]*G + matrix[7]*B + matrix[8]*A + matrix[9] // G通道 matrix[10]*R + matrix[11]*G + matrix[12]*B + matrix[13]*A + matrix[14] // B通道 matrix[15]*R + matrix[16]*G + matrix[17]*B + matrix[18]*A + matrix[19] // A通道 ]
|
举例说明:如果想要一个值为 rgba(200, 100, 50, 1 ) 的颜色,只保留红色通道的色彩。我们只需要调整 matrix 并做如下运算:
1 2 3 4 5 6 7 8 9
| [ 200, 100, 50, 1 ] * [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 ] = [ 1*200 + 0*100 + 0*50 + 0*1 + 0, 0*200 + 0*100 + 0*50 + 0*1 +0, 0*200 + 0*100 + 0*50 + 0*1 +0, 0*200 + 0*100 + 0*50 + 1*1 +0, ] = [ 200, 0, 0, 1 ]
|
如果我们想对颜色应用多个滤镜,比如我们想要在得到红色通道的基础上,再把颜色亮度 +10,那么我们可以这样:
1 2 3 4 5 6 7 8
| [ 200, 100, 50, 1 ] * [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 ] * [ 1, 0, 0, 0, 10, 0, 1, 0, 0, 10, 0, 0, 1, 0, 10, 0, 0, 0, 1, 0 ]
|
这里有个小技巧,在实际应用中,图片的颜色信息肯定要多很多。在一张100px×100px大小的图片上就有10000个像素点。在每个像素点跟矩阵做乘法运算的时候,这个运算量是很大。上面的计算是从左至右运算的,我们需要遍历图片所有的像素点至少两次,也就是说一共要计算2×10000次。还好矩阵乘法是适用结合律的,也就是说我们可以这样:
1 2 3 4 5 6 7 8
| [ 200, 100, 50, 1 ] * ([ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 ] * [ 1, 0, 0, 0, 10, 0, 1, 0, 0, 10, 0, 0, 1, 0, 10, 0, 0, 0, 1, 0 ])
|
先算后面的乘积,再把他去跟图片信息相乘,这样运算效率会提高很多。关于多维矩阵之间的乘法可以参考上面提到到的矩阵乘法的原理介绍。
创建colorMatrixFilter对象
假如我们想要获取图片的红色通道:
1 2 3 4
| var F = new FILTER.Create(imgEle); var cmf = new FILTER.ColorMatrixFilter(); cmf.redChannel(); cmf.apply(F.imgData);
|
FILTER.ColorMatrixFilter 的实例 cmf 带有一个 matrix 的属性,这里保存了4行5列的多维矩阵(20个元素的数组)。
matrix 的属性的默认值为:
[ 1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0 ]
然后通过 redChannel() 方法来得到一个红色通道的矩阵滤镜,此时 matrix 的属性值变为:
[ 1, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 1, 0 ]
最后通过 cmf.apply(F.imgData) 把滤镜应用到 imgData 上。
另外在实例化ColorMatrixFilter时,可以指定matrix的值:
1 2 3 4 5 6 7 8 9
| var matrix = []; matrix=matrix.concat([1, 0, 0, 0, 0]); matrix=matrix.concat([0, 0, 0, 0, 0]); matrix=matrix.concat([0, 0, 0, 0, 0]); matrix=matrix.concat([0, 0, 0, 1, 0]); var F = new FILTER.Create(imgEle); var cmf = new FILTER.ColorMatrixFilter(matrix); cmf.apply(F.imgData);
|
以上代码的cmf同样是一个红色通道的矩阵滤镜
colorMatrixFilter methods
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| cmf.add(matrix) cmf.reset() cmf.clear() cmf.clone() cmf.apply(imgData) cmf.CMconcat(mat1,mat2)
cmf.redChannel(asGray);
cmf.reviseGreen(1.5,10);
cmf.desaturate();
cmf.average(1,0,0);
cmf.brightness(80,50);
cmf.colorize(0xff9900,.5);
cmf.invert(); cmf.invertRed(); cmf.invertGreen(); cmf.invertBlue(); cmf.invertAlpha();
cmf.saturate(0.2);
cmf.contrast(2);
cmf.quickContrastCorrection();
cmf.adjustHue(180);
cmf.sepia(1);
cmf.sepia2(1);
cmf.threshold(125,66);
cmf.threshold_rgb(125,66);
cmf.RGB2YCbCr();
cmf.YCbCr2RGB();
cmf.swapChannels(0,1);
|
其中的 RGB2YCbCr 与 YCbCr2RGB 是色彩空间YUV和RGB的相互转换。
最后来看一下效果: