2017-09-23 82 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當圖像是緩存它得到下一行之前加載,並且不久頭不得到重視的請求。