我有一个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/

10-09 14:32