[html5 canvas] 实现转换图片为灰度模式

十二月 28, 2011

站点升级新版本, 代码部分由jquery逐步迁移到dojo.. 下午收到一个活.. 需要把之前用jq来做的图片改”黑白”转成dojo实现. 折腾一下午, 算是基本搞定了(网上一顿找).

思路

么有思路..囧. 网上找到解决办法. 大概是如下这样. 因为需求说明了, 针对非IE浏览器.

  1. 在canvas中绘制出目标图像.
  2. 获取图像的所有像素点, getImageData().
  3. 遍历所有像素, 将RGB转换为灰度值(灰度值对应的RGB三个值相等. 即R=G=B=灰度值)
  4. 将处理之后的图片数据重新载入原图片, 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.

扯点别的

“照葫芦画瓢不会, 照葫芦画葫芦也不会, 这不是能力问题, 是态度问题. 某些事儿让我着实很生气. 非常生气.”

Tags: , , ,
Posted in dojo, HTML5, js/jQuery by ADD~``

Follow comments via the RSS Feed | 留下评论 | Trackback URL

Leave a comment
8 Comments.
  1. 我在你微博上看到效果了,很牛B的效果哈,不过我想在哪里才可以应用上这种转换成黑白图片的效果呢 :roll:

    • 一个是我们公司项目上需要(当然- -. 不知道为毛要把人的头像弄成黑白的. :arrow: )
      另外的使用情形, 比如, 图片展示, 默认让他们全是黑白, 鼠标经过, 渐变到彩色.
      或者, 点击某个按钮, 其他有色部分全部变成黑白, 只有当前是彩色, 或者弹出框是彩色. 就想很多点击按钮, 弹出层后, 当前窗口有个灰色的遮罩一样~~ :twisted:

  2. 原地复活??血满了么…… :!:


[ Ctrl + Enter ]

 
  |  新浪微博  @不逊的螃蟹 |  Copyright © 2012 web-Add~'' <现役且越发不逊的螃蟹> | Powered by WordPress | Theme designed by Evlos [小邪]
要时刻保持心情愉悦.| 生活在利益驱动的社会里, 绝对不可以丢掉自己的梦想 | 今天(2011.4.27)在微博和Q上扬言封号. 封一段时间吧. 那是个容易让时间流逝的地方.