DisplacementMapFilter如何工作?

时间:2012-03-13 21:00:33

标签: actionscript-3 flash flex

我是动作中的初学者。如果我理解正确,DisplacementMapFilter会根据“MAP图像”中相应像素位置的颜色从“源图像”移动像素。

问题是我的目标图像包含不在源图像中的像素!

例如,我使用此BitMapData获取UNICOLOR 10 * 10像素的“源图像”:

sourceBitmap = new BitmapData(BITMAP_WIDTH, BITMAP_HEIGHT, false, 0x000002);

produce:

  0   1   2   3   4   5   6   7   8   9
[002,002,002,002,002,002,002,002,002,002] Row 0
[002,002,002,002,002,002,002,002,002,002] Row 1
[002,002,002,002,002,002,002,002,002,002] Row 2
[002,002,002,002,002,002,002,002,002,002] Row 3
[002,002,002,002,002,002,002,002,002,002] Row 4
[002,002,002,002,002,002,002,002,002,002] Row 5
[002,002,002,002,002,002,002,002,002,002] Row 6
[002,002,002,002,002,002,002,002,002,002] Row 7
[002,002,002,002,002,002,002,002,002,002] Row 8
[002,002,002,002,002,002,002,002,002,002] Row 9

现在,我采用这个BLACK置换MAP并添加一个蓝色方块:

displacementBitmap = new BitmapData(BITMAP_WIDTH,BITMAP_HEIGHT,false,0x000000);
for(i=5;i<10;i++)
    for(j=5;j<10;j++)
        displacementBitmap.setPixel(i,j,255);

produce:

 0   1   2   3   4   5   6   7   8   9 
[000,000,000,000,000,000,000,000,000,000] Row 0
[000,000,000,000,000,000,000,000,000,000] Row 1
[000,000,000,000,000,000,000,000,000,000] Row 2
[000,000,000,000,000,000,000,000,000,000] Row 3
[000,000,000,000,000,000,000,000,000,000] Row 4
[000,000,000,000,000,255,255,255,255,255] Row 5
[000,000,000,000,000,255,255,255,255,255] Row 6
[000,000,000,000,000,255,255,255,255,255] Row 7
[000,000,000,000,000,255,255,255,255,255] Row 8
[000,000,000,000,000,255,255,255,255,255] Row 9

结果:

displacementFilter = new DisplacementMapFilter();
displacementFilter.alpha=0;
displacementFilter.color=0;
displacementFilter.mapPoint=new Point(0,0);
displacementFilter.scaleX=1;
displacementFilter.scaleY=1;
displacementFilter.componentX = flash.display.BitmapDataChannel.BLUE;
displacementFilter.componentY = flash.display.BitmapDataChannel.BLUE;
displacementFilter.mapBitmap = displacementBitmap;

destinationBitmap = new BitmapData(BITMAP_WIDTH,BITMAP_HEIGHT,false,0xFFFFFFFF);
destinationBitmap.applyFilter(
    sourceBitmap.bitmapData,
    new Rectangle(0,0,BITMAP_WIDTH,BITMAP_HEIGHT),
    new Point(0,0),
    displacementFilter
);

produce:        

  0   1   2   3   4   5   6   7   8   9 
[002,002,002,002,002,002,002,002,002,002] Row 0
[002,002,002,002,002,002,002,002,002,002] Row 1
[002,002,002,002,002,002,002,002,002,002] Row 2
[002,002,002,002,002,002,002,002,002,002] Row 3
[002,002,002,002,002,002,002,002,002,002] Row 4
[002,002,002,002,002,001,001,001,001,001] Row 5
[002,002,002,002,002,001,001,001,001,001] Row 6
[002,002,002,002,002,001,001,001,001,001] Row 7
[002,002,002,002,002,001,001,001,001,001] Row 8
[002,002,002,002,002,001,001,001,001,001] Row 9

所以我不明白为什么我的'001'像素在源图像中不存在。

非常感谢你。

1 个答案:

答案 0 :(得分:3)

置换贴图滤镜使用this formula决定从源位图抓取哪个像素:

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

dstPixel是目标位图,srcPixel是源位图,componentX/Y来自位移位图。映射由组件通道距离128的距离确定。请注意,128是中性值,其中没有变换,并且使用相同的源像素。

例如,让我们考虑你的情况下的(1,1)像素。您的组件通道为蓝色,位移图中(1,1)的蓝色通道的值为0.因此我们将取代(0 - 128)/ 256或-0.5。因此,我们从源位图中获取的最终像素为(0.5,0.5)。

但是使用一半像素是什么意思?事实证明,Flash使用bilinear filtering来平滑结果。您最终会在(0,0)和(1,1)之间的四个像素中混合使用颜色。

这是您看到不在源图像中的奇数像素的原因。尽管源图像中的所有像素都是相同的颜色,但当Flash在颜色之间进行插值时,似乎存在一些浮点不准确性,因此有时您会得到一个仅稍微关闭的值。请注意,如果在位移位图中使用“干净”除以128的值(例如0或64),则会得到正确的结果。但是如果使用255或19之类的值,则会出现错误。

不幸的是,似乎没有办法关闭过滤并使用简单的最近邻点采样。因此,如果您需要保证不会引入新颜色,则必须仔细选择置换贴图中的值。

或者,您可以使用Pixel Bender创建一个满足您需求的内核。 Pixel Bender允许您从源位图进行最近邻采样。