/*
* 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));