Image not drawn correctly in canvas? Check the size attributes
2 min read

Image not drawn correctly in canvas? Check the size attributes

Here's an interesting fact about the HTML5 canvas that took us over an hour to figure (and a lot of nerves).

We were trying to break a large image into 4 equal canvases. The breaking only involved preserving the ratio of the image, not its size and scaling the pieces was also necessary, depending on the size of the browser window. The whole thing was about the iOS Safari PDF zooming, we wanted to see if using 4 smaller canvas objects consumed less memory, since using a single canvas caused a browser crash after a couple of images. Well, to be honest, I was quite certain that using 4 objects instead of one was a bad idea in this case but since someone else claimed it did, the best thing to do was to run some tests. Let me save you your time: it didn't. Using 4 canvases instead of one actually consumed more memory, but that's not the point.

We had a nasty problem with the image pieces: they weren't right. It looked like only a small portion was actually selected and scaled, and the whole 1/4th of the image for each canvas. We tried and tried and tried only to find out that the cause of it was the lack of an width and height for the canvas.

The basic idea was the following: we create 4 equal canvas elements, absolutely positioned. Since we wanted to draw a scaled image with a width and height way over the window size, no tricky positioning was involved. In the first canvas we drew the image starting from (0, 0) to (w/2, h/2), in the second from (w/2, 0) to (w, h/2) and so on. But instead of seeing the first quarter of the scaled image, we saw only a piece of the corner stretched to fill the canvas.

What we did wrong was to use CSS to set the canvas size, using style="width:x pixels; height: y pixels". This caused the canvas to be created at the default size of 350x150 pixels and then stretched to fit the size defined in the CSS. The fix was easy: declare a width and height for the canvas.

You can do this in three ways:

1. With html size attributes

<canvas id="canvas" width="512" height="512"> </canvas>

2. With object size attributes

<canvas id="canvas2">

var cnv2 = document.getElementById('canvas2'),
    ctx2 = cnv2.getContext('2d');

cnv2.width  = 512;
cnv2.height = 512;

ctx2.drawImage(img, 0, 0);

3. With object size attributes set from image

<canvas id="canvas3"> </canvas>

var cnv3 = document.getElementById('canvas3'),
    ctx3 = cnv5.getContext('2d'),
    img = new Image();

cnv3.width  = img.width;
cnv3.height = img.height;

ctx3.drawImage(img, 0, 0);

You can see the results here, on this test page I made, or read more about the subject on this StackOverflow question.