lou*_*ong 6 javascript performance canvas
我需要扫描画布图像中的每个像素并做一些颜色等等.为了获得最佳性能,我应该一次性获取所有数据并通过阵列处理它吗?或者我应该在处理每个像素时调用它们.
基本上......
data = context.getImageData(x, y, height, width);
Run Code Online (Sandbox Code Playgroud)
VS
data = context.getImageData(x, y, 1, 1); //in a loop height*width times.
Run Code Online (Sandbox Code Playgroud)
Gam*_*ist 16
通过一次抓取图像,您将获得更高的性能,因为:a)对数组的(连续)访问比函数调用快得多.b)特别是当此函数是具有一些开销的DOM对象的方法时.c)并且可能存在可能延迟响应的缓冲区刷新问题(如果画布在视线上......或者不依赖于双缓冲实现).
所以去抓一次.
我建议你研究一下Javascript Typed Arrays,以获得最大的imageData结果.
如果我可以自己引用,请看看如何在我的这个旧帖子中快速处理像素(请看2)):
(我引用下面的相关部分:)
您可以在ImageData上获取UInt32Array视图:
var myGetImageData = myTempCanvas.getImageData(0,0,sizeX, sizeY);
var sourceBuffer32 = new Uint32Array(myGetImageData.data.buffer);
Run Code Online (Sandbox Code Playgroud)
然后sourceBuffer32 [i]包含红色,绿色,蓝色和透明度,打包成一个无符号的32位int.将其与0进行比较,以了解像素是否为非黑色(!=(0,0,0,0))
或者你可以使用Uint8Array视图更精确:
var myGetImageData = myTempCanvas.getImageData(0,0,sizeX, sizeY);
var sourceBuffer8 = new Uint8Array(myGetImageData.data.buffer);
Run Code Online (Sandbox Code Playgroud)
如果你只处理灰色阴影,那么R = G = B,所以请注意
sourceBuffer8[4*i]>Threshold
Run Code Online (Sandbox Code Playgroud)
并且您可以使用UInt32Array视图一次将第i个像素设置为黑色:
sourceBuffer32[i]=0xff000000;
Run Code Online (Sandbox Code Playgroud)
设置为任何颜色/ alpha:
sourceBuffer32[i]= (A<<24) | (B<<16) | (G<<8) | R ;
Run Code Online (Sandbox Code Playgroud)
或者只是任何颜色:
sourceBuffer32[i]= 0xff000000 | (B<<16) | (G<<8) | R ;
Run Code Online (Sandbox Code Playgroud)
(确保R是圆形的).
听@ Ken的评论,当你一次开始用32位进行战斗时,是的,结尾可能是一个问题.大多数计算机都使用little-endian,所以RGBA在处理32位一次时变为ABGR.
既然是绝大多数的系统中,如果处理32位整数假设是这样的话,你可以写-对于在大端系统的32个结果之前兼容性-扭转你的计算.让我分享这两个功能:
function isLittleEndian() {
// from TooTallNate / endianness.js. https://gist.github.com/TooTallNate/4750953
var b = new ArrayBuffer(4);
var a = new Uint32Array(b);
var c = new Uint8Array(b);
a[0] = 0xdeadbeef;
if (c[0] == 0xef) { isLittleEndian = function() {return true }; return true; }
if (c[0] == 0xde) { isLittleEndian = function() {return false }; return false; }
throw new Error('unknown endianness');
}
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)
除了 GameAlchemist 所说的,如果您想同时获取或设置一个像素的所有颜色,但又不想检查字节序,则可以使用DataView:
var data = context.getImageData(0, 0, canvas.width, canvas.height);
var view = new DataView(data.data.buffer);
// Read or set pixel (x,y) as #RRGGBBAA (big endian)
view.getUint32(4 * (x + y*canvas.width));
view.setUint32(4 * (x + y*canvas.width), 0xRRGGBBAA);
// Read or set pixel (x,y) as #AABBGGRR (little endian)
view.getUint32(4 * (x + y*canvas.width), true);
view.setUint32(4 * (x + y*canvas.width), 0xAABBGGRR, true);
// Save changes
ctx.putImageData(data, 0, 0);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6632 次 |
| 最近记录: |