2.3 图像数据与 URLs
2.3.1 图像数据
我们在HTML5的canvas中可以使用 getImageData() 方法和图像对象的属性来获取图像中每一
个像素的数据。图像数据中的每个像素都由 red, green, blue, 和 alpha 值来表示。我们就可以用 putImageData() 方法来设置图像的像素值,然后重画经过修改的图像。如:
<script>
context.drawImage(imageObj, destX, destY); var imageData = context.getImageData(0, 0, canvas.width, canvas.height); vardata = imageData.data;
// 处理像素数据
context.putImageData(imageData, 0, 0); </script>
注意:方法 getImageData() 要求图像数据存储在 web 服务器上,并且操作这个图像的代码必
须是在同一台服务器上,如果这两条中的任一条不满足的话,将会抛出 SECURITY_ERR 异常。
代码
window.onload = function(){ var imageObj = new Image(); imageObj.onload = function(){ drawImage(this);
};
imageObj.src = "darth-vader.jpg";
};
function drawImage(imageObj){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var destX = 69; var destY = 50;
var sourceWidth = imageObj.width; var sourceHeight = imageObj.height;
context.drawImage(imageObj, destX, destY);
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
// 快速遍历所有的像素
for (var i = 0; i < data.length; i += 4) {
var red = data[i]; // red var green = data[i + 1]; // green var blue = data[i + 2]; // blue
// i+3 就是 alpha 值
}
// 另一种遍历像素的方式
for (var y = 0; y < sourceHeight; y++) {
// 遍历每一列
for (var x = 0; x < sourceWidth; x++) { var red = data[((sourceWidth * y) + x) * 4]; var green = data[((sourceWidth * y) + x) * 4 + 1]; var blue = data[((sourceWidth * y) + x) * 4 + 2];
}
}
// 如果修改了像素数据,就用下面这行代码把图像数据再写回canvas显示
context.putImageData(imageData, 0, 0); }
2.3.2 反转颜色
如果要反转图像上每个像素的颜色,我们可以用255去减每个像素的 red、 green、 blue 的值,
然后再写回 canvas 中去。
注意:方法 getImageData() 要求图像数据存储在 web 服务器上,并且操作这个图像的代码必
须是在同一台服务器上,如果这两条中的任一条不满足的话,将会抛出 SECURITY_ERR 异常。
效果图
代码
window.onload = function(){ var imageObj = new Image(); imageObj.onload = function(){ drawImage(this);
};
imageObj.src = "darth-vader.jpg";
};
function drawImage(imageObj){
var canvas = document.getElementById("myCanvas"); var context = canvas.getContext("2d");
var destX = 69; var destY = 50;
context.drawImage(imageObj, destX, destY);
var imageData = context.getImageData(0, 0, canvas.width,
canvas.height);
var data = imageData.data;
for (var i = 0; i < data.length; i += 4) { data[i] = 255 - data[i]; // red data[i + 1] = 255 - data[i + 1]; // green data[i + 2] = 255 - data[i + 2]; // blue
// i+3 是 alpha值
}
// 覆盖原数据
context.putImageData(imageData, 0, 0); }
2.3.3 灰度图
要把一个图像转换为灰度图,我们只需要遍历图像中的每个像素,计算像素的亮度值,然后把像素的red、 green、 blue 值都设为亮度值就可以了。
效果图
代码
window.onload = function(){ var imageObj = new Image(); imageObj.onload = function(){ drawImage(this);
};
imageObj.src = "darth-vader.jpg";
};
function drawImage(imageObj){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var destX = 69; var destY = 50;
context.drawImage(imageObj, destX, destY);
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
for (var i = 0; i < data.length; i += 4) {
var brightness = 0.34 * data[i] + 0.5 * data[i + 1] + 0.16 *
data[i + 2];
data[i] = brightness; // red data[i + 1] = brightness; // green data[i + 2] = brightness; // blue
// i+3 是 alpha 值
}
// 覆盖原数据
context.putImageData(imageData, 0, 0); }
2.3.4 获得图像数据 URL
通过 toDataURL() 方法,我们可以得到一个指向当前图像的 64 bit PNG 格式图像文件的
URL. 如 :
<script>
canvas.toDataURL(); </script>
注意:如果 canvas 包含一个来自其他主机的图像,那么这个 canvas 被称为“脏”的。如果在
这个“脏”的 canvas 上调用 toDataURL() 方法的话,将抛出 SECURITY_ERR 异常。
代码
window.onload = function(){
var canvas = document.getElementById("myCanvas"); var context = canvas.getContext("2d");
// 画云
context.beginPath(); // 开始用户定义图形 context.moveTo(170, 80);
context.bezierCurveTo(130, 100, 130, 150, 230, 150); context.bezierCurveTo(250, 180, 320, 180, 340, 150); context.bezierCurveTo(420, 150, 420, 120, 390, 100); context.bezierCurveTo(430, 40, 370, 30, 340, 50); context.bezierCurveTo(320, 5, 250, 20, 250, 50); context.bezierCurveTo(200, 5, 150, 20, 170, 80); context.closePath(); // 完成图形 context.lineWidth = 5; context.fillStyle = "#8ED6FF";
context.fill();
context.strokeStyle = "#0000ff";
context.stroke();
// 将canvas图像保存为url(默认是PNG格式)
var dataURL = canvas.toDataURL(); };
2.3.5 加载图像数据 URL
如果已知一个图像的数据 URL ,我们可以用 drawImage() 方法来把图像输出到 canvas 上。
在这里我们用ajax技术获取图像数据的url,由此url创建一个图像对象,然后用 drawImage() 输出图像。
代码
function loadCanvas(dataURL){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
// 从图像url加载图像数据
var imageObj = new Image(); imageObj.onload = function(){ context.drawImage(this, 0, 0);
};
imageObj.src = dataURL;
}
window.onload = function(){
// 使用 ajax 获取图像数据 url
var request = new XMLHttpRequest(); request.open("GET", "dataURL.txt", true); request.onreadystatechange = function(){
if (request.readyState == 4) { // 确保文档已经做好解析准备 if (request.status == 200) { // 确保能够获取文件 loadCanvas(request.responseText);
}
}
};
request.send(null); };
2.3.6 将绘制的图形保存为图像
如果想将在 canvas 中绘制的图形保存为图像文件,我们只需将图像的数据 url 赋值给HTML页
面上的 img 标签的 src 属性,用户就可以通过右键保存的形式把图形保存到本地机器上了。
注意:如果 canvas 包含一个来自其他主机的图像,那么这个 canvas 被称为“脏”的。如果在
这个“脏”的 canvas 上调用 toDataURL() 方法的话,将抛出 SECURITY_ERR 异常。
代码
<head>
<script>
window.onload = function(){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
// 画云
context.beginPath(); // 开始用户定义图形 context.moveTo(170, 80);
context.bezierCurveTo(130, 100, 130, 150, 230, 150); context.bezierCurveTo(250, 180, 320, 180, 340, 150); context.bezierCurveTo(420, 150, 420, 120, 390, 100); context.bezierCurveTo(430, 40, 370, 30, 340, 50); context.bezierCurveTo(320, 5, 250, 20, 250, 50); context.bezierCurveTo(200, 5, 150, 20, 170, 80); context.closePath(); // 完成用户定义图形 context.lineWidth = 5; context.fillStyle = "#8ED6FF";
context.fill();
context.strokeStyle = "#0000ff";
context.stroke();
// 将canvas图像保存为数据url var dataURL = canvas.toDataURL();
// 将数据 url 作为 canvasImg 的图像源
// 这样就可以保存到客户机器上了
document.getElementById("canvasImg").src = dataURL;
};
</script>
</head>
<body onmousedown="return false;">
<canvas id="myCanvas" width="578" height="200" style="display:none;">
</canvas>
<img id="canvasImg" alt="Right click to save me!">
</body>