【问题标题】:HTML5 Canvas - How to get adjacent pixels position from the linearized imagedata Uint8ClampedArray?HTML5 Canvas - 如何从线性化图像数据 Uint8ClampedArray 中获取相邻像素位置?
【发布时间】:2018-02-08 08:07:48
【问题描述】:

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。

【问题讨论】:

  • 你需要知道图片的尺寸,然后也很简单——分别是负4*size和正4*size。
  • @Bergi 是的,图像尺寸很容易通过 image.width 和 image.height 检索,因为我正在使用 Image() 构造函数。

标签: javascript html canvas


【解决方案1】:

访问像素数据

来自.getImageData().data 的像素数据是TypedArray 类型的Uint8ClampedArray。读取值时,它们将在 0-255 范围内,按红、绿、蓝、阿尔法的顺序排列。如果 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

您可以通过使用不同的数组类型来加快访问和处理速度。例如使用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];

通道存储在 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);

警告

如果画布有任何来自不受信任的来源的像素,它将被污染,您将无法读取像素数据。受信任的来源是使用适当的 CORS 标头信息提供的相同域或图像。文件系统上的图像无法访问其像素。一旦画布被污染,就无法清洗。

当您调用ctx.getImageData(0,0,1,1,) 时,受污染的画布会抛出错误@ MDN 出于某种原因没有列出此异常。您将看到“SecurityError”DOMException;在 DevTools 控制台中,并且 StackOverflow 中有很多关于该主题的已回答问题。

【讨论】:

  • 是的,所以相邻像素为:index - imageData.width * 4 - 4, index - imageData.width * 4, index - imageData.width * 4 + 4, index - 4, index + 4 , index + imageData.width * 4 - 4, index + imageData.width * 4, index + imageData.width * 4 + 4。谢谢!
【解决方案2】:

你可以用矩阵的宽度和4的一个单位的长度来计算索引。

访问是从零开始的。

function getPos(array, x, y, width) {
    var p = 4 * (x + y * width);
    return array.slice(p, p + 4);
}

var array = [
        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, 241, 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
    ];

// element above
console.log(JSON.stringify(getPos(array, 2, 1, 5))); // [0, 0, 0, 240]

// actual element
console.log(JSON.stringify(getPos(array, 2, 2, 5))); // [0, 0, 0, 255]

// element below
console.log(JSON.stringify(getPos(array, 2, 3, 5))); // [0, 0, 0, 241]

【讨论】:

  • 对角线不相邻?
  • 只取坐标,然后你得到值。
  • 感谢@NinaScholz,这是一种像矩阵一样访问像素的好方法。
猜你喜欢
  • 1970-01-01
  • 2022-01-10
  • 2013-06-06
  • 1970-01-01
  • 2015-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多