[html5 canvas] 实现转换图片为灰度模式
十二月 28, 2011
站点升级新版本, 代码部分由jquery逐步迁移到dojo.. 下午收到一个活.. 需要把之前用jq来做的图片改”黑白”转成dojo实现. 折腾一下午, 算是基本搞定了(网上一顿找).
思路
么有思路..囧. 网上找到解决办法. 大概是如下这样. 因为需求说明了, 针对非IE浏览器.
- 在canvas中绘制出目标图像.
- 获取图像的所有像素点, getImageData().
- 遍历所有像素, 将RGB转换为灰度值(灰度值对应的RGB三个值相等. 即R=G=B=灰度值)
- 将处理之后的图片数据重新载入原图片, putImageData()
这里涉及到一个灰度值的计算公式, 网上找了些, 老版本的解决方案是grayscale= (R+G+B)/3, 然后将grayout赋值给RGB, 这个不够精确, 新版本为grayscale = R*0.3+G*0.59+B*0.11.
同时, 在实现过程中, chrome浏览器出现了bug. console面板无报错, 但是drawImage(html5提供的绘图API)无效. 搜了一圈, 解释为图片的加载为异步, drawImage在加载完毕前就已经执行, 解决办法是判断图片加载完毕之后, 再执行drawImage操作.
最后一点, canvas作为一个新兴的html标签, 默认尺寸是300px x 150px的一个透明矩形区域. 如果需要改变其尺寸, 需要直接在canvas标签中加width=”500″ height=”500″这种方式, css也可以正常改变canvas的外观尺寸, 但是会导致内部绘图的尺寸改变. 这点尤为操蛋….
实现
首先, 解决判断图片是否加载完全的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | function loadImage(url, callback) { //canvas中需要接收image或canvas对象. var img = new Image(); img.src = url; //如果img.complet返回true, 则表示该图片已经被缓存 //直接读取缓存信息, 并将img对象返回给canvas部分 if (img.complete){ callback.call(img); return; } //如果没有缓存, 则在图片onload结束后, 回调img img.onload = function(){ callback.call(img); }; }; |
至此, 判断图片加载完全的问题已经解决, 接下来是核心部分, 网上满是相似代码. 无特别之处.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | //项目需要, dojo实现. dojo.ready(function(){ 判断非IE浏览器 if(!dojo.isIE){ loadImage("style/img/forGrayout.png",function(){ //获取canvas, 并缓存节点 var canvas = dojo.byId("demo"); //绘制2d图像 var cxt = canvas.getContext("2d"); //绘制图像, 这里有三种方式绘制. 分别对应3个参数, 5个参数, 9个参数 //可以参考: https://developer.mozilla.org/en/Canvas_tutorial/Using_images cxt.drawImage(this,0,0,this.width,this.height); //获取图片的值(每个像素) var imageData = cxt.getImageData(0,0,this.width,this.height); //将像素值使用.data取出, 保存为数组(一维) var pix = imageData.data; //RGB->灰度 for(var i=0, len=pix.length; i<len; i+=4){ var grayscale = pix[i ] * .3 + pix[i+1] * .59 + pix[i+2] * .11; pix[i] = grayscale; pix[i+1] = grayscale; pix[i+2] = grayscale; } //处理后的数据重新压回图片. cxt.putImageData(imageData,0,0); }); } }); |
如此一来, RGB->灰度的问题. 搞定了. 算是各处搜扒的结果. Mark.
扯点别的
“照葫芦画瓢不会, 照葫芦画葫芦也不会, 这不是能力问题, 是态度问题. 某些事儿让我着实很生气. 非常生气.”
Leave a comment
8 Comments.
我在你微博上看到效果了,很牛B的效果哈,不过我想在哪里才可以应用上这种转换成黑白图片的效果呢
一个是我们公司项目上需要(当然- -. 不知道为毛要把人的头像弄成黑白的.
)
另外的使用情形, 比如, 图片展示, 默认让他们全是黑白, 鼠标经过, 渐变到彩色.
或者, 点击某个按钮, 其他有色部分全部变成黑白, 只有当前是彩色, 或者弹出框是彩色. 就想很多点击按钮, 弹出层后, 当前窗口有个灰色的遮罩一样~~
原地复活??血满了么……
哥, 其实这次是回光返照~
为了拯救全人类~
这句话让我想到了蜡笔小新……
那个眉毛~~