Fastest canvas drawing (v38)

Revision 38 of this benchmark created by OpenGG on


Description

What is the fastest way to draw on a canvas? Image from public URL? Image from data URL? Image from URL.createObjectURL? Canvas used as image?

I'm testing this to know what method to use for storing and blitting tiles in a 2D tile engine.

Preparation HTML

<canvas id="canvas" width="400" height="300"></canvas>
<script>
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    var img = new Image();
    var imgpix;
    var dataImg = new Image();
    var objectImg = new Image();
    var cvsImg = document.createElement('canvas');
    var width;
    var height;
    (function(){
        function toBlob(str){
            var chunks = str.split(',');
            var byteString = atob(chunks[1]);
            var arrayBuffer = new ArrayBuffer(byteString.length);
            var intArray = new Uint8Array(arrayBuffer);
            for (i = 0; i < byteString.length; i += 1) {
                intArray[i] = byteString.charCodeAt(i) & 0xff;
            }
            var mimeString = chunks[0].split(':')[1].split(';')[0];
            return new Blob(
                [arrayBuffer],
                {type: mimeString}
            );
        }
        var URL = window.URL || window.webkitURL;
        var url = 'http://www.baidu.com/img/bdlogo.gif';
        img.addEventListener('load', function onLoad() {
            img.removeEventListener('load', onLoad, false);
            var t = document.createElement('canvas');
            var c = t.getContext('2d');
            width = cvsImg.width = canvas.width = t.width = img.width;
            height = cvsImg.height = canvas.height = t.height = img.height;
            ctx.fillStyle = '#000';
            ctx.fillRect(0,0,width,height);
            c.drawImage(img, 0, 0);

            var b64Str = t.toDataURL('image/png');
            dataImg.src = b64Str;

            function onBlob(blob){
                var url = URL.createObjectURL(blob);
                objectImg.addEventListener('load', function onLoad(){
                    objectImg.removeEventListener('load', onLoad, false);
                    URL.revokeObjectURL(url);
                }, false);
                objectImg.src = url;
            }
            if(t.toBlob){
                t.toBlob(onBlob);
            }else{
                onBlob(toBlob(b64Str));
            }
            
            cvsImg.getContext('2d').drawImage(img, 0, 0);
            
            imgpix = c.getImageData(0,0, width, height);
        }, false);
        img.crossOrigin = '';
        img.src = url;
    })();
</script>

Setup

ctx.clearRect(0, 0, width, height);

Test runner

Ready to run.

Testing in
TestOps/sec
Web URL Image
//ctx.globalCompositeOperation = 'source-in';
ctx.drawImage(img, 0, 0);
ready
data URL Image
//ctx.globalCompositeOperation = 'source-in';
ctx.drawImage(dataImg, 0, 0);
ready
createObjectURL Image
//ctx.globalCompositeOperation = 'source-in';
ctx.drawImage(objectImg, 0, 0);
ready
Canvas Image
//ctx.globalCompositeOperation = 'source-in';
ctx.drawImage(cvsImg, 0, 0);
ready
putImageData (pixel render)
//ctx.globalCompositeOperation = 'source-in';
ctx.putImageData(imgpix, 0, 0);
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.