Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using drawImage with Canvas is very slow on Chrome

I've been trying to draw a large number of instances of an SVG file to a canvas using drawImage. By creating a single image element using the SVG as the source, then using drawImage for each instance on the canvas, I was hoping I could produce a composite image in the canvas very quickly even with a large number of instances.

Performance-wise, this works well in Firefox - I can draw 60,000 instances in about 300ms. But on Chrome it is terribly slow: 16,000 instances is taking over 5 seconds. I've put a version of the code on jsfiddle, which demonstrates the problem on Chrome.

I've got an example of how I'm calling drawImage below, where the canvas is filled with as many size x size images as possible. I had read a suggestion to try using a second, hidden canvas to buffer all the instances, then update the visible canvas with one call. But that didn't impact performance, the individual drawImage calls still appear to be bogging things down.

Any thoughts on what's going wrong and what I can do to fix it?

            svgImg = new Image;

            can.width = 1800; can.height = 900;
            svgImg.onload = function () {
                if (internalSize == size)
                    return;
                internalSize = size;
                var timeBefore = new Date().getTime();
                var tot = 0;

                var canWidth = can.width;
                var canHeight = can.height;
                for (var x = 0; x < canWidth; x += size) {
                    for (var y = 0; y < canHeight; y += size) {
                        ctx.drawImage(svgImg, x, y, size, size);
                        tot++;
                    }
                }
                document.getElementById('count').innerHTML = "Total Count: " + tot;
                var timeAfter = new Date().getTime();
            };
            svgImg.src = "http://www.w3.org/Icons/SVG/svg-logo.svg";
            svgImg.width = size;
            svgImg.height = size;
like image 682
DerekMuk Avatar asked Apr 15 '13 18:04

DerekMuk


1 Answers

Slowdown 1: Occurs when either the source or destination canvas is in RAM and the other canvas is on GPU.

Slowdown 2: Occurs when src and dest canvases are different sizes


Relevant bug: http://code.google.com/p/chromium/issues/detail?id=170021

I have noticed the same issue, and simplified the case to drawing one blank canvas to another. It doesn't seem to be an issue when the canvases are the same size, but at a certain point performance takes a nose dive. Here is the jspref, and my results:

jspref chrome results

Notice the difference in 255x255 to 100x100 and 260x260 to 100x100.

like image 69
forresto Avatar answered Oct 18 '22 03:10

forresto