图像模糊,其实是一个关于图像像素的操作。其根本就是降低相邻像素之间的差异度,从而使图片变得模糊。
最近笔者一直在研究html5的新功能canvas,恰好在网上看到一些关于图片模糊的文章,于是笔者就用HTML5的Canvas做了一个图片模糊的效果。
演示地址:http://kevinblog.net/lab/lab10.html
上面这个地址后面可以传入变量s来控制图片模糊的半径,比如http://kevinblog.net/lab/lab10.html?s=10
接下来说说实现的过程。
首先,是读入被模糊的图片,然后获取其每个像素的RGB值,通过算法重新计算像素点的RGB值,然后将新的RGB值写入canvas元素中。
首先是载入,这个不难,为了简化,我使用jquery来处理。
var image = new Image();
image.src = '文件路径';
$(image).load(function(){
$('#main').html('正在渲染');
//这里进行进一步的处理
});
之后是计算图像的RGB值,这是重点。
笔者之前在网上看阮一峰先生的一篇介绍高斯模糊的文章,里面比较简单地介绍了高斯模糊的算法。可惜笔者大学虚度光阴,统计学里正态分布的知识以及完全还给老师了。所以笔者使用了一种更加简单,或者说傻瓜的方式。那就是忽视不同像素的权重,对只是单纯取周围像素的平均值。
如果接下来的步骤需要Canvas像素级操作的知识,不懂可以看这里。不懂基本的Canvas可以直接上w3school看看。
/**
* 模糊函数
*
* @param HTMLCanvasElement 目标Canvas
* @param HTMLImageElement 被渲染的图片对象
* @param int p 模糊半径
*/
var blur = function (obj, img, p) {
/**
* 将CanvasPixelArray里的值转换为对应坐标值
*
* @param int pos 像素数组里的像素的第一个值
* @param int width 图像的宽度
* @return array 对应坐标值
*/
var posToPx = function (pos, width) {
var Pixel = pos / 4;
var t = Math.ceil(Pixel / width);
var l = Pixel % width;
var result = new Array();
result.push(l);
result.push(t);
return result;
};
/**
* 将图像里的坐标值转换为对应CanvasPixelArray里的值
*
* @param int left x坐标值
* @param int top y坐标值
* @param int width 图像的宽度
* @return int 对应CanvasPixelArray里的值
*/
var pxToPos = function (left, top, width) {
return (left + width * top) * 4;
};
//初始化处理
var fcav = obj.getContext('2d');
var bcavObj = document.createElement('canvas');//建立后台的CanvasObject用于处理
var WIDTH = obj.width;
var HEIGHT = obj.height;
bcavObj.width = WIDTH;
bcavObj.height = HEIGHT;
var bcav = bcavObj.getContext('2d');
//将图像写入后台CanvasObject
bcav.drawImage(img, 0, 0, WIDTH, HEIGHT, 0, 0, WIDTH, HEIGHT);
var imgdata = bcav.getImageData(0, 0, WIDTH, HEIGHT);
var newImgData = fcav.createImageData(WIDTH, HEIGHT);
//历遍每个像素点
for (var i = 0; i < imgdata.data.length; i+= 4) {
var px = posToPx(i, WIDTH);
var y = px[1];
var x = px[0];
var r = 0;
var g = 0;
var b = 0;
var times = 0;
//对周围像素点进行采样采样
for (var row = -p;row <= p;row++) {
for (var col = -p;col <= p;col++) {
var thisX = x + row;
var thisY = y + col;
//如果越界了则忽略
if (thisX < 0 || thisX >= WIDTH) {
continue;
}
if (thisY < 0 || thisY >= HEIGHT) {
continue;
}
times++;
var tp = pxToPos(thisX, thisY, WIDTH);
r += imgdata.data[tp];
g += imgdata.data[tp + 1];
b += imgdata.data[tp + 2];
}
}
//取周围像素的平均值
r /= times;
g /= times;
b /= times;
//写入新的CanvasPixelArray
newImgData.data[i] = Math.round(r);
newImgData.data[i + 1] = Math.round(g);
newImgData.data[i + 2] = Math.round(b);
newImgData.data[i + 3] = 255;
}
//写入前台Canvas
fcav.putImageData(newImgData, 0, 0);
};