Canvas getImageData()为了获得最佳性能。要拉出所有数据还是一次一个? [英] Canvas getImageData() For optimal performance. To pull out all data or one at a time?

查看:2222
本文介绍了Canvas getImageData()为了获得最佳性能。要拉出所有数据还是一次一个?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要扫描一个画布图像中的每个像素,并做一些fiddling与颜色等。为了最佳性能,我应该一次抓住所有的数据,并通过数组工作?或者我应该调用每个像素,因为我的工作。

I need to scan through every pixel in a canvas image and do some fiddling with the colors etc. For optimal performance, should I grab all the data in one go and work on it through the array? Or should I call each pixel as I work on it.

基本上...

data = context.getImageData(x, y, height, width);

VS

data = context.getImageData(x, y, 1, 1); //in a loop height*width times.


推荐答案

所有的一次,因为:
a)a(连续)访问数组的方式比函数调用快。
b)特别是当这个函数是一个DOM对象的方法有一些开销。
c),并且可能有缓冲区刷新问题,可能会延迟响应(如果画布是
在视线...或不取决于双缓冲实现)。

You'll get much higher performances by grabbing the image all at once since : a) a (contiguous) acces to an array is way faster than a function call. b) especially when this function isa method of a DOM object having some overhead. c) and there might be buffer refresh issues that might delay response (if canvas is on sight... or not depending on double buffering implementation).

所以去一次性抓。

我建议您查看Javascript类型数组,以获取
imageData结果的最大值。

I'll suggest you look into Javascript Typed Arrays to get the most of the imageData result.

如果我可以引用自己,看看你如何可以处理像素在这个老帖子我的
(看看2)后快速):

If i may quote myself, look at how you can handle pixels fast in this old post of mine (look after 2) ):

(引用下面的相关部分)

(i quoted the relevant part below : )

您可以在ImageData上获得UInt32Array视图与:

You can get a UInt32Array view on your ImageData with :

var myGetImageData = myTempCanvas.getImageData(0,0,sizeX, sizeY);
var sourceBuffer32     = new Uint32Array(myGetImageData.data.buffer);

那么sourceBuffer32 [i]包含红色,绿色,蓝色和透明度打包成一个无符号32位int 。比较它到0知道像素是否是非黑色的(!=(0,0,0,0))

then sourceBuffer32[i] contains Red, Green, Blue, and transparency packed into one unsigned 32 bit int. Compare it to 0 to know if pixel is non-black ( != (0,0,0,0) )

或者你可以更精确的Uint8Array视图:

OR you can be more precise with a Uint8Array view :

var myGetImageData = myTempCanvas.getImageData(0,0,sizeX, sizeY);
var sourceBuffer8     = new Uint8Array(myGetImageData.data.buffer);

如果你只处理灰度阴影,那么R = G = B, p>

If you deal only with shades of grey, then R=G=B, so watch for

sourceBuffer8[4*i]>Threshold

,您可以使用UInt32Array视图一次将第i个像素设置为黑色:

and you can set the i-th pixel to black in one time using the UInt32Array view :

sourceBuffer32[i]=0xff000000;

设置为任何颜色/字母:

set to any color/alpha with :

sourceBuffer32[i]= (A<<24) | (B<<16) | (G<<8) | R ;

或只适用于任何颜色:

sourceBuffer32[i]= 0xff000000 | (B<<16) | (G<<8) | R ;

(请确保R是圆角)。

听到@ Ken的评论,是endianness可能是一个问题,当你开始与位32战斗一次。
大多数计算机都使用little-endian,因此当处理32bits一次时,RGBA变成ABGR。

由于是绝大多数系统,如果处理32位整数,假设这是case ,
,你可以兼容性 - 在Big endian系统上写32位结果之前,反转你的计算。让我分享这两个函数:

Listening to @Ken's comment, yes endianness can be an issue when you start fighting with bits 32 at a time. Most computer are using little-endian, so RGBA becomes ABGR when dealing with them 32bits a once.
Since it is the vast majority of systems, if dealing with 32bit integer assume this is the case, and you can -for compatibility- reverse your computation before writing the 32 bits results on Big endian systems. Let me share those two functions :

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);
};

这篇关于Canvas getImageData()为了获得最佳性能。要拉出所有数据还是一次一个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