我有一个BGRA数组,需要将其绘制到画布上。
目前我正在这样做:
var aVal = returnedFromChromeWorker;
var can = doc.createElementNS(NS_HTML, 'canvas');
can.width = aVal.width;
can.height = aVal.height;
var ctx = can.getContext('2d');
ctx.putImageData(aVal, 0, 0);
doc.documentElement.appendChild(can);
有什么办法可以将BGRA数组放到画布上吗?我正在探索:https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/imgIEncoder
我无法对阵列进行重新排序,因为我的目标是拍摄屏幕快照,即使对于大屏幕,即使是1280x1024,也需要2.3秒才能完成重新排列。
我尝试在ctypes端重新排序,但这给了我一个古怪的问题:0,使整个图像不可见> _ BITMAPV5HEADER getting RGBA keep A at 255
最佳答案
如何将BGRA数组放入画布而无需重新排序
空无一人。
必须重组字节顺序,因为画布只能保存RGBA格式的数据(小尾数,即缓冲区中的ABGR)。这是执行此操作的一种方法:
您可以为工作人员增加一个额外的步骤来处理重新排序。为原始字节缓冲区(ArrayBuffer)创建一个DataView
,然后迭代每个Uint32值。
在Uint32之下被读取为little-endian。这是因为在这种情况下,这种格式更容易互换,因为我们只需要右移BGR并将A放回前面即可。如果您的原始缓冲区在big-endian中,则您当然需要将其读取为big-endian,然后再设置为little-endian(getUint32(pos,false)):
例
var uint32 = new Uint32Array(1), pos = 0; // create some dummy data
var view = new DataView(uint32.buffer); // create DataView for byte-buffer
var pos = 0; // byte-position (we'll skip 4 bytes each time)
// dummy data in BGRA format
uint32[0] = 0x7722ddff; // magenta-ish in BGRA format
document.write("BGRA: 0x" + (uint32[0]).toString(16) + "<br>");
// --- Iterate buffer, for each: ---
var v = view.getUint32(pos, true); // BGRA -> RGBA, read as little-endian
var n = (v >>> 8) | (v << 24); // rotate - move A from last to first position
view.setUint32(pos, n, true); // set back
pos += 4; // do this when inside the loop
// result
document.write("ABGR: 0x" + (uint32[0]>>>0).toString(16));
更新如果两端的字节顺序(字节顺序)相同,则可以跳过
DataView
并直接使用Uint32Array
,这也会加快速度:var uint32 = new Uint32Array(1), pos = 0; // create some dummy data
// inside loop:
var v = uint32[pos];
uint32[pos++] = (v >>> 8) | (v << 24); // pos index is now per uint32
关于javascript - 如何将BGRA数组放入 Canvas 而无需重新排序,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30110973/