[英]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.