8

I try to render a local image loaded with a FileReader object on a Canvas on Safari Mobile on iOS6. But every image with data-URL gets rendered vertically scaled. Is this a bug? On Chrome it's rendered correctly.

ScreenShot from iOS6 (above: Canvas, below: Original Image)

Is there any way to work-around this bug? Is this a bug?

If I resize the image on the device first with the "PhotoWizard" App (scale it down to 720px width), the Canvas renders it correctly. It seems to be a problem with image size or images taken with the Camera App:

Tried suggestions from Jake Archibald, looks a bit better, but still gets vertically scaled:

I tried it today on a Galaxy Nexus with Android 4.1.1 installed. Works like expected, so this really looks like a mobile Safari issue:

Michael
  • 41,989
  • 11
  • 82
  • 128
André Fiedler
  • 1,093
  • 4
  • 16
  • 25
  • I have found simular things when trying to resize an image in JS see – NimmoNet Sep 24 '12 at 13:57
  • Any workaround? I tried to add a five second delay between "onload" and getting the image w/h and rendering it on the canvas. Didn´t fix it. I also thought of "requestAnimationFrame" before rendering the image on the canvas, didn´t fixed it either. – André Fiedler Sep 24 '12 at 15:47
  • Tried to use a Blob URL like this: window.URL.createObjectURL(file) ... and load it into img.src Results in the same failure, rendering a image with "Blob-src" get´s also rendered vertically scaled on Canvas – André Fiedler Sep 24 '12 at 18:15

2 Answers2

30

This might be related to the restriction which resides in iOS Safari resource limitation. According to following link, JPEG files over 2M pixels will be subsampled.

https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/CreatingContentforSafarioniPhone/CreatingContentforSafarioniPhone.html#//apple_ref/doc/uid/TP40006482-SW15

I'm doubting that canvas in Safari cannot deal with this subsampling correctly.

I've created some workaround detecting whether the image is subsampled or not and stretching it to original size.

https://github.com/stomita/ios-imagefile-megapixel

Cœur
  • 37,241
  • 25
  • 195
  • 267
stomita
  • 476
  • 4
  • 2
  • When using above library, your sample becomes like this: http://jsbin.com/aqirel/13 OK with my iPhone5 (iOS 6.0). – stomita Sep 27 '12 at 06:33
  • 1
    Created an online demo of another file upload widget I just wrote. It can detect the iOS rendering issue. In case the image does not appear to have been rendered correctly, the image is re-rendered with a fix applied. Doubling the y scale by two seems to fix it too, see sources for details... http://sandbox.juurlink.org/html5imageuploader/ – Rob Juurlink Feb 13 '13 at 20:01
  • @stomita I used your library and while it fixed the vertical height issue, the image is showing in very poor/low resolution. Do you know how I would upscale to keep the resolution? – Don Rhummy May 11 '14 at 04:56
  • @stomita I figured it out. To get higher quality drawing, keep the tmpCanvas the same, but make the regular canvas like this: `canvas.height = canvas.height * 2; canvas.width = canvas.width * 2; ctx.scale( 2, 2 );` That will draw the image from tmpContext in a higher resolution. – Don Rhummy May 11 '14 at 05:16
  • @stomita This worked great for me on ios7. Thanks much. – gregdevs Sep 29 '14 at 19:19
0
var cnv = document.createElement("canvas");
        ctx = cnv.getContext("2d");

        image = new Image();

        image.src = src;

        image.onload = function() {

            var size = scaleSizeRatio(image.width,image.height);
            cnv.width = size[0];
            cnv.height = size[1];
            ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, image.width , image.height);

            var div = container;  
            div.appendChild(cnv);       

        }

ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, image.width , image.height); This function will fix the squeezing issue in iPod more than 3Mb. First if your image is more than 3Mb then calculate the scaled width and height for the image and set that width and height to the canvas. Then call the drawImage function. It will give the final image what you expected...