图像模糊,其实是一个关于图像像素的操作。其根本就是降低相邻像素之间的差异度,从而使图片变得模糊。
最近笔者一直在研究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); };