HTML5 Canvas drawImage ratio bug iOS HTML5 Canvas drawImage ratio bug iOS ios ios

HTML5 Canvas drawImage ratio bug iOS


If you still need to use the long version of the drawImage function you can change this:

context.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);

to this:

drawImageIOSFix(context, img, sx, sy, sw, sh, dx, dy, dw, dh);

You just need to include these two functions somewhere:

/** * Detecting vertical squash in loaded image. * Fixes a bug which squash image vertically while drawing into canvas for some images. * This is a bug in iOS6 devices. This function from https://github.com/stomita/ios-imagefile-megapixel *  */function detectVerticalSquash(img) {    var iw = img.naturalWidth, ih = img.naturalHeight;    var canvas = document.createElement('canvas');    canvas.width = 1;    canvas.height = ih;    var ctx = canvas.getContext('2d');    ctx.drawImage(img, 0, 0);    var data = ctx.getImageData(0, 0, 1, ih).data;    // search image edge pixel position in case it is squashed vertically.    var sy = 0;    var ey = ih;    var py = ih;    while (py > sy) {        var alpha = data[(py - 1) * 4 + 3];        if (alpha === 0) {            ey = py;        } else {            sy = py;        }        py = (ey + sy) >> 1;    }    var ratio = (py / ih);    return (ratio===0)?1:ratio;}/** * A replacement for context.drawImage * (args are for source and destination). */function drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {    var vertSquashRatio = detectVerticalSquash(img); // Works only if whole image is displayed: // ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio); // The following works correct also when only a part of the image is displayed:    ctx.drawImage(img, sx * vertSquashRatio, sy * vertSquashRatio,                        sw * vertSquashRatio, sh * vertSquashRatio,                        dx, dy, dw, dh );}

This will work fine whether it is run on iOS or other platforms.

This is based on the great work by stomita and you should credit him in your work.


There is a JavaScript canvas resize library which works around the subsampling and vertical squash issues encountered when drawing scaled images on canvas on iOS devices:http://github.com/stomita/ios-imagefile-megapixel

There are side issues when scaling images with alpha channel (as it uses the alpha channel for the issues detection) and when trying to resize existing canvas elements, however it's the first solution I've found that actually works with the issue at hand.

stomita is also a StackOverflow user and posted his solution here:https://stackoverflow.com/a/12615436/644048


It looks like this is an iOS 6 bug. There is no reason for the aspect to get out of whack from your code. I have the same problem which was only introduced in iOS 6. It seems that their sub-sampling routine gives the wrong height. I submitted a bug report to Apple, and you should do the same. The more bug reports they get for this the better.