线性化图像数据数组中的 5 x 5 像素图像数据是这样的-
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 255, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0]
因此,3x3 像素数据为 - 0 0 0 255。如何获取相邻像素位置?左右相邻的很容易,分别负4和正4就可以了。
最佳答案
访问像素数据
来自 .getImageData().data
的像素数据是 TypedArray
类型 Uint8ClampedArray
.读取值时,它们将在 0-255 范围内,并按红色、绿色、蓝色、Alpha 的顺序排列。如果 alpha 的值为零,则红色、绿色和蓝色也将为零。
获取像素的索引
const imageData = ctx.getImageData(0,0,ctx.canvas.width, ctx.canvas.height);
var index = (x + y * imageData.width) * 4;
const red = imageData.data[index];
const green = imageData.data[index + 1];
const blue = imageData.data[index + 2];
const alpha = imageData.data[index + 3];
向下移动一个像素
index += imageData.width * 4;
向上移动一个
index -= imageData.width * 4;
向左移动。
index -= 4;
向右移动
index += 4;
如果你在左边缘或右边缘并且你沿着边缘的方向移动你将环绕,如果向左移动则在上方和右侧的线上,如果向下移动则在下方和左侧的线。
当设置图像数据时,值将被降低并限制在 0-255
imageData.data[index] = 29.5
console.log(imageData.data[index]); // 29
imageData.data[index] = -283
console.log(imageData.data[index]); // 0
imageData.data[index] = 283
console.log(imageData.data[index]); // 255
如果您设置的索引超出数组大小,它将被忽略
imageData.data[-100] = 255;
console.log(imageData.data[-100]); // Undefined
imageData.data[imageData.data.length + 4] = 255;
console.log(imageData.data[imageData.data.length + 4]); // Undefined
您可以通过使用不同的数组类型来加快访问和处理速度。例如,一个像素的所有 channel 作为一个值使用 Uint32Array
const imageData = ctx.getImageData(0,0,ctx.canvas.width, ctx.canvas.height);
const pixels = new Uint32Array(imageData.data.buffer);
var index32 = x + y * imageData.width; // note there is no 4*;
const pixel = pixels[index32];
channel 存储在位 31-24 Alpha、23-16 Blue、15-8 Green、7-0 Red 中。
您可以使用十六进制值设置像素
pixels[x + y * imageData.width] = 0xFF0000FF; // red
pixels[x + y * imageData.width] = 0xFF00FF00; // Green
pixels[x + y * imageData.width] = 0xFFFF0000; // Blue
pixels[x + y * imageData.width] = 0xFF000000; // Black
pixels[x + y * imageData.width] = 0xFFFFFFFF; // White
pixels[x + y * imageData.width] = 0; // Transparent
您可以在一次调用中设置所有像素
pixels.fill(0xFF000000); // all pixels black
您可以使用以下命令将数组数据复制到数组中
// set 3 pixels in a row at x,y Red, Yellow, White
pixels.set([0xFF0000FF,0xFF00FFFF,0xFFFFFFFF], x+y * imageData.width);
警告
如果 Canvas 有任何来自不受信任来源的像素,它将被污染,您将无法读取像素数据。可信来源是使用适当的 CORS header 信息提供的相同域或图像。文件系统上的图像无法访问其像素。一旦 Canvas 被污染,就无法清洗。
当您调用 ctx.getImageData(0,0,1,1,)
时,受污染的 Canvas 会抛出错误> MDN 出于某种原因没有列出此异常。您将看到“SecurityError”DOMException;在 DevTools 控制台中,StackOverflow 中有很多关于该主题的已回答问题。
关于javascript - HTML5 Canvas - 如何从线性化图像数据 Uint8ClampedArray 获取相邻像素位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45963306/