javascript - HTML5 Canvas - 如何从线性化图像数据 Uint8ClampedArray 获取相邻像素位置?

标签 javascript html canvas

线性化图像数据数组中的 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/

相关文章:

javascript - Android Webview,formhash 在某些 Android 设备上不工作

html - 在子菜单上使用滚动条时如何显示子菜单?

javascript - .js 脚本没有响应

php - 显示在使用 php 从 mysql 检索的内容上的特殊字符

在 "for"循环中使用的html5 jcanvas点击功能出错了

javascript - ionic 部署上未加载插件

javascript - Cordova cordova-plugin-qrscanner : Opaque camera view

javascript - 在 vue 中,如何检查是否有父组件订阅了子组件发出的事件?

javascript - 有没有一种方法可以在不使用三 Angular 函数的情况下处理 Angular (Javascript)

javascript - 如何使用 FabricJS 绘制 1/16 英寸乘 1/16 英寸的网格