繁体   English   中英

模糊算法Canvas无法正常运行JS

[英]Blurring algorithm canvas not working JS

我正在尝试实现一种简单的模糊算法,对3x3区域中周围像素的颜色进行平均。

我以4为增量循环遍历像素数组。然后有一个函数包含6个参数:

r -> red value [0-255] int
g -> green value [0-255] int
b -> blue value [0-255] int
a -> alpha value(opacity) [0-255] int
d -> pixel array [r0,g0,b0,a0,r1,g1,b1,a1,r2... etc] array
i -> current index

然后生成4个新值,即新红色,新绿色,新蓝色和新alpha,并将它们返回到对象中。

这是完整的代码:

//canvas setup
var width = 400;
var height = 400;

var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');

canvas.width = width;
canvas.height = height;

//create image
var img = new Image();
img.src = 'images/input.jpg';

var pixels;

img.onload = function(){
    ctx.drawImage(img, 0, 0);
    pixels = ctx.getImageData(0, 0, width, height);
}

function action(pixels, callback){
    var newData = ctx.createImageData(width, height);

    for(var i = 0; i < pixels.data.length; i+=4){
        var r = pixels.data[i];
        var g = pixels.data[i+1];
        var b = pixels.data[i+2];
        var a = pixels.data[i+3];

        var channels = callback(r, g, b, a, pixels.data, i);

        newData.data[i] = channels.r;
        newData.data[i+1] = channels.g;
        newData.data[i+2] = channels.b;
        newData.data[i+3] = channels.a;

        pixels.data[i] = channels.r;
        pixels.data[i+1] = channels.g;
        pixels.data[i+2] = channels.b;
        pixels.data[i+3] = channels.a;
    }

    ctx.putImageData(newData, 0, 0);
}

function run(){
    action(pixels, function(r,g,b,a,d,i){

        var nr = (r
            + (d[i - 4] || r)
            + (d[i + 4] || r)
            + (d[i - 4 * width] || r)
            + (d[i + 4 * width] || r)
            + (d[i - 4 * width - 4] || r)
            + (d[i + 4 * width + 4] || r)
            + (d[i - 4 * width + 4] || r)
            + (d[i + 4 * width - 4] || r)
        ) / 9;

        var ng = (g
            + (d[i - 4] || g)
            + (d[i + 4] || g)
            + (d[i - 4 * width] || g)
            + (d[i + 4 * width] || g)
            + (d[i - 4 * width - 4] || g)
            + (d[i + 4 * width + 4] || g)
            + (d[i - 4 * width + 4] || g)
            + (d[i + 4 * width - 4] || g)
        ) / 9;

        var nb = (b
            + (d[i - 4] || b)
            + (d[i + 4] || b)
            + (d[i - 4 * width] || b)
            + (d[i + 4 * width] || b)
            + (d[i - 4 * width - 4] || b)
            + (d[i + 4 * width + 4] || b)
            + (d[i - 4 * width + 4] || b)
            + (d[i + 4 * width - 4] || b)
        ) / 9;

        return {r: nr, g: ng, b: nb, a: 255};
    });
}

如您所见,周围的像素值被硬编码。 您可以在这里进行测试:

https://codepen.io/tyrellrummage/pen/Ewgzzx

如果运行按钮没有执行任何操作,请重新加载并重试(codepen跨源某些问题)。 尝试多次点击运行按钮以增加算法的通过率。

您会注意到,2/3通过后它将完全使图像灰度。 提前致谢!

您在回调中索引了错误的通道。 而且不确定为什么要||

在回调中的每个颜色通道之后添加i++

平均值也应该是每个通道值的平方的平均值,因为每个通道的值是亮度的〜sqrt。 不对值进行平方将产生比应有的平均值暗的平均值。

function run(){
    const w = width * 4;
    // the offset index for each pixel excluding the center pixel
    const grid = [-w - 4, -w, -w + 4, -4, 4, w - 4, w, w + 4];

    action(pixels,(r,g,b,a,dat,i) => {
        var idx, count;         
        r *= r;
        g *= g;
        b *= b;
        count = 1;
        for(idx = 0; idx < grid.length; idx ++){
            const off = grid[idx];
            if(i + off >= 0 && i + off < w * height){
                r += dat[i + off] * dat[i + off];
                g += dat[i + 1 + off] * dat[i + 1 + off];
                b += dat[i + 2 + off] * dat[i + 2 + off];
                a += dat[i + 3 + off];
                count ++;
            }
        }
        r = Math.sqrt(r / count);
        g = Math.sqrt(g / count);
        b = Math.sqrt(b / count);
        a = a / count;
        return {r,g,b,a};
     });
}

BTW移动行img.crossOrigin = "Anonymous"; 在您将img.src设置为行的img.src因为在缓存图像时,它会在下一行之前加载,并且anon标头不会附加到请求。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM