Search code examples
javascriptiosipadcanvasmobile-safari

When scaling and drawing an image to canvas in iOS Safari, width is correct but height is squished


I am loading an image and then drawing that image to a canvas. I am also scaling the image down to fit the canvas. When I do this, the image draws onto the canvas at the proper width but the height is about 1/4 of what the canvas' actual height is.

//Calculate height from canvas-to-image width ratio
var width = canvas.width;
var height = ( width / img.width ) * img.height;

//Draw scale image (This results in a squished height, despite "height" being correct)
context.drawImage( image, 0, 0, img.width, img.height, 0, 0, width, height );

Even though height is correct (checked in console), the image draws to the canvas at a much smaller height.

Also, when I check the ratio of the canvas.width / canvas.height vs img.width / img.height I get: .707234 vs .707818. That's so close it could not account for the huge height problem.

Why does this happen? How do I fix this?

EDIT: On Chrome, this exact code shows correctly.


Solution

  • This is a bug in iOS Safari. It's described here: Mobile Safari renders <img src="data:image/jpeg;base64..."> scaled on Canvas?

    Solution is here: https://github.com/stomita/ios-imagefile-megapixel

    Problem

    If you have an image with very high resolution (greater than 1024x1024) it will be subsampled (reduces the number of pixels by 16x). When doing this, Safari introduces an error that results in a too-small vertical height.

    Solution

    To solve, this, you take small chunks of the image (like reading from a file into a buffer in chunks), adjust for the vertical height differential, draw just those to a temporary canvas, and then draw that temporary canvas' pixels to the destination canvas.