15.2.10 使用图像数据

优质
小牛编辑
125浏览
2023-12-01
2D 上下文的一个明显的长处就是,可以通过getImageData()取得原始图像数据。这个方法接收4 个参数:要取得其数据的画面区域的x 和y 坐标以及该区域的像素宽度和高度。例如,要取得左上角坐标为(10,5)、大小为50×50 像素的区域的图像数据,可以使用以下代码:
var imageData = context.getImageData(10, 5, 50, 50);

这里返回的对象是ImageData 的实例。每个ImageData 对象都有三个属性:width、height 和data。其中data 属性是一个数组,保存着图像中每一个像素的数据。在data 数组中,每一个像素用图 15-12 4 个元素来保存,分别表示红、绿、蓝和透明度值。因此,第一个像素的数据就保存在数组的第0 到第3 个元素中,例如:

var data = imageData.data,
red = data[0],
green = data[1],
blue = data[2],
alpha = data[3];
数组中每个元素的值都介于0 到255 之间(包括0 和255)。能够直接访问到原始图像数据,就能够以各种方式来操作这些数据。例如,通过修改图像数据,可以像下面这样创建一个简单的灰阶过滤器。
var drawing = document.getElementById("drawing");
//确定浏览器支持<canvas>元素
if (drawing.getContext) {
var context = drawing.getContext("2d"),
image = document.images[0],
imageData,
data,
i,
len,
average,
red,
green,
blue,
alpha;
//绘制原始图像
context.drawImage(image, 0, 0);
//取得图像数据
imageData = context.getImageData(0, 0, image.width, image.height);
data = imageData.data;
for (i = 0, len = data.length; i < len; i += 4) {red = data[i];green = data[i + 1];blue = data[i + 2];alpha = data[i + 3];//求得rgb 平均值average = Math.floor((red + green + blue) / 3);//设置颜色值,透明度不变data[i] = average;data[i + 1] = average;data[i + 2] = average;
}
//回写图像数据并显示结果
imageData.data = data;
context.putImageData(imageData, 0, 0);
}
运行一下

这个例子首先在画面上绘制了一幅图像,然后取得了原始图像数据。其中的for 循环遍历了图像数据中的每一个像素。这里要注意的是,每次循环控制变量i 都递增4。在取得每个像素的红、绿、蓝颜色值后,计算出它们的平均值。再把这个平均值设置为每个颜色的值,结果就是去掉了每个像素的颜色,只保留了亮度接近的灰度值(即彩色变黑白)。在把data 数组回写到imageData 对象后,调用putImageData()方法把图像数据绘制到画布上。最终得到了图像的黑白版。

当然,通过操作原始像素值不仅能实现灰阶过滤,还能实现其他功能。要了解通过操作原始图像数据实现过滤器的更多信息,请参考Ilmari Heikkinen 的文章“Making Image Filters with Canvas”(基于Canvas 的图像过滤器):http://www.html5rocks.com/en/tutorials/canvas/imagefilters/。

只有在画布“干净”的情况下(即图像并非来自其他域),才可以取得图像数据。如果画布“不干净”,那么访问图像数据时会导致JavaScript 错误。