Pet*_*sen 3 html javascript 32-bit canvas
我正在创建一个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/
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);
Run Code Online (Sandbox Code Playgroud)
这里讨论的颜色是:
它在其他颜色上是一样的,非常感谢!
编辑:感谢@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);
};
Run Code Online (Sandbox Code Playgroud)
使用它像: 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 endianRun Code Online (Sandbox Code Playgroud)
因此在小端,订单变为AABBGGRR而不是AARRGGBB.
你可以扭转0x80d7ffff到0xffffd780,但那就不是在大端机器工作.
要避免这些问题,可以使用a DataView,它允许指定字节序,默认为big endian:
view.setUint32(offset, 0xffffd780, true); // #80d7ff, in little endian
view.setUint32(offset, 0x80d7ffff, false); // #80d7ff, in big endian
Run Code Online (Sandbox Code Playgroud)
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);Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas" height="256" width="256"></canvas>Run Code Online (Sandbox Code Playgroud)
但似乎浏览器没有太多优化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);Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas" height="256" width="256"></canvas>Run Code Online (Sandbox Code Playgroud)
最好的解决方案是进行字节序测试。
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;
}
})();
Run Code Online (Sandbox Code Playgroud)
根据测试写入像素。
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;
}
Run Code Online (Sandbox Code Playgroud)
性能概览
在使用 (View) 写入一个值所需的时间内,view.Uint32(i,val);您可以使用 (Direct) 写入 33 个值data[i] = val;
来自 Firefox 的统计数据。
用于恒定循环时间测试。
第一个 % 是占总数的百分比。第二个 % 是最快的百分比(直接)
每 10,000 次写入的性能时间(时间以 1/1,000,000 秒为单位)
请注意,View 的高方差值是由于 Javascript 优化造成的。通过 View 进行短时间的写入可能会显着变慢。
对于每 10,000 次写入的性能时间(时间为 1/1,000,000 秒),允许方差稳定。
根据评论中的要求,进行更多测试。测试单元是对测试功能之一的调用。因此,在以下测试中,每个测试单元 10000 次 32Bit 写入。
比较 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",
}
];
Run Code Online (Sandbox Code Playgroud)
常见上下文
var i
var i,arr;
var data = new Uint8ClampedArray(100000);
var view2 = new Uint32Array(data.buffer);
Run Code Online (Sandbox Code Playgroud)
测试结果原始转储。
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
Run Code Online (Sandbox Code Playgroud)
视图和直接写入
本答案开头描述的测试运行的详细视图。
函数和共享上下文
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",
}
];
Run Code Online (Sandbox Code Playgroud)
结果
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
Run Code Online (Sandbox Code Playgroud)
注意每个测试功能都作为 4 个独立的功能运行。稳定测试是指所有 4 个当前循环测试时间都与之前的测试循环时间相匹配。Javascript 优化会导致时间发生变化,并且由于无法确定何时进行优化,测试代码会等待所有测试函数返回至少 100 个周期的稳定时间。进一步的周期时间不稳定性将显示在方差值中。
每个周期的测试是平均值(结果中未注明)
所有测试功能都通过随机顺序运行
testFunction[ Math.floor(Math.random() * testFunctionCount * testsPerFunction) ]();Timing is via
performance.now();,只测量测试函数的内部内容。