首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么putImageData这么慢?

为什么putImageData这么慢?
EN

Stack Overflow用户
提问于 2010-10-17 18:37:32
回答 4查看 16.5K关注 0票数 39

我正在使用一个相对较大的画布,在那里可以画出各种(复杂的)东西。然后我想保存画布的状态,这样我就可以在以后快速地将它重置为现在的状态。为此,我使用getImageData并将数据存储在一个变量中。然后,我在画布上绘制了更多的内容,稍后将使用putImageData将画布重置为保存状态时的位置。

然而,事实证明,putImageData非常慢。事实上,它比简单地从头开始重新绘制整个画布要慢,这涉及到覆盖大部分表面的几个drawImage,以及随后的40.000多个笔划和填充的lineTo操作。

从头开始重新绘制大约2000x5000像素的画布需要大约170ms,而使用putImageData则需要高达240ms。尽管重绘画布需要用drawImage填充几乎整个画布,然后使用lineTo、笔划和填充再次用多边形填充大约50%的画布,但为什么putImageData比重绘画布要慢得多。因此,基本上每个像素都会在重绘时至少接触一次。

因为drawImage似乎比putImageData快得多(毕竟,重新绘制画布的drawImage部分只需要不到30ms)。我决定不使用getImageData保存画布的状态,而是使用canvas.toDataURL,然后从data URL创建一个图像,然后将其粘贴到drawImage中以将其绘制到画布上。事实证明,整个过程要快得多,只需要大约35ms就可以完成。

那么,为什么putImageData比其他选择(使用getDataURL或简单地重绘)要慢得多呢?我如何才能进一步加快速度呢?通常情况下,存储画布状态的最佳方法是什么?

(所有数字都是在Firefox中使用Firebug测量的)

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-05-15 00:28:34

只是关于最好的方法是什么的小更新。我的学士学位论文实际上是在High Performance ECMAScript and HTML5 Canvas上写的(pdf,德语;密码: stackoverflow),所以我现在收集了一些关于这个主题的专业知识。显然最好的解决方案是使用多个画布元素。从一个画布绘制到另一个画布的速度与将任意图像绘制到画布的速度一样快。因此,当使用两个画布元素时,“存储”画布的状态与稍后再次恢复它的速度一样快。

This jsPerf testcase非常清楚地展示了各种方法及其优缺点。

为了完整起见,下面是你真正应该怎么做:

代码语言:javascript
复制
// setup
var buffer = document.createElement('canvas');
buffer.width = canvas.width;
buffer.height = canvas.height;


// save
buffer.getContext('2d').drawImage(canvas, 0, 0);

// restore
canvas.getContext('2d').drawImage(buffer, 0, 0);

根据浏览器的不同,这个解决方案比获得好评的解决方案快5000倍。

票数 87
EN

Stack Overflow用户

发布于 2010-11-26 11:24:25

在Firefox3.6.8中,我可以通过使用toDataUrl/drawImage来解决putImageData速度慢的问题。对我来说,它的工作速度足够快,我可以在处理mousemove事件时调用它:

要保存:

代码语言:javascript
复制
savedImage = new Image()
savedImage.src = canvas.toDataURL("image/png")

要恢复的内容:

代码语言:javascript
复制
ctx = canvas.getContext('2d')
ctx.drawImage(savedImage,0,0)
票数 11
EN

Stack Overflow用户

发布于 2010-10-17 19:00:59

首先,您说您正在使用Firebug进行测量。实际上,我发现Firebug大大降低了JS的执行速度,因此您可能无法获得好的性能数据。

至于putImageData,我怀疑这是因为函数需要一个包含许多Number对象的大型JS数组,所有这些对象都必须检查范围(0..255)并复制到本机canvas缓冲区中。

也许一旦WebGL ByteArray类型可用,这类事情就会变得更快。

奇怪的是,base64解码和解压缩数据(使用PNG data URL)更快,但它只使用一个JS字符串调用一个JS函数,因此它主要使用本机代码和类型。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3952856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档