我正在创建一个JS画布,我想在其中显示一个不同颜色的框。
我正在使用uint32来提高速度,我的颜色永远不会正确显示! 我在这里主要看了一些例子:https://stackoverflow.com/a/19502117有人在评论中说:
(小I或JS会抛出错误)。 OP的提示:Uint32的颜色也可以简单地使用十六进制 - 不需要进行移位:0xff00000 =黑色+ alpha设置为255;对于little-endian / LSB CPU,与big-endian / MSB CPU相反。“
我确定我的笔记本电脑是小端的。
我在这里有一个关于我的问题的演示:http://jsfiddle.net/GhwUC/357/
Sponsorship.first
这里讨论的颜色是:
其他颜色也一样,非常感谢!
编辑:感谢@Oriol快速回答!我使用以下函数来反转我的颜色(如果有人感兴趣的话):
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);
使用它: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);
};
答案 0 :(得分:5)
当您将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
,它允许指定字节序,默认为大端:
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>
答案 1 :(得分:3)
最佳解决方案是进行endian测试。
var isLittleEndian = true;
(()=>{
var buf = new ArrayBuffer(4);
var buf8 = new Uint8ClampedArray(buf);
var data = new Uint32Array(buf);
data[0] = 0x0F000000;
if(buf8[0] === 0x0f){
isLittleEndian = false;
}
})();
根据测试写入像素。
var imageData = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
var data = new Uint32Array(imageData.data.buffer);
var val = 0xffffd780;
if(isLittleEndian){
val = 0x80d7ffff;
}
var i = 0;
while(i < data.length) {
data[i++] = val;
}
了解效果
在使用(查看)view.Uint32(i,val);
编写一个值所花费的时间内,您可以使用(直接)data[i] = val;
Firefox的统计数据。
用于恒定循环时间测试。
首先%是总数的百分比。第二个百分比是最快(直接)
的百分比每10,000次写入的演出时间(1 / 1,000,000秒的时间)
请注意View的高差异值是由于Javascript优化。通过View进行短暂的写入突发可能会慢得多。
对于每10,000次写入的性能时间(1 / 1,000,000秒的时间),允许方差稳定。
根据评论中的要求进行更多测试。测试单元是对其中一个测试功能的调用。因此,在以下测试中,每个测试单元10000个32位写入。
比较8Bit写入32Bit写入
功能测试
testFunctions = [{
func:function(){
for(i = 0; i < 40000; i ++){
data[i++] = 0xFF;
data[i++] = 0xFF;
data[i++] = 0xd7;
data[i] = 0x80;
}},
name:"8Bit",
},{
func:function(){
for(i = 0; i < 10000; i ++){
view2[i] = 0x80d7ffff;
}},
name:"32Bit",
}
];
共同背景
var i
var i,arr;
var data = new Uint8ClampedArray(100000);
var view2 = new Uint32Array(data.buffer);
测试结果raw dump。
Test complete Results.
Function name, Calls per sec, % cycle time, % of best time
32Bit : 33743 : 76.84% 100%.
8Bit : 10170 : 23.16% 30.14%
Total cycles : 1000
Stable cycles : 899 Total.
Tests per cycle : 660
Testing cycles stable for : 800 of 800 cycles 100.00%
Max test variance 0.000%
Test results are good.
List of all test function results.
Mean times in micro secs 1/1,000,000 times mark with ms in milliseconds 1/1,000
# calls, total time, mean time
--------------------
Test function : 8Bit
62264 tests 6122.825ms Mean : 98
61942 tests 6088.945ms Mean : 98
62283 tests 6124.810ms Mean : 98
62233 tests 6121.010ms Mean : 98
Variance : 0.000micro sec. normalised : 0.000%
Ran : 248722 over 24457.590ms Mean : 98.333micro sec
--------------------
Test function : 32Bit
62084 tests 1839.180ms Mean : 30
61738 tests 1829.285ms Mean : 30
62282 tests 1846.225ms Mean : 30
62390 tests 1849.650ms Mean : 30
Variance : 0.000micro sec. normalised : 0.000%
Ran : 248494 over 7364.340ms Mean : 29.636micro sec
Total number of tests run : 497216
查看和直接撰写
本答案开头描述的测试运行的详细视图。
功能和共享上下文
sharedFunction = function(){
var i;
var data = new Uint8ClampedArray(100000);
var view1 = new DataView(data.buffer);
var view2 = new Uint32Array(data.buffer);
}
testFunctions = [{
func:function(){
for(i = 0; i < 10000; i ++){
view1.setUint32(i, 0x80d7ffff);
}
},
name:"View",
},{
func:function(){
for(i = 0; i < 10000; i ++){
view2[i] = 0x80d7ffff;
}},
name:"Direct",
}
];
结果
Test complete Results.
Calls per sec, % cycle time, % of best time
Direct : 35766 : 97.07% 100%.
View : 1080 : 2.93% 3.02%
Total cycles : 1000
Stable cycles : 899 Total.
Tests per cycle : 73
Testing cycles stable for : 800 of 800 cycles 100.00%
Max test variance 5.231%
Test results are good.
Mean times in micro secs 1/1,000,000 times mark with ms in milliseconds 1/1,000
# calls, total time, mean time
--------------------
Test function : View
8583 tests 7850.680ms Mean : 915
8454 tests 7830.950ms Mean : 926
8201 tests 7639.375ms Mean : 932
8459 tests 7883.150ms Mean : 932
Variance : 48.445micro sec. normalised : 5.231%
Ran : 33697 over 31204.155ms Mean : 926.022micro sec
--------------------
Test function : Direct
8434 tests 235.295ms Mean : 28
8347 tests 234.190ms Mean : 28
8451 tests 237.045ms Mean : 28
8260 tests 229.900ms Mean : 28
Variance : 0.009micro sec. normalised : 0.033%
Ran : 33492 over 936.430ms Mean : 27.960micro sec
Total number of tests run : 67189
注意每个测试功能作为4个独立的功能运行。当所有4个当前循环测试时间与先前的测试循环时间匹配时,稳定测试。 Javascript优化会导致时间变化,因为无法确定何时发生优化,测试代码会等待所有测试函数返回至少100个循环的稳定时间。进一步的循环时间不稳定性将在方差值中显示。
每个周期的测试是一个平均值(未在结果中注明)
所有测试函数都是通过
以随机顺序运行的testFunction[ Math.floor(Math.random() * testFunctionCount * testsPerFunction) ]();
时间是
performance.now();
,仅测量测试函数的内部内容。