ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

javascript – 使用Uint32Array的Canvas:正在呈现错误的颜色

2019-07-27 12:37:26  阅读:369  来源: 互联网

标签:html 32-bit javascript canvas


我正在创建一个JS画布,我想在其中显示一个不同颜色的框.

我正在使用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

但小提琴显示黄色的颜色:
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缓冲区视为小端的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,它允许指定字节序,默认为big endian:

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>

标签:html,32-bit,javascript,canvas
来源: https://codeday.me/bug/20190727/1554127.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有