最快的高斯模糊不起作用
Posted
技术标签:
【中文标题】最快的高斯模糊不起作用【英文标题】:Fastest Gaussian Blur Not Working 【发布时间】:2016-09-26 23:53:48 【问题描述】:我不擅长 javascript,一直试图让 Ivan Kuckir's Fastest Gaussian Blur 代码工作但没有成功。当我加载页面时,它变得无响应,因此我将不得不以某种方式关闭窗口。我使用的代码如下。做错了什么?
<html>
<head>
<script src="Path_To_GaussianBlur.js"></script>
</head>
<body>
<img id="sourceImage" src="SomeImage_200px_x_200px.jpg" />
<canvas id="canvas1" style="border: 1px solid blue"></canvas>
<canvas id="canvas2" style="border: 1px solid red"></canvas>
<script>
document.getElementById("sourceImage").onload = function ()
var c1 = document.getElementById("canvas1");
var c2 = document.getElementById("canvas2");
var ctx1 = c1.getContext("2d");
var ctx2 = c2.getContext("2d");
var img = document.getElementById("sourceImage");
ctx1.drawImage(img, 0, 0);
ctx2.drawImage(img, 0, 0);
var source = ctx1.getImageData(0, 0, c1.width, c1.height);
var target = ctx2.getImageData(0, 0, c2.width, c2.height);
for (var i = 0; i < source.data.length; i += 4)
// red chanel
gaussBlur_4(source.data[i], target.data[i], c1.width, c1.height, 2);
// green channel
gaussBlur_4(source.data[i + 1], target.data[i + 1], c1.width, c1.height, 2);
// blue channel
gaussBlur_4(source.data[i + 2], target.data[i + 2], c1.width, c1.height, 2);
ctx2.putImageData(target, 0, 0);
;
</script>
</body>
</html>
【问题讨论】:
发生这种情况是因为这个算法有点小,我猜有一些无限递归,因为 javascript 执行永远不会停止和停止/挂起浏览器...... 看来我用错误的参数调用gaussBlur_4(...)
方法!
我也这么认为@kamran
我已将您的画布缩短为 10 像素 x 10 像素,算法运行良好,然后我将其调整为 20 像素 x 20 像素,它开始停止浏览器,但最终确实有效,然后是更大的尺寸它崩溃了浏览器,所以这个高斯算法真的很重,它正在崩溃浏览器,可能你需要为你的解决方案找到一些更轻的算法,或者对高斯算法进行一些修改以使其更轻
它很慢,因为您正在为每个像素和每个颜色通道对整个图像应用模糊。您需要分离出 3 个颜色通道(每个通道一个数组),然后只为每个通道调用 gaussBlur_4 ONCE
【参考方案1】:
如 cmets 中所述,您需要将 rgba 数组拆分为单独的通道。您可以通过多种方式做到这一点,这里是一种:
拆分
var idata = ctx.getImageData(0, 0, w, h), // assumes ctx/w/h to be defined
rgba = idata.data,
len = w * h,
rSrc = new Uint8Array(len), // source arrays
gSrc = new Uint8Array(len),
bSrc = new Uint8Array(len),
aSrc = new Uint8Array(len),
// define target arrays the same way as above
i = 0, offset = 0;
for(; i < len; i++)
rSrc[i] = rgba[offset++];
gSrc[i] = rgba[offset++];
bSrc[i] = rgba[offset++];
aSrc[i] = rgba[offset++];
现在您可以使用与源数组类似的方式设置的目标数组将这些数组中的每一个传递给模糊函数,然后将结果合并回 rgba 格式。
申请
gaussBlur_4(rSrc, rTrg, w, h, radius);
gaussBlur_4(gSrc, gTrg, w, h, radius);
gaussBlur_4(bSrc, bTrg, w, h, radius);
gaussBlur_4(aSrc, aTrg, w, h, radius);
附加提示:如果您使用的是图像(如照片),则可以跳过模糊 Alpha 通道,因为没有(或者从技术上讲,在画布中完全不透明)。
合并
要合并,只需:
for(i = 0, offset = 0; i < len; i++)
rgba[offset++] = rTrg[i];
rgba[offset++] = gTrg[i];
rgba[offset++] = bTrg[i];
rgba[offset++] = aTrg[i]; // or just increase offset if you skipped alpha
ctx.putImageData(idata, 0, 0);
由于 SO 上的许可冲突,可以在此 fiddle 中找到一个运行示例(here 是使用 32 位方法的替代拆分/合并)。
【讨论】:
不错的答案!我补充一下,如果你想用透明度进行模糊,你应该在模糊之前将 RGB 乘以 alpha,然后在模糊之后再除以。以上是关于最快的高斯模糊不起作用的主要内容,如果未能解决你的问题,请参考以下文章
iOS 7 导航栏背景模糊效果在 iPhone 4 中不起作用
TextField 模糊在 Nativescript vue 中不起作用