DisplacementMapFilter如何工作?

Jos*_*der 6 apache-flex flash actionscript-3

我是动作脚本的初学者.如果我理解正确,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
Run Code Online (Sandbox Code Playgroud)

现在,我采用这个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
Run Code Online (Sandbox Code Playgroud)

结果:

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
Run Code Online (Sandbox Code Playgroud)

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

非常感谢你.

Mik*_*lsh 3

置换贴图过滤器使用以下公式决定从源位图中抓取哪个像素:

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

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

例如,在您的情况下,让我们考虑 (1, 1) 处的像素。您的组件通道是蓝色的,位移图中 (1, 1) 处的蓝色通道的值为 0。因此我们位移 (0 - 128)/256,即 -0.5。所以我们从源位图中获取的最终像素位于 (0.5, 0.5)。

但是使用半个像素意味着什么?事实证明,Flash使用双线性过滤来平滑结果。最终得到 (0,0) 和 (1,1) 之间四个像素的颜色混合。

这就是您看到源图像中不存在的奇怪像素的原因。尽管源图像中的所有像素都具有相同的颜色,但当 Flash 在颜色之间进行插值时,似乎会出现一些浮点不准确的情况,因此有时您会得到一个稍有偏差的值。请注意,如果您在置换位图中使用“干净地”除以 128 的值(例如 0 或 64),那么您会得到正确的结果。但如果您使用 255 或 19 这样的值,则会出现一些错误。

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

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