简体   繁体   English

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

[英]Blurring algorithm canvas not working JS

I'm trying to implement a simple blurring algorithm averaging the colors from the surrounding pixels in a 3x3 area. 我正在尝试实现一种简单的模糊算法,对3x3区域中周围像素的颜色进行平均。

I loop throught the pixel array, in increments of 4. Then I have a function which takes 6 parameters: 我以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

And I generate 4 new value, new red, new green, new blue and new alpha and return them in an object. 然后生成4个新值,即新红色,新绿色,新蓝色和新alpha,并将它们返回到对象中。

This is the entire code: 这是完整的代码:

//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};
    });
}

As you can see, surrounding pixels value are hardcoded. 如您所见,周围的像素值被硬编码。 You can test it here: 您可以在这里进行测试:

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

If the run button does nothing, reload and try again (some issue with codepen cross-origin). 如果运行按钮没有执行任何操作,请重新加载并重试(codepen跨源某些问题)。 Try hitting the run button several times to increase the passes of the algorithm. 尝试多次点击运行按钮以增加算法的通过率。

You'll notice that it will completely grayscale the image after 2/3 passes. 您会注意到,2/3通过后它将完全使图像灰度。 Thanks in advance! 提前致谢!

You are indexing the wrong channels in the callback. 您在回调中索引了错误的通道。 And Not sure why you do the || 而且不确定为什么要||

Add i++ after each colour channel in the callback. 在回调中的每个颜色通道之后添加i++

Also the mean value should be the mean of the square of each channels value as the value of each channel is the ~sqrt of the brightness. 平均值也应该是每个通道值的平方的平均值,因为每个通道的值是亮度的〜sqrt。 Not squaring the values will produce a mean that is darker than what it should be. 不对值进行平方将产生比应有的平均值暗的平均值。

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 move the line img.crossOrigin = "Anonymous"; BTW移动行img.crossOrigin = "Anonymous"; above the line you set the img.src as when the image is in cached it gets loaded before the next line and the anon header does not get attached to the request. 在您将img.src设置为行的img.src因为在缓存图像时,它会在下一行之前加载,并且anon标头不会附加到请求。

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

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