为什么putImageData这么慢? [英] Why is putImageData so slow?

查看:245
本文介绍了为什么putImageData这么慢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一个相对较大的Canvas绘制各种(复杂)的东西。然后我想保存画布的状态,所以我可以快速重置它的状态,现在是在稍后的点。我使用getImageData为此和存储在一个变量的数据。然后我绘制一些更多的东西到画布,并将稍后重置画布到当它保存它的状态,使用putImageData的状态。



然而,事实证明,putImageData非常慢。事实上,它比从头开始重绘整个画布要慢,这涉及到几个drawImage覆盖大部分表面,还有超过40.000个lineTo操作,后面跟着笔画和填充。



从头开始重绘约2000 x 5000像素的画布大约需要170ms,使用putImageData虽然需要高达240ms。为什么putImageData与重绘canvas相比很慢,虽然重绘画布涉及用drawImage填充几乎整个画布,然后再使用lineTo,stroke和fill用多边形填充大约50%的画布。所以基本上每个像素在重画时至少触摸一次。



因为drawImage似乎要快得多,所以putImageData(毕竟drawImage部分重绘canvas需要小于30ms)。我决定尝试保存画布的状态不使用getImageData,而是使用canvas.toDataURL,然后从数据URL创建一个图像,我会坚持到drawImage绘制到画布。原因是这整个过程更快,只需要大约35ms完成。



那么为什么putImageData这么慢的替代(使用getDataURL或简单的重绘)?我怎么能进一步加快速度?



(所有的数字都是使用Firefox内的Firebug来测量的)

解决方案

只是一个小小的更新,最好的方法是这样做。我实际上在高性能ECMAScript和HTML5画布(pdf,德语)上写了我的学士学位论文,因此我收集了一些专业知识这个话题现在。最明显的解决方案是使用多个canvas元素。从一个画布到另一个画布上的绘制速度与将任意图像绘制到画布上一样快。因此,存储画布的状态与使用两个画布元素时再次恢复一样快。



这个jsPerf测试用例非常清楚地显示了各种方法及其优点和缺点。



为了完整性,应:

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

根据浏览器的不同,这个解决方案的速度比获得upvote的速度快5000倍。 p>

I am working with a relatively large Canvas where various (complex) stuff is drawn to. I then want to save the Canvas' state, so I can quickly reset it to the state it now is at a later point. I use getImageData for this and store the data in a variable. I then draw some more stuff to the canvas and will later reset the Canvas to where it was when I saved it's state, using putImageData.

However, it turns out, that putImageData is very slow. Infact, it is slower than simply redrawing the entire Canvas from scratch, which involves several drawImage covering most of the surface, and over 40.000 lineTo operations followed up by strokes and fills.

Redrawing the approx 2000 x 5000 pixel canvas from scratch takes ~ 170ms, using putImageData though takes whopping 240ms. Why is putImageData so slow compared to redrawing the canvas, although redrawing the canvas involves filling nearly the entire canvas with drawImage and then again filling roughly 50% of the canvas with polygons using lineTo, stroke and fill. So basicly every single pixel ist touched at least once when redrawing.

Because drawImage seems to be so much faster then putImageData (after all, the drawImage part of redrawing the canvas takes less than 30 ms). I decided to try to save the state of the canvas not using getImageData, but instead using canvas.toDataURL and then creating an Image from the data URL which I would stick into drawImage to draw it to the canvas. Turns out this whole procedure is much faster and only takes roughly 35ms to complete.

So why is putImageData so much slower then the alternatives (using getDataURL or simply redrawing)? How could I speed things up further? Is there and if, what is in general the best way to store the state of a canvas?

(All the numbers are measured using Firebug from within Firefox)

解决方案

Just a small update on what the best way is to do this. I actually wrote my Bachelor Thesis on High Performance ECMAScript and HTML5 Canvas (pdf, german), so I gathered some expertise on this topic by now. The clearly best solution is to use multiple canvas elements. Drawing from one canvas onto another canvas is just as fast as drawing an arbitary image to a canvas. Thus "storing" the state of a canvas is just as fast as restoring it later again when using two canvas elements.

This jsPerf testcase shows the various approaches and their benefits and drawbacks very clearly.

Just for completeness, here how you really should do it:

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

This solution is, depending on browser, up to 5000x faster than the one getting the upvotes.

这篇关于为什么putImageData这么慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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