[转] 使用ColorMatrixFilter与ConvolutionFilter来做视觉效果

Manipulate Visual Effects With the ColorMatrixFilter and ConvolutionFilter

原英文页面: Manipulate Visual Effects With the ColorMatrixFilter and ConvolutionFilter  原英文作者: Martin Christov

原翻译页面: http://bbs.9ria.com/viewthread.php?tid=47853                                            原翻译作者: eko

Demo源代码下载,  EffectsTester Demo:

ColorMatrixFilter与ConvolutionFilter能够被用来改变Flash中显示对象的视觉效果。在这篇文章中,我将会用一个很酷的例子来告诉你它们是多么容易操作。


简介

你使用过flash的ColorMatrixFilter 和 ConvolutionFilter 吗?我在挖掘一些有趣的Flash功能,然后我发现用它们可以实现一些有趣的效果。我写了一个上面的 EffectsTester 可以更方便的进行实验。

现在,如果你觉得很有趣,那么让我来告诉你有关它们的一切。


ColorMatrixFilter

ColorMatrixFilter是用来操纵先是对象的颜色的。让我来解释ColorMatrixFilter是如何进行精确的计算的。图像中的每个像素都是一个红绿蓝混合体。这些原色能够混合成任何颜色。

红色的数值范围在0-255。绿色和蓝色也一样。所以在上面那张图你能够看出,纯黄是由255的红与255的绿构成。白色由255的红绿蓝构成。而黑色则是0的红绿蓝。color matrixFilter关注源图中的每个像素,并且通过改变像素中红蓝绿的数值来改变图像。从而你能获得一个全新的图像。


来看看它怎么工作的

首先,我们关注一下三原色的值。(用a[20]表示这个5x4的矩阵)

让我们依次标注a[0], a[1], a[2]的值。现在想象源图上的1个像素。
红色数值为srcR,绿色数值为srcG,还有蓝色的数值为srcB。
现在的问题是:最终图像上像素该有多少红,记为destR?
Flash是这样计算的:
destR = ( a[0] * srcR ) + ( a[1] * srcG ) + ( a[2] * srcB );  
在这里你能看到a[0]为1,a[1],a[2]都是0
destR =  ( 1 * srcR ) + ( 0 * srcG ) + ( 0 * srcB );//这意味着...destR = srcR;没有什么变化。
但是如果我将a[0]变为0而a[1]变为1,那么
destR = ( 0 * srcR ) + ( 1 * srcG ) + ( 0 * srcB );//这意味着...destR = srcG;目标像素上红与绿相等。
此外,如果你将第二行改为“1 0 0”。然后目标像素上的绿将和红一样多。
交换第一行和第二行的数值,你的橘色鱼就会变成绿色。(你可以直接在上面的demo中做验证)

你肯定想知道A列和Offset列代表什么意思。
A表示透明度。A同RGB的效果相同,但由于这些例子图片都不是透明的,所以不好看到效果。
Offset列可以让你简单的增加或者减少像素上的红绿蓝: 在R行的Offset列上输入 -255,你就会看到图像上就没有红色了。


实验

我知道如果只是阅读很难理解,所以,我们来看一些很酷的例子。这样会更有趣,但首先,我们先研究一下Flash中运用的数学公式:

destR = ( a[0]  * srcR ) + ( a[1]  * srcG ) + ( a[2]  * srcB ) + ( a[3]  * srcA ) + a[4];   
destG = ( a[5]  * srcR ) + ( a[6]  * srcG ) + ( a[7]  * srcB ) + ( a[8]  * srcA ) + a[9];   
destB = ( a[10] * srcR ) + ( a[11] * srcG ) + ( a[12] * srcB ) + ( a[13] * srcA ) + a[14];   
destA = ( a[15] * srcR ) + ( a[16] * srcG ) + ( a[17] * srcB ) + ( a[18] * srcA ) + a[19];  

你在5x4的矩阵中看到的每一个值都介于-255到255之间。看看“色表”示例图片:

现在,假设你要从图片中删除所有的红。只需要把所有R行上的值设为0就可以了

这就意味着:

destR = ( 0 * srcR ) + ( 0 * srcG ) + ( 0 * srcB ) + ( 0 * srcA ) + 0;
//==>
destR = 0 + 0 + 0 + 0 + 0;
//==>
destR = 0;

现在让我们假设你想在以前红色的地方添加更多的绿。那么就只要把G行设置为“1 1 0 0 0”

现在让我们把G行设置为“0  -1  0  0  50”,会看到一个很奇怪的效果。

刚才发生了什么?举个例子来说,如果在某些随机像素里,你的绿为30,它乘以-1 后又偏移了50,所以结果将是(30*-1)+50=20;因此,一个创建了阈值:对于每一个绿值大于50的像素将被完全关闭(变黑了)。这是为什么呢?好,让我们假设像素的绿色通道的值为51:

destG = ( 0 * srcR ) + ( -1 * srcG ) + ( 0 * srcB ) + ( 0 * srcA ) + 50;
//记住 srcG = 51:
destG = 0 + (-51) + 0 + 0 + 50;
//所以:
destG = - 51 + 50;
//所以:
destG = -1;
//由于像素的绿不能为负值,所以设0:
destG = 0;

现在,让我们再试试看这个效果

所有绿色大于50的像素都将关闭,并且绿低于50的三色通道都增加了。这样,你就能看到鱼图上只有非常少量的绿了。

在这里,只有那些绿低于50的像素。像素颜色越深,源图上的绿就越多。这些都是基本的原理。我知道初步接触的时候会觉得它很复杂,但是只要多加练习你就能掌握它。


灰度

好了,让我们搞一张灰度图来玩玩。依照下图设置你的矩阵:

