3.5 获取图像数据
现在,我们知道如何绘制图像和视频,让我们尝试去访问图像的数据,看看什么类型的属性我们可以操作。
警告:由于getImageData()方法的安全限制,本节的例子必须在Web服务器上运行。
准备工作
在开始处理图像数据之前,很重要是要了解一下画布的安全和RGBA颜色空间。
那么,在访问图像数据方面,为什么画布安全很重要?简言之,为了访问图像数据,需要使用画布上下文对象的getImateData()方法,如果我们试图访问非Web服务器的文件系统、或不同域下的图像数据,该方法就会抛出SECURITY_ERR异常。换句话说,如果你想在本地文件系统中尝试运行这些例子,这恐怕不行。同样,本章后面各节的例子,也需要在Web服务器上运行。
其次,由于像素处理全部是通过改变一个像素的RGB来实现的,我们应该了解一下RGB颜色模式和RGBA颜色空间。RGB代表一个像素点的红(red)、绿(green)、蓝(blue)三种颜色的分量,每个分量取0到255之间的值,其中,0代表无色,255代表全色。RGB值通常以下面形式表示:
rgb(red,green,blue)
这里是使用RGB颜色模式表示时的一些常用颜色值:
rgb(0,0,0) = black
rgb(255,255,255) = white
rgb(255,0,0) = red
rgb(0,255,0) = green
rgb(0,0,255) = blue
rgb(255,255,0) = yellow
rgb(255,0,255) = magenta
rgb(0,255,255) = cyan
除了RGB,像素还有一个代表其透明度的透明通道。透明通道取值为0代表完全透明,取值为255代表完全不透明。RGBA颜色空间仅仅是指加入了透明通道(A)RGB颜色模式。
请当心,不要把HTML5画布的透明通道和CSS中的透明通道搞混。HTML5画布中,透明通道为整数,取值范围是0到255;CSS中,透明通道为小数,取值范围0.0到1.0。
绘制步骤
按照以下步骤,输出一幅图像的数据属性:
1. 定义画布上下文:
window.onload = function(){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
2. 创建一个image对象,把onload属性设置为一个绘制图像的函数:
var imageObj = new Image();
imageObj.onload = function() {
var sourceWidth = this.width;
var sourceHeight = this.height;
var destX = canvas.width / 2 - sourceWidth / 2;
var destY = canvas.height / 2 - sourceHeight / 2;
var sourceX = destX;
var sourceY = destY;
// draw image on canvas
context.drawImage(this, destX, destY);
3. 获取图像数据,输出其属性,然后在onload定义的外面设置image对象的源地址:
//从画布上包含图像的矩形区域中获取图像数据
var imageData = context.getImageData(sourceX, sourceY, sourceWidth, sourceHeight);
var data = imageData.data;
//把图像数据相关的属性输出到屏幕上
var str = "width=" + imageData.width + ", height=" + imageData.height + ", data length=" + data.length;
context.font = "12pt Calibri";
context.fillText(str, 4, 14);
};
imageObj.src = "jet_300x214.jpg";
};
4. 在HTML文档的body部分嵌入canvas标签:
<canvas id="myCanvas" width="600" height="250" style="border:1px solid black;">
</canvas>
工作原理
本节背后的思想是,绘制图像,并获取图像数据,然后把图像数据相关的属性输出到屏幕上。从前面的代码可以看到,我们可以调用画布上下文对象的getImageData()方法来获取图像数据:
context.getImageData(sourceX,sourceY,sourceWidth,sourceHeight);
请注意,getImageData()方法只能被画布上下文对象调用,而不能被image对象调用。因此,为了获取图像数据,我们必须先在画布中绘制一幅图像,再调用画布上下文对象的getImageData()方法。
ImageData对象有三个属性:width, height, 和data。从本节开始时的截屏可以看到,ImageData对象包含一个width属性,其值为300,一个height属性,其值为214,一个data属性,其值是一个像素信息的数组,本例中该数组有256,800个元素。说实话,ImageData对象的关键,就是data属性。data属性包含图像中每一个像素的RGBA信息。因为我们的图像是由300 * 214 = 64,200个像素组成,所以数组的元素个数就是4 * 64,200 = 256,800。