javascript - HTML5 Canvas - How to get adjacent pixels position from the linearized imagedata Uint8ClampedArray? - Stack Overflo

A 5 by 5 pixel image data is something like this in linearized imagedata array-[0, 0, 0, 0, 0, 0, 0, 0,

A 5 by 5 pixel image data is something like this in linearized imagedata 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, 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]

So, the 3x3 pixel data is- 0 0 0 255. How can I get the adjacent pixel positions? Left and right adjacent ones are easy, just minus 4 and plus 4 respectively.

A 5 by 5 pixel image data is something like this in linearized imagedata 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, 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]

So, the 3x3 pixel data is- 0 0 0 255. How can I get the adjacent pixel positions? Left and right adjacent ones are easy, just minus 4 and plus 4 respectively.

Share Improve this question edited Aug 30, 2017 at 14:47 yemon asked Aug 30, 2017 at 14:38 yemonyemon 639 bronze badges 2
  • You need to know the dimensions of the image, then it's easy as well - just minus 4*size and plus 4*size respectively. – Bergi Commented Aug 30, 2017 at 21:39
  • @Bergi Yes, image dimensions are easy to retrieve through image.width and image.height as I am using Image() constructor. – yemon Commented Aug 30, 2017 at 22:38
Add a ment  | 

2 Answers 2

Reset to default 6

Accessing pixel data

The pixel data from .getImageData().data is a TypedArray of type Uint8ClampedArray. When reading the values they will be in the range 0-255 and in the order Red, Green, Blue, Alpha. If the value of alpha is zero then red, green, and blue will also be zero.

To get the index of a pixel

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];

To move down one pixel

index += imageData.width * 4;

To move up one

index -= imageData.width * 4;

To move left.

index -= 4;

To move right

index += 4;

If you are on the left or right edge and you move in the direction of the edge you will wrap around, on the line above and to the right if moving left and the line below and on the left if moving down.

When setting the image data the values will be floored and clamped to 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

If you set an index that is outside the array size it will be ignored

 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

You can speed up access and processing by using different array types. For example all of a pixel's channels as one value using 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];

The channels are stored in bits 31-24 Alpha, 23-16 Blue, 15-8 Green, 7-0 Red.

You can set a pixel using a hex value

 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

You can set all the pixels in a single call

 pixels.fill(0xFF000000); // all pixels black

You can copy array data onto the array with

 // set 3 pixels in a row at x,y Red, Yellow, White
 pixels.set([0xFF0000FF,0xFF00FFFF,0xFFFFFFFF], x+y * imageData.width);

Warning

If the canvas has any pixel/s that are from an untrusted source it will be tainted and you will not be able to read the pixel data. Trusted sources are same domain or images served with the appropriate CORS header information. Images that are on the file system can not have their pixels accessed. Once a canvas is tainted it can not be cleaned.

A tainted canvas will throw an error when you call ctx.getImageData(0,0,1,1,) MDN does not list this exception for some reason. You will see "SecurityError" DOMException; in the DevTools console and there are plenty of answered question here in StackOverflow on the subject.

You could calculate the index with the width of the matrix and the length of one unit of 4.

The access is zero based.

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]

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745611193a4635959.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信