你就会得到一个灰度图,奶丝(nice)~

反色

让我们来实现另外一个很常见的颜色状态:反色。
将颜色颠倒,每个像素中255的红改为0,反之亦然。其它两个颜色也这么操作。因此,我们需要Flash运行下面的代码:

destR = 255 - srcR;   
destG = 255 - srcG;   
destB = 255 - srcB; 

这太容易了,我们所要做的就是这样设置矩阵:

太好了,电鱼:

更多的效果

通过ColorMatrixFilter你可以实现更多的效果,只需要将颜色的值与偏移量设置为负数 -- 或者相反。将0x3列与2x3列(透明度)设为-1,并且将4x3偏移量设为255。哇哦,我现在指导他们怎么弄终结者2的了。
老实说,我不知道我在做什么 -- 跟踪一段时间后就会变得很难。虽然可以从数学的角度来理解ColorMatrixFilter,但是你永远也无法确切的知道你设置的值会有什么效果。这就是我做EffectsTester的原因。因此,玩吧。创造你自己的金属绿,或者红色,或者无色。

真实世界的应用

当你有喜欢的效果的时候,你可以应用到任何的显示对象上(MovieClip,Sprite,Bitmap……),代码如下:

//首先导入ColorMatrixFilter类
import flash.filters.ColorMatrixFilter;

//...接着:
var filters:Array = new Array();
//在实例化后,从 EffectsTester中复制和粘贴出数据:
var cmf:ColorMatrixFilter = new ColorMatrixFilter(new Array(-1,0,0,0,255,0,-1,0,0,255,0,0,-1,0,255,0,0,0,1,0));
//接下来两行就是把滤镜应用到你的显示对象上。:
filters.push( cmf );
myDisplayObject.filters = filters;

接下来看看convolution filter

Adobe官方类参考 中这么说:

“ConvolutionFilter 类应用矩阵盘绕滤镜效果。卷积将输入图像的像素与相邻的像素合并以生成图像。通过卷积,可以实现大量的图像效果,包括模糊、边缘检测、锐化、浮雕和斜角。您可以将滤镜应用于任何显示对象(即,从 DisplayObject 类继承的对象),例如 MovieClip、SimpleButton、TextField 和 Video 对象,以及 BitmapData 对象。”

ConvolutionFilter会遍历显示对象所有像素。每个像素,都会使用矩阵的中心值。例如,在一个3x3的矩阵中。中心值就在(1,1)。然后乘以周围像素的值。然后为所有的点增加中心值。要精确理解下面的Convolution matrix需要写一篇全新的文章,所以在这里我不会涵盖方方面面。如果你想深入了解它,可以看看这篇文章。然而,通过简单的改变一些值就会你最终就会创造特殊效果。这将是非常有趣的,所以让我们来看看我们能做什么。

实验

convolution filter使用一个矩阵,就像color matrix filter一样。同样,数值在-255到255之间。再次,正负相调能实现非常有趣的效果。我想和大家分享一下我理解的工作原理。尝试给矩阵设置一些随机值。无论你怎么选择都能使图片变亮;如果你想图片保持正常的亮度,确保“除数”的值等于矩阵中所有值的总和。现在如果你尝试一个低于0的随机数,那就要同时保持至少一个大于0的值。你就能看到产生什么效果了。它会影响你的边缘。

这里有另一个奶丝(nice)的效果:看上去象个士兵?尝试如下的参数:

现在,降低“除数(divisor)”值为-1,效果像个黑夜中执行任务的士兵。只要你用鼠标点点增加减少按钮,你就能实现很多效果。不要忘记调整“除数” -- 这是至关重要的。放大你的矩阵,例如5x5,再继续尝试吧。

真实世界的应用

在你的代码中应用这个效果,使用filters对象,就像你在ColormatrixFilter中那样用。

//导入 ConvolutionFilter:
import flash.filters.ConvolutionFilter;

//..接着:
var filters:Array = new Array();
//在所有的东西都实例化后.复制和粘贴EffectsTester上的值:
var cf:ConvolutionFilter = new ConvolutionFilter(3,3,new Array(1,0,-10,-2,3,1,6,1,-1),0);
//下面两行将滤镜应用到你的显示对象上:
filters.push( cf );
myDisplayObject.filters = filters;

最后,同时运用这两个滤镜

//导入类: 
import flash.filters.ColorMatrixFilter;
import flash.filters.ConvolutionFilter;

//... 接着:
var filters:Array = new Array();
//在所有东西实例化后,复制粘贴EffectsTester上的值:
var cmf:ColorMatrixFilter = new ColorMatrixFilter(new Array(-1,0,0,0,255,0,-1,0,0,255,0,0,-1,0,255,0,0,0,1,0));
var cf:ConvolutionFilter = new ConvolutionFilter(3,3,new Array(1,0,-10,-2,3,1,6,1,-1),0);

//接下来的三行就是将滤镜数应用到显示对象上。
filters.push( cf );
filters.push( cmf );
myDisplayObject.filters = filters;

祝你玩的愉快,感谢阅读

smithfox | Sunday 16 January 2011 at 10:58 am | | UI        | Used tags: , , , ,

One comment

LV Wallet Cases For iPhone 6

Another rumour circulating the web is that the iPhone 7 will come with a new iPhone charger, with a Lightning connector on one end and a new reversible USB connector on the other end.

LV Wallet Cases For iPhone 6, (URL) - 04-06-’15 15:07
(optional field)
(optional field)
为阻止垃圾广告, 请在提交评论前, 回答一个简单问题(Please answer an simple question)
Remember personal info?
Notify
Small print: All html tags except <b> and <i> will be removed from your comment. You can make links by just typing the url or mail-address.