javascript中的子像素抗锯齿画布像素移位算法

时间:2012-12-16 04:44:05

标签: javascript image-processing canvas html5-canvas gaussian

我正试图找出一种做伪3d的方法,用javascript画布扭曲纹理。

到目前为止,满足我需求的最佳方法是使用displacement maps,我主要关注this tutorial and source code example

基本原理是使用位移图中所选像素的通道级别(RGBA),然后应用像素移位算法......到目前为止一切都很好。

问题在于,这种移动纹理图像像素的方法是非常二进制的,并且由于以下事实而呈现略微“锯齿状”的边缘 - 它只是移动“完整”像素。

与PhotoShop或某些ImageMagick examples here相比,javascript方法看起来不那么逼真。这是由于PS& IM的子像素处理能力,可以为像素间数据导出中位数。

问题:任何人都可以建议一个可以集成到我的算法中的步骤,以便为输出产生高斯/混叠平滑度吗?

也许我可以通过FFT再次运行图像数据?有没有这方面的例子?

我有点难过,非常欣赏一些指示。

1 个答案:

答案 0 :(得分:2)

1)你提到了两种非常不同的算法:置换贴图是一种3D技术,所以它涉及'Z'和投影,而另一种是2D像素移位算法更简单。

(提供的soundtep链接使用“置换映射”一词,但它是一个像素移位 技术。)

2)无论MVC项目的大小如何,算法应该被隔离,并且具有如下签名:

var pixelShift = function (sourceCanvas, shiftCanvas, xOffset, yOffset) 

并返回一个新画布或更改sourceCanvas。

如果没有这样的功能,请不要谈论MVC,除非M代表'Mess'。 ;-) -

3)算法非常简单,你必须遍历目标像素并查看它们应该来自的像素的颜色(而不是相反):

var pixelShift = function (sourceCanvas, shiftCanvas, xOffset, yOffset) {
    var shiftXY           = { xS:0, yS:0     };
    var shiftCanvasWidth  = shiftCanvas.width ;
    var shiftCanvasHeight = shiftCanvas.height;
    for ( var x=0 ; x < shiftCanvasWidth ; x ++) {
        for ( var y = 0 ; y < shiftCanvasHeight ; y++ ) {
            readShift ( shiftCanvas, x, y, shiftXY );
            var sourceColor = readPixelColor ( sourceCanvas, 
                                                 xOffset + shiftXY.xS, 
                                                         yOffset + shiftXY.yS) ;
            writePixel(sourceCanvas, xOffset + x , yOffset + y, sourceColor );
        }
     }
 };

 // sourceColor represents the color within a 32 bits integer (r,g,b,a * 8 bits).

在这里写下所有内容会太长,但是:

- 在pixelShift循环中你不应该处理源画布,而应该使用32位性能数组。

- 移位画布应该转换为ONCE到Int8Array数组,并存储为此。
 这个数组大小是shiftWidth * shiftHeight
 奇数索引包含x shift,甚至包含y shift  数组被预处理,并包含移位值 - 128  对于这个shiftArray:

shiftX (x,y) = shiftArray [ 2 * (x + y * shiftWidth)     ] ;                                               
shiftY (x,y) = shiftArray [ 2 * (x + y * shiftWidth) + 1 ] ;  

- 所以pixelShift应该是这样的:

var pixelShift = function (sourceCanvas, 
                               shiftArray, shiftWidth, shiftHeight, xOffset, yOffset) {  
          [ Get a 32 bit performance array out of the canvas's target area ]  
          [ process this array using the shiftArray ]  
          [ write back the processed array onto the canvas's target area ]  
 }

- 核心循环可以线性方式处理:

        var areaSize = shiftWidth * shiftHeight ;
        for ( pixelIndex=0 ; pixelIndex < areaSize ; pixelIndex++ ) {
            var linearShift = shiftArray [ 2*pixelIndex ] 
                                       + shiftWidth * shiftArray [ 2*pixelIndex + 1 ]  ;
            targetAreaArray [ pixelIndex ] = targetAreaArray [ pixelIndex + linearShift ] ;
            }

- Rq:你可能想在[0,areaSize [。

]内对(pixelIndex + linearShift)进行边界检查

- 我想现在你不能更快 性能瓶颈将是获取/放置目标区域所需的getImageData和putImageData,但据我所知,除了这两个slooooow函数之外,没有其他方法可以在Canvas上获取二进制视图。