最近刚接触HTML5的Canvas,然后想做点小东西。
直方图是用来直观地表示图片的RGB三种颜色通道在不同亮度值上面,所占的量的多少。
大家都知道,电脑上的数码照片的每个像素由红绿蓝三种颜色合成,所以一个像素具有R-红色,G-绿色,B-蓝色三种颜色的信息;每种颜色取值是0-255————当为0的时候,表示当前像素没有这种颜色,当为最大值255的时候,表示这种颜色含量已经最高。
比如,纯红色的RGB就是(255,0,0),即红色最多,不含绿色和蓝色。黄色由红色和绿色合成,所以纯黄色RGB就是(255,255,0)。
然后,直方图的横坐标从左到右依次是0到255,纵坐标没有上限,当x为定值的时候,不同颜色的y值表示的是:亮度(姑且这么称呼)为x的这种颜色的量有y这么多。
直方图在摄影中经常用到,通过查看照片的直方图,可以知道曝光是否准确。如果需要的是正常的曝光,那么就应该使照片的各种颜色集中在x的中间值,大约100-150区间内,直方图呈现中间凸起的形状。
更多的信息,大家可以搜索查看照片直方图
。
说了这么多,终于进入正题了。
点击查看:Canvas生成照片直方图
先载入一张图,然后获取图片的每个像素的值,然后对每个像素的R\G\B值分别统计,然后得到一个数组包含了3种颜色的量。这里设的是一个叫做tj的二维数组,红色是tj[0],绿色是tj1,蓝色是tj[2];用tj[0][210]的值来表示亮度为210的红色像素的数量。
得到tj数组之后转换为直方图:例如tj[1][145]=3872转换为在x为145,y为3872的像素的地方用绿色画一个点,当然,y太大的话,直方图太高,所以下面会将y除以10来“压扁”直方图。
代码部分的说明直接写到注释中了。
HTML部分很简单:
<canvas id="canvas" width="756" height="300"></canvas>
JS部分:
var c = document.getElementById("canvas"),
ctx = c.getContext("2d"),
img = new Image,
tj=[[],[],[],[]]; //三维数组,统计RGB三种颜色的
//初始化统计数组
for (var i = 0; i < 256; i++) {
tj[0][i]=0;
tj[1][i]=0;
tj[2][i]=0;
};
img.src='RGB.jpg'; //这里需要遵循同源原则,图片和JS要同域,不然待会读取不到图片像素数据
img.onload=function(){
ctx.drawImage(img, 0, 0, 400,300);
imgData=ctx.getImageData(0,0,400,300);
imgDataTemp=ctx.createImageData(400,300);
//imgDataTemp用来储存直方图的像素,这一步是将之用黑色背景初始化,setColor是自定义函数
setColor(imgDataTemp.data,0);
for (var i = 0; i < imgData.data.length; i++) {
//统计不同颜色的数量,tj[0][210]的值表示亮度为210的红色像素的数量
tj[i%4][ imgData.data[i] ] ++;
};
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 256; j++) {
drawPoint(imgDataTemp,j,tj[i][j]/10,i) //将颜色的数量除以10,防止直方图太高
};
};
ctx.putImageData(imgDataTemp, 500, 0);
};
//函数drawPoint(img,x,y,c)表示在img对象的x、y坐标处用颜色c画一个点。c=0,1,2分别表示R,G,B
function drawPoint(img,x,y,c){
x=Math.round(x);
y=Math.round(y);
var _px;
for (var i = 300-y; i < 300; i++) {
_px=(img.width*i+x)*4+c;
img.data[_px]=255;
};
}
//将imgData的每个像素用灰色填充(c,c,c),同时每个像素点的Alph透明度设置为不透明(255);
function setColor(o,c) {
var l=o.length, i=0;
for(;i<l;i++) {
if (i%4!==3) {
o[i] = c;
}else{
o[i] = 255;
}
};
};
本文结束,今天是广州今年最热的一天,下了一个多月的暴雨的季节应该也快结束了,夏天来了,蚊子来了。