2017-09-23 43 views
0

我试图实现一个简单的模糊算法,平均来自3x3区域周围像素的颜色。模糊算法画布不工作JS

我环像素阵列throught,在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遍之后完全灰度化图像。 在此先感谢!

回答

0

您正在索回回调中的错误频道。并且不确定您为什么要这样做||

在回调中的每个颜色通道之后添加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当图像是缓存它得到下一行之前加载,并且不久头不得到重视的请求。