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

时间:2017-08-30 14:38:34

标签: javascript html5 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,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,220, 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,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,0,0,0,0,0,0,0,0,0 ,0,0,0,0,0]

因此,3x3像素数据为-0 0 0 255.如何获得相邻的像素位置?左右相邻的很容易,分别只有4和4加。

2 个答案:

答案 0 :(得分:3)

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

IEnumerable

To move down one pixel

IEnumerable<Voter>

To move up one

public class VoterWithPollName {
    public long Id { get; set; }
    public sitrng FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public DateTime DateBirth { get; set; }
    public sting Gender { get; set; }
    public string ResidentialAddress { get; set; }
    public string PollName { get; set; }
    public long VoterIDNumber { get; set; }
    public string LifeStatus { get; set; }
}

...

// set method return type to IEnumerable<VoterWithPollName>

var results = (from voter in context.Voters
                          join voter2 in context.PollingShehias on voter.PollingStationId equals voter2.PollingStationId
                          join poll in context.PollingStations on voter.PollingStationId equals poll.Id
                          where voter2.WordId == Id
                          orderby voter.FirstName, voter.MiddleName, voter.LastName, voter.Gender ascending
                          select new VoterWithPollName
                          {
                              Id = voter.Id,
                              FirstName = voter.FirstName,
                              MiddleName = voter.MiddleName,
                              LastName = voter.LastName,
                              DateBirth = voter.DateBirth,
                              Gender = voter.Gender,
                              ResidentialAddress = voter.ResidentialAddress,
                              PollName = poll.Name,
                              VoterIDNumber = voter.VoterIDNumber,
                              LifeStatus = voter.LifeStatus
                          });

return results;

To move left.

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 right

index += imageData.width * 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

index -= imageData.width * 4;

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

index -= 4;

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

index += 4;

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

 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

You can set all the pixels in a single call

 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 copy array data onto the array with

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

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 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 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.

答案 1 :(得分:2)

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

访问权限为零。

&#13;
&#13;
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]
&#13;
&#13;
&#13;