AS3中置换滤镜的理解

ActionScription中,DisplacementMapFilter是一个非常强大的滤镜,很多的特效,比如火焰,波纹等都会使用到它。另一方面,它也比较多变,让初学者难以掌握它的功能。下面的分析从AS3中使用的公式开始。

Adobe的官方文档中,提到DisplacementMapFilter使用如下的公式:

dstPixel[x, y] = srcPixel[x + ((componentX(x, y) - 128) * scaleX) / 256, y + ((componentY(x, y) - 128) * scaleY) / 256)]

我们先来理解该公式。

这里面涉及到三个像素,源图上的srcPixel,置换图上的componentXcomponentY以及最后生成的目标图上的dstPixel。为了便于理解,我们把上面的公式变化一下:

dstPixel[x, y] = srcPixel[(x + X), (y + Y)]
X = (componentX(x, y) - 128) * scaleX) / 256
Y = (componentY(x, y) - 128) * scaleY) / 256

有上面的公式就可能很容易的看出来,,目标像素dstPixel[x, y] 就是源像素srcPixel[x, y]分别在x方向上偏移X距离,y方向上偏移Y距离后的一个结果。

所以DisplacementMapFilter的根本效果就是像素的偏移!

那么像素的偏移如何可以创造出那么绚烂的效果呢?很简单,就是对偏移量的控制。很容易想象一张正常的图片,上面的每个像素经过不同距离的偏移之后,它会产生的扭曲、挤压的效果。结合其他的滤镜,就可以创建很酷的效果。

我们回到偏移量的公式:

X = (componentX(x, y) - 128) * scaleX) / 256
Y = (componentY(x, y) - 128) * scaleY) / 256

里面有四个变数:置换图的像素 componentXcomponentY 以及scaleXscaleY。变数越多,结果就越难以琢磨。这也是置换滤镜的困难所在。

我们来深入看一下这个公式每一个量(变量和常量)的含义。

先看componentXcomponentY的含义。

我们知道一个像素有四个通道:3个颜色通道RGB和1个Alpha通道。componentXcomponentY在这里表示一个像素的颜色通道。因此,componentX(x, y)componentY表示置换图上位置为(x, y)的像素点的指定颜色通道的值。颜色通道的设置可以通过构造函数来指定,并且源像素srcPixel(x, y)xy方向的偏移量可以由componentX(x, y)componentY(x, y)分别指定。scaleXscaleY作用类似,不必再提。

举个例子,比如置换图上(x, y)的点RGB值为0xaabbcc。现在指定 x 方向上的颜色通道为红色,y 方向上的颜色通道为绿色。componentX(x, y)的值就是0xaacomponentY(x, y)的值就是0xbb。其他值忽略。

再看常量128。这里不说为什么要减128,只看减了128之后是什么。

我们知道一个颜色通道的范围为 0 ~ 255, (componentX(x, y) - 128)的结果为 (-128, 127),其效果就是这个指定的颜色通道的值的范围只有 0 ~ 127,但是它有方向。看偏移量的公式,这个方向也是最后偏移量的方向,这个很好理解,就不再赘述。

最后我们看256以及scaleXscaleY。我们再把偏移量公式稍微变化一下:

X = ((componentX(x, y) - 128) / 256) * scaleX
Y = ((componentY(x, y) - 128) / 256) * scaleY

上面我们知道,(componentX(x, y) - 128)的值为 -128 ~ 127,除以256之后就是±(0, 0.5),这可以看成是scale的一个系数。

整个偏移量的含义就比较明显了:scale的值缩小若干倍就是偏移量

至此,置换滤镜的含义就可以总结为:

  • 用置换图上某个位置的像素的某个颜色通道值控制缩放比例,得到一个偏移量;
  • 用该偏移量对源图上对应的像素进行偏移,得到目标图上对应位置的像素值。

说白了就是 用置换图上的像素控制源图上的像素进行偏移

虽然上面的结论比较拗口,但还不是DisplacementMapFilter提供的功能的全部。我们看一下它的构造函数:

DisplacementMapFilter(
mapBitmap:[BitmapData](../../flash/display/BitmapData.html) = null,
mapPoint:[Point](../../flash/geom/Point.html) = null,
componentX:[uint](../../uint.html) = 0,
componentY:[uint](../../uint.html) = 0,
scaleX:[Number](../../Number.html) = 0.0,
scaleY:[Number](../../Number.html) = 0.0,
mode:[String](../../String.html) = "wrap",
color:[uint](../../uint.html) = 0,
alpha:[Number](../../Number.html) = 0.0
)

其中mapPoint, mode, coloralpha我们并没有讨论。好在他们的含义并不难以理解,不提。