javascript - 使用 Uint32Array : Wrong colors are being rendered 的 Canvas

标签 javascript html canvas 32-bit

我目前正在创建一个 JS Canvas ,我想在其中显示不同颜色的框。

我正在使用 uint32 来提高速度,但我的颜色始终无法正确显示! 我主要看了这里的例子:https://stackoverflow.com/a/19502117有人在评论中说:

(small I or JS will throw an error). Tip for OP: colors for Uint32 can also be given simply be using hex - no need to do shifting: 0xff00000 = black + alpha set to 255; for little-endian/LSB CPUs, opposite on big-endian/MSB CPUs."

我确定我的笔记本电脑是小端的。

我在这里有我的问题的演示:http://jsfiddle.net/GhwUC/357/

var canvas = document.getElementById('canvas');
var canvasWidth  = canvas.width;
var canvasHeight = canvas.height;
var ctx = canvas.getContext('2d');
var imageData = ctx.getImageData(0, 0, canvasWidth, canvasHeight);

var buf = new ArrayBuffer(imageData.data.length);
var buf8 = new Uint8ClampedArray(buf);
var data = new Uint32Array(buf);

for (var y = 0; y < canvasHeight; ++y) {
    for (var x = 0; x < canvasWidth; ++x) {
        data[y * canvasWidth + x] = 0xff80d7ff // Should be light blue (#80d7ff)
    }
}

imageData.data.set(buf8);

ctx.putImageData(imageData, 0, 0);

这里有问题的颜色是:

color

但是 fiddle 显示黄色: color fail

其他颜色也一样,先谢谢了!

编辑:感谢@Oriol 的快速回答!我使用以下函数来反转我的颜色(以防有人感兴趣):

function reverseUint32 (uint32) {
    var s32 = new Uint32Array(4);
    var s8 = new Uint8Array(s32.buffer);
    var t32 = new Uint32Array(4);
    var t8 = new Uint8Array(t32.buffer);        
    reverseUint32 = function (x) {
        s32[0] = x;
        t8[0] = s8[3];
        t8[1] = s8[2];
        t8[2] = s8[1];
        t8[3] = s8[0];
        return t32[0];
    }
    return reverseUint32(uint32);
};

像这样使用:reverseUint32(0xfc66feff)

最佳答案

当您将 Uint8Array 缓冲区视为 little endian 中的 Uint32 时,会发生这种情况:

var buf = new Uint8Array([0x12, 0x34, 0x56, 0x78]).buffer;
console.log(new Uint32Array(buf)[0].toString(16));
// "78563412" in little endian, "12345678" in big endian

因此在小端中,顺序变为 AABBGGRR 而不是 AARRGGBB。

您可以将 0x80d7ffff 反转为 0xffffd780,但这样就无法在大端机器上运行。

为避免这些问题,您可以使用 DataView,它允许指定字节序,默认为大字节序:

view.setUint32(offset, 0xffffd780, true);  // #80d7ff, in little endian
view.setUint32(offset, 0x80d7ffff, false); // #80d7ff, in big endian

var canvas = document.getElementById('canvas'),
    canvasWidth  = canvas.width,
    canvasHeight = canvas.height,
    ctx = canvas.getContext('2d'),
    imageData = ctx.getImageData(0, 0, canvasWidth, canvasHeight),
    view = new DataView(imageData.data.buffer);
for (var y = 0; y < canvasHeight; ++y) {
  for (var x = 0; x < canvasWidth; ++x) {
    var offset = 4 * (y * canvasWidth + x);
    view.setUint32(offset, 0x80d7ffff); // light blue (#80d7ff)
  }
}
ctx.putImageData(imageData, 0, 0);
<canvas id="canvas" height="256" width="256"></canvas>

不过好像浏览器对DataView优化不多,所以比较慢。那么最好在 Uint8ClampedArray 中单独设置颜色分量:

var canvas = document.getElementById('canvas'),
    canvasWidth  = canvas.width,
    canvasHeight = canvas.height,
    ctx = canvas.getContext('2d'),
    imageData = ctx.getImageData(0, 0, canvasWidth, canvasHeight),
    data = imageData.data;
for (var y = 0; y < canvasHeight; ++y) {
  for (var x = 0; x < canvasWidth; ++x) {
    var offset = 4 * (y * canvasWidth + x);
    // light blue (#80d7ff)
    data[offset+0] = 0x80; // red
    data[offset+1] = 0xd7; // green
    data[offset+2] = 0xff; // blue
    data[offset+3] = 0xff; // alpha
  }
}
ctx.putImageData(imageData, 0, 0);
<canvas id="canvas" height="256" width="256"></canvas>

关于javascript - 使用 Uint32Array : Wrong colors are being rendered 的 Canvas ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39213661/

相关文章:

javascript - JavaScript V5中的bind和JQuery之间有什么关系吗?

javascript - 展平使用 d3.js 嵌套创建的对象层次结构

html - 分享按钮 - 悬停和 Googleplus/Facebook 链接

css - 3个div在同一行的水平对齐

javascript - 如何清除 Canvas 但保留填充?

javascript - 我可以用 HTML5 Canvas 重现这种效果吗?

javascript - 如何判断图像是否触及屏幕顶部?

javascript - 小屏幕的 scaleY 属性未正确维护

javascript - 如何使用Javascript从HTML元素中获取数据?

javascript - 如何将php数据传递给kinetic js