Reputation:
I have a 2D matrix of hexadecimal RGB values which represents an image. Ideally I'd like to call a function like "putImageData" on it to draw the image on a canvas. However, it isn't in the right format.
What is the best way to display my matrix as an image on a HTML5 Canvas?
Upvotes: 0
Views: 873
Reputation:
Whatever format your original source data is in it must be converted to a bitmap format compatible with canvas.
Luckily there is only one format and that is RGBA format using 8-bit values.
So say your source consists of 3 bytes, RGB, you simply map each pixel to the format of canvas.
To setup a bitmap you can take a Uint8Array and calculate its size using the width and height of the source matrix, and then multiply with 4 (RGBA):
var bitmap = new Uint8ArrayClampedArray(width * height * 4);
You could also, depending on how you want to pack the pixel data, use a Uint32Array in which case only width and height is used:
var bitmap = new Uint32Array(width * height);
And then set the buffer of it onto a clamped view.
But if we stick with the former for the sake of simplicity and assume (as you don't tell us) that the source is RGB (and 8:8:8 bits), you would do:
var srcBmp = ??, width = ??, height = ??;
var dstBmp = new Uint8ArrayClampedArray(width * height * 4);
var ptrSrc = 0; // source pointer
var ptrDst = 0; // destination pointer
var dstLen = dstBmp.length;
while(ptrDst < dstLen) {
dstBmp[ptrDst++] = dstBmp[ptrSrc++]; // copy R
dstBmp[ptrDst++] = dstBmp[ptrSrc++]; // copy G
dstBmp[ptrDst++] = dstBmp[ptrSrc++]; // copy B
dstBmp[ptrDst++] = 255; // set alpha to opaque
}
// finally create a ImageData object using the typed array:
var idata = new ImageData(dstBmp, width, height);
ctx.putImageData(idata, x, y); // set x and y
If your format is reverse, which is often the case with BMP files for instance, you would do something like this instead, still assuming only RGB:
while(ptrDst < dstLen) {
dstBmp[ptrDst++] = dstBmp[ptrSrc+2]; // copy R from BGR
dstBmp[ptrDst++] = dstBmp[ptrSrc+1]; // copy G
dstBmp[ptrDst++] = dstBmp[ptrSrc ]; // copy B
dstBmp[ptrDst++] = 255; // set alpha to opaque
ptrSrc += 3; // skip to next source pixel
}
For 16-bit values or floating point you would first convert the component value into a 8-bit integer one [0, 255]. There is only the case of stride handling in case you use formats such as BMP, and other special cases, but since there is no information about it I'll leave the answer as a generic one.
And so forth. Its just a matter of finding the mapping for the pixel format and extract each component and then insert that to the destination bitmap for canvas.
Upvotes: 1