/* * JavaScript Load Image 1.7 * https://github.com/blueimp/JavaScript-Load-Image * * Copyright 2011, Sebastian Tschan * https://blueimp.net * * Licensed under the MIT license: * http://www.opensource.org/licenses/MIT */ /*jslint nomen: true */ /*global define, window, document, URL, webkitURL, Blob, File, FileReader */ (function ($) { 'use strict'; // Loads an image for a given File object. // Invokes the callback with an img or optional canvas // element (if supported by the browser) as parameter: var loadImage = function (file, callback, options) { var img = document.createElement('img'), url, oUrl; img.onerror = callback; img.onload = function () { if (oUrl && !(options && options.noRevoke)) { loadImage.revokeObjectURL(oUrl); } if (callback) { callback(loadImage.scale(img, options)); } }; if (loadImage.isInstanceOf('Blob', file) || // Files are also Blob instances, but some browsers // (Firefox 3.6) support the File API but not Blobs: loadImage.isInstanceOf('File', file)) { url = oUrl = loadImage.createObjectURL(file); // Store the file type for resize processing: img._type = file.type; } else if (typeof file === 'string') { url = file; if (options && options.crossOrigin) { img.crossOrigin = options.crossOrigin; } } else { return false; } if (url) { img.src = url; return img; } return loadImage.readFile(file, function (e) { var target = e.target; if (target && target.result) { img.src = target.result; } else { if (callback) { callback(e); } } }); }, // The check for URL.revokeObjectURL fixes an issue with Opera 12, // which provides URL.createObjectURL but doesn't properly implement it: urlAPI = (window.createObjectURL && window) || (window.URL && URL.revokeObjectURL && URL) || (window.webkitURL && webkitURL); loadImage.isInstanceOf = function (type, obj) { // Cross-frame instanceof check return Object.prototype.toString.call(obj) === '[object ' + type + ']'; }; // Transform image orientation based on the given EXIF orientation data: loadImage.transformCoordinates = function (canvas, orientation) { var ctx = canvas.getContext('2d'), width = canvas.width, height = canvas.height; if (orientation > 4) { canvas.width = height; canvas.height = width; } switch (orientation) { case 2: // horizontal flip ctx.translate(width, 0); ctx.scale(-1, 1); break; case 3: // 180 rotate left ctx.translate(width, height); ctx.rotate(Math.PI); break; case 4: // vertical flip ctx.translate(0, height); ctx.scale(1, -1); break; case 5: // vertical flip + 90 rotate right ctx.rotate(0.5 * Math.PI); ctx.scale(1, -1); break; case 6: // 90 rotate right ctx.rotate(0.5 * Math.PI); ctx.translate(0, -height); break; case 7: // horizontal flip + 90 rotate right ctx.rotate(0.5 * Math.PI); ctx.translate(width, -height); ctx.scale(-1, 1); break; case 8: // 90 rotate left ctx.rotate(-0.5 * Math.PI); ctx.translate(-width, 0); break; } }; // Canvas render method, allows to override the // rendering e.g. to work around issues on iOS: loadImage.renderImageToCanvas = function ( canvas, img, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight ) { canvas.getContext('2d').drawImage( img, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight ); return canvas; }; // Scales the given image (img or canvas HTML element) // using the given options. // Returns a canvas object if the browser supports canvas // and the canvas or crop option is true or a canvas object // is passed as image, else the scaled image: loadImage.scale = function (img, options) { options = options || {}; var canvas = document.createElement('canvas'), useCanvas = img.getContext || ((options.canvas || options.crop || options.orientation) && canvas.getContext), width = img.width, height = img.height, sourceWidth = width, sourceHeight = height, sourceX = 0, sourceY = 0, destX = 0, destY = 0, maxWidth, maxHeight, minWidth, minHeight, destWidth, destHeight, scale; if (useCanvas && options.orientation > 4) { maxWidth = options.maxHeight; maxHeight = options.maxWidth; minWidth = options.minHeight; minHeight = options.minWidth; } else { maxWidth = options.maxWidth; maxHeight = options.maxHeight; minWidth = options.minWidth; minHeight = options.minHeight; } if (useCanvas && maxWidth && maxHeight && options.crop) { destWidth = maxWidth; destHeight = maxHeight; if (width / height < maxWidth / maxHeight) { sourceHeight = maxHeight * width / maxWidth; sourceY = (height - sourceHeight) / 2; } else { sourceWidth = maxWidth * height / maxHeight; sourceX = (width - sourceWidth) / 2; } } else { destWidth = width; destHeight = height; scale = Math.max( (minWidth || destWidth) / destWidth, (minHeight || destHeight) / destHeight ); if (scale > 1) { destWidth = Math.ceil(destWidth * scale); destHeight = Math.ceil(destHeight * scale); } scale = Math.min( (maxWidth || destWidth) / destWidth, (maxHeight || destHeight) / destHeight ); if (scale < 1) { destWidth = Math.ceil(destWidth * scale); destHeight = Math.ceil(destHeight * scale); } } if (useCanvas) { canvas.width = destWidth; canvas.height = destHeight; loadImage.transformCoordinates( canvas, options.orientation ); return loadImage.renderImageToCanvas( canvas, img, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight ); } img.width = destWidth; img.height = destHeight; return img; }; loadImage.createObjectURL = function (file) { return urlAPI ? urlAPI.createObjectURL(file) : false; }; loadImage.revokeObjectURL = function (url) { return urlAPI ? urlAPI.revokeObjectURL(url) : false; }; // Loads a given File object via FileReader interface, // invokes the callback with the event object (load or error). // The result can be read via event.target.result: loadImage.readFile = function (file, callback, method) { if (window.FileReader) { var fileReader = new FileReader(); fileReader.onload = fileReader.onerror = callback; method = method || 'readAsDataURL'; if (fileReader[method]) { fileReader[method](file); return fileReader; } } return false; }; if (typeof define === 'function' && define.amd) { define(function () { return loadImage; }); } else { $.loadImage = loadImage; } }(this));