博客简介
HTML5中的canvas允许我们直接对像素进行操作,我们可以通过ImageData对象操纵像素数据,读取或将数据数组写入该对象中。这里还会介绍如何控制图像使其平滑(反锯齿)以及如何从Canvas画布中保存图像。
- imageData对象
- 读取或写入imageDate对象
- 缩放和反锯齿
- 保存图片
ImageData对象
ImageData对象中存储着canvas对象真实的像素数据,包含以下只读属性
- iwidth:图片的宽度,单位px
- height:图片的高度,单位px
- data:Uint8ClampedArray类型的一维数组,包含着RGBA格式的整型数据,范围在0至255之间(包括255)。
- data属性返回一个像素数组 Uint8ClampedArray,它可以被使用作为查看初始像素数据。每个像素用4个1bytes值(按照红,绿,蓝和透明值的顺序; 这就是"RGBA"格式) 来代表。每个颜色值部份用0至255来代表。每个部份被分配到一个在数组内连续的索引,左上角像素的红色部份在数组的索引0位置。像素从左到右被处理,然后往下,遍历整个数组。
- 获取i行j列的R/G/B/A值:
imageData.data[((行数-1)*imageData.width + (列数-1))*4 - 1 + 1/2/3/4];
- 获取像素数组Uint8ClampedArray的大小:
var numBytes = imageData.data.length;
创建一个ImageData对象
一般的,创建一个ImageData对象,我们可以使用createImageData方法:
- var myImageData = ctx.createImageData(width, height):创建一个新的尺寸为width,height的ImageData对象,所有的像素被预设为黑色透明。
- var myImageData = ctx.createImageData(anotherImageData):创建一个被anotherImageData对象指定的相同像素的ImageData对象。这个新的对象像素全部被预设为透明黑。这个并非复制了图片数据。
var myImageData = ctx.createImageData(width, height);
var myImageData = ctx.createImageData(anotherImageData);
获取场景canvas区域的ImageData对象
我们可以通过getImageData方法获取canvas指定区域的像素数据:
- getImageData(x,y,width,height):返回一个ImageData对象,该对象描述了(x,y,x+width,y+height)区域的像素
举例:取色器
这个例子中,我们将返回鼠标位置的像素:
- 获取鼠标的位置x,y
- 获取该位置的ImageData对象
- 获取对象的数据
- 将数据返回,并且用该RGBA值绘制颜色
var img=new Image();
window.onload=function()
{
img.src="spiderMan.jpg";//获取图片
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext('2d');
img.onload=function()
{
ctx.drawImage(img,0,0,400,300);//画出图片
//获取ImageData对象
canvas.addEventListener("mousemove",function(e)
{
var x=e.layerX;
var y=e.layerY;//获取坐标
var imageData=ctx.getImageData(x,y,1,1);//获取x,y处像素1*1的图片
var data=imageData.data;//获取像素数据
var r=data[0];
var g=data[1];
var b=data[2];
var a=data[3];
var color="rgba("+r+","+g+","+b+","+a+")";
ctx.clearRect(0,305,400,400)
ctx.save();
ctx.fillStyle=color;
ctx.fillRect(0,305,100,40);//绘制矩形
ctx.font="15px 幼圆";
ctx.save();
ctx.fillStyle=" #7B68EE";
ctx.fillRect(0,375,250,40);
ctx.restore();
ctx.fillText("光标处像素="+color,0,400);
ctx.restore();
})
}
}
在场景canvas中写入像素数据
我们通过getImageData方法获取canvas指定区域的像素数据,同时也可以用putImageData()方法将像素写入写入canvas中
- putImageData(imageData,x,y):将ImageData对象代表的图片绘制在x,y位置
- 直接修改ImageData.data就能够改变ImageData对象
putImageData举例
以下我们将会操纵一张图片像素,取出像素值后,对它进行灰度和反相操作,我们设置两个函数grayscale 和invert 来实现:
- grayscale 灰度处理 :x = 0.299r + 0.587g + 0.114b
function grayscale()//灰度
{
for(var i=0;i<data.length;i+=4)
{
avg=0.299*data[i] + 0.587*data[i+1] + 0.114*data[i+2];
data[i]=data[i+1]=data[i+2]=avg;
}
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.putImageData(imageData,0,0);
}
- invert 反相处理 :x=255-i
function intervar()//反相
{
for(var i=0;i<data.length;i+=4)
{
data[i]=255-data[i];//r
data[i+1]=255-data[i+1];//g
data[i+2]=255-data[i+2];//b
}
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.putImageData(imageData,0,0);
}
最后添加监听
var invertbtn = document.getElementById('invertbtn');
invertbtn.addEventListener('click', intervar);
var grayscalebtn = document.getElementById('grayscalebtn');
grayscalebtn.addEventListener('click', grayscale);
缩放和反锯齿
关于canvas操作图像的放缩,我们在前面已经介绍过了,通过drawImage(x,y,w,h)来实现,放缩过程中默认是反锯齿的,如果我们想要去掉反锯齿,看到具体的像素,可以使用imageSmoothingEnabled属性:
- imageSmoothingEnabled锯齿:如果为true,则展示反锯齿,为false展示锯齿
缩放和反锯齿举例
var img=new Image();
img.src="../纸飞机.jpg";
var canvas;
var able=1;
img.onload=function()
{
draw(this);
}
function toggleSmoothing()
{
able=able?false:true;
ctx.imageSmoothingEnabled=able;
}
function show(e)
{
var x=e.layerX;
var y=e.layerY;//获取坐标
ctx.clearRect(500,0,200,200);
ctx.drawImage(canvas,Math.abs(x-5),Math.abs(y-5),10,10,500,0,200,200);
}
function draw(img) {
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0,480,300);
img.style.display = 'none';
var smoothbtn = document.getElementById('smoothbtn');//获取区域
smoothbtn.addEventListener('click',toggleSmoothing);
canvas.addEventListener('mousemove',show);
}
保存图片
HTMLCanvasElement 提供一个toDataURL()方法,此方法在保存图片的时候非常有用。它返回一个包含被类型参数规定的图像表现格式的数据链接。返回的图片分辨率是96dpi。
- canvas.toDataURL(‘image/png’) :默认设定。创建一个PNG图片。
- canvas.toDataURL(‘image/jpeg’, quality):创建一个JPG图片。你可以有选择地提供从0到1的品质量,1表示最好品质,0基本不被辨析但有比较小的文件大小。
当你从画布中生成了一个数据链接,例如,你可以将它用于任何< image >元素,或者将它放在一个有download属性的超链接里用于保存到本地 - canvas.toBlob(callback, type, encoderOptions):这个创建了一个在画布中的代表图片的Blob对像。
用超链接保存图片:
我们对以上的图片稍加修改,并且插入超链接
var img=new Image();
img.src="../纸飞机.jpg";
var canvas;
var able=1;
img.onload=function()
{
draw(this);
}
function toggleSmoothing()
{
able=able?false:true;
ctx.imageSmoothingEnabled=able;
}
function show(e)
{
var x=e.layerX;
var y=e.layerY;//获取坐标
ctx.clearRect(500,0,200,200);
ctx.drawImage(canvas,Math.abs(x-5),Math.abs(y-5),10,10,500,0,200,200);
}
function draw(img) {
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0,480,300);
img.style.display = 'none';
var smoothbtn = document.getElementById('smoothbtn');//获取区域
smoothbtn.addEventListener('click',toggleSmoothing);
canvas.addEventListener('mousemove',show);
canvas.addEventListener("click",function(){
var area=document.getElementsByTagName("a")[0];
area.setAttribute("href",canvas.toDataURL("纸飞机",1));
})
}
当图片被点击时,就会生成一个toDataURL对象,点击超链接则会下载图片:
图片下载完成