Canvas 2D API 的 CanvasRenderingContext2D.getImageData()
返回一个 ImageData 对象,用于描述 canvas 指定区域的隐含像素数据。
语法
getImageData(sx, sy, sw, sh, settings)
参数
sx
要提取
ImageData
的矩形左上角的 x 轴坐标。
sy
要提取
ImageData
的矩形左上角的 y 轴坐标。
sw
要提取
ImageData
的矩形的宽度。正值向右延伸,负值向左延伸。
sh
要提取
ImageData
的矩形的高度。正值向下延伸,负值向上延伸。
settings 可选
一个具有以下属性的对象:
colorSpace
:指定图像数据的颜色空间。可以设置为"srgb"
表示 sRGB 色彩空间,或"display-p3"
表示 display-p3 色彩空间。
像素操作
ImageData
对象中存储着 canvas 对象真实的像素数据,它包含以下几个只读属性:
- width
图片宽度,单位是像素
- height
图片高度,单位是像素
- data
Uint8ClampedArray类型的一维数组,包含着 RGBA 格式的整型数据,范围在 0 至 255 之间(包括 255)。
data 属性返回一个 ,它可以被使用作为查看初始像素数据。每个像素用 4 个 1bytes 值 (按照红,绿,蓝和透明值的顺序; 这就是"RGBA"格式) 来代表。每个颜色值部份用 0 至 255 来代表。每个部份被分配到一个在数组内连续的索引,左上角像素的红色部份在数组的索引 0 位置。像素从左到右被处理,然后往下,遍历整个数组。
Uint8ClampedArray包含
height
×width
× 4 字节数据,索引值从 0 到 (height
×width
× 4)-1
获取canvas中某个点位的RGBA值
// 要读取图片中位于第 50 行,第 200 列的像素的R/G/B/A 值
imageData.data[50 * (imageData.width * 4) + 200 * 4 + 0]; // R
imageData.data[50 * (imageData.width * 4) + 200 * 4 + 1]; // G
imageData.data[50 * (imageData.width * 4) + 200 * 4 + 2]; // B
imageData.data[50 * (imageData.width * 4) + 200 * 4 + 3]; // A
getImageData()方法的应用
-
获取图片中点位的颜色值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<style>
.container {
display: flex;
height: 40px;
width: 300px;
}
#color {
height: 40px;
width: 40px;
}
#text {
padding-left: 10px;
line-height: 40px;
}
</style>
<canvas id="canvas"></canvas>
<div class="container">
<div id="color"></div>
<div id="text"></div>
</div>
<script>
var img = new Image();
img.src = 'https://img.zbt.com/e/steam/item/730/QUstNDcgfCBBc2lpbW92IChNaW5pbWFsIFdlYXIp.png';
img.crossOrigin = 'Anonymous';
var canvas = document.getElementById('canvas');
var color = document.getElementById('color');
var text = document.getElementById('text');
var ctx = canvas.getContext('2d');
img.onload = function () {
// 在canvas上画图片
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
canvas.addEventListener('mousemove', pick);
};
function pick(event) {
// 获取鼠标坐标
var x = event.layerX;
var y = event.layerY;
// 获取图片像素信息
var pixel = ctx.getImageData(x, y, 1, 1);
var data = pixel.data;
console.log(x, y, pixel, data);
// 获取rgba值
var rgba = 'rgba(' + data[0] + ',' + data[1] + ',' + data[2] + ',' + (data[3] / 255) + ')';
// 设置小正方形的背景颜色
color.style.background = rgba;
// 把拼接的字符串设置为元素的文本内容
text.textContent = rgba;
}
</script>
</body>
</html>
-
透明图片描边
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>outline</title>
</head>
<body>
<style>
canvas {
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
img {
position: absolute;
top: 0;
left: 0;
z-index: 9999;
}
</style>
<canvas id="can"></canvas>
<script>
// 某点位的RGBA值
const pointXA = function (Val) {
const { distance, data, x, y, width, isExist } = Val,
Index = y * (width * 4) + (x + distance) * 4,
A = data[Index + 3];
return isExist ? A === 0 : A !== 0;
}
const pointYA = function (Val) {
const { distance, data, x, y, width, height, isExist } = Val,
Index = (y + distance) * (width * 4) + (x + 1) * 4,
A = data[Index + 3];
if (y > 30 && y < height - 30) {
return isExist ? A === 0 : A !== 0;
} else {
return false;
}
}
function isEdgePixel(data, x, y, width, height, direction = 'x') {
// y 为 行 x 为 列
let index = y * (width * 4) + x * 4, fun = null;
if (direction === 'x') {
fun = pointXA;
} else {
fun = pointYA;
}
const val = { data, x, y, width, height },
currentA = fun({ ...val, isExist: true, distance: 0 }),
distance2A = fun({ ...val, isExist: true, distance: 2 });
distanceopposite2YA = fun({ ...val, isExist: true, distance: -2 }),
distance4YA = fun({ ...val, isExist: false, distance: 4 }),
distanceopposite4YA = fun({ ...val, isExist: false, distance: -4 }),
isEdge = currentA && distance2A && distanceopposite2YA && (distance4YA || distanceopposite4YA);
return isEdge;
}
(function createdCanvas() {
const canvas = document.querySelector("#can"); // 创建canvas标签
const ctx = canvas.getContext("2d"); // 获取2D渲染上下文
const img = new Image(); // 创建新的图片对象
img.crossOrigin = "Anonymous"
img.src = "https://img.zbt.com/e/steam/item/730/QUstNDcgfCBBc2lpbW92IChNaW5pbWFsIFdlYXIp.png"
let edgeXPoints = [], edgeYPoints = [];
img.onload = () => {
// 图片加载完成后执行的操作
canvas.width = img.width; // 设置canvas宽度
canvas.height = img.height; // 设置canvas高度
// 绘制图片
ctx.drawImage(img, 0, 0, img.width, img.height);
// 获取像素数据
const imageData = ctx.getImageData(
0,
0,
canvas.width,
canvas.height
);
const data = imageData.data;
// 遍历像素数据
for (let y = 0; y < canvas.height; y++) {
for (let x = 0; x < canvas.width; x++) {
const index = (y * canvas.width + x) * 4;
// 根据像素颜色判断是否为边缘像素(这里只是一个简单的示例,你可能需要更复杂的算法来检测边缘)
if (isEdgePixel(data, x, y, canvas.width, canvas.height, 'x')) {
// 如果是边缘像素,记录坐标
edgeXPoints.push({ x, y });
}
if (isEdgePixel(data, x, y, canvas.width, canvas.height, 'y')) {
// 如果是边缘像素,记录坐标
edgeYPoints.push({ x, y });
}
}
}
// 描边
ctx.beginPath();
[...edgeXPoints, ...edgeYPoints].forEach((point, index) => {
let x = point.x, y = point.y;
ctx.fillStyle = "gold";
ctx.fillRect(x, y, 1, 1);
});
};
})();
</script>
</body>
</html>