javascript - JavaScript 中的子像素抗锯齿 Canvas 像素移位算法

标签 javascript image-processing canvas html5-canvas gaussian

我正在尝试找出一种使用 JavaScript Canvas 进行伪 3D 扭曲纹理的方法。

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

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

问题在于,这种移动纹理图像像素的方法是非常二元的,并且会渲染出稍微“锯齿状”的边缘,因为它只是移动“完整”像素。

与 PhotoShop 或某些 ImageMagick examples here 相比javascript 方法看起来不太现实。这是由于 PS 和 IM 的子像素处理能力,可以导出像素间数据的中值。

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

也许我可以简单地通过 FFT 运行图像数据并再次返回?有没有实际的例子?

我有点困惑,非常感谢一些指点。

最佳答案

1)您提到了两种截然不同的算法:位移贴图是一种 3D 技术,因此它涉及“Z”和投影,另一种是更简单的 2D 像素移位算法。

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

2) 无论您的 MVC 项目有多大,算法都应该是隔离的,并且具有如下签名:

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

并且返回一个新的 Canvas 或就地更改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 循环中,您不应处理源 Canvas ,而应处理 32 位性能数组。

-- 移位 Canvas 应一次转换为 Int8Array 数组,并以此存储。
该数组大小为shiftWidth * shiftHeight
奇数索引包含 x 偏移,偶数包含 y 偏移。
该数组经过预处理,包含移位值 - 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 上获取二进制 View 。

关于javascript - JavaScript 中的子像素抗锯齿 Canvas 像素移位算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13898684/

相关文章:

javascript - 获取不在另一个标签内的元素的 InnerHTML

javascript - 设置函数的最大执行时间

javascript - 放大图像后获取图像裁剪的 x 和 y 坐标

python - OpenCV 和 Python - 图像太大而无法显示

javascript - Fabric js 用键盘移动图像

javascript - 尝试使用 JavaScript 突出显示子字符串

c# - 如何避免在 asp.net 中单击按钮事件后页面刷新

image-processing - 如何在图像中找到矩形的角坐标

javascript - 数组显示其长度为 0 但控制台显示否则

javascript - 如何将文本设置为 Canvas 圆