/* * JavaScript Load Image iOS scaling fixes 1.0.3 * https://github.com/blueimp/JavaScript-Load-Image * * Copyright 2013, Sebastian Tschan * https://blueimp.net * * iOS image scaling fixes based on * https://github.com/stomita/ios-imagefile-megapixel * * Licensed under the MIT license: * http://www.opensource.org/licenses/MIT */ /*jslint nomen: true, bitwise: true */ /*global define, window, document */ (function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: define(['load-image'], factory); } else { // Browser globals: factory(window.loadImage); } }(function (loadImage) { 'use strict'; // Only apply fixes on the iOS platform: if (!window.navigator || !window.navigator.platform || !(/iP(hone|od|ad)/).test(window.navigator.platform)) { return; } var originalRenderMethod = loadImage.renderImageToCanvas; // Detects subsampling in JPEG images: loadImage.detectSubsampling = function (img) { var canvas, context; if (img.width * img.height > 1024 * 1024) { // only consider mexapixel images canvas = document.createElement('canvas'); canvas.width = canvas.height = 1; context = canvas.getContext('2d'); context.drawImage(img, -img.width + 1, 0); // subsampled image becomes half smaller in rendering size. // check alpha channel value to confirm image is covering edge pixel or not. // if alpha value is 0 image is not covering, hence subsampled. return context.getImageData(0, 0, 1, 1).data[3] === 0; } return false; }; // Detects vertical squash in JPEG images: loadImage.detectVerticalSquash = function (img, subsampled) { var naturalHeight = img.naturalHeight || img.height, canvas = document.createElement('canvas'), context = canvas.getContext('2d'), data, sy, ey, py, alpha; if (subsampled) { naturalHeight /= 2; } canvas.width = 1; canvas.height = naturalHeight; context.drawImage(img, 0, 0); data = context.getImageData(0, 0, 1, naturalHeight).data; // search image edge pixel position in case it is squashed vertically: sy = 0; ey = naturalHeight; py = naturalHeight; while (py > sy) { alpha = data[(py - 1) * 4 + 3]; if (alpha === 0) { ey = py; } else { sy = py; } py = (ey + sy) >> 1; } return (py / naturalHeight) || 1; }; // Renders image to canvas while working around iOS image scaling bugs: // https://github.com/blueimp/JavaScript-Load-Image/issues/13 loadImage.renderImageToCanvas = function ( canvas, img, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight ) { if (img._type === 'image/jpeg') { var context = canvas.getContext('2d'), tmpCanvas = document.createElement('canvas'), tileSize = 1024, tmpContext = tmpCanvas.getContext('2d'), subsampled, vertSquashRatio, tileX, tileY; tmpCanvas.width = tileSize; tmpCanvas.height = tileSize; context.save(); subsampled = loadImage.detectSubsampling(img); if (subsampled) { sourceX /= 2; sourceY /= 2; sourceWidth /= 2; sourceHeight /= 2; } vertSquashRatio = loadImage.detectVerticalSquash(img, subsampled); if (subsampled || vertSquashRatio !== 1) { sourceY *= vertSquashRatio; destWidth = Math.ceil(tileSize * destWidth / sourceWidth); destHeight = Math.ceil( tileSize * destHeight / sourceHeight / vertSquashRatio ); destY = 0; tileY = 0; while (tileY < sourceHeight) { destX = 0; tileX = 0; while (tileX < sourceWidth) { tmpContext.clearRect(0, 0, tileSize, tileSize); tmpContext.drawImage( img, sourceX, sourceY, sourceWidth, sourceHeight, -tileX, -tileY, sourceWidth, sourceHeight ); context.drawImage( tmpCanvas, 0, 0, tileSize, tileSize, destX, destY, destWidth, destHeight ); tileX += tileSize; destX += destWidth; } tileY += tileSize; destY += destHeight; } context.restore(); return canvas; } } return originalRenderMethod( canvas, img, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight ); }; }));