From 7598f8a740526a1deb54886f0710cb1d16b93d9e Mon Sep 17 00:00:00 2001
From: Joe Wood
Date: Mon, 16 Jul 2012 01:07:05 -0400
Subject: [PATCH 001/386] Fix to check valid 'options' before noRevoke chk
Added a test to see if options is set before dereferencing the object to
check for noRevoke.
---
load-image.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/load-image.js b/load-image.js
index fe93c89..544d62a 100644
--- a/load-image.js
+++ b/load-image.js
@@ -24,7 +24,7 @@
oUrl;
img.onerror = callback;
img.onload = function () {
- if (oUrl && !options.noRevoke) {
+ if (oUrl && !(typeof(options)!="undefined" && options.noRevoke)) {
loadImage.revokeObjectURL(oUrl);
}
callback(loadImage.scale(img, options));
From 0c6b9628f8a903440e7121e913fd8a1d8289e740 Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Mon, 16 Jul 2012 10:06:06 +0200
Subject: [PATCH 002/386] Refactor last merge and update version number.
Add tests for the noRevoke option.
---
load-image.js | 4 ++--
load-image.min.js | 2 +-
test/test.js | 22 +++++++++++++++++++++-
3 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/load-image.js b/load-image.js
index 544d62a..4697f68 100644
--- a/load-image.js
+++ b/load-image.js
@@ -1,5 +1,5 @@
/*
- * JavaScript Load Image 1.2
+ * JavaScript Load Image 1.2.1
* https://github.com/blueimp/JavaScript-Load-Image
*
* Copyright 2011, Sebastian Tschan
@@ -24,7 +24,7 @@
oUrl;
img.onerror = callback;
img.onload = function () {
- if (oUrl && !(typeof(options)!="undefined" && options.noRevoke)) {
+ if (oUrl && !(options && options.noRevoke)) {
loadImage.revokeObjectURL(oUrl);
}
callback(loadImage.scale(img, options));
diff --git a/load-image.min.js b/load-image.min.js
index 8f902fb..0f7ab3f 100644
--- a/load-image.min.js
+++ b/load-image.min.js
@@ -1 +1 @@
-(function(a){"use strict";var b=function(a,c,d){var e=document.createElement("img"),f,g;return e.onerror=c,e.onload=function(){g&&!d.noRevoke&&b.revokeObjectURL(g),c(b.scale(e,d))},window.Blob&&a instanceof Blob||window.File&&a instanceof File?f=g=b.createObjectURL(a):f=a,f?(e.src=f,e):b.readFile(a,function(a){e.src=a})},c=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;b.scale=function(a,b){b=b||{};var c=document.createElement("canvas"),d=a.width,e=a.height,f=Math.max((b.minWidth||d)/d,(b.minHeight||e)/e);return f>1&&(d=parseInt(d*f,10),e=parseInt(e*f,10)),f=Math.min((b.maxWidth||d)/d,(b.maxHeight||e)/e),f<1&&(d=parseInt(d*f,10),e=parseInt(e*f,10)),a.getContext||b.canvas&&c.getContext?(c.width=d,c.height=e,c.getContext("2d").drawImage(a,0,0,d,e),c):(a.width=d,a.height=e,a)},b.createObjectURL=function(a){return c?c.createObjectURL(a):!1},b.revokeObjectURL=function(a){return c?c.revokeObjectURL(a):!1},b.readFile=function(a,b){if(window.FileReader&&FileReader.prototype.readAsDataURL){var c=new FileReader;return c.onload=function(a){b(a.target.result)},c.readAsDataURL(a),c}return!1},typeof define!="undefined"&&define.amd?define(function(){return b}):a.loadImage=b})(this);
\ No newline at end of file
+(function(a){"use strict";var b=function(a,c,d){var e=document.createElement("img"),f,g;return e.onerror=c,e.onload=function(){g&&(!d||!d.noRevoke)&&b.revokeObjectURL(g),c(b.scale(e,d))},window.Blob&&a instanceof Blob||window.File&&a instanceof File?f=g=b.createObjectURL(a):f=a,f?(e.src=f,e):b.readFile(a,function(a){e.src=a})},c=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;b.scale=function(a,b){b=b||{};var c=document.createElement("canvas"),d=a.width,e=a.height,f=Math.max((b.minWidth||d)/d,(b.minHeight||e)/e);return f>1&&(d=parseInt(d*f,10),e=parseInt(e*f,10)),f=Math.min((b.maxWidth||d)/d,(b.maxHeight||e)/e),f<1&&(d=parseInt(d*f,10),e=parseInt(e*f,10)),a.getContext||b.canvas&&c.getContext?(c.width=d,c.height=e,c.getContext("2d").drawImage(a,0,0,d,e),c):(a.width=d,a.height=e,a)},b.createObjectURL=function(a){return c?c.createObjectURL(a):!1},b.revokeObjectURL=function(a){return c?c.revokeObjectURL(a):!1},b.readFile=function(a,b){if(window.FileReader&&FileReader.prototype.readAsDataURL){var c=new FileReader;return c.onload=function(a){b(a.target.result)},c.readAsDataURL(a),c}return!1},typeof define!="undefined"&&define.amd?define(function(){return b}):a.loadImage=b})(this);
\ No newline at end of file
diff --git a/test/test.js b/test/test.js
index b2f945d..2acef5b 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1,5 +1,5 @@
/*
- * JavaScript Load Image Test 1.1.6
+ * JavaScript Load Image Test 1.2
* https://github.com/blueimp/JavaScript-Load-Image
*
* Copyright 2011, Sebastian Tschan
@@ -54,6 +54,26 @@
})).to.be.ok();
});
+ it('Keep object URL if options.noRevoke is true', function (done) {
+ expect(loadImage(blob, function (img) {
+ loadImage(img.src, function (img2) {
+ done();
+ expect(img.width).to.be(img2.width);
+ expect(img.height).to.be(img2.height);
+ });
+ }, {noRevoke: true})).to.be.ok();
+ });
+
+ it('Discard object URL if options.noRevoke is undefined or false', function (done) {
+ expect(loadImage(blob, function (img) {
+ loadImage(img.src, function (img2) {
+ done();
+ expect(img2).to.be.a(window.Event);
+ expect(img2.type).to.be('error');
+ });
+ })).to.be.ok();
+ });
+
});
describe('Scaling', function () {
From 7de8cd23883cb81cd1e29b68bcdca19c3dc314e4 Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Tue, 17 Jul 2012 12:15:53 +0200
Subject: [PATCH 003/386] Added X-UA-Compatible meta tag to force latest IE
rendering engine or ChromeFrame if installed.
---
index.html | 3 ++-
package.json | 2 +-
test/index.html | 3 ++-
test/test.js | 2 +-
4 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/index.html b/index.html
index 624b03e..668961d 100644
--- a/index.html
+++ b/index.html
@@ -1,7 +1,7 @@
+
JavaScript Load Image
diff --git a/package.json b/package.json
index 6580ac7..b4b081b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "blueimp-load-image",
- "version": "1.2.0",
+ "version": "1.2.1",
"title": "JavaScript Load Image",
"description": "JavaScript Load Image is a function to load images provided as File or Blob objects or via URL. It returns an optionally scaled HTML img or canvas element.",
"keywords": [
diff --git a/test/index.html b/test/index.html
index dcccf3c..1cc5ac9 100644
--- a/test/index.html
+++ b/test/index.html
@@ -1,7 +1,7 @@
+
JavaScript Load Image Test
diff --git a/test/test.js b/test/test.js
index 2acef5b..350738f 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1,5 +1,5 @@
/*
- * JavaScript Load Image Test 1.2
+ * JavaScript Load Image Test 1.2.1
* https://github.com/blueimp/JavaScript-Load-Image
*
* Copyright 2011, Sebastian Tschan
From c882fecc719d1379b90ce22cdf4da7005ae9ef7c Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Fri, 24 Aug 2012 11:56:38 +0900
Subject: [PATCH 004/386] Minor JSLint compatibility update.
---
load-image.js | 2 +-
load-image.min.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/load-image.js b/load-image.js
index 4697f68..96a149e 100644
--- a/load-image.js
+++ b/load-image.js
@@ -111,7 +111,7 @@
return false;
};
- if (typeof define !== 'undefined' && define.amd) {
+ if (typeof define === 'function' && define.amd) {
define(function () {
return loadImage;
});
diff --git a/load-image.min.js b/load-image.min.js
index 0f7ab3f..f6817db 100644
--- a/load-image.min.js
+++ b/load-image.min.js
@@ -1 +1 @@
-(function(a){"use strict";var b=function(a,c,d){var e=document.createElement("img"),f,g;return e.onerror=c,e.onload=function(){g&&(!d||!d.noRevoke)&&b.revokeObjectURL(g),c(b.scale(e,d))},window.Blob&&a instanceof Blob||window.File&&a instanceof File?f=g=b.createObjectURL(a):f=a,f?(e.src=f,e):b.readFile(a,function(a){e.src=a})},c=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;b.scale=function(a,b){b=b||{};var c=document.createElement("canvas"),d=a.width,e=a.height,f=Math.max((b.minWidth||d)/d,(b.minHeight||e)/e);return f>1&&(d=parseInt(d*f,10),e=parseInt(e*f,10)),f=Math.min((b.maxWidth||d)/d,(b.maxHeight||e)/e),f<1&&(d=parseInt(d*f,10),e=parseInt(e*f,10)),a.getContext||b.canvas&&c.getContext?(c.width=d,c.height=e,c.getContext("2d").drawImage(a,0,0,d,e),c):(a.width=d,a.height=e,a)},b.createObjectURL=function(a){return c?c.createObjectURL(a):!1},b.revokeObjectURL=function(a){return c?c.revokeObjectURL(a):!1},b.readFile=function(a,b){if(window.FileReader&&FileReader.prototype.readAsDataURL){var c=new FileReader;return c.onload=function(a){b(a.target.result)},c.readAsDataURL(a),c}return!1},typeof define!="undefined"&&define.amd?define(function(){return b}):a.loadImage=b})(this);
\ No newline at end of file
+(function(a){"use strict";var b=function(a,c,d){var e=document.createElement("img"),f,g;return e.onerror=c,e.onload=function(){g&&(!d||!d.noRevoke)&&b.revokeObjectURL(g),c(b.scale(e,d))},window.Blob&&a instanceof Blob||window.File&&a instanceof File?f=g=b.createObjectURL(a):f=a,f?(e.src=f,e):b.readFile(a,function(a){e.src=a})},c=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;b.scale=function(a,b){b=b||{};var c=document.createElement("canvas"),d=a.width,e=a.height,f=Math.max((b.minWidth||d)/d,(b.minHeight||e)/e);return f>1&&(d=parseInt(d*f,10),e=parseInt(e*f,10)),f=Math.min((b.maxWidth||d)/d,(b.maxHeight||e)/e),f<1&&(d=parseInt(d*f,10),e=parseInt(e*f,10)),a.getContext||b.canvas&&c.getContext?(c.width=d,c.height=e,c.getContext("2d").drawImage(a,0,0,d,e),c):(a.width=d,a.height=e,a)},b.createObjectURL=function(a){return c?c.createObjectURL(a):!1},b.revokeObjectURL=function(a){return c?c.revokeObjectURL(a):!1},b.readFile=function(a,b){if(window.FileReader&&FileReader.prototype.readAsDataURL){var c=new FileReader;return c.onload=function(a){b(a.target.result)},c.readAsDataURL(a),c}return!1},typeof define=="function"&&define.amd?define(function(){return b}):a.loadImage=b})(this);
\ No newline at end of file
From cd5cb5c4dd6b2be60769277f4327cb9a83bc143a Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Wed, 10 Oct 2012 20:55:56 +0900
Subject: [PATCH 005/386] Fixed image scaling on iOS devices - Fixes #13.
iOS image scaling fixes based on
https://github.com/stomita/ios-imagefile-megapixel
---
load-image.js | 115 ++++++++++++++++++++++++++++++++++++++++++++--
load-image.min.js | 2 +-
2 files changed, 112 insertions(+), 5 deletions(-)
diff --git a/load-image.js b/load-image.js
index 96a149e..2eda67a 100644
--- a/load-image.js
+++ b/load-image.js
@@ -1,15 +1,18 @@
/*
- * JavaScript Load Image 1.2.1
+ * JavaScript Load Image 1.2.2
* https://github.com/blueimp/JavaScript-Load-Image
*
* Copyright 2011, 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 */
+/*jslint nomen: true, bitwise: true */
/*global window, document, URL, webkitURL, Blob, File, FileReader, define */
(function ($) {
@@ -34,6 +37,8 @@
// (Firefox 3.6) support the File API but not Blobs:
(window.File && file instanceof File)) {
url = oUrl = loadImage.createObjectURL(file);
+ // Store the file type for resize processing:
+ img._type = file.type;
} else {
url = file;
}
@@ -51,6 +56,103 @@
(window.URL && URL.revokeObjectURL && URL) ||
(window.webkitURL && webkitURL);
+ // Detects subsampling in JPEG images:
+ loadImage.detectSubsampling = function (img) {
+ var iw = img.width,
+ ih = img.height,
+ canvas,
+ ctx;
+ if (iw * ih > 1024 * 1024) { // only consider mexapixel images
+ canvas = document.createElement('canvas');
+ canvas.width = canvas.height = 1;
+ ctx = canvas.getContext('2d');
+ ctx.drawImage(img, -iw + 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 ctx.getImageData(0, 0, 1, 1).data[3] === 0;
+ }
+ return false;
+ };
+
+ // Detects vertical squash in JPEG images:
+ loadImage.detectVerticalSquash = function (img, ih) {
+ var canvas = document.createElement('canvas'),
+ ctx = canvas.getContext('2d'),
+ data,
+ sy,
+ ey,
+ py,
+ alpha;
+ canvas.width = 1;
+ canvas.height = ih;
+ ctx.drawImage(img, 0, 0);
+ data = ctx.getImageData(0, 0, 1, ih).data;
+ // search image edge pixel position in case it is squashed vertically:
+ sy = 0;
+ ey = ih;
+ py = ih;
+ while (py > sy) {
+ alpha = data[(py - 1) * 4 + 3];
+ if (alpha === 0) {
+ ey = py;
+ } else {
+ sy = py;
+ }
+ py = (ey + sy) >> 1;
+ }
+ return py / ih;
+ };
+
+ // Renders image to canvas while working around iOS image scaling bugs:
+ // https://github.com/blueimp/JavaScript-Load-Image/issues/13
+ loadImage.renderImageToCanvas = function (img, canvas, width, height) {
+ var iw = img.width,
+ ih = img.height,
+ ctx = canvas.getContext('2d'),
+ vertSquashRatio,
+ d = 1024, // size of tiling canvas
+ tmpCanvas = document.createElement('canvas'),
+ tmpCtx,
+ sy,
+ sh,
+ sx,
+ sw;
+ ctx.save();
+ if (loadImage.detectSubsampling(img)) {
+ iw /= 2;
+ ih /= 2;
+ }
+ vertSquashRatio = loadImage.detectVerticalSquash(img, ih);
+ tmpCanvas.width = tmpCanvas.height = d;
+ tmpCtx = tmpCanvas.getContext('2d');
+ sy = 0;
+ while (sy < ih) {
+ sh = sy + d > ih ? ih - sy : d;
+ sx = 0;
+ while (sx < iw) {
+ sw = sx + d > iw ? iw - sx : d;
+ tmpCtx.clearRect(0, 0, d, d);
+ tmpCtx.drawImage(img, -sx, -sy);
+ ctx.drawImage(
+ tmpCanvas,
+ 0,
+ 0,
+ sw,
+ sh,
+ Math.floor(sx * width / iw),
+ Math.floor(sy * height / ih / vertSquashRatio),
+ Math.ceil(sw * width / iw),
+ Math.ceil(sh * height / ih / vertSquashRatio)
+ );
+ sx += d;
+ }
+ sy += d;
+ }
+ ctx.restore();
+ tmpCanvas = tmpCtx = null;
+ };
+
// Scales the given image (img or canvas HTML element)
// using the given options.
// Returns a canvas object if the browser supports canvas
@@ -80,8 +182,13 @@
if (img.getContext || (options.canvas && canvas.getContext)) {
canvas.width = width;
canvas.height = height;
- canvas.getContext('2d')
- .drawImage(img, 0, 0, width, height);
+ if (img._type === 'image/jpeg') {
+ loadImage
+ .renderImageToCanvas(img, canvas, width, height);
+ } else {
+ canvas.getContext('2d')
+ .drawImage(img, 0, 0, width, height);
+ }
return canvas;
}
img.width = width;
diff --git a/load-image.min.js b/load-image.min.js
index f6817db..2bd2287 100644
--- a/load-image.min.js
+++ b/load-image.min.js
@@ -1 +1 @@
-(function(a){"use strict";var b=function(a,c,d){var e=document.createElement("img"),f,g;return e.onerror=c,e.onload=function(){g&&(!d||!d.noRevoke)&&b.revokeObjectURL(g),c(b.scale(e,d))},window.Blob&&a instanceof Blob||window.File&&a instanceof File?f=g=b.createObjectURL(a):f=a,f?(e.src=f,e):b.readFile(a,function(a){e.src=a})},c=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;b.scale=function(a,b){b=b||{};var c=document.createElement("canvas"),d=a.width,e=a.height,f=Math.max((b.minWidth||d)/d,(b.minHeight||e)/e);return f>1&&(d=parseInt(d*f,10),e=parseInt(e*f,10)),f=Math.min((b.maxWidth||d)/d,(b.maxHeight||e)/e),f<1&&(d=parseInt(d*f,10),e=parseInt(e*f,10)),a.getContext||b.canvas&&c.getContext?(c.width=d,c.height=e,c.getContext("2d").drawImage(a,0,0,d,e),c):(a.width=d,a.height=e,a)},b.createObjectURL=function(a){return c?c.createObjectURL(a):!1},b.revokeObjectURL=function(a){return c?c.revokeObjectURL(a):!1},b.readFile=function(a,b){if(window.FileReader&&FileReader.prototype.readAsDataURL){var c=new FileReader;return c.onload=function(a){b(a.target.result)},c.readAsDataURL(a),c}return!1},typeof define=="function"&&define.amd?define(function(){return b}):a.loadImage=b})(this);
\ No newline at end of file
+(function(a){"use strict";var b=function(a,c,d){var e=document.createElement("img"),f,g;return e.onerror=c,e.onload=function(){g&&(!d||!d.noRevoke)&&b.revokeObjectURL(g),c(b.scale(e,d))},window.Blob&&a instanceof Blob||window.File&&a instanceof File?(f=g=b.createObjectURL(a),e._type=a.type):f=a,f?(e.src=f,e):b.readFile(a,function(a){e.src=a})},c=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;b.detectSubsampling=function(a){var b=a.width,c=a.height,d,e;return b*c>1048576?(d=document.createElement("canvas"),d.width=d.height=1,e=d.getContext("2d"),e.drawImage(a,-b+1,0),e.getImageData(0,0,1,1).data[3]===0):!1},b.detectVerticalSquash=function(a,b){var c=document.createElement("canvas"),d=c.getContext("2d"),e,f,g,h,i;c.width=1,c.height=b,d.drawImage(a,0,0),e=d.getImageData(0,0,1,b).data,f=0,g=b,h=b;while(h>f)i=e[(h-1)*4+3],i===0?g=h:f=h,h=g+f>>1;return h/b},b.renderImageToCanvas=function(a,c,d,e){var f=a.width,g=a.height,h=c.getContext("2d"),i,j=1024,k=document.createElement("canvas"),l,m,n,o,p;h.save(),b.detectSubsampling(a)&&(f/=2,g/=2),i=b.detectVerticalSquash(a,g),k.width=k.height=j,l=k.getContext("2d"),m=0;while(mg?g-m:j,o=0;while(of?f-o:j,l.clearRect(0,0,j,j),l.drawImage(a,-o,-m),h.drawImage(k,0,0,p,n,Math.floor(o*d/f),Math.floor(m*e/g/i),Math.ceil(p*d/f),Math.ceil(n*e/g/i)),o+=j;m+=j}h.restore(),k=l=null},b.scale=function(a,c){c=c||{};var d=document.createElement("canvas"),e=a.width,f=a.height,g=Math.max((c.minWidth||e)/e,(c.minHeight||f)/f);return g>1&&(e=parseInt(e*g,10),f=parseInt(f*g,10)),g=Math.min((c.maxWidth||e)/e,(c.maxHeight||f)/f),g<1&&(e=parseInt(e*g,10),f=parseInt(f*g,10)),a.getContext||c.canvas&&d.getContext?(d.width=e,d.height=f,a._type==="image/jpeg"?b.renderImageToCanvas(a,d,e,f):d.getContext("2d").drawImage(a,0,0,e,f),d):(a.width=e,a.height=f,a)},b.createObjectURL=function(a){return c?c.createObjectURL(a):!1},b.revokeObjectURL=function(a){return c?c.revokeObjectURL(a):!1},b.readFile=function(a,b){if(window.FileReader&&FileReader.prototype.readAsDataURL){var c=new FileReader;return c.onload=function(a){b(a.target.result)},c.readAsDataURL(a),c}return!1},typeof define=="function"&&define.amd?define(function(){return b}):a.loadImage=b})(this);
\ No newline at end of file
From 8e7c998acf9eef5b2c1d45a48a885a2798b9f7fc Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Tue, 13 Nov 2012 15:19:07 +0100
Subject: [PATCH 006/386] Handle empty results and errors for images loaded via
FileReader interface.
---
index.html | 40 ++++++++++++++++++++++++++--------------
load-image.js | 18 +++++++++++-------
load-image.min.js | 2 +-
package.json | 2 +-
4 files changed, 39 insertions(+), 23 deletions(-)
diff --git a/index.html b/index.html
index 668961d..7440537 100644
--- a/index.html
+++ b/index.html
@@ -1,7 +1,7 @@
+
-
-
+
+
@@ -54,7 +53,7 @@
JavaScript Load Image Demo
JavaScript Load Image is a function to load images provided as File or Blob objects or via URL.
- It returns an optionally scaled HTML img or canvas element.
+ It returns an optionally scaled and/or cropped HTML img or canvas element.
diff --git a/load-image.js b/load-image.js
index 2c1843a..80f211f 100644
--- a/load-image.js
+++ b/load-image.js
@@ -1,5 +1,5 @@
/*
- * JavaScript Load Image 1.4.1
+ * JavaScript Load Image 1.5
* https://github.com/blueimp/JavaScript-Load-Image
*
* Copyright 2011, Sebastian Tschan
@@ -77,40 +77,38 @@
// Detects subsampling in JPEG images:
loadImage.detectSubsampling = function (img) {
- var iw = img.width,
- ih = img.height,
- canvas,
- ctx;
- if (iw * ih > 1024 * 1024) { // only consider mexapixel images
+ var canvas,
+ context;
+ if (img.width * img.height > 1024 * 1024) { // only consider mexapixel images
canvas = document.createElement('canvas');
canvas.width = canvas.height = 1;
- ctx = canvas.getContext('2d');
- ctx.drawImage(img, -iw + 1, 0);
+ 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 ctx.getImageData(0, 0, 1, 1).data[3] === 0;
+ return context.getImageData(0, 0, 1, 1).data[3] === 0;
}
return false;
};
// Detects vertical squash in JPEG images:
- loadImage.detectVerticalSquash = function (img, ih) {
+ loadImage.detectVerticalSquash = function (img, correctedHeight) {
var canvas = document.createElement('canvas'),
- ctx = canvas.getContext('2d'),
+ context = canvas.getContext('2d'),
data,
sy,
ey,
py,
alpha;
canvas.width = 1;
- canvas.height = ih;
- ctx.drawImage(img, 0, 0);
- data = ctx.getImageData(0, 0, 1, ih).data;
+ canvas.height = correctedHeight;
+ context.drawImage(img, 0, 0);
+ data = context.getImageData(0, 0, 1, correctedHeight).data;
// search image edge pixel position in case it is squashed vertically:
sy = 0;
- ey = ih;
- py = ih;
+ ey = correctedHeight;
+ py = correctedHeight;
while (py > sy) {
alpha = data[(py - 1) * 4 + 3];
if (alpha === 0) {
@@ -120,94 +118,164 @@
}
py = (ey + sy) >> 1;
}
- return (py / ih) || 1;
+ return (py / correctedHeight) || 1;
};
// Renders image to canvas while working around iOS image scaling bugs:
// https://github.com/blueimp/JavaScript-Load-Image/issues/13
- loadImage.renderImageToCanvas = function (img, canvas, width, height) {
- var iw = img.width,
- ih = img.height,
- ctx = canvas.getContext('2d'),
- vertSquashRatio,
- d = 1024, // size of tiling canvas
+ loadImage.renderImageToCanvas = function (
+ canvas,
+ img,
+ sourceX,
+ sourceY,
+ sourceWidth,
+ sourceHeight,
+ destX,
+ destY,
+ destWidth,
+ destHeight
+ ) {
+ var context = canvas.getContext('2d'),
tmpCanvas = document.createElement('canvas'),
- tmpCtx,
- dw,
- dh,
- dx,
- dy,
- sx,
- sy;
- ctx.save();
+ tileSize = tmpCanvas.width = tmpCanvas.height = 1024,
+ tmpContext = tmpCanvas.getContext('2d'),
+ vertSquashRatio,
+ tileX,
+ tileY;
+ context.save();
if (loadImage.detectSubsampling(img)) {
- iw /= 2;
- ih /= 2;
+ sourceWidth /= 2;
+ sourceHeight /= 2;
}
- vertSquashRatio = loadImage.detectVerticalSquash(img, ih);
- tmpCanvas.width = tmpCanvas.height = d;
- tmpCtx = tmpCanvas.getContext('2d');
- dw = Math.ceil(d * width / iw);
- dh = Math.ceil(d * height / ih / vertSquashRatio);
- dy = 0;
- sy = 0;
- while (sy < ih) {
- dx = 0;
- sx = 0;
- while (sx < iw) {
- tmpCtx.clearRect(0, 0, d, d);
- tmpCtx.drawImage(img, -sx, -sy);
- ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh);
- sx += d;
- dx += dw;
+ vertSquashRatio = loadImage.detectVerticalSquash(img, sourceHeight);
+ 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;
}
- sy += d;
- dy += dh;
+ tileY += tileSize;
+ destY += destHeight;
}
- ctx.restore();
- tmpCanvas = tmpCtx = null;
+ context.restore();
};
// 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 option is true or a canvas object is passed
- // as image, else the scaled image:
+ // 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) && canvas.getContext),
width = img.width,
height = img.height,
+ maxWidth = options.maxWidth,
+ maxHeight = options.maxHeight,
+ sourceWidth = width,
+ sourceHeight = height,
+ sourceX = 0,
+ sourceY = 0,
+ destX = 0,
+ destY = 0,
+ destWidth,
+ destHeight,
+ scale;
+ 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(
- (options.minWidth || width) / width,
- (options.minHeight || height) / height
+ (options.minWidth || destWidth) / destWidth,
+ (options.minHeight || destHeight) / destHeight
);
- if (scale > 1) {
- width = Math.ceil(width * scale);
- height = Math.ceil(height * scale);
- }
- scale = Math.min(
- (options.maxWidth || width) / width,
- (options.maxHeight || height) / height
- );
- if (scale < 1) {
- width = Math.ceil(width * scale);
- height = Math.ceil(height * scale);
+ 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 (img.getContext || (options.canvas && canvas.getContext)) {
- canvas.width = width;
- canvas.height = height;
+ if (useCanvas) {
+ canvas.width = destWidth;
+ canvas.height = destHeight;
if (img._type === 'image/jpeg') {
- loadImage
- .renderImageToCanvas(img, canvas, width, height);
+ loadImage.renderImageToCanvas(
+ canvas,
+ img,
+ sourceX,
+ sourceY,
+ sourceWidth,
+ sourceHeight,
+ destX,
+ destY,
+ destWidth,
+ destHeight
+ );
} else {
- canvas.getContext('2d')
- .drawImage(img, 0, 0, width, height);
+ canvas.getContext('2d').drawImage(
+ img,
+ sourceX,
+ sourceY,
+ sourceWidth,
+ sourceHeight,
+ destX,
+ destY,
+ destWidth,
+ destHeight
+ );
}
return canvas;
}
- img.width = width;
- img.height = height;
+ img.width = destWidth;
+ img.height = destHeight;
return img;
};
diff --git a/load-image.min.js b/load-image.min.js
index 6e3e791..5ac991b 100644
--- a/load-image.min.js
+++ b/load-image.min.js
@@ -1 +1 @@
-(function(e){"use strict";var t=function(e,a,n){var r,i,c=document.createElement("img");if(c.onerror=a,c.onload=function(){!i||n&&n.noRevoke||t.revokeObjectURL(i),a&&a(t.scale(c,n))},t.isInstanceOf("Blob",e)||t.isInstanceOf("File",e))r=i=t.createObjectURL(e),c._type=e.type;else{if("string"!=typeof e)return!1;r=e,n&&n.crossOrigin&&(c.crossOrigin=n.crossOrigin)}return r?(c.src=r,c):t.readFile(e,function(e){var t=e.target;t&&t.result?c.src=t.result:a&&a(e)})},a=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;t.isInstanceOf=function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},t.detectSubsampling=function(e){var t,a,n=e.width,r=e.height;return n*r>1048576?(t=document.createElement("canvas"),t.width=t.height=1,a=t.getContext("2d"),a.drawImage(e,-n+1,0),0===a.getImageData(0,0,1,1).data[3]):!1},t.detectVerticalSquash=function(e,t){var a,n,r,i,c,o=document.createElement("canvas"),d=o.getContext("2d");for(o.width=1,o.height=t,d.drawImage(e,0,0),a=d.getImageData(0,0,1,t).data,n=0,r=t,i=t;i>n;)c=a[4*(i-1)+3],0===c?r=i:n=i,i=r+n>>1;return i/t||1},t.renderImageToCanvas=function(e,a,n,r){var i,c,o,d,g,h,s,u,l=e.width,m=e.height,f=a.getContext("2d"),w=1024,v=document.createElement("canvas");for(f.save(),t.detectSubsampling(e)&&(l/=2,m/=2),i=t.detectVerticalSquash(e,m),v.width=v.height=w,c=v.getContext("2d"),o=Math.ceil(w*n/l),d=Math.ceil(w*r/m/i),h=0,u=0;m>u;){for(g=0,s=0;l>s;)c.clearRect(0,0,w,w),c.drawImage(e,-s,-u),f.drawImage(v,0,0,w,w,g,h,o,d),s+=w,g+=o;u+=w,h+=d}f.restore(),v=c=null},t.scale=function(e,a){a=a||{};var n=document.createElement("canvas"),r=e.width,i=e.height,c=Math.max((a.minWidth||r)/r,(a.minHeight||i)/i);return c>1&&(r=Math.ceil(r*c),i=Math.ceil(i*c)),c=Math.min((a.maxWidth||r)/r,(a.maxHeight||i)/i),1>c&&(r=Math.ceil(r*c),i=Math.ceil(i*c)),e.getContext||a.canvas&&n.getContext?(n.width=r,n.height=i,"image/jpeg"===e._type?t.renderImageToCanvas(e,n,r,i):n.getContext("2d").drawImage(e,0,0,r,i),n):(e.width=r,e.height=i,e)},t.createObjectURL=function(e){return a?a.createObjectURL(e):!1},t.revokeObjectURL=function(e){return a?a.revokeObjectURL(e):!1},t.readFile=function(e,t){if(window.FileReader&&FileReader.prototype.readAsDataURL){var a=new FileReader;return a.onload=a.onerror=t,a.readAsDataURL(e),a}return!1},"function"==typeof define&&define.amd?define(function(){return t}):e.loadImage=t})(this);
\ No newline at end of file
+(function(e){"use strict";var t=function(e,a,n){var r,i,c=document.createElement("img");if(c.onerror=a,c.onload=function(){!i||n&&n.noRevoke||t.revokeObjectURL(i),a&&a(t.scale(c,n))},t.isInstanceOf("Blob",e)||t.isInstanceOf("File",e))r=i=t.createObjectURL(e),c._type=e.type;else{if("string"!=typeof e)return!1;r=e,n&&n.crossOrigin&&(c.crossOrigin=n.crossOrigin)}return r?(c.src=r,c):t.readFile(e,function(e){var t=e.target;t&&t.result?c.src=t.result:a&&a(e)})},a=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;t.isInstanceOf=function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},t.detectSubsampling=function(e){var t,a;return e.width*e.height>1048576?(t=document.createElement("canvas"),t.width=t.height=1,a=t.getContext("2d"),a.drawImage(e,-e.width+1,0),0===a.getImageData(0,0,1,1).data[3]):!1},t.detectVerticalSquash=function(e,t){var a,n,r,i,c,o=document.createElement("canvas"),d=o.getContext("2d");for(o.width=1,o.height=t,d.drawImage(e,0,0),a=d.getImageData(0,0,1,t).data,n=0,r=t,i=t;i>n;)c=a[4*(i-1)+3],0===c?r=i:n=i,i=r+n>>1;return i/t||1},t.renderImageToCanvas=function(e,a,n,r,i,c,o,d,g,s){var h,u,l,m=e.getContext("2d"),f=document.createElement("canvas"),w=f.width=f.height=1024,v=f.getContext("2d");for(m.save(),t.detectSubsampling(a)&&(i/=2,c/=2),h=t.detectVerticalSquash(a,c),g=Math.ceil(w*g/i),s=Math.ceil(w*s/c/h),d=0,l=0;c>l;){for(o=0,u=0;i>u;)v.clearRect(0,0,w,w),v.drawImage(a,n,r,i,c,-u,-l,i,c),m.drawImage(f,0,0,w,w,o,d,g,s),u+=w,o+=g;l+=w,d+=s}m.restore()},t.scale=function(e,a){a=a||{};var n,r,i,c=document.createElement("canvas"),o=e.getContext||(a.canvas||a.crop)&&c.getContext,d=e.width,g=e.height,s=a.maxWidth,h=a.maxHeight,u=d,l=g,m=0,f=0,w=0,v=0;return o&&s&&h&&a.crop?(n=s,r=h,s/h>d/g?(l=h*d/s,f=(g-l)/2):(u=s*g/h,m=(d-u)/2)):(n=d,r=g,i=Math.max((a.minWidth||n)/n,(a.minHeight||r)/r),i>1&&(n=Math.ceil(n*i),r=Math.ceil(r*i)),i=Math.min((s||n)/n,(h||r)/r),1>i&&(n=Math.ceil(n*i),r=Math.ceil(r*i))),o?(c.width=n,c.height=r,"image/jpeg"===e._type?t.renderImageToCanvas(c,e,m,f,u,l,w,v,n,r):c.getContext("2d").drawImage(e,m,f,u,l,w,v,n,r),c):(e.width=n,e.height=r,e)},t.createObjectURL=function(e){return a?a.createObjectURL(e):!1},t.revokeObjectURL=function(e){return a?a.revokeObjectURL(e):!1},t.readFile=function(e,t){if(window.FileReader&&FileReader.prototype.readAsDataURL){var a=new FileReader;return a.onload=a.onerror=t,a.readAsDataURL(e),a}return!1},"function"==typeof define&&define.amd?define(function(){return t}):e.loadImage=t})(this);
\ No newline at end of file
diff --git a/package.json b/package.json
index 5cce2e2..7fc224c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "blueimp-load-image",
- "version": "1.4.1",
+ "version": "1.5.0",
"title": "JavaScript Load Image",
"description": "JavaScript Load Image is a function to load images provided as File or Blob objects or via URL. It returns an optionally scaled HTML img or canvas element.",
"keywords": [
@@ -12,7 +12,7 @@
"blob",
"url",
"scale",
- "scaling",
+ "crop",
"img",
"canvas"
],
diff --git a/test/index.html b/test/index.html
index 831df01..040e22a 100644
--- a/test/index.html
+++ b/test/index.html
@@ -1,7 +1,7 @@
JavaScript Load Image Test
-
+
diff --git a/test/test.js b/test/test.js
index 350738f..579f7db 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1,5 +1,5 @@
/*
- * JavaScript Load Image Test 1.2.1
+ * JavaScript Load Image Test 1.5
* https://github.com/blueimp/JavaScript-Load-Image
*
* Copyright 2011, Sebastian Tschan
@@ -15,11 +15,11 @@
'use strict';
// 80x60px GIF image (color black, base64 data):
- var b64Data = 'R0lGODdhUAA8AIABAAAAAP///ywAAAAAUAA8AAACS4SPqcvtD6' +
+ var b64Data = 'R0lGODdhUAA8AIABAAAAAP///ywAAAAAUAA8AAACS4SPqcvtD6' +
'OctNqLs968+w+G4kiW5omm6sq27gvH8kzX9o3n+s73/g8MCofE' +
'ovGITCqXzKbzCY1Kp9Sq9YrNarfcrvcLDovH5PKsAAA7',
- imageUrl = 'data:image/gif;base64,' + b64Data,
- blob = window.dataURLtoBlob && window.dataURLtoBlob(imageUrl);
+ imageUrl = 'data:image/gif;base64,' + b64Data,
+ blob = window.dataURLtoBlob && window.dataURLtoBlob(imageUrl);
describe('Loading', function () {
@@ -160,6 +160,27 @@
});
+
+ describe('Cropping', function () {
+
+ it('Crop to same values for options.maxWidth and options.maxHeight', function (done) {
+ expect(loadImage(blob, function (img) {
+ done();
+ expect(img.width).to.be(40);
+ expect(img.height).to.be(40);
+ }, {maxWidth: 40, maxHeight: 40, crop: true})).to.be.ok();
+ });
+
+ it('Crop to different values for options.maxWidth and options.maxHeight', function (done) {
+ expect(loadImage(blob, function (img) {
+ done();
+ expect(img.width).to.be(40);
+ expect(img.height).to.be(60);
+ }, {maxWidth: 40, maxHeight: 60, crop: true})).to.be.ok();
+ });
+
+ });
+
describe('Canvas', function () {
it('Return img element to callback if options.canvas is not true', function (done) {
From f4d13a35879add68013300ab92888954363c711b Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Mon, 3 Jun 2013 18:12:22 -0500
Subject: [PATCH 022/386] Added orientation support.
---
load-image.js | 76 +++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 71 insertions(+), 5 deletions(-)
diff --git a/load-image.js b/load-image.js
index 80f211f..79a22c1 100644
--- a/load-image.js
+++ b/load-image.js
@@ -1,5 +1,5 @@
/*
- * JavaScript Load Image 1.5
+ * JavaScript Load Image 1.6
* https://github.com/blueimp/JavaScript-Load-Image
*
* Copyright 2011, Sebastian Tschan
@@ -75,6 +75,55 @@
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;
+ }
+ };
+
// Detects subsampling in JPEG images:
loadImage.detectSubsampling = function (img) {
var canvas,
@@ -202,17 +251,30 @@
((options.canvas || options.crop) && canvas.getContext),
width = img.width,
height = img.height,
- maxWidth = options.maxWidth,
- maxHeight = options.maxHeight,
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;
@@ -227,8 +289,8 @@
destWidth = width;
destHeight = height;
scale = Math.max(
- (options.minWidth || destWidth) / destWidth,
- (options.minHeight || destHeight) / destHeight
+ (minWidth || destWidth) / destWidth,
+ (minHeight || destHeight) / destHeight
);
if (scale > 1) {
destWidth = Math.ceil(destWidth * scale);
@@ -246,6 +308,10 @@
if (useCanvas) {
canvas.width = destWidth;
canvas.height = destHeight;
+ loadImage.transformCoordinates(
+ canvas,
+ options.orientation
+ );
if (img._type === 'image/jpeg') {
loadImage.renderImageToCanvas(
canvas,
From 198297597e9cbd5c3b5f72e97941c32142032857 Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Mon, 3 Jun 2013 19:09:57 -0500
Subject: [PATCH 023/386] Accept the reading method as third argument to
loadImage.readFile.
---
load-image.js | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/load-image.js b/load-image.js
index 79a22c1..f31a771 100644
--- a/load-image.js
+++ b/load-image.js
@@ -356,11 +356,15 @@
// 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) {
+ loadImage.readFile = function (file, callback, method) {
if (window.FileReader && FileReader.prototype.readAsDataURL) {
var fileReader = new FileReader();
fileReader.onload = fileReader.onerror = callback;
- fileReader.readAsDataURL(file);
+ method = method || 'readAsDataURL';
+ if (!fileReader[method]) {
+ return false;
+ }
+ fileReader[method](file);
return fileReader;
}
return false;
From c48262ab98fe8f0347997382364101b3dfa81f13 Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Mon, 3 Jun 2013 19:11:40 -0500
Subject: [PATCH 024/386] Added an EXIF Reader library to demonstrate the
orientation option.
---
index.html | 46 +-
vendor/exif-reader.js | 1291 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 1324 insertions(+), 13 deletions(-)
create mode 100644 vendor/exif-reader.js
diff --git a/index.html b/index.html
index 51dbb8d..4d75c2d 100644
--- a/index.html
+++ b/index.html
@@ -1,7 +1,7 @@
+
+
diff --git a/vendor/exif-reader.js b/vendor/exif-reader.js
new file mode 100644
index 0000000..2e90c8c
--- /dev/null
+++ b/vendor/exif-reader.js
@@ -0,0 +1,1291 @@
+// Generated by CoffeeScript 1.6.2
+/*
+# ExifReader 0.1
+# http://github.com/mattiasw/exifreader
+# Copyright (C) 2011 Mattias Wallander
+# Licensed under the GNU Lesser General Public License version 3 or later
+# See license text at http://www.gnu.org/licenses/lgpl.txt
+*/
+
+
+(function() {
+ (typeof exports !== "undefined" && exports !== null ? exports : this).ExifReader = (function() {
+ function ExifReader() {
+ var _this = this;
+
+ this._getTagValueAt = {
+ 1: function(offset) {
+ return _this._getByteAt(offset);
+ },
+ 2: function(offset) {
+ return _this._getAsciiAt(offset);
+ },
+ 3: function(offset) {
+ return _this._getShortAt(offset);
+ },
+ 4: function(offset) {
+ return _this._getLongAt(offset);
+ },
+ 5: function(offset) {
+ return _this._getRationalAt(offset);
+ },
+ 7: function(offset) {
+ return _this._getUndefinedAt(offset);
+ },
+ 9: function(offset) {
+ return _this._getSlongAt(offset);
+ },
+ 10: function(offset) {
+ return _this._getSrationalAt(offset);
+ }
+ };
+ }
+
+ /*
+ # Loads all the Exif tags from the specified image file buffer.
+ #
+ # data ArrayBuffer Image file data
+ */
+
+
+ ExifReader.prototype.load = function(data) {
+ return this.loadView(new DataView(data));
+ };
+
+ /*
+ # Loads all the Exif tags from the specified image file buffer view. Probably
+ # used when DataView isn't supported by the browser.
+ #
+ # @_dataView DataView Image file data view
+ */
+
+
+ ExifReader.prototype.loadView = function(_dataView) {
+ this._dataView = _dataView;
+ this._tags = {};
+ this._checkImageHeader();
+ return this._readTags();
+ };
+
+ ExifReader.prototype._checkImageHeader = function() {
+ var byteLength, dataView, i;
+
+ dataView = this._dataView;
+ byteLength = dataView.byteLength;
+ if (byteLength < 12) {
+ throw "Data buffer too short";
+ }
+ if (dataView.getUint32(0, false) === 0xffd8ffe1) {
+ if (dataView.getUint32(6, false) === 0x45786966 && dataView.getUint16(10, false) === 0x0000) {
+ this._tiffHeaderOffset = 0x0c;
+ return;
+ }
+ } else if (dataView.getUint32(0, false) === 0xffd8ffe0) {
+ i = 10;
+ while (i < byteLength) {
+ if (dataView.getUint8(i, false) === 0x45 && dataView.getUint32(i, false) === 0x45786966 && dataView.getUint16(i + 4, false) === 0x0000) {
+ this._tiffHeaderOffset = i + 6;
+ return;
+ }
+ i++;
+ }
+ } else {
+ throw "Invalid image format";
+ }
+ throw "No Exif data";
+ };
+
+ ExifReader.prototype._readTags = function() {
+ this._setByteOrder();
+ this._read0thIfd();
+ this._readExifIfd();
+ this._readGpsIfd();
+ return this._readInteroperabilityIfd();
+ };
+
+ ExifReader.prototype._setByteOrder = function() {
+ if (this._dataView.getUint16(this._tiffHeaderOffset) === 0x4949) {
+ return this._littleEndian = true;
+ } else if (this._dataView.getUint16(this._tiffHeaderOffset) === 0x4d4d) {
+ return this._littleEndian = false;
+ } else {
+ throw 'Illegal byte order value. Faulty image.';
+ }
+ };
+
+ ExifReader.prototype._read0thIfd = function() {
+ var ifdOffset;
+
+ ifdOffset = this._getIfdOffset();
+ return this._readIfd('0th', ifdOffset);
+ };
+
+ ExifReader.prototype._getIfdOffset = function() {
+ return this._tiffHeaderOffset + this._getLongAt(this._tiffHeaderOffset + 4);
+ };
+
+ ExifReader.prototype._readExifIfd = function() {
+ var ifdOffset;
+
+ if (this._tags['Exif IFD Pointer'] != null) {
+ ifdOffset = this._tiffHeaderOffset + this._tags['Exif IFD Pointer'].value;
+ return this._readIfd('exif', ifdOffset);
+ }
+ };
+
+ ExifReader.prototype._readGpsIfd = function() {
+ var ifdOffset;
+
+ if (this._tags['GPS Info IFD Pointer'] != null) {
+ ifdOffset = this._tiffHeaderOffset + this._tags['GPS Info IFD Pointer'].value;
+ return this._readIfd('gps', ifdOffset);
+ }
+ };
+
+ ExifReader.prototype._readInteroperabilityIfd = function() {
+ var ifdOffset;
+
+ if (this._tags['Interoperability IFD Pointer'] != null) {
+ ifdOffset = this._tiffHeaderOffset + this._tags['Interoperability IFD Pointer'].value;
+ return this._readIfd('interoperability', ifdOffset);
+ }
+ };
+
+ ExifReader.prototype._readIfd = function(ifdType, offset) {
+ var fieldIndex, numberOfFields, tag, _i, _results;
+
+ numberOfFields = this._getShortAt(offset);
+ offset += 2;
+ _results = [];
+ for (fieldIndex = _i = 0; 0 <= numberOfFields ? _i < numberOfFields : _i > numberOfFields; fieldIndex = 0 <= numberOfFields ? ++_i : --_i) {
+ tag = this._readTag(ifdType, offset);
+ this._tags[tag.name] = {
+ 'value': tag.value,
+ 'description': tag.description
+ };
+ _results.push(offset += 12);
+ }
+ return _results;
+ };
+
+ ExifReader.prototype._readTag = function(ifdType, offset) {
+ var tagCode, tagCount, tagDescription, tagName, tagType, tagValue, tagValueOffset;
+
+ tagCode = this._getShortAt(offset);
+ tagType = this._getShortAt(offset + 2);
+ tagCount = this._getLongAt(offset + 4);
+ if (this._typeSizes[tagType] * tagCount <= 4) {
+ tagValue = this._getTagValue(offset + 8, tagType, tagCount);
+ } else {
+ tagValueOffset = this._getLongAt(offset + 8);
+ tagValue = this._getTagValue(this._tiffHeaderOffset + tagValueOffset, tagType, tagCount);
+ }
+ if (tagType === this._tagTypes['ASCII']) {
+ tagValue = this._splitNullSeparatedAsciiString(tagValue);
+ }
+ if (this._tagNames[ifdType][tagCode] != null) {
+ if ((this._tagNames[ifdType][tagCode]['name'] != null) && (this._tagNames[ifdType][tagCode]['description'] != null)) {
+ tagName = this._tagNames[ifdType][tagCode]['name'];
+ tagDescription = this._tagNames[ifdType][tagCode]['description'](tagValue);
+ } else {
+ tagName = this._tagNames[ifdType][tagCode];
+ if (tagValue instanceof Array) {
+ tagDescription = tagValue.join(', ');
+ } else {
+ tagDescription = tagValue;
+ }
+ }
+ return {
+ 'name': tagName,
+ 'value': tagValue,
+ 'description': tagDescription
+ };
+ } else {
+ return {
+ 'name': "undefined-" + tagCode,
+ 'value': tagValue,
+ 'description': tagValue
+ };
+ }
+ };
+
+ ExifReader.prototype._getTagValue = function(offset, type, count) {
+ var tagValue, value, valueIndex;
+
+ value = (function() {
+ var _i, _results;
+
+ _results = [];
+ for (valueIndex = _i = 0; 0 <= count ? _i < count : _i > count; valueIndex = 0 <= count ? ++_i : --_i) {
+ tagValue = this._getTagValueAt[type](offset);
+ offset += this._typeSizes[type];
+ _results.push(tagValue);
+ }
+ return _results;
+ }).call(this);
+ if (value.length === 1) {
+ value = value[0];
+ } else if (type === this._tagTypes['ASCII']) {
+ value = this._getAsciiValue(value);
+ }
+ return value;
+ };
+
+ ExifReader.prototype._getAsciiValue = function(charArray) {
+ var char, newCharArray;
+
+ return newCharArray = (function() {
+ var _i, _len, _results;
+
+ _results = [];
+ for (_i = 0, _len = charArray.length; _i < _len; _i++) {
+ char = charArray[_i];
+ _results.push(String.fromCharCode(char));
+ }
+ return _results;
+ })();
+ };
+
+ ExifReader.prototype._getByteAt = function(offset) {
+ return this._dataView.getUint8(offset);
+ };
+
+ ExifReader.prototype._getAsciiAt = function(offset) {
+ return this._dataView.getUint8(offset);
+ };
+
+ ExifReader.prototype._getShortAt = function(offset) {
+ return this._dataView.getUint16(offset, this._littleEndian);
+ };
+
+ ExifReader.prototype._getLongAt = function(offset) {
+ return this._dataView.getUint32(offset, this._littleEndian);
+ };
+
+ ExifReader.prototype._getRationalAt = function(offset) {
+ return this._getLongAt(offset) / this._getLongAt(offset + 4);
+ };
+
+ ExifReader.prototype._getUndefinedAt = function(offset) {
+ return this._getByteAt(offset);
+ };
+
+ ExifReader.prototype._getSlongAt = function(offset) {
+ return this._dataView.getInt32(offset, this._littleEndian);
+ };
+
+ ExifReader.prototype._getSrationalAt = function(offset) {
+ return this._getSlongAt(offset) / this._getSlongAt(offset + 4);
+ };
+
+ ExifReader.prototype._splitNullSeparatedAsciiString = function(string) {
+ var char, i, tagValue, _i, _len;
+
+ tagValue = [];
+ i = 0;
+ for (_i = 0, _len = string.length; _i < _len; _i++) {
+ char = string[_i];
+ if (char === '\x00') {
+ i++;
+ continue;
+ }
+ if (tagValue[i] == null) {
+ tagValue[i] = '';
+ }
+ tagValue[i] += char;
+ }
+ return tagValue;
+ };
+
+ ExifReader.prototype._typeSizes = {
+ 1: 1,
+ 2: 1,
+ 3: 2,
+ 4: 4,
+ 5: 8,
+ 7: 1,
+ 9: 4,
+ 10: 8
+ };
+
+ ExifReader.prototype._tagTypes = {
+ 'BYTE': 1,
+ 'ASCII': 2,
+ 'SHORT': 3,
+ 'LONG': 4,
+ 'RATIONAL': 5,
+ 'UNDEFINED': 7,
+ 'SLONG': 9,
+ 'SRATIONAL': 10
+ };
+
+ ExifReader.prototype._tagNames = {
+ '0th': {
+ 0x0100: 'ImageWidth',
+ 0x0101: 'ImageLength',
+ 0x0102: 'BitsPerSample',
+ 0x0103: 'Compression',
+ 0x0106: 'PhotometricInterpretation',
+ 0x010e: 'ImageDescription',
+ 0x010f: 'Make',
+ 0x0110: 'Model',
+ 0x0111: 'StripOffsets',
+ 0x0112: {
+ 'name': 'Orientation',
+ 'description': function(value) {
+ switch (value) {
+ case 1:
+ return 'top-left';
+ case 2:
+ return 'top-right';
+ case 3:
+ return 'bottom-right';
+ case 4:
+ return 'bottom-left';
+ case 5:
+ return 'left-top';
+ case 6:
+ return 'right-top';
+ case 7:
+ return 'right-bottom';
+ case 8:
+ return 'left-bottom';
+ default:
+ return 'Undefined';
+ }
+ }
+ },
+ 0x0115: 'SamplesPerPixel',
+ 0x0116: 'RowsPerStrip',
+ 0x0117: 'StripByteCounts',
+ 0x011a: 'XResolution',
+ 0x011b: 'YResolution',
+ 0x011c: 'PlanarConfiguration',
+ 0x0128: {
+ 'name': 'ResolutionUnit',
+ 'description': function(value) {
+ switch (value) {
+ case 2:
+ return 'inches';
+ case 3:
+ return 'centimeters';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x012d: 'TransferFunction',
+ 0x0131: 'Software',
+ 0x0132: 'DateTime',
+ 0x013b: 'Artist',
+ 0x013e: 'WhitePoint',
+ 0x013f: 'PrimaryChromaticities',
+ 0x0201: 'JPEGInterchangeFormat',
+ 0x0202: 'JPEGInterchangeFormatLength',
+ 0x0211: 'YCbCrCoefficients',
+ 0x0212: 'YCbCrSubSampling',
+ 0x0213: {
+ 'name': 'YCbCrPositioning',
+ 'description': function(value) {
+ switch (value) {
+ case 1:
+ return 'centered';
+ case 2:
+ return 'co-sited';
+ default:
+ return 'undefied ' + value;
+ }
+ }
+ },
+ 0x0214: 'ReferenceBlackWhite',
+ 0x8298: {
+ 'name': 'Copyright',
+ 'description': function(value) {
+ return value.join('; ');
+ }
+ },
+ 0x8769: 'Exif IFD Pointer',
+ 0x8825: 'GPS Info IFD Pointer'
+ },
+ 'exif': {
+ 0x829a: 'ExposureTime',
+ 0x829d: 'FNumber',
+ 0x8822: {
+ 'name': 'ExposureProgram',
+ 'description': function(value) {
+ switch (value) {
+ case 0:
+ return 'Undefined';
+ case 1:
+ return 'Manual';
+ case 2:
+ return 'Normal program';
+ case 3:
+ return 'Aperture priority';
+ case 4:
+ return 'Shutter priority';
+ case 5:
+ return 'Creative program';
+ case 6:
+ return 'Action program';
+ case 7:
+ return 'Portrait mode';
+ case 8:
+ return 'Landscape mode';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x8824: 'SpectralSensitivity',
+ 0x8827: 'ISOSpeedRatings',
+ 0x8828: {
+ 'name': 'OECF',
+ 'description': function(value) {
+ return '[Raw OECF table data]';
+ }
+ },
+ 0x9000: {
+ 'name': 'ExifVersion',
+ 'description': function(value) {
+ var char, string, _i, _len;
+
+ string = '';
+ for (_i = 0, _len = value.length; _i < _len; _i++) {
+ char = value[_i];
+ string += String.fromCharCode(char);
+ }
+ return string;
+ }
+ },
+ 0x9003: 'DateTimeOriginal',
+ 0x9004: 'DateTimeDigitized',
+ 0x9101: {
+ 'name': 'ComponentsConfiguration',
+ 'description': function(value) {
+ var char, string, _i, _len;
+
+ string = '';
+ for (_i = 0, _len = value.length; _i < _len; _i++) {
+ char = value[_i];
+ switch (char) {
+ case 0x31:
+ string += 'Y';
+ break;
+ case 0x32:
+ string += 'Cb';
+ break;
+ case 0x33:
+ string += 'Cr';
+ break;
+ case 0x34:
+ string += 'R';
+ break;
+ case 0x35:
+ string += 'G';
+ break;
+ case 0x36:
+ string += 'B';
+ }
+ }
+ return string;
+ }
+ },
+ 0x9102: 'CompressedBitsPerPixel',
+ 0x9201: 'ShutterSpeedValue',
+ 0x9202: 'ApertureValue',
+ 0x9203: 'BrightnessValue',
+ 0x9204: 'ExposureBiasValue',
+ 0x9205: 'MaxApertureValue',
+ 0x9206: 'SubjectDistance',
+ 0x9207: {
+ 'name': 'MeteringMode',
+ 'description': function(value) {
+ switch (value) {
+ case 1:
+ return 'Average';
+ case 2:
+ return 'CenterWeightedAverage';
+ case 3:
+ return 'Spot';
+ case 4:
+ return 'MultiSpot';
+ case 5:
+ return 'Pattern';
+ case 6:
+ return 'Partial';
+ case 255:
+ return 'Other';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x9208: {
+ 'name': 'LightSource',
+ 'description': function(value) {
+ switch (value) {
+ case 1:
+ return 'Daylight';
+ case 2:
+ return 'Fluorescent';
+ case 3:
+ return 'Tungsten (incandescent light)';
+ case 4:
+ return 'Flash';
+ case 9:
+ return 'Fine weather';
+ case 10:
+ return 'Cloudy weather';
+ case 11:
+ return 'Shade';
+ case 12:
+ return 'Daylight fluorescent (D 5700 – 7100K)';
+ case 13:
+ return 'Day white fluorescent (N 4600 – 5400K)';
+ case 14:
+ return 'Cool white fluorescent (W 3900 – 4500K)';
+ case 15:
+ return 'White fluorescent (WW 3200 – 3700K)';
+ case 17:
+ return 'Standard light A';
+ case 18:
+ return 'Standard light B';
+ case 19:
+ return 'Standard light C';
+ case 20:
+ return 'D55';
+ case 21:
+ return 'D65';
+ case 22:
+ return 'D75';
+ case 23:
+ return 'D50';
+ case 24:
+ return 'ISO studio tungsten';
+ case 255:
+ return 'Other light source';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x9209: {
+ 'name': 'Flash',
+ 'description': function(value) {
+ switch (value) {
+ case 0x00:
+ return 'Flash did not fire';
+ case 0x01:
+ return 'Flash fired';
+ case 0x05:
+ return 'Strobe return light not detected';
+ case 0x07:
+ return 'Strobe return light detected';
+ case 0x09:
+ return 'Flash fired, compulsory flash mode';
+ case 0x0d:
+ return 'Flash fired, compulsory flash mode, return light not detected';
+ case 0x0f:
+ return 'Flash fired, compulsory flash mode, return light detected';
+ case 0x10:
+ return 'Flash did not fire, compulsory flash mode';
+ case 0x18:
+ return 'Flash did not fire, auto mode';
+ case 0x19:
+ return 'Flash fired, auto mode';
+ case 0x1d:
+ return 'Flash fired, auto mode, return light not detected';
+ case 0x1f:
+ return 'Flash fired, auto mode, return light detected';
+ case 0x20:
+ return 'No flash function';
+ case 0x41:
+ return 'Flash fired, red-eye reduction mode';
+ case 0x45:
+ return 'Flash fired, red-eye reduction mode, return light not detected';
+ case 0x47:
+ return 'Flash fired, red-eye reduction mode, return light detected';
+ case 0x49:
+ return 'Flash fired, compulsory flash mode, red-eye reduction mode';
+ case 0x4d:
+ return 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected';
+ case 0x4f:
+ return 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected';
+ case 0x59:
+ return 'Flash fired, auto mode, red-eye reduction mode';
+ case 0x5d:
+ return 'Flash fired, auto mode, return light not detected, red-eye reduction mode';
+ case 0x5f:
+ return 'Flash fired, auto mode, return light detected, red-eye reduction mode';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x920a: 'FocalLength',
+ 0x9214: {
+ 'name': 'SubjectArea',
+ 'description': function(value) {
+ switch (value.length) {
+ case 2:
+ return "Location; X: " + value[0] + ", Y: " + value[1];
+ case 3:
+ return "Circle; X: " + value[0] + ", Y: " + value[1] + ", diameter: " + value[2];
+ case 4:
+ return "Rectangle; X: " + value[0] + ", Y: " + value[1] + ", width: " + value[2] + ", height: " + value[3];
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x927c: {
+ 'name': 'MakerNote',
+ 'description': function(value) {
+ return '[Raw maker note data]';
+ }
+ },
+ 0x9286: {
+ 'name': 'UserComment',
+ 'description': function(value) {
+ switch (value.slice(0, 8).map(function(byte) {
+ return String.fromCharCode(byte);
+ }).join('')) {
+ case 'ASCII\x00\x00\x00':
+ return value.slice(8, value.length).map(function(byte) {
+ return String.fromCharCode(byte);
+ }).join('');
+ case 'JIS\x00\x00\x00\x00\x00':
+ return '[JIS encoded text]';
+ case 'UNICODE\x00':
+ return '[Unicode encoded text]';
+ case '\x00\x00\x00\x00\x00\x00\x00\x00':
+ return '[Undefined encoding]';
+ }
+ }
+ },
+ 0x9290: 'SubSecTime',
+ 0x9291: 'SubSecTimeOriginal',
+ 0x9292: 'SubSecTimeDigitized',
+ 0xa000: {
+ 'name': 'FlashpixVersion',
+ 'description': function(value) {
+ var char, string, _i, _len;
+
+ string = '';
+ for (_i = 0, _len = value.length; _i < _len; _i++) {
+ char = value[_i];
+ string += String.fromCharCode(char);
+ }
+ return string;
+ }
+ },
+ 0xa001: {
+ 'name': 'ColorSpace',
+ 'description': function(value) {
+ switch (value) {
+ case 1:
+ return 'sRGB';
+ case 0xffff:
+ return 'Uncalibrated';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0xa002: 'PixelXDimension',
+ 0xa003: 'PixelYDimension',
+ 0xa004: 'RelatedSoundFile',
+ 0xa005: 'Interoperability IFD Pointer',
+ 0xa20b: 'FlashEnergy',
+ 0xa20c: {
+ 'name': 'SpatialFrequencyResponse',
+ 'description': function(value) {
+ return '[Raw SFR table data]';
+ }
+ },
+ 0xa20e: 'FocalPlaneXResolution',
+ 0xa20f: 'FocalPlaneYResolution',
+ 0xa210: {
+ 'name': 'FocalPlaneResolutionUnit',
+ 'description': function(value) {
+ switch (value) {
+ case 2:
+ return 'inches';
+ case 3:
+ return 'centimeters';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0xa214: {
+ 'name': 'SubjectLocation',
+ 'description': function(value) {
+ return "X: " + value[0] + ", Y: " + value[1];
+ }
+ },
+ 0xa215: 'ExposureIndex',
+ 0xa217: {
+ 'name': 'SensingMethod',
+ 'description': function(value) {
+ switch (value) {
+ case 1:
+ return 'Undefined';
+ case 2:
+ return 'One-chip color area sensor';
+ case 3:
+ return 'Two-chip color area sensor';
+ case 4:
+ return 'Three-chip color area sensor';
+ case 5:
+ return 'Color sequential area sensor';
+ case 7:
+ return 'Trilinear sensor';
+ case 8:
+ return 'Color sequential linear sensor';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0xa300: {
+ 'name': 'FileSource',
+ 'description': function(value) {
+ switch (value) {
+ case 3:
+ return 'DSC';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0xa301: {
+ 'name': 'SceneType',
+ 'description': function(value) {
+ switch (value) {
+ case 1:
+ return 'A directly photographed image';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0xa302: {
+ 'name': 'CFAPattern',
+ 'description': function(value) {
+ return '[Raw CFA pattern table data]';
+ }
+ },
+ 0xa401: {
+ 'name': 'CustomRendered',
+ 'description': function(value) {
+ switch (value) {
+ case 0:
+ return 'Normal process';
+ case 1:
+ return 'Custom process';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0xa402: {
+ 'name': 'ExposureMode',
+ 'description': function(value) {
+ switch (value) {
+ case 0:
+ return 'Auto exposure';
+ case 1:
+ return 'Manual exposure';
+ case 2:
+ return 'Auto bracket';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0xa403: {
+ 'name': 'WhiteBalance',
+ 'description': function(value) {
+ switch (value) {
+ case 0:
+ return 'Auto white balance';
+ case 1:
+ return 'Manual white balance';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0xa404: {
+ 'name': 'DigitalZoomRatio',
+ 'description': function(value) {
+ switch (value) {
+ case 0:
+ return 'Digital zoom was not used';
+ default:
+ return value;
+ }
+ }
+ },
+ 0xa405: {
+ 'name': 'FocalLengthIn35mmFilm',
+ 'description': function(value) {
+ switch (value) {
+ case 0:
+ return 'Unknown';
+ default:
+ return value;
+ }
+ }
+ },
+ 0xa406: {
+ 'name': 'SceneCaptureType',
+ 'description': function(value) {
+ switch (value) {
+ case 0:
+ return 'Standard';
+ case 1:
+ return 'Landscape';
+ case 2:
+ return 'Portrait';
+ case 3:
+ return 'Night scene';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0xa407: {
+ 'name': 'GainControl',
+ 'description': function(value) {
+ switch (value) {
+ case 0:
+ return 'None';
+ case 1:
+ return 'Low gain up';
+ case 2:
+ return 'High gain up';
+ case 3:
+ return 'Low gain down';
+ case 4:
+ return 'High gain down';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0xa408: {
+ 'name': 'Contrast',
+ 'description': function(value) {
+ switch (value) {
+ case 0:
+ return 'Normal';
+ case 1:
+ return 'Soft';
+ case 2:
+ return 'Hard';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0xa409: {
+ 'name': 'Saturation',
+ 'description': function(value) {
+ switch (value) {
+ case 0:
+ return 'Normal';
+ case 1:
+ return 'Low saturation';
+ case 2:
+ return 'High saturation';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0xa40a: {
+ 'name': 'Sharpness',
+ 'description': function(value) {
+ switch (value) {
+ case 0:
+ return 'Normal';
+ case 1:
+ return 'Soft';
+ case 2:
+ return 'Hard';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0xa40b: {
+ 'name': 'DeviceSettingDescription',
+ 'description': function(value) {
+ return '[Raw device settings table data]';
+ }
+ },
+ 0xa40c: {
+ 'name': 'SubjectDistanceRange',
+ 'description': function(value) {
+ switch (value) {
+ case 1:
+ return 'Macro';
+ case 2:
+ return 'Close view';
+ case 3:
+ return 'Distant view';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0xa420: 'ImageUniqueID'
+ },
+ 'gps': {
+ 0x0000: {
+ 'name': 'GPSVersionID',
+ 'description': function(value) {
+ var _ref, _ref1;
+
+ if ((value[0] === (_ref = value[1]) && _ref === 2) && (value[2] === (_ref1 = value[3]) && _ref1 === 0)) {
+ return 'Version 2.2';
+ } else {
+ return 'Unknown';
+ }
+ }
+ },
+ 0x0001: {
+ 'name': 'GPSLatitudeRef',
+ 'description': function(value) {
+ switch (value.join('')) {
+ case 'N':
+ return 'North latitude';
+ case 'S':
+ return 'South latitude';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x0002: {
+ 'name': 'GPSLatitude',
+ 'description': function(value) {
+ return value[0] + value[1] / 60 + value[2] / 3600;
+ }
+ },
+ 0x0003: {
+ 'name': 'GPSLongitudeRef',
+ 'description': function(value) {
+ switch (value.join('')) {
+ case 'E':
+ return 'East longitude';
+ case 'W':
+ return 'West longitude';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x0004: {
+ 'name': 'GPSLongitude',
+ 'description': function(value) {
+ return value[0] + value[1] / 60 + value[2] / 3600;
+ }
+ },
+ 0x0005: {
+ 'name': 'GPSAltitudeRef',
+ 'description': function(value) {
+ switch (value) {
+ case 0:
+ return 'Sea level';
+ case 1:
+ return 'Sea level reference (negative value)';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x0006: {
+ 'name': 'GPSAltitude',
+ 'description': function(value) {
+ return value + ' m';
+ }
+ },
+ 0x0007: {
+ 'name': 'GPSTimeStamp',
+ 'description': function(value) {
+ var padZero;
+
+ padZero = function(num) {
+ var i;
+
+ return ((function() {
+ var _i, _ref, _results;
+
+ _results = [];
+ for (i = _i = 0, _ref = 2 - ('' + Math.floor(num)).length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
+ _results.push('0');
+ }
+ return _results;
+ })()) + num;
+ };
+ return value.map(padZero).join(':');
+ }
+ },
+ 0x0008: 'GPSSatellites',
+ 0x0009: {
+ 'name': 'GPSStatus',
+ 'description': function(value) {
+ switch (value.join('')) {
+ case 'A':
+ return 'Measurement in progress';
+ case 'V':
+ return 'Measurement Interoperability';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x000a: {
+ 'name': 'GPSMeasureMode',
+ 'description': function(value) {
+ switch (value.join('')) {
+ case '2':
+ return '2-dimensional measurement';
+ case '3':
+ return '3-dimensional measurement';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x000b: 'GPSDOP',
+ 0x000c: {
+ 'name': 'GPSSpeedRef',
+ 'description': function(value) {
+ switch (value.join('')) {
+ case 'K':
+ return 'Kilometers per hour';
+ case 'M':
+ return 'Miles per hour';
+ case 'N':
+ return 'Knots';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x000d: 'GPSSpeed',
+ 0x000e: {
+ 'name': 'GPSTrackRef',
+ 'description': function(value) {
+ switch (value.join('')) {
+ case 'T':
+ return 'True direction';
+ case 'M':
+ return 'Magnetic direction';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x000f: 'GPSTrack',
+ 0x0010: {
+ 'name': 'GPSImgDirectionRef',
+ 'description': function(value) {
+ switch (value.join('')) {
+ case 'T':
+ return 'True direction';
+ case 'M':
+ return 'Magnetic direction';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x0011: 'GPSImgDirection',
+ 0x0012: 'GPSMapDatum',
+ 0x0013: {
+ 'name': 'GPSDestLatitudeRef',
+ 'description': function(value) {
+ switch (value.join('')) {
+ case 'N':
+ return 'North latitude';
+ case 'S':
+ return 'South latitude';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x0014: {
+ 'name': 'GPSDestLatitude',
+ 'description': function(value) {
+ return value[0] + value[1] / 60 + value[2] / 3600;
+ }
+ },
+ 0x0015: {
+ 'name': 'GPSDestLongitudeRef',
+ 'description': function(value) {
+ switch (value.join('')) {
+ case 'E':
+ return 'East longitude';
+ case 'W':
+ return 'West longitude';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x0016: {
+ 'name': 'GPSDestLongitude',
+ 'description': function(value) {
+ return value[0] + value[1] / 60 + value[2] / 3600;
+ }
+ },
+ 0x0017: {
+ 'name': 'GPSDestBearingRef',
+ 'description': function(value) {
+ switch (value.join('')) {
+ case 'T':
+ return 'True direction';
+ case 'M':
+ return 'Magnetic direction';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x0018: 'GPSDestBearing',
+ 0x0019: {
+ 'name': 'GPSDestDistanceRef',
+ 'description': function(value) {
+ switch (value.join('')) {
+ case 'K':
+ return 'Kilometers';
+ case 'M':
+ return 'Miles';
+ case 'N':
+ return 'Knots';
+ default:
+ return 'Unknown';
+ }
+ }
+ },
+ 0x001a: 'GPSDestDistance',
+ 0x001b: {
+ 'name': 'GPSProcessingMethod',
+ 'description': function(value) {
+ switch (value.slice(0, 8).map(function(byte) {
+ return String.fromCharCode(byte);
+ }).join('')) {
+ case 'ASCII\x00\x00\x00':
+ return value.slice(8, value.length).map(function(byte) {
+ return String.fromCharCode(byte);
+ }).join('');
+ case 'JIS\x00\x00\x00\x00\x00':
+ return '[JIS encoded text]';
+ case 'UNICODE\x00':
+ return '[Unicode encoded text]';
+ case '\x00\x00\x00\x00\x00\x00\x00\x00':
+ return '[Undefined encoding]';
+ }
+ }
+ },
+ 0x001c: {
+ 'name': 'GPSAreaInformation',
+ 'description': function(value) {
+ switch (value.slice(0, 8).map(function(byte) {
+ return String.fromCharCode(byte);
+ }).join('')) {
+ case 'ASCII\x00\x00\x00':
+ return value.slice(8, value.length).map(function(byte) {
+ return String.fromCharCode(byte);
+ }).join('');
+ case 'JIS\x00\x00\x00\x00\x00':
+ return '[JIS encoded text]';
+ case 'UNICODE\x00':
+ return '[Unicode encoded text]';
+ case '\x00\x00\x00\x00\x00\x00\x00\x00':
+ return '[Undefined encoding]';
+ }
+ }
+ },
+ 0x001d: 'GPSDateStamp',
+ 0x001e: {
+ 'name': 'GPSDifferential',
+ 'description': function(value) {
+ switch (value) {
+ case 0:
+ return 'Measurement without differential correction';
+ case 1:
+ return 'Differential correction applied';
+ default:
+ return 'Unknown';
+ }
+ }
+ }
+ },
+ 'interoperability': {
+ 0x0001: 'InteroperabilityIndex',
+ 0x0002: 'UnknownInteroperabilityTag0x0002',
+ 0x1001: 'UnknownInteroperabilityTag0x1001',
+ 0x1002: 'UnknownInteroperabilityTag0x1002'
+ }
+ };
+
+ /*
+ # Gets the image's value of the tag with the given name.
+ #
+ # name string The name of the tag to get the value of
+ #
+ # Returns the value of the tag with the given name if it exists,
+ # otherwise throws "Undefined".
+ */
+
+
+ ExifReader.prototype.getTagValue = function(name) {
+ if (this._tags[name] != null) {
+ return this._tags[name].value;
+ } else {
+ throw 'Undefined';
+ }
+ };
+
+ /*
+ # Gets the image's description of the tag with the given name.
+ #
+ # name string The name of the tag to get the description of
+ #
+ # Returns the description of the tag with the given name if it exists,
+ # otherwise throws "Undefined".
+ */
+
+
+ ExifReader.prototype.getTagDescription = function(name) {
+ if (this._tags[name] != null) {
+ return this._tags[name].description;
+ } else {
+ throw 'Undefined';
+ }
+ };
+
+ /*
+ # Gets all the image's tags.
+ #
+ # Returns the image's tags as an associative array: name -> description.
+ */
+
+
+ ExifReader.prototype.getAllTags = function() {
+ return this._tags;
+ };
+
+ return ExifReader;
+
+ })();
+
+}).call(this);
From 727f9cd35fa3c5ed52f298b88220d20f382ba9e5 Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Mon, 3 Jun 2013 19:12:24 -0500
Subject: [PATCH 025/386] Updated the minified version.
---
load-image.min.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/load-image.min.js b/load-image.min.js
index 5ac991b..4354498 100644
--- a/load-image.min.js
+++ b/load-image.min.js
@@ -1 +1 @@
-(function(e){"use strict";var t=function(e,a,n){var r,i,c=document.createElement("img");if(c.onerror=a,c.onload=function(){!i||n&&n.noRevoke||t.revokeObjectURL(i),a&&a(t.scale(c,n))},t.isInstanceOf("Blob",e)||t.isInstanceOf("File",e))r=i=t.createObjectURL(e),c._type=e.type;else{if("string"!=typeof e)return!1;r=e,n&&n.crossOrigin&&(c.crossOrigin=n.crossOrigin)}return r?(c.src=r,c):t.readFile(e,function(e){var t=e.target;t&&t.result?c.src=t.result:a&&a(e)})},a=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;t.isInstanceOf=function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},t.detectSubsampling=function(e){var t,a;return e.width*e.height>1048576?(t=document.createElement("canvas"),t.width=t.height=1,a=t.getContext("2d"),a.drawImage(e,-e.width+1,0),0===a.getImageData(0,0,1,1).data[3]):!1},t.detectVerticalSquash=function(e,t){var a,n,r,i,c,o=document.createElement("canvas"),d=o.getContext("2d");for(o.width=1,o.height=t,d.drawImage(e,0,0),a=d.getImageData(0,0,1,t).data,n=0,r=t,i=t;i>n;)c=a[4*(i-1)+3],0===c?r=i:n=i,i=r+n>>1;return i/t||1},t.renderImageToCanvas=function(e,a,n,r,i,c,o,d,g,s){var h,u,l,m=e.getContext("2d"),f=document.createElement("canvas"),w=f.width=f.height=1024,v=f.getContext("2d");for(m.save(),t.detectSubsampling(a)&&(i/=2,c/=2),h=t.detectVerticalSquash(a,c),g=Math.ceil(w*g/i),s=Math.ceil(w*s/c/h),d=0,l=0;c>l;){for(o=0,u=0;i>u;)v.clearRect(0,0,w,w),v.drawImage(a,n,r,i,c,-u,-l,i,c),m.drawImage(f,0,0,w,w,o,d,g,s),u+=w,o+=g;l+=w,d+=s}m.restore()},t.scale=function(e,a){a=a||{};var n,r,i,c=document.createElement("canvas"),o=e.getContext||(a.canvas||a.crop)&&c.getContext,d=e.width,g=e.height,s=a.maxWidth,h=a.maxHeight,u=d,l=g,m=0,f=0,w=0,v=0;return o&&s&&h&&a.crop?(n=s,r=h,s/h>d/g?(l=h*d/s,f=(g-l)/2):(u=s*g/h,m=(d-u)/2)):(n=d,r=g,i=Math.max((a.minWidth||n)/n,(a.minHeight||r)/r),i>1&&(n=Math.ceil(n*i),r=Math.ceil(r*i)),i=Math.min((s||n)/n,(h||r)/r),1>i&&(n=Math.ceil(n*i),r=Math.ceil(r*i))),o?(c.width=n,c.height=r,"image/jpeg"===e._type?t.renderImageToCanvas(c,e,m,f,u,l,w,v,n,r):c.getContext("2d").drawImage(e,m,f,u,l,w,v,n,r),c):(e.width=n,e.height=r,e)},t.createObjectURL=function(e){return a?a.createObjectURL(e):!1},t.revokeObjectURL=function(e){return a?a.revokeObjectURL(e):!1},t.readFile=function(e,t){if(window.FileReader&&FileReader.prototype.readAsDataURL){var a=new FileReader;return a.onload=a.onerror=t,a.readAsDataURL(e),a}return!1},"function"==typeof define&&define.amd?define(function(){return t}):e.loadImage=t})(this);
\ No newline at end of file
+(function(e){"use strict";var t=function(e,a,r){var n,i,c=document.createElement("img");if(c.onerror=a,c.onload=function(){!i||r&&r.noRevoke||t.revokeObjectURL(i),a&&a(t.scale(c,r))},t.isInstanceOf("Blob",e)||t.isInstanceOf("File",e))n=i=t.createObjectURL(e),c._type=e.type;else{if("string"!=typeof e)return!1;n=e,r&&r.crossOrigin&&(c.crossOrigin=r.crossOrigin)}return n?(c.src=n,c):t.readFile(e,function(e){var t=e.target;t&&t.result?c.src=t.result:a&&a(e)})},a=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;t.isInstanceOf=function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},t.transformCoordinates=function(e,t){var a=e.getContext("2d"),r=e.width,n=e.height;switch(t>4&&(e.width=n,e.height=r),t){case 2:a.translate(r,0),a.scale(-1,1);break;case 3:a.translate(r,n),a.rotate(Math.PI);break;case 4:a.translate(0,n),a.scale(1,-1);break;case 5:a.rotate(.5*Math.PI),a.scale(1,-1);break;case 6:a.rotate(.5*Math.PI),a.translate(0,-n);break;case 7:a.rotate(.5*Math.PI),a.translate(r,-n),a.scale(-1,1);break;case 8:a.rotate(-.5*Math.PI),a.translate(-r,0)}},t.detectSubsampling=function(e){var t,a;return e.width*e.height>1048576?(t=document.createElement("canvas"),t.width=t.height=1,a=t.getContext("2d"),a.drawImage(e,-e.width+1,0),0===a.getImageData(0,0,1,1).data[3]):!1},t.detectVerticalSquash=function(e,t){var a,r,n,i,c,o=document.createElement("canvas"),s=o.getContext("2d");for(o.width=1,o.height=t,s.drawImage(e,0,0),a=s.getImageData(0,0,1,t).data,r=0,n=t,i=t;i>r;)c=a[4*(i-1)+3],0===c?n=i:r=i,i=n+r>>1;return i/t||1},t.renderImageToCanvas=function(e,a,r,n,i,c,o,s,d,h){var g,l,u,m=e.getContext("2d"),f=document.createElement("canvas"),w=f.width=f.height=1024,v=f.getContext("2d");for(m.save(),t.detectSubsampling(a)&&(i/=2,c/=2),g=t.detectVerticalSquash(a,c),d=Math.ceil(w*d/i),h=Math.ceil(w*h/c/g),s=0,u=0;c>u;){for(o=0,l=0;i>l;)v.clearRect(0,0,w,w),v.drawImage(a,r,n,i,c,-l,-u,i,c),m.drawImage(f,0,0,w,w,o,s,d,h),l+=w,o+=d;u+=w,s+=h}m.restore()},t.scale=function(e,a){a=a||{};var r,n,i,c,o,s,d,h=document.createElement("canvas"),g=e.getContext||(a.canvas||a.crop)&&h.getContext,l=e.width,u=e.height,m=l,f=u,w=0,v=0,b=0,R=0;return g&&a.orientation>4?(r=a.maxHeight,n=a.maxWidth,i=a.minHeight,c=a.minWidth):(r=a.maxWidth,n=a.maxHeight,i=a.minWidth,c=a.minHeight),g&&r&&n&&a.crop?(o=r,s=n,r/n>l/u?(f=n*l/r,v=(u-f)/2):(m=r*u/n,w=(l-m)/2)):(o=l,s=u,d=Math.max((i||o)/o,(c||s)/s),d>1&&(o=Math.ceil(o*d),s=Math.ceil(s*d)),d=Math.min((r||o)/o,(n||s)/s),1>d&&(o=Math.ceil(o*d),s=Math.ceil(s*d))),g?(h.width=o,h.height=s,t.transformCoordinates(h,a.orientation),"image/jpeg"===e._type?t.renderImageToCanvas(h,e,w,v,m,f,b,R,o,s):h.getContext("2d").drawImage(e,w,v,m,f,b,R,o,s),h):(e.width=o,e.height=s,e)},t.createObjectURL=function(e){return a?a.createObjectURL(e):!1},t.revokeObjectURL=function(e){return a?a.revokeObjectURL(e):!1},t.readFile=function(e,t,a){if(window.FileReader&&FileReader.prototype.readAsDataURL){var r=new FileReader;return r.onload=r.onerror=t,a=a||"readAsDataURL",r[a]?(r[a](e),r):!1}return!1},"function"==typeof define&&define.amd?define(function(){return t}):e.loadImage=t})(this);
\ No newline at end of file
From a0669855c991833d366d264c98815fa040aa74fd Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Mon, 3 Jun 2013 19:14:29 -0500
Subject: [PATCH 026/386] Added orientation information to the options listing.
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index b18b431..fa48281 100644
--- a/README.md
+++ b/README.md
@@ -89,6 +89,7 @@ The optional third argument is a map of options:
* **minWidth**: Defines the minimum width of the img/canvas element.
* **minHeight**: Defines the minimum height of the img/canvas element.
* **crop**: Defines if the canvas element should be cropped to the maxWidth/maxHeight constraints.
+* **orientation**: Allows to transform the canvas coordinates according to the EXIF orientation specification.
* **canvas**: Defines if the returned element should be a [canvas](https://developer.mozilla.org/en/HTML/Canvas) element.
* **crossOrigin**: Sets the crossOrigin property on the img element for loading [CORS enabled images](https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image).
* **noRevoke**: By default, the [created object URL](https://developer.mozilla.org/en/DOM/window.URL.createObjectURL) is revoked after the image has been loaded, except when this option is set to *true*.
From 7a31e83af3bf428275aeacd6196a6c4074019249 Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Mon, 3 Jun 2013 19:14:37 -0500
Subject: [PATCH 027/386] Updated package version.
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 7fc224c..d91440c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "blueimp-load-image",
- "version": "1.5.0",
+ "version": "1.6.0",
"title": "JavaScript Load Image",
"description": "JavaScript Load Image is a function to load images provided as File or Blob objects or via URL. It returns an optionally scaled HTML img or canvas element.",
"keywords": [
From 4c10b9bfca5871ecde5a5ff47f728081aa4b56b4 Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Mon, 3 Jun 2013 19:25:29 -0500
Subject: [PATCH 028/386] Assume canvas:true if an orientation is given.
---
load-image.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/load-image.js b/load-image.js
index f31a771..0f6a3a6 100644
--- a/load-image.js
+++ b/load-image.js
@@ -248,7 +248,8 @@
options = options || {};
var canvas = document.createElement('canvas'),
useCanvas = img.getContext ||
- ((options.canvas || options.crop) && canvas.getContext),
+ ((options.canvas || options.crop || options.orientation) &&
+ canvas.getContext),
width = img.width,
height = img.height,
sourceWidth = width,
From 19c12990888b707fbfcaf8b2eaaa9834fee6fb2c Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Mon, 3 Jun 2013 19:30:27 -0500
Subject: [PATCH 029/386] Added orientation tests.
---
test/test.js | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/test/test.js b/test/test.js
index 579f7db..ebac5be 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1,5 +1,5 @@
/*
- * JavaScript Load Image Test 1.5
+ * JavaScript Load Image Test 1.6
* https://github.com/blueimp/JavaScript-Load-Image
*
* Copyright 2011, Sebastian Tschan
@@ -181,6 +181,42 @@
});
+ describe('Orientation', function () {
+
+ it('Should keep the orientation', function (done) {
+ expect(loadImage(blob, function (img) {
+ done();
+ expect(img.width).to.be(80);
+ expect(img.height).to.be(60);
+ }, {orientation: 1})).to.be.ok();
+ });
+
+ it('Should rotate right', function (done) {
+ expect(loadImage(blob, function (img) {
+ done();
+ expect(img.width).to.be(60);
+ expect(img.height).to.be(80);
+ }, {orientation: 6})).to.be.ok();
+ });
+
+ it('Should rotate left', function (done) {
+ expect(loadImage(blob, function (img) {
+ done();
+ expect(img.width).to.be(60);
+ expect(img.height).to.be(80);
+ }, {orientation: 8})).to.be.ok();
+ });
+
+ it('Should adjust constraints to new coordinates', function (done) {
+ expect(loadImage(blob, function (img) {
+ done();
+ expect(img.width).to.be(60);
+ expect(img.height).to.be(80);
+ }, {orientation: 6, maxWidth: 60, maxHeight: 80})).to.be.ok();
+ });
+
+ });
+
describe('Canvas', function () {
it('Return img element to callback if options.canvas is not true', function (done) {
From 2c2d7038e8d74c403895a67dbf6d7be67f7d2991 Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Mon, 3 Jun 2013 19:30:49 -0500
Subject: [PATCH 030/386] Updated the minified version.
---
load-image.min.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/load-image.min.js b/load-image.min.js
index 4354498..9f19c32 100644
--- a/load-image.min.js
+++ b/load-image.min.js
@@ -1 +1 @@
-(function(e){"use strict";var t=function(e,a,r){var n,i,c=document.createElement("img");if(c.onerror=a,c.onload=function(){!i||r&&r.noRevoke||t.revokeObjectURL(i),a&&a(t.scale(c,r))},t.isInstanceOf("Blob",e)||t.isInstanceOf("File",e))n=i=t.createObjectURL(e),c._type=e.type;else{if("string"!=typeof e)return!1;n=e,r&&r.crossOrigin&&(c.crossOrigin=r.crossOrigin)}return n?(c.src=n,c):t.readFile(e,function(e){var t=e.target;t&&t.result?c.src=t.result:a&&a(e)})},a=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;t.isInstanceOf=function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},t.transformCoordinates=function(e,t){var a=e.getContext("2d"),r=e.width,n=e.height;switch(t>4&&(e.width=n,e.height=r),t){case 2:a.translate(r,0),a.scale(-1,1);break;case 3:a.translate(r,n),a.rotate(Math.PI);break;case 4:a.translate(0,n),a.scale(1,-1);break;case 5:a.rotate(.5*Math.PI),a.scale(1,-1);break;case 6:a.rotate(.5*Math.PI),a.translate(0,-n);break;case 7:a.rotate(.5*Math.PI),a.translate(r,-n),a.scale(-1,1);break;case 8:a.rotate(-.5*Math.PI),a.translate(-r,0)}},t.detectSubsampling=function(e){var t,a;return e.width*e.height>1048576?(t=document.createElement("canvas"),t.width=t.height=1,a=t.getContext("2d"),a.drawImage(e,-e.width+1,0),0===a.getImageData(0,0,1,1).data[3]):!1},t.detectVerticalSquash=function(e,t){var a,r,n,i,c,o=document.createElement("canvas"),s=o.getContext("2d");for(o.width=1,o.height=t,s.drawImage(e,0,0),a=s.getImageData(0,0,1,t).data,r=0,n=t,i=t;i>r;)c=a[4*(i-1)+3],0===c?n=i:r=i,i=n+r>>1;return i/t||1},t.renderImageToCanvas=function(e,a,r,n,i,c,o,s,d,h){var g,l,u,m=e.getContext("2d"),f=document.createElement("canvas"),w=f.width=f.height=1024,v=f.getContext("2d");for(m.save(),t.detectSubsampling(a)&&(i/=2,c/=2),g=t.detectVerticalSquash(a,c),d=Math.ceil(w*d/i),h=Math.ceil(w*h/c/g),s=0,u=0;c>u;){for(o=0,l=0;i>l;)v.clearRect(0,0,w,w),v.drawImage(a,r,n,i,c,-l,-u,i,c),m.drawImage(f,0,0,w,w,o,s,d,h),l+=w,o+=d;u+=w,s+=h}m.restore()},t.scale=function(e,a){a=a||{};var r,n,i,c,o,s,d,h=document.createElement("canvas"),g=e.getContext||(a.canvas||a.crop)&&h.getContext,l=e.width,u=e.height,m=l,f=u,w=0,v=0,b=0,R=0;return g&&a.orientation>4?(r=a.maxHeight,n=a.maxWidth,i=a.minHeight,c=a.minWidth):(r=a.maxWidth,n=a.maxHeight,i=a.minWidth,c=a.minHeight),g&&r&&n&&a.crop?(o=r,s=n,r/n>l/u?(f=n*l/r,v=(u-f)/2):(m=r*u/n,w=(l-m)/2)):(o=l,s=u,d=Math.max((i||o)/o,(c||s)/s),d>1&&(o=Math.ceil(o*d),s=Math.ceil(s*d)),d=Math.min((r||o)/o,(n||s)/s),1>d&&(o=Math.ceil(o*d),s=Math.ceil(s*d))),g?(h.width=o,h.height=s,t.transformCoordinates(h,a.orientation),"image/jpeg"===e._type?t.renderImageToCanvas(h,e,w,v,m,f,b,R,o,s):h.getContext("2d").drawImage(e,w,v,m,f,b,R,o,s),h):(e.width=o,e.height=s,e)},t.createObjectURL=function(e){return a?a.createObjectURL(e):!1},t.revokeObjectURL=function(e){return a?a.revokeObjectURL(e):!1},t.readFile=function(e,t,a){if(window.FileReader&&FileReader.prototype.readAsDataURL){var r=new FileReader;return r.onload=r.onerror=t,a=a||"readAsDataURL",r[a]?(r[a](e),r):!1}return!1},"function"==typeof define&&define.amd?define(function(){return t}):e.loadImage=t})(this);
\ No newline at end of file
+(function(e){"use strict";var t=function(e,a,r){var n,i,o=document.createElement("img");if(o.onerror=a,o.onload=function(){!i||r&&r.noRevoke||t.revokeObjectURL(i),a&&a(t.scale(o,r))},t.isInstanceOf("Blob",e)||t.isInstanceOf("File",e))n=i=t.createObjectURL(e),o._type=e.type;else{if("string"!=typeof e)return!1;n=e,r&&r.crossOrigin&&(o.crossOrigin=r.crossOrigin)}return n?(o.src=n,o):t.readFile(e,function(e){var t=e.target;t&&t.result?o.src=t.result:a&&a(e)})},a=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;t.isInstanceOf=function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},t.transformCoordinates=function(e,t){var a=e.getContext("2d"),r=e.width,n=e.height;switch(t>4&&(e.width=n,e.height=r),t){case 2:a.translate(r,0),a.scale(-1,1);break;case 3:a.translate(r,n),a.rotate(Math.PI);break;case 4:a.translate(0,n),a.scale(1,-1);break;case 5:a.rotate(.5*Math.PI),a.scale(1,-1);break;case 6:a.rotate(.5*Math.PI),a.translate(0,-n);break;case 7:a.rotate(.5*Math.PI),a.translate(r,-n),a.scale(-1,1);break;case 8:a.rotate(-.5*Math.PI),a.translate(-r,0)}},t.detectSubsampling=function(e){var t,a;return e.width*e.height>1048576?(t=document.createElement("canvas"),t.width=t.height=1,a=t.getContext("2d"),a.drawImage(e,-e.width+1,0),0===a.getImageData(0,0,1,1).data[3]):!1},t.detectVerticalSquash=function(e,t){var a,r,n,i,o,c=document.createElement("canvas"),s=c.getContext("2d");for(c.width=1,c.height=t,s.drawImage(e,0,0),a=s.getImageData(0,0,1,t).data,r=0,n=t,i=t;i>r;)o=a[4*(i-1)+3],0===o?n=i:r=i,i=n+r>>1;return i/t||1},t.renderImageToCanvas=function(e,a,r,n,i,o,c,s,d,h){var g,l,u,m=e.getContext("2d"),f=document.createElement("canvas"),w=f.width=f.height=1024,v=f.getContext("2d");for(m.save(),t.detectSubsampling(a)&&(i/=2,o/=2),g=t.detectVerticalSquash(a,o),d=Math.ceil(w*d/i),h=Math.ceil(w*h/o/g),s=0,u=0;o>u;){for(c=0,l=0;i>l;)v.clearRect(0,0,w,w),v.drawImage(a,r,n,i,o,-l,-u,i,o),m.drawImage(f,0,0,w,w,c,s,d,h),l+=w,c+=d;u+=w,s+=h}m.restore()},t.scale=function(e,a){a=a||{};var r,n,i,o,c,s,d,h=document.createElement("canvas"),g=e.getContext||(a.canvas||a.crop||a.orientation)&&h.getContext,l=e.width,u=e.height,m=l,f=u,w=0,v=0,b=0,R=0;return g&&a.orientation>4?(r=a.maxHeight,n=a.maxWidth,i=a.minHeight,o=a.minWidth):(r=a.maxWidth,n=a.maxHeight,i=a.minWidth,o=a.minHeight),g&&r&&n&&a.crop?(c=r,s=n,r/n>l/u?(f=n*l/r,v=(u-f)/2):(m=r*u/n,w=(l-m)/2)):(c=l,s=u,d=Math.max((i||c)/c,(o||s)/s),d>1&&(c=Math.ceil(c*d),s=Math.ceil(s*d)),d=Math.min((r||c)/c,(n||s)/s),1>d&&(c=Math.ceil(c*d),s=Math.ceil(s*d))),g?(h.width=c,h.height=s,t.transformCoordinates(h,a.orientation),"image/jpeg"===e._type?t.renderImageToCanvas(h,e,w,v,m,f,b,R,c,s):h.getContext("2d").drawImage(e,w,v,m,f,b,R,c,s),h):(e.width=c,e.height=s,e)},t.createObjectURL=function(e){return a?a.createObjectURL(e):!1},t.revokeObjectURL=function(e){return a?a.revokeObjectURL(e):!1},t.readFile=function(e,t,a){if(window.FileReader&&FileReader.prototype.readAsDataURL){var r=new FileReader;return r.onload=r.onerror=t,a=a||"readAsDataURL",r[a]?(r[a](e),r):!1}return!1},"function"==typeof define&&define.amd?define(function(){return t}):e.loadImage=t})(this);
\ No newline at end of file
From 02dcbd04f8c09ea2ffafd7010887da765afa1b23 Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Wed, 5 Jun 2013 16:44:15 -0500
Subject: [PATCH 031/386] Catch "No Exif data" errors.
Log parsed EXIF data.
---
index.html | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/index.html b/index.html
index 4d75c2d..6f75d76 100644
--- a/index.html
+++ b/index.html
@@ -1,7 +1,7 @@
JavaScript Load Image
-
+
@@ -35,10 +35,10 @@
JavaScript Load Image
- JavaScript Load Image is a function to load images provided as File or Blob objects or via URL.
- It returns an optionally scaled and/or cropped HTML img or canvas element.
+ JavaScript Load Image is a library to load images provided as File or Blob objects or via URL.
+ It returns an optionally scaled and/or cropped HTML img or canvas element.
+ It also provides a method to parse image meta data to extract Exif tags and thumbnails and to restore the complete image header after resizing.
@@ -61,6 +62,13 @@
JavaScript Load Image Demo
Select an image file
Notice Or drag & drop an image file onto this webpage.
+
+
Result
@@ -69,16 +77,21 @@ Result
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/test.js b/test/test.js
index ebac5be..24ee168 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1,5 +1,5 @@
/*
- * JavaScript Load Image Test 1.6
+ * JavaScript Load Image Test 1.7
* https://github.com/blueimp/JavaScript-Load-Image
*
* Copyright 2011, Sebastian Tschan
diff --git a/vendor/exif-reader.js b/vendor/exif-reader.js
deleted file mode 100644
index 2e90c8c..0000000
--- a/vendor/exif-reader.js
+++ /dev/null
@@ -1,1291 +0,0 @@
-// Generated by CoffeeScript 1.6.2
-/*
-# ExifReader 0.1
-# http://github.com/mattiasw/exifreader
-# Copyright (C) 2011 Mattias Wallander
-# Licensed under the GNU Lesser General Public License version 3 or later
-# See license text at http://www.gnu.org/licenses/lgpl.txt
-*/
-
-
-(function() {
- (typeof exports !== "undefined" && exports !== null ? exports : this).ExifReader = (function() {
- function ExifReader() {
- var _this = this;
-
- this._getTagValueAt = {
- 1: function(offset) {
- return _this._getByteAt(offset);
- },
- 2: function(offset) {
- return _this._getAsciiAt(offset);
- },
- 3: function(offset) {
- return _this._getShortAt(offset);
- },
- 4: function(offset) {
- return _this._getLongAt(offset);
- },
- 5: function(offset) {
- return _this._getRationalAt(offset);
- },
- 7: function(offset) {
- return _this._getUndefinedAt(offset);
- },
- 9: function(offset) {
- return _this._getSlongAt(offset);
- },
- 10: function(offset) {
- return _this._getSrationalAt(offset);
- }
- };
- }
-
- /*
- # Loads all the Exif tags from the specified image file buffer.
- #
- # data ArrayBuffer Image file data
- */
-
-
- ExifReader.prototype.load = function(data) {
- return this.loadView(new DataView(data));
- };
-
- /*
- # Loads all the Exif tags from the specified image file buffer view. Probably
- # used when DataView isn't supported by the browser.
- #
- # @_dataView DataView Image file data view
- */
-
-
- ExifReader.prototype.loadView = function(_dataView) {
- this._dataView = _dataView;
- this._tags = {};
- this._checkImageHeader();
- return this._readTags();
- };
-
- ExifReader.prototype._checkImageHeader = function() {
- var byteLength, dataView, i;
-
- dataView = this._dataView;
- byteLength = dataView.byteLength;
- if (byteLength < 12) {
- throw "Data buffer too short";
- }
- if (dataView.getUint32(0, false) === 0xffd8ffe1) {
- if (dataView.getUint32(6, false) === 0x45786966 && dataView.getUint16(10, false) === 0x0000) {
- this._tiffHeaderOffset = 0x0c;
- return;
- }
- } else if (dataView.getUint32(0, false) === 0xffd8ffe0) {
- i = 10;
- while (i < byteLength) {
- if (dataView.getUint8(i, false) === 0x45 && dataView.getUint32(i, false) === 0x45786966 && dataView.getUint16(i + 4, false) === 0x0000) {
- this._tiffHeaderOffset = i + 6;
- return;
- }
- i++;
- }
- } else {
- throw "Invalid image format";
- }
- throw "No Exif data";
- };
-
- ExifReader.prototype._readTags = function() {
- this._setByteOrder();
- this._read0thIfd();
- this._readExifIfd();
- this._readGpsIfd();
- return this._readInteroperabilityIfd();
- };
-
- ExifReader.prototype._setByteOrder = function() {
- if (this._dataView.getUint16(this._tiffHeaderOffset) === 0x4949) {
- return this._littleEndian = true;
- } else if (this._dataView.getUint16(this._tiffHeaderOffset) === 0x4d4d) {
- return this._littleEndian = false;
- } else {
- throw 'Illegal byte order value. Faulty image.';
- }
- };
-
- ExifReader.prototype._read0thIfd = function() {
- var ifdOffset;
-
- ifdOffset = this._getIfdOffset();
- return this._readIfd('0th', ifdOffset);
- };
-
- ExifReader.prototype._getIfdOffset = function() {
- return this._tiffHeaderOffset + this._getLongAt(this._tiffHeaderOffset + 4);
- };
-
- ExifReader.prototype._readExifIfd = function() {
- var ifdOffset;
-
- if (this._tags['Exif IFD Pointer'] != null) {
- ifdOffset = this._tiffHeaderOffset + this._tags['Exif IFD Pointer'].value;
- return this._readIfd('exif', ifdOffset);
- }
- };
-
- ExifReader.prototype._readGpsIfd = function() {
- var ifdOffset;
-
- if (this._tags['GPS Info IFD Pointer'] != null) {
- ifdOffset = this._tiffHeaderOffset + this._tags['GPS Info IFD Pointer'].value;
- return this._readIfd('gps', ifdOffset);
- }
- };
-
- ExifReader.prototype._readInteroperabilityIfd = function() {
- var ifdOffset;
-
- if (this._tags['Interoperability IFD Pointer'] != null) {
- ifdOffset = this._tiffHeaderOffset + this._tags['Interoperability IFD Pointer'].value;
- return this._readIfd('interoperability', ifdOffset);
- }
- };
-
- ExifReader.prototype._readIfd = function(ifdType, offset) {
- var fieldIndex, numberOfFields, tag, _i, _results;
-
- numberOfFields = this._getShortAt(offset);
- offset += 2;
- _results = [];
- for (fieldIndex = _i = 0; 0 <= numberOfFields ? _i < numberOfFields : _i > numberOfFields; fieldIndex = 0 <= numberOfFields ? ++_i : --_i) {
- tag = this._readTag(ifdType, offset);
- this._tags[tag.name] = {
- 'value': tag.value,
- 'description': tag.description
- };
- _results.push(offset += 12);
- }
- return _results;
- };
-
- ExifReader.prototype._readTag = function(ifdType, offset) {
- var tagCode, tagCount, tagDescription, tagName, tagType, tagValue, tagValueOffset;
-
- tagCode = this._getShortAt(offset);
- tagType = this._getShortAt(offset + 2);
- tagCount = this._getLongAt(offset + 4);
- if (this._typeSizes[tagType] * tagCount <= 4) {
- tagValue = this._getTagValue(offset + 8, tagType, tagCount);
- } else {
- tagValueOffset = this._getLongAt(offset + 8);
- tagValue = this._getTagValue(this._tiffHeaderOffset + tagValueOffset, tagType, tagCount);
- }
- if (tagType === this._tagTypes['ASCII']) {
- tagValue = this._splitNullSeparatedAsciiString(tagValue);
- }
- if (this._tagNames[ifdType][tagCode] != null) {
- if ((this._tagNames[ifdType][tagCode]['name'] != null) && (this._tagNames[ifdType][tagCode]['description'] != null)) {
- tagName = this._tagNames[ifdType][tagCode]['name'];
- tagDescription = this._tagNames[ifdType][tagCode]['description'](tagValue);
- } else {
- tagName = this._tagNames[ifdType][tagCode];
- if (tagValue instanceof Array) {
- tagDescription = tagValue.join(', ');
- } else {
- tagDescription = tagValue;
- }
- }
- return {
- 'name': tagName,
- 'value': tagValue,
- 'description': tagDescription
- };
- } else {
- return {
- 'name': "undefined-" + tagCode,
- 'value': tagValue,
- 'description': tagValue
- };
- }
- };
-
- ExifReader.prototype._getTagValue = function(offset, type, count) {
- var tagValue, value, valueIndex;
-
- value = (function() {
- var _i, _results;
-
- _results = [];
- for (valueIndex = _i = 0; 0 <= count ? _i < count : _i > count; valueIndex = 0 <= count ? ++_i : --_i) {
- tagValue = this._getTagValueAt[type](offset);
- offset += this._typeSizes[type];
- _results.push(tagValue);
- }
- return _results;
- }).call(this);
- if (value.length === 1) {
- value = value[0];
- } else if (type === this._tagTypes['ASCII']) {
- value = this._getAsciiValue(value);
- }
- return value;
- };
-
- ExifReader.prototype._getAsciiValue = function(charArray) {
- var char, newCharArray;
-
- return newCharArray = (function() {
- var _i, _len, _results;
-
- _results = [];
- for (_i = 0, _len = charArray.length; _i < _len; _i++) {
- char = charArray[_i];
- _results.push(String.fromCharCode(char));
- }
- return _results;
- })();
- };
-
- ExifReader.prototype._getByteAt = function(offset) {
- return this._dataView.getUint8(offset);
- };
-
- ExifReader.prototype._getAsciiAt = function(offset) {
- return this._dataView.getUint8(offset);
- };
-
- ExifReader.prototype._getShortAt = function(offset) {
- return this._dataView.getUint16(offset, this._littleEndian);
- };
-
- ExifReader.prototype._getLongAt = function(offset) {
- return this._dataView.getUint32(offset, this._littleEndian);
- };
-
- ExifReader.prototype._getRationalAt = function(offset) {
- return this._getLongAt(offset) / this._getLongAt(offset + 4);
- };
-
- ExifReader.prototype._getUndefinedAt = function(offset) {
- return this._getByteAt(offset);
- };
-
- ExifReader.prototype._getSlongAt = function(offset) {
- return this._dataView.getInt32(offset, this._littleEndian);
- };
-
- ExifReader.prototype._getSrationalAt = function(offset) {
- return this._getSlongAt(offset) / this._getSlongAt(offset + 4);
- };
-
- ExifReader.prototype._splitNullSeparatedAsciiString = function(string) {
- var char, i, tagValue, _i, _len;
-
- tagValue = [];
- i = 0;
- for (_i = 0, _len = string.length; _i < _len; _i++) {
- char = string[_i];
- if (char === '\x00') {
- i++;
- continue;
- }
- if (tagValue[i] == null) {
- tagValue[i] = '';
- }
- tagValue[i] += char;
- }
- return tagValue;
- };
-
- ExifReader.prototype._typeSizes = {
- 1: 1,
- 2: 1,
- 3: 2,
- 4: 4,
- 5: 8,
- 7: 1,
- 9: 4,
- 10: 8
- };
-
- ExifReader.prototype._tagTypes = {
- 'BYTE': 1,
- 'ASCII': 2,
- 'SHORT': 3,
- 'LONG': 4,
- 'RATIONAL': 5,
- 'UNDEFINED': 7,
- 'SLONG': 9,
- 'SRATIONAL': 10
- };
-
- ExifReader.prototype._tagNames = {
- '0th': {
- 0x0100: 'ImageWidth',
- 0x0101: 'ImageLength',
- 0x0102: 'BitsPerSample',
- 0x0103: 'Compression',
- 0x0106: 'PhotometricInterpretation',
- 0x010e: 'ImageDescription',
- 0x010f: 'Make',
- 0x0110: 'Model',
- 0x0111: 'StripOffsets',
- 0x0112: {
- 'name': 'Orientation',
- 'description': function(value) {
- switch (value) {
- case 1:
- return 'top-left';
- case 2:
- return 'top-right';
- case 3:
- return 'bottom-right';
- case 4:
- return 'bottom-left';
- case 5:
- return 'left-top';
- case 6:
- return 'right-top';
- case 7:
- return 'right-bottom';
- case 8:
- return 'left-bottom';
- default:
- return 'Undefined';
- }
- }
- },
- 0x0115: 'SamplesPerPixel',
- 0x0116: 'RowsPerStrip',
- 0x0117: 'StripByteCounts',
- 0x011a: 'XResolution',
- 0x011b: 'YResolution',
- 0x011c: 'PlanarConfiguration',
- 0x0128: {
- 'name': 'ResolutionUnit',
- 'description': function(value) {
- switch (value) {
- case 2:
- return 'inches';
- case 3:
- return 'centimeters';
- default:
- return 'Unknown';
- }
- }
- },
- 0x012d: 'TransferFunction',
- 0x0131: 'Software',
- 0x0132: 'DateTime',
- 0x013b: 'Artist',
- 0x013e: 'WhitePoint',
- 0x013f: 'PrimaryChromaticities',
- 0x0201: 'JPEGInterchangeFormat',
- 0x0202: 'JPEGInterchangeFormatLength',
- 0x0211: 'YCbCrCoefficients',
- 0x0212: 'YCbCrSubSampling',
- 0x0213: {
- 'name': 'YCbCrPositioning',
- 'description': function(value) {
- switch (value) {
- case 1:
- return 'centered';
- case 2:
- return 'co-sited';
- default:
- return 'undefied ' + value;
- }
- }
- },
- 0x0214: 'ReferenceBlackWhite',
- 0x8298: {
- 'name': 'Copyright',
- 'description': function(value) {
- return value.join('; ');
- }
- },
- 0x8769: 'Exif IFD Pointer',
- 0x8825: 'GPS Info IFD Pointer'
- },
- 'exif': {
- 0x829a: 'ExposureTime',
- 0x829d: 'FNumber',
- 0x8822: {
- 'name': 'ExposureProgram',
- 'description': function(value) {
- switch (value) {
- case 0:
- return 'Undefined';
- case 1:
- return 'Manual';
- case 2:
- return 'Normal program';
- case 3:
- return 'Aperture priority';
- case 4:
- return 'Shutter priority';
- case 5:
- return 'Creative program';
- case 6:
- return 'Action program';
- case 7:
- return 'Portrait mode';
- case 8:
- return 'Landscape mode';
- default:
- return 'Unknown';
- }
- }
- },
- 0x8824: 'SpectralSensitivity',
- 0x8827: 'ISOSpeedRatings',
- 0x8828: {
- 'name': 'OECF',
- 'description': function(value) {
- return '[Raw OECF table data]';
- }
- },
- 0x9000: {
- 'name': 'ExifVersion',
- 'description': function(value) {
- var char, string, _i, _len;
-
- string = '';
- for (_i = 0, _len = value.length; _i < _len; _i++) {
- char = value[_i];
- string += String.fromCharCode(char);
- }
- return string;
- }
- },
- 0x9003: 'DateTimeOriginal',
- 0x9004: 'DateTimeDigitized',
- 0x9101: {
- 'name': 'ComponentsConfiguration',
- 'description': function(value) {
- var char, string, _i, _len;
-
- string = '';
- for (_i = 0, _len = value.length; _i < _len; _i++) {
- char = value[_i];
- switch (char) {
- case 0x31:
- string += 'Y';
- break;
- case 0x32:
- string += 'Cb';
- break;
- case 0x33:
- string += 'Cr';
- break;
- case 0x34:
- string += 'R';
- break;
- case 0x35:
- string += 'G';
- break;
- case 0x36:
- string += 'B';
- }
- }
- return string;
- }
- },
- 0x9102: 'CompressedBitsPerPixel',
- 0x9201: 'ShutterSpeedValue',
- 0x9202: 'ApertureValue',
- 0x9203: 'BrightnessValue',
- 0x9204: 'ExposureBiasValue',
- 0x9205: 'MaxApertureValue',
- 0x9206: 'SubjectDistance',
- 0x9207: {
- 'name': 'MeteringMode',
- 'description': function(value) {
- switch (value) {
- case 1:
- return 'Average';
- case 2:
- return 'CenterWeightedAverage';
- case 3:
- return 'Spot';
- case 4:
- return 'MultiSpot';
- case 5:
- return 'Pattern';
- case 6:
- return 'Partial';
- case 255:
- return 'Other';
- default:
- return 'Unknown';
- }
- }
- },
- 0x9208: {
- 'name': 'LightSource',
- 'description': function(value) {
- switch (value) {
- case 1:
- return 'Daylight';
- case 2:
- return 'Fluorescent';
- case 3:
- return 'Tungsten (incandescent light)';
- case 4:
- return 'Flash';
- case 9:
- return 'Fine weather';
- case 10:
- return 'Cloudy weather';
- case 11:
- return 'Shade';
- case 12:
- return 'Daylight fluorescent (D 5700 – 7100K)';
- case 13:
- return 'Day white fluorescent (N 4600 – 5400K)';
- case 14:
- return 'Cool white fluorescent (W 3900 – 4500K)';
- case 15:
- return 'White fluorescent (WW 3200 – 3700K)';
- case 17:
- return 'Standard light A';
- case 18:
- return 'Standard light B';
- case 19:
- return 'Standard light C';
- case 20:
- return 'D55';
- case 21:
- return 'D65';
- case 22:
- return 'D75';
- case 23:
- return 'D50';
- case 24:
- return 'ISO studio tungsten';
- case 255:
- return 'Other light source';
- default:
- return 'Unknown';
- }
- }
- },
- 0x9209: {
- 'name': 'Flash',
- 'description': function(value) {
- switch (value) {
- case 0x00:
- return 'Flash did not fire';
- case 0x01:
- return 'Flash fired';
- case 0x05:
- return 'Strobe return light not detected';
- case 0x07:
- return 'Strobe return light detected';
- case 0x09:
- return 'Flash fired, compulsory flash mode';
- case 0x0d:
- return 'Flash fired, compulsory flash mode, return light not detected';
- case 0x0f:
- return 'Flash fired, compulsory flash mode, return light detected';
- case 0x10:
- return 'Flash did not fire, compulsory flash mode';
- case 0x18:
- return 'Flash did not fire, auto mode';
- case 0x19:
- return 'Flash fired, auto mode';
- case 0x1d:
- return 'Flash fired, auto mode, return light not detected';
- case 0x1f:
- return 'Flash fired, auto mode, return light detected';
- case 0x20:
- return 'No flash function';
- case 0x41:
- return 'Flash fired, red-eye reduction mode';
- case 0x45:
- return 'Flash fired, red-eye reduction mode, return light not detected';
- case 0x47:
- return 'Flash fired, red-eye reduction mode, return light detected';
- case 0x49:
- return 'Flash fired, compulsory flash mode, red-eye reduction mode';
- case 0x4d:
- return 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected';
- case 0x4f:
- return 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected';
- case 0x59:
- return 'Flash fired, auto mode, red-eye reduction mode';
- case 0x5d:
- return 'Flash fired, auto mode, return light not detected, red-eye reduction mode';
- case 0x5f:
- return 'Flash fired, auto mode, return light detected, red-eye reduction mode';
- default:
- return 'Unknown';
- }
- }
- },
- 0x920a: 'FocalLength',
- 0x9214: {
- 'name': 'SubjectArea',
- 'description': function(value) {
- switch (value.length) {
- case 2:
- return "Location; X: " + value[0] + ", Y: " + value[1];
- case 3:
- return "Circle; X: " + value[0] + ", Y: " + value[1] + ", diameter: " + value[2];
- case 4:
- return "Rectangle; X: " + value[0] + ", Y: " + value[1] + ", width: " + value[2] + ", height: " + value[3];
- default:
- return 'Unknown';
- }
- }
- },
- 0x927c: {
- 'name': 'MakerNote',
- 'description': function(value) {
- return '[Raw maker note data]';
- }
- },
- 0x9286: {
- 'name': 'UserComment',
- 'description': function(value) {
- switch (value.slice(0, 8).map(function(byte) {
- return String.fromCharCode(byte);
- }).join('')) {
- case 'ASCII\x00\x00\x00':
- return value.slice(8, value.length).map(function(byte) {
- return String.fromCharCode(byte);
- }).join('');
- case 'JIS\x00\x00\x00\x00\x00':
- return '[JIS encoded text]';
- case 'UNICODE\x00':
- return '[Unicode encoded text]';
- case '\x00\x00\x00\x00\x00\x00\x00\x00':
- return '[Undefined encoding]';
- }
- }
- },
- 0x9290: 'SubSecTime',
- 0x9291: 'SubSecTimeOriginal',
- 0x9292: 'SubSecTimeDigitized',
- 0xa000: {
- 'name': 'FlashpixVersion',
- 'description': function(value) {
- var char, string, _i, _len;
-
- string = '';
- for (_i = 0, _len = value.length; _i < _len; _i++) {
- char = value[_i];
- string += String.fromCharCode(char);
- }
- return string;
- }
- },
- 0xa001: {
- 'name': 'ColorSpace',
- 'description': function(value) {
- switch (value) {
- case 1:
- return 'sRGB';
- case 0xffff:
- return 'Uncalibrated';
- default:
- return 'Unknown';
- }
- }
- },
- 0xa002: 'PixelXDimension',
- 0xa003: 'PixelYDimension',
- 0xa004: 'RelatedSoundFile',
- 0xa005: 'Interoperability IFD Pointer',
- 0xa20b: 'FlashEnergy',
- 0xa20c: {
- 'name': 'SpatialFrequencyResponse',
- 'description': function(value) {
- return '[Raw SFR table data]';
- }
- },
- 0xa20e: 'FocalPlaneXResolution',
- 0xa20f: 'FocalPlaneYResolution',
- 0xa210: {
- 'name': 'FocalPlaneResolutionUnit',
- 'description': function(value) {
- switch (value) {
- case 2:
- return 'inches';
- case 3:
- return 'centimeters';
- default:
- return 'Unknown';
- }
- }
- },
- 0xa214: {
- 'name': 'SubjectLocation',
- 'description': function(value) {
- return "X: " + value[0] + ", Y: " + value[1];
- }
- },
- 0xa215: 'ExposureIndex',
- 0xa217: {
- 'name': 'SensingMethod',
- 'description': function(value) {
- switch (value) {
- case 1:
- return 'Undefined';
- case 2:
- return 'One-chip color area sensor';
- case 3:
- return 'Two-chip color area sensor';
- case 4:
- return 'Three-chip color area sensor';
- case 5:
- return 'Color sequential area sensor';
- case 7:
- return 'Trilinear sensor';
- case 8:
- return 'Color sequential linear sensor';
- default:
- return 'Unknown';
- }
- }
- },
- 0xa300: {
- 'name': 'FileSource',
- 'description': function(value) {
- switch (value) {
- case 3:
- return 'DSC';
- default:
- return 'Unknown';
- }
- }
- },
- 0xa301: {
- 'name': 'SceneType',
- 'description': function(value) {
- switch (value) {
- case 1:
- return 'A directly photographed image';
- default:
- return 'Unknown';
- }
- }
- },
- 0xa302: {
- 'name': 'CFAPattern',
- 'description': function(value) {
- return '[Raw CFA pattern table data]';
- }
- },
- 0xa401: {
- 'name': 'CustomRendered',
- 'description': function(value) {
- switch (value) {
- case 0:
- return 'Normal process';
- case 1:
- return 'Custom process';
- default:
- return 'Unknown';
- }
- }
- },
- 0xa402: {
- 'name': 'ExposureMode',
- 'description': function(value) {
- switch (value) {
- case 0:
- return 'Auto exposure';
- case 1:
- return 'Manual exposure';
- case 2:
- return 'Auto bracket';
- default:
- return 'Unknown';
- }
- }
- },
- 0xa403: {
- 'name': 'WhiteBalance',
- 'description': function(value) {
- switch (value) {
- case 0:
- return 'Auto white balance';
- case 1:
- return 'Manual white balance';
- default:
- return 'Unknown';
- }
- }
- },
- 0xa404: {
- 'name': 'DigitalZoomRatio',
- 'description': function(value) {
- switch (value) {
- case 0:
- return 'Digital zoom was not used';
- default:
- return value;
- }
- }
- },
- 0xa405: {
- 'name': 'FocalLengthIn35mmFilm',
- 'description': function(value) {
- switch (value) {
- case 0:
- return 'Unknown';
- default:
- return value;
- }
- }
- },
- 0xa406: {
- 'name': 'SceneCaptureType',
- 'description': function(value) {
- switch (value) {
- case 0:
- return 'Standard';
- case 1:
- return 'Landscape';
- case 2:
- return 'Portrait';
- case 3:
- return 'Night scene';
- default:
- return 'Unknown';
- }
- }
- },
- 0xa407: {
- 'name': 'GainControl',
- 'description': function(value) {
- switch (value) {
- case 0:
- return 'None';
- case 1:
- return 'Low gain up';
- case 2:
- return 'High gain up';
- case 3:
- return 'Low gain down';
- case 4:
- return 'High gain down';
- default:
- return 'Unknown';
- }
- }
- },
- 0xa408: {
- 'name': 'Contrast',
- 'description': function(value) {
- switch (value) {
- case 0:
- return 'Normal';
- case 1:
- return 'Soft';
- case 2:
- return 'Hard';
- default:
- return 'Unknown';
- }
- }
- },
- 0xa409: {
- 'name': 'Saturation',
- 'description': function(value) {
- switch (value) {
- case 0:
- return 'Normal';
- case 1:
- return 'Low saturation';
- case 2:
- return 'High saturation';
- default:
- return 'Unknown';
- }
- }
- },
- 0xa40a: {
- 'name': 'Sharpness',
- 'description': function(value) {
- switch (value) {
- case 0:
- return 'Normal';
- case 1:
- return 'Soft';
- case 2:
- return 'Hard';
- default:
- return 'Unknown';
- }
- }
- },
- 0xa40b: {
- 'name': 'DeviceSettingDescription',
- 'description': function(value) {
- return '[Raw device settings table data]';
- }
- },
- 0xa40c: {
- 'name': 'SubjectDistanceRange',
- 'description': function(value) {
- switch (value) {
- case 1:
- return 'Macro';
- case 2:
- return 'Close view';
- case 3:
- return 'Distant view';
- default:
- return 'Unknown';
- }
- }
- },
- 0xa420: 'ImageUniqueID'
- },
- 'gps': {
- 0x0000: {
- 'name': 'GPSVersionID',
- 'description': function(value) {
- var _ref, _ref1;
-
- if ((value[0] === (_ref = value[1]) && _ref === 2) && (value[2] === (_ref1 = value[3]) && _ref1 === 0)) {
- return 'Version 2.2';
- } else {
- return 'Unknown';
- }
- }
- },
- 0x0001: {
- 'name': 'GPSLatitudeRef',
- 'description': function(value) {
- switch (value.join('')) {
- case 'N':
- return 'North latitude';
- case 'S':
- return 'South latitude';
- default:
- return 'Unknown';
- }
- }
- },
- 0x0002: {
- 'name': 'GPSLatitude',
- 'description': function(value) {
- return value[0] + value[1] / 60 + value[2] / 3600;
- }
- },
- 0x0003: {
- 'name': 'GPSLongitudeRef',
- 'description': function(value) {
- switch (value.join('')) {
- case 'E':
- return 'East longitude';
- case 'W':
- return 'West longitude';
- default:
- return 'Unknown';
- }
- }
- },
- 0x0004: {
- 'name': 'GPSLongitude',
- 'description': function(value) {
- return value[0] + value[1] / 60 + value[2] / 3600;
- }
- },
- 0x0005: {
- 'name': 'GPSAltitudeRef',
- 'description': function(value) {
- switch (value) {
- case 0:
- return 'Sea level';
- case 1:
- return 'Sea level reference (negative value)';
- default:
- return 'Unknown';
- }
- }
- },
- 0x0006: {
- 'name': 'GPSAltitude',
- 'description': function(value) {
- return value + ' m';
- }
- },
- 0x0007: {
- 'name': 'GPSTimeStamp',
- 'description': function(value) {
- var padZero;
-
- padZero = function(num) {
- var i;
-
- return ((function() {
- var _i, _ref, _results;
-
- _results = [];
- for (i = _i = 0, _ref = 2 - ('' + Math.floor(num)).length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- _results.push('0');
- }
- return _results;
- })()) + num;
- };
- return value.map(padZero).join(':');
- }
- },
- 0x0008: 'GPSSatellites',
- 0x0009: {
- 'name': 'GPSStatus',
- 'description': function(value) {
- switch (value.join('')) {
- case 'A':
- return 'Measurement in progress';
- case 'V':
- return 'Measurement Interoperability';
- default:
- return 'Unknown';
- }
- }
- },
- 0x000a: {
- 'name': 'GPSMeasureMode',
- 'description': function(value) {
- switch (value.join('')) {
- case '2':
- return '2-dimensional measurement';
- case '3':
- return '3-dimensional measurement';
- default:
- return 'Unknown';
- }
- }
- },
- 0x000b: 'GPSDOP',
- 0x000c: {
- 'name': 'GPSSpeedRef',
- 'description': function(value) {
- switch (value.join('')) {
- case 'K':
- return 'Kilometers per hour';
- case 'M':
- return 'Miles per hour';
- case 'N':
- return 'Knots';
- default:
- return 'Unknown';
- }
- }
- },
- 0x000d: 'GPSSpeed',
- 0x000e: {
- 'name': 'GPSTrackRef',
- 'description': function(value) {
- switch (value.join('')) {
- case 'T':
- return 'True direction';
- case 'M':
- return 'Magnetic direction';
- default:
- return 'Unknown';
- }
- }
- },
- 0x000f: 'GPSTrack',
- 0x0010: {
- 'name': 'GPSImgDirectionRef',
- 'description': function(value) {
- switch (value.join('')) {
- case 'T':
- return 'True direction';
- case 'M':
- return 'Magnetic direction';
- default:
- return 'Unknown';
- }
- }
- },
- 0x0011: 'GPSImgDirection',
- 0x0012: 'GPSMapDatum',
- 0x0013: {
- 'name': 'GPSDestLatitudeRef',
- 'description': function(value) {
- switch (value.join('')) {
- case 'N':
- return 'North latitude';
- case 'S':
- return 'South latitude';
- default:
- return 'Unknown';
- }
- }
- },
- 0x0014: {
- 'name': 'GPSDestLatitude',
- 'description': function(value) {
- return value[0] + value[1] / 60 + value[2] / 3600;
- }
- },
- 0x0015: {
- 'name': 'GPSDestLongitudeRef',
- 'description': function(value) {
- switch (value.join('')) {
- case 'E':
- return 'East longitude';
- case 'W':
- return 'West longitude';
- default:
- return 'Unknown';
- }
- }
- },
- 0x0016: {
- 'name': 'GPSDestLongitude',
- 'description': function(value) {
- return value[0] + value[1] / 60 + value[2] / 3600;
- }
- },
- 0x0017: {
- 'name': 'GPSDestBearingRef',
- 'description': function(value) {
- switch (value.join('')) {
- case 'T':
- return 'True direction';
- case 'M':
- return 'Magnetic direction';
- default:
- return 'Unknown';
- }
- }
- },
- 0x0018: 'GPSDestBearing',
- 0x0019: {
- 'name': 'GPSDestDistanceRef',
- 'description': function(value) {
- switch (value.join('')) {
- case 'K':
- return 'Kilometers';
- case 'M':
- return 'Miles';
- case 'N':
- return 'Knots';
- default:
- return 'Unknown';
- }
- }
- },
- 0x001a: 'GPSDestDistance',
- 0x001b: {
- 'name': 'GPSProcessingMethod',
- 'description': function(value) {
- switch (value.slice(0, 8).map(function(byte) {
- return String.fromCharCode(byte);
- }).join('')) {
- case 'ASCII\x00\x00\x00':
- return value.slice(8, value.length).map(function(byte) {
- return String.fromCharCode(byte);
- }).join('');
- case 'JIS\x00\x00\x00\x00\x00':
- return '[JIS encoded text]';
- case 'UNICODE\x00':
- return '[Unicode encoded text]';
- case '\x00\x00\x00\x00\x00\x00\x00\x00':
- return '[Undefined encoding]';
- }
- }
- },
- 0x001c: {
- 'name': 'GPSAreaInformation',
- 'description': function(value) {
- switch (value.slice(0, 8).map(function(byte) {
- return String.fromCharCode(byte);
- }).join('')) {
- case 'ASCII\x00\x00\x00':
- return value.slice(8, value.length).map(function(byte) {
- return String.fromCharCode(byte);
- }).join('');
- case 'JIS\x00\x00\x00\x00\x00':
- return '[JIS encoded text]';
- case 'UNICODE\x00':
- return '[Unicode encoded text]';
- case '\x00\x00\x00\x00\x00\x00\x00\x00':
- return '[Undefined encoding]';
- }
- }
- },
- 0x001d: 'GPSDateStamp',
- 0x001e: {
- 'name': 'GPSDifferential',
- 'description': function(value) {
- switch (value) {
- case 0:
- return 'Measurement without differential correction';
- case 1:
- return 'Differential correction applied';
- default:
- return 'Unknown';
- }
- }
- }
- },
- 'interoperability': {
- 0x0001: 'InteroperabilityIndex',
- 0x0002: 'UnknownInteroperabilityTag0x0002',
- 0x1001: 'UnknownInteroperabilityTag0x1001',
- 0x1002: 'UnknownInteroperabilityTag0x1002'
- }
- };
-
- /*
- # Gets the image's value of the tag with the given name.
- #
- # name string The name of the tag to get the value of
- #
- # Returns the value of the tag with the given name if it exists,
- # otherwise throws "Undefined".
- */
-
-
- ExifReader.prototype.getTagValue = function(name) {
- if (this._tags[name] != null) {
- return this._tags[name].value;
- } else {
- throw 'Undefined';
- }
- };
-
- /*
- # Gets the image's description of the tag with the given name.
- #
- # name string The name of the tag to get the description of
- #
- # Returns the description of the tag with the given name if it exists,
- # otherwise throws "Undefined".
- */
-
-
- ExifReader.prototype.getTagDescription = function(name) {
- if (this._tags[name] != null) {
- return this._tags[name].description;
- } else {
- throw 'Undefined';
- }
- };
-
- /*
- # Gets all the image's tags.
- #
- # Returns the image's tags as an associative array: name -> description.
- */
-
-
- ExifReader.prototype.getAllTags = function() {
- return this._tags;
- };
-
- return ExifReader;
-
- })();
-
-}).call(this);
From 6fe3dc93c37dd7aa5685f29a28468558cfbc8965 Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Tue, 11 Jun 2013 03:54:16 -0500
Subject: [PATCH 033/386] Fixed demo error.
---
index.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/index.html b/index.html
index dae4429..1207e0e 100644
--- a/index.html
+++ b/index.html
@@ -136,8 +136,8 @@ Result
dropChangeHandler = function (e) {
e = e.originalEvent;
e.preventDefault();
- var files = e.dataTransfer || e.target,
- file = files && files[0],
+ var target = e.dataTransfer || e.target,
+ file = target && target.files && target.files[0],
options = {
maxWidth: result.children().outerWidth(),
canvas: true
From e6f20ab4999aa14f6a7322d462c7f8a792c58c70 Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Wed, 12 Jun 2013 04:04:16 -0500
Subject: [PATCH 034/386] Added meta data tests.
---
test/test.js | 110 +++++++++++++++++++++++++++++++++++++--------------
1 file changed, 80 insertions(+), 30 deletions(-)
diff --git a/test/test.js b/test/test.js
index 24ee168..b9ad217 100644
--- a/test/test.js
+++ b/test/test.js
@@ -9,29 +9,53 @@
* http://www.opensource.org/licenses/MIT
*/
-/*global window, describe, it, expect */
+/*global window, describe, it, expect, Blob */
(function (expect, loadImage) {
'use strict';
- // 80x60px GIF image (color black, base64 data):
- var b64Data = 'R0lGODdhUAA8AIABAAAAAP///ywAAAAAUAA8AAACS4SPqcvtD6' +
+ var canCreateBlob = !!window.dataURLtoBlob,
+ // 80x60px GIF image (color black, base64 data):
+ b64DataGIF = 'R0lGODdhUAA8AIABAAAAAP///ywAAAAAUAA8AAACS4SPqcvtD6' +
'OctNqLs968+w+G4kiW5omm6sq27gvH8kzX9o3n+s73/g8MCofE' +
'ovGITCqXzKbzCY1Kp9Sq9YrNarfcrvcLDovH5PKsAAA7',
- imageUrl = 'data:image/gif;base64,' + b64Data,
- blob = window.dataURLtoBlob && window.dataURLtoBlob(imageUrl);
+ imageUrlGIF = 'data:image/gif;base64,' + b64DataGIF,
+ blobGIF = canCreateBlob && window.dataURLtoBlob(imageUrlGIF),
+ // 1x2px JPEG (color white, with the Exif orientation flag set to 6):
+ b64DataJPEG = '/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAASUkqAAgAAA' +
+ 'ABABIBAwABAAAABgASAAAAAAD/2wBDAAEBAQEBAQEBAQEBAQEB' +
+ 'AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ' +
+ 'EBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEB' +
+ 'AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ' +
+ 'EBAQEBAQH/wAARCAABAAIDASIAAhEBAxEB/8QAHwAAAQUBAQEB' +
+ 'AQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBA' +
+ 'QAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAk' +
+ 'M2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1' +
+ 'hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKj' +
+ 'pKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+' +
+ 'Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAA' +
+ 'AAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAx' +
+ 'EEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl' +
+ '8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2' +
+ 'hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmq' +
+ 'srO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8v' +
+ 'P09fb3+Pn6/9oADAMBAAIRAxEAPwD+/iiiigD/2Q==',
+ imageUrlJPEG = 'data:image/jpeg;base64,' + b64DataJPEG,
+ blobJPEG = canCreateBlob && window.dataURLtoBlob(imageUrlJPEG);
describe('Loading', function () {
it('Return the img element or FileReader object to allow aborting the image load', function () {
- var img = loadImage(blob, function () {});
+ var img = loadImage(blobGIF, function () {
+ return;
+ });
expect(img).to.be.an(Object);
expect(img.onload).to.be.a('function');
expect(img.onerror).to.be.a('function');
});
it('Load image url', function (done) {
- expect(loadImage(imageUrl, function (img) {
+ expect(loadImage(imageUrlGIF, function (img) {
done();
expect(img.width).to.be(80);
expect(img.height).to.be(60);
@@ -39,7 +63,7 @@
});
it('Load image blob', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(80);
expect(img.height).to.be(60);
@@ -55,7 +79,7 @@
});
it('Keep object URL if options.noRevoke is true', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
loadImage(img.src, function (img2) {
done();
expect(img.width).to.be(img2.width);
@@ -65,7 +89,7 @@
});
it('Discard object URL if options.noRevoke is undefined or false', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
loadImage(img.src, function (img2) {
done();
expect(img2).to.be.a(window.Event);
@@ -79,7 +103,7 @@
describe('Scaling', function () {
it('Scale to options.maxWidth', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(40);
expect(img.height).to.be(30);
@@ -87,7 +111,7 @@
});
it('Scale to options.maxHeight', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(20);
expect(img.height).to.be(15);
@@ -95,7 +119,7 @@
});
it('Scale to options.minWidth', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(160);
expect(img.height).to.be(120);
@@ -103,7 +127,7 @@
});
it('Scale to options.minHeight', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(320);
expect(img.height).to.be(240);
@@ -111,7 +135,7 @@
});
it('Scale to options.minWidth but respect options.maxWidth', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(160);
expect(img.height).to.be(120);
@@ -119,7 +143,7 @@
});
it('Scale to options.minHeight but respect options.maxHeight', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(160);
expect(img.height).to.be(120);
@@ -127,7 +151,7 @@
});
it('Scale to options.minWidth but respect options.maxHeight', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(160);
expect(img.height).to.be(120);
@@ -135,7 +159,7 @@
});
it('Scale to options.minHeight but respect options.maxWidth', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(160);
expect(img.height).to.be(120);
@@ -143,7 +167,7 @@
});
it('Do not scale to max settings without min settings', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(80);
expect(img.height).to.be(60);
@@ -151,7 +175,7 @@
});
it('Do not scale to min settings without max settings', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(80);
expect(img.height).to.be(60);
@@ -164,7 +188,7 @@
describe('Cropping', function () {
it('Crop to same values for options.maxWidth and options.maxHeight', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(40);
expect(img.height).to.be(40);
@@ -172,7 +196,7 @@
});
it('Crop to different values for options.maxWidth and options.maxHeight', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(40);
expect(img.height).to.be(60);
@@ -184,7 +208,7 @@
describe('Orientation', function () {
it('Should keep the orientation', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(80);
expect(img.height).to.be(60);
@@ -192,7 +216,7 @@
});
it('Should rotate right', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(60);
expect(img.height).to.be(80);
@@ -200,7 +224,7 @@
});
it('Should rotate left', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(60);
expect(img.height).to.be(80);
@@ -208,7 +232,7 @@
});
it('Should adjust constraints to new coordinates', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.width).to.be(60);
expect(img.height).to.be(80);
@@ -220,7 +244,7 @@
describe('Canvas', function () {
it('Return img element to callback if options.canvas is not true', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.getContext).to.not.be.ok();
expect(img.nodeName.toLowerCase()).to.be('img');
@@ -228,7 +252,7 @@
});
it('Return canvas element to callback if options.canvas is true', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.getContext).to.be.ok();
expect(img.nodeName.toLowerCase()).to.be('canvas');
@@ -236,7 +260,7 @@
});
it('Return scaled canvas element to callback', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
expect(img.getContext).to.be.ok();
expect(img.nodeName.toLowerCase()).to.be('canvas');
@@ -246,7 +270,7 @@
});
it('Accept a canvas element as parameter for loadImage.scale', function (done) {
- expect(loadImage(blob, function (img) {
+ expect(loadImage(blobGIF, function (img) {
done();
img = loadImage.scale(img, {
maxWidth: 40
@@ -260,6 +284,32 @@
});
+ describe('Metadata', function () {
+
+ it('Should parse Exif information', function (done) {
+ loadImage.parseMetaData(blobJPEG, function (data) {
+ done();
+ expect(data.exif).to.be.ok();
+ expect(data.exif.get('Orientation')).to.be(6);
+ });
+ });
+
+ it('Should parse the complete image head', function (done) {
+ loadImage.parseMetaData(blobJPEG, function (data) {
+ expect(data.imageHead).to.be.ok();
+ loadImage.parseMetaData(
+ new Blob([data.imageHead], {type: 'image/jpeg'}),
+ function (data) {
+ done();
+ expect(data.exif).to.be.ok();
+ expect(data.exif.get('Orientation')).to.be(6);
+ }
+ );
+ });
+ });
+
+ });
+
}(
this.expect,
this.loadImage
From 30fc45c6f8703c83e66aa47f953dac348c92ff64 Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Wed, 12 Jun 2013 15:25:33 -0500
Subject: [PATCH 035/386] Provide the loadImage.blobSlice method only if the
browser supports slicing Blobs.
---
README.md | 5 ++++-
load-image-meta.js | 17 ++++++++++-------
load-image.min.js | 2 +-
3 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/README.md b/README.md
index f6b6370..3c02e5d 100644
--- a/README.md
+++ b/README.md
@@ -147,11 +147,14 @@ The extension provides the method **loadImage.parseMetaData**, which can be used
loadImage.parseMetaData(
fileOrBlob,
function (data) {
+ if (!data.imageHead) {
+ return;
+ }
// Combine data.imageHead with the image body of a resized file
// to create scaled images with the original image meta data, e.g.:
var blob = new Blob([
data.imageHead,
- // Resized images always have a head size of 20,
+ // Resized images always have a head size of 20 bytes,
// including the JPEG marker and a minimal JFIF header:
loadImage.blobSlice.call(resizedImage, 20)
], {type: resizedImage.type});
diff --git a/load-image-meta.js b/load-image-meta.js
index b5e526d..9e0f25f 100644
--- a/load-image-meta.js
+++ b/load-image-meta.js
@@ -28,7 +28,10 @@
}(function (loadImage) {
'use strict';
- loadImage.blobSlice = function () {
+ var hasblobSlice = window.Blob && (Blob.prototype.slice ||
+ Blob.prototype.webkitSlice || Blob.prototype.mozSlice);
+
+ loadImage.blobSlice = hasblobSlice && function () {
var slice = this.slice || this.webkitSlice || this.mozSlice;
return slice.apply(this, arguments);
};
@@ -48,8 +51,8 @@
options = options || {};
var that = this,
data = {},
- noMetaData = !window.DataView || !file || file.size < 12 ||
- file.type !== 'image/jpeg';
+ noMetaData = !(window.DataView && file && file.size >= 12 &&
+ file.type === 'image/jpeg' && loadImage.blobSlice);
if (noMetaData || !loadImage.readFile(
// 128 KiB should contain all EXIF/ICC/IPTC segments:
loadImage.blobSlice.call(file, 0, 131072),
@@ -77,10 +80,10 @@
if ((markerBytes >= 0xffe0 && markerBytes <= 0xffef) ||
markerBytes === 0xfffe) {
// The marker bytes (2) are always followed by
- // the length bytes, indicating the length of the
- // marker segment, which include the length bytes,
+ // the length bytes (2), indicating the length of the
+ // marker segment, which includes the length bytes,
// but not the marker bytes, so we add 2:
- markerLength = dataView.getUint16(offset + 2);
+ markerLength = dataView.getUint16(offset + 2) + 2;
if (offset + markerLength > dataView.byteLength) {
console.log('Invalid meta data: Invalid segment size.');
continue;
@@ -98,7 +101,7 @@
);
}
}
- offset += markerLength + 2;
+ offset += markerLength;
headLength = offset;
} else {
// Not an APPn or COM marker, probably safe to
diff --git a/load-image.min.js b/load-image.min.js
index c5f85eb..b58f4e9 100644
--- a/load-image.min.js
+++ b/load-image.min.js
@@ -1 +1 @@
-(function(e){"use strict";var t=function(e,i,a){var n,r,o=document.createElement("img");if(o.onerror=i,o.onload=function(){!r||a&&a.noRevoke||t.revokeObjectURL(r),i&&i(t.scale(o,a))},t.isInstanceOf("Blob",e)||t.isInstanceOf("File",e))n=r=t.createObjectURL(e),o._type=e.type;else{if("string"!=typeof e)return!1;n=e,a&&a.crossOrigin&&(o.crossOrigin=a.crossOrigin)}return n?(o.src=n,o):t.readFile(e,function(e){var t=e.target;t&&t.result?o.src=t.result:i&&i(e)})},i=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;t.isInstanceOf=function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},t.transformCoordinates=function(e,t){var i=e.getContext("2d"),a=e.width,n=e.height;switch(t>4&&(e.width=n,e.height=a),t){case 2:i.translate(a,0),i.scale(-1,1);break;case 3:i.translate(a,n),i.rotate(Math.PI);break;case 4:i.translate(0,n),i.scale(1,-1);break;case 5:i.rotate(.5*Math.PI),i.scale(1,-1);break;case 6:i.rotate(.5*Math.PI),i.translate(0,-n);break;case 7:i.rotate(.5*Math.PI),i.translate(a,-n),i.scale(-1,1);break;case 8:i.rotate(-.5*Math.PI),i.translate(-a,0)}},t.renderImageToCanvas=function(e,t,i,a,n,r,o,s,d,l){return e.getContext("2d").drawImage(t,i,a,n,r,o,s,d,l),e},t.scale=function(e,i){i=i||{};var a,n,r,o,s,d,l,c=document.createElement("canvas"),u=e.getContext||(i.canvas||i.crop||i.orientation)&&c.getContext,g=e.width,f=e.height,h=g,m=f,p=0,S=0,x=0,y=0;return u&&i.orientation>4?(a=i.maxHeight,n=i.maxWidth,r=i.minHeight,o=i.minWidth):(a=i.maxWidth,n=i.maxHeight,r=i.minWidth,o=i.minHeight),u&&a&&n&&i.crop?(s=a,d=n,a/n>g/f?(m=n*g/a,S=(f-m)/2):(h=a*f/n,p=(g-h)/2)):(s=g,d=f,l=Math.max((r||s)/s,(o||d)/d),l>1&&(s=Math.ceil(s*l),d=Math.ceil(d*l)),l=Math.min((a||s)/s,(n||d)/d),1>l&&(s=Math.ceil(s*l),d=Math.ceil(d*l))),u?(c.width=s,c.height=d,t.transformCoordinates(c,i.orientation),t.renderImageToCanvas(c,e,p,S,h,m,x,y,s,d)):(e.width=s,e.height=d,e)},t.createObjectURL=function(e){return i?i.createObjectURL(e):!1},t.revokeObjectURL=function(e){return i?i.revokeObjectURL(e):!1},t.readFile=function(e,t,i){if(window.FileReader){var a=new FileReader;if(a.onload=a.onerror=t,i=i||"readAsDataURL",a[i])return a[i](e),a}return!1},"function"==typeof define&&define.amd?define(function(){return t}):e.loadImage=t})(this),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image"],e):e(window.loadImage)}(function(e){"use strict";if(window.navigator&&window.navigator.platform&&/iP(hone|od|ad)/.test(window.navigator.platform)){var t=e.renderImageToCanvas;e.detectSubsampling=function(e){var t,i;return e.width*e.height>1048576?(t=document.createElement("canvas"),t.width=t.height=1,i=t.getContext("2d"),i.drawImage(e,-e.width+1,0),0===i.getImageData(0,0,1,1).data[3]):!1},e.detectVerticalSquash=function(e,t){var i,a,n,r,o,s=document.createElement("canvas"),d=s.getContext("2d");for(s.width=1,s.height=t,d.drawImage(e,0,0),i=d.getImageData(0,0,1,t).data,a=0,n=t,r=t;r>a;)o=i[4*(r-1)+3],0===o?n=r:a=r,r=n+a>>1;return r/t||1},e.renderImageToCanvas=function(i,a,n,r,o,s,d,l,c,u){if("image/jpeg"===a._type){var g,f,h,m,p=i.getContext("2d"),S=document.createElement("canvas"),x=1024,y=S.getContext("2d");if(S.width=x,S.height=x,p.save(),g=e.detectSubsampling(a),g&&(o/=2,s/=2),f=e.detectVerticalSquash(a,s),g&&1!==f){for(c=Math.ceil(x*c/o),u=Math.ceil(x*u/s/f),l=0,m=0;s>m;){for(d=0,h=0;o>h;)y.clearRect(0,0,x,x),y.drawImage(a,n,r,o,s,-h,-m,o,s),p.drawImage(S,0,0,x,x,d,l,c,u),h+=x,d+=c;m+=x,l+=u}return p.restore(),i}}return t(i,a,n,r,o,s,d,l,c,u)}}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image"],e):e(window.loadImage)}(function(e){"use strict";e.blobSlice=function(){var e=this.slice||this.webkitSlice||this.mozSlice;return e.apply(this,arguments)},e.metaDataParsers={jpeg:{65505:[]}},e.parseMetaData=function(t,i,a){a=a||{};var n=this,r={},o=!window.DataView||!t||12>t.size||"image/jpeg"!==t.type;(o||!e.readFile(e.blobSlice.call(t,0,131072),function(t){var o,s,d,l,c=t.target.result,u=new DataView(c),g=2,f=u.byteLength-4,h=g;if(65496===u.getUint16(0)){for(;f>g&&(o=u.getUint16(g),o>=65504&&65519>=o||65534===o);)if(s=u.getUint16(g+2),g+s>u.byteLength)console.log("Invalid meta data: Invalid segment size.");else{if(d=e.metaDataParsers.jpeg[o])for(l=0;d.length>l;l+=1)d[l].call(n,u,g,s,r,a);g+=s+2,h=g}!a.disableImageHead&&h>6&&(r.imageHead=c.slice?c.slice(0,h):new Uint8Array(c).subarray(0,h))}else console.log("Invalid JPEG file: Missing JPEG marker.");i(r)},"readAsArrayBuffer"))&&i(r)}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-meta"],e):e(window.loadImage)}(function(e){"use strict";e.ExifMap=function(){return this},e.ExifMap.prototype.map={Orientation:274},e.ExifMap.prototype.get=function(e){return this[e]||this[this.map[e]]},e.getExifThumbnail=function(e,t,i){var a,n,r;if(!i||t+i>e.byteLength)return console.log("Invalid Exif data: Invalid thumbnail data."),void 0;for(a=[],n=0;i>n;n+=1)r=e.getUint8(t+n),a.push((16>r?"0":"")+r.toString(16));return"data:image/jpeg,%"+a.join("%")},e.exifTagTypes={1:{getValue:function(e,t){return e.getUint8(t)},size:1},2:{getValue:function(e,t){return String.fromCharCode(e.getUint8(t))},size:1,ascii:!0},3:{getValue:function(e,t,i){return e.getUint16(t,i)},size:2},4:{getValue:function(e,t,i){return e.getUint32(t,i)},size:4},5:{getValue:function(e,t,i){return e.getUint32(t,i)/e.getUint32(t+4,i)},size:8},9:{getValue:function(e,t,i){return e.getInt32(t,i)},size:4},10:{getValue:function(e,t,i){return e.getInt32(t,i)/e.getInt32(t+4,i)},size:8}},e.exifTagTypes[7]=e.exifTagTypes[1],e.getExifValue=function(t,i,a,n,r,o){var s,d,l,c,u,g,f=e.exifTagTypes[n];if(!f)return console.log("Invalid Exif data: Invalid tag type."),void 0;if(s=f.size*r,d=s>4?i+t.getUint32(a+8,o):a+8,d+s>t.byteLength)return console.log("Invalid Exif data: Invalid data offset."),void 0;if(1===r)return f.getValue(t,d,o);for(l=[],c=0;r>c;c+=1)l[c]=f.getValue(t,d+c*f.size,o);if(f.ascii){for(u="",c=0;l.length>c&&(g=l[c],"\0"!==g);c+=1)u+=g;return u}return l},e.parseExifTag=function(t,i,a,n,r){var o=t.getUint16(a,n);r.exif[o]=e.getExifValue(t,i,a,t.getUint16(a+2,n),t.getUint32(a+4,n),n)},e.parseExifTags=function(e,t,i,a,n){var r,o,s;if(i+6>e.byteLength)return console.log("Invalid Exif data: Invalid directory offset."),void 0;if(r=e.getUint16(i,a),o=i+2+12*r,o+4>e.byteLength)return console.log("Invalid Exif data: Invalid directory size."),void 0;for(s=0;r>s;s+=1)this.parseExifTag(e,t,i+2+12*s,a,n);return e.getUint32(o,a)},e.parseExifData=function(t,i,a,n,r){if(!r.disableExif){var o,s,d,l=i+10;if(1165519206===t.getUint32(i+4)){if(l+8>t.byteLength)return console.log("Invalid Exif data: Invalid segment size."),void 0;if(0!==t.getUint16(i+8))return console.log("Invalid Exif data: Missing byte alignment offset."),void 0;switch(t.getUint16(l)){case 18761:o=!0;break;case 19789:o=!1;break;default:return console.log("Invalid Exif data: Invalid byte alignment marker."),void 0}if(42!==t.getUint16(l+2,o))return console.log("Invalid Exif data: Missing TIFF marker."),void 0;s=t.getUint32(l+4,o),n.exif=new e.ExifMap,s=e.parseExifTags(t,l,l+s,o,n),s&&!r.disableExifThumbnail&&(d={exif:{}},s=e.parseExifTags(t,l,l+s,o,d),d.exif[513]&&(n.exif.Thumbnail=e.getExifThumbnail(t,l+d.exif[513],d.exif[514]))),n.exif[34665]&&!r.disableExifSub&&e.parseExifTags(t,l,l+n.exif[34665],o,n),n.exif[34853]&&!r.disableExifGps&&e.parseExifTags(t,l,l+n.exif[34853],o,n)}}},e.metaDataParsers.jpeg[65505].push(e.parseExifData)}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-exif"],e):e(window.loadImage)}(function(e){"use strict";var t,i,a;e.ExifMap.prototype.tags={256:"ImageWidth",257:"ImageHeight",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer",40965:"InteroperabilityIFDPointer",258:"BitsPerSample",259:"Compression",262:"PhotometricInterpretation",274:"Orientation",277:"SamplesPerPixel",284:"PlanarConfiguration",530:"YCbCrSubSampling",531:"YCbCrPositioning",282:"XResolution",283:"YResolution",296:"ResolutionUnit",273:"StripOffsets",278:"RowsPerStrip",279:"StripByteCounts",513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength",301:"TransferFunction",318:"WhitePoint",319:"PrimaryChromaticities",529:"YCbCrCoefficients",532:"ReferenceBlackWhite",306:"DateTime",270:"ImageDescription",271:"Make",272:"Model",305:"Software",315:"Artist",33432:"Copyright",36864:"ExifVersion",40960:"FlashpixVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",37121:"ComponentsConfiguration",37122:"CompressedBitsPerPixel",37500:"MakerNote",37510:"UserComment",40964:"RelatedSoundFile",36867:"DateTimeOriginal",36868:"DateTimeDigitized",37520:"SubsecTime",37521:"SubsecTimeOriginal",37522:"SubsecTimeDigitized",33434:"ExposureTime",33437:"FNumber",34850:"ExposureProgram",34852:"SpectralSensitivity",34855:"ISOSpeedRatings",34856:"OECF",37377:"ShutterSpeedValue",37378:"ApertureValue",37379:"BrightnessValue",37380:"ExposureBias",37381:"MaxApertureValue",37382:"SubjectDistance",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37396:"SubjectArea",37386:"FocalLength",41483:"FlashEnergy",41484:"SpatialFrequencyResponse",41486:"FocalPlaneXResolution",41487:"FocalPlaneYResolution",41488:"FocalPlaneResolutionUnit",41492:"SubjectLocation",41493:"ExposureIndex",41495:"SensingMethod",41728:"FileSource",41729:"SceneType",41730:"CFAPattern",41985:"CustomRendered",41986:"ExposureMode",41987:"WhiteBalance",41988:"DigitalZoomRation",41989:"FocalLengthIn35mmFilm",41990:"SceneCaptureType",41991:"GainControl",41992:"Contrast",41993:"Saturation",41994:"Sharpness",41995:"DeviceSettingDescription",41996:"SubjectDistanceRange",42016:"ImageUniqueID",0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude",5:"GPSAltitudeRef",6:"GPSAltitude",7:"GPSTimeStamp",8:"GPSSatellites",9:"GPSStatus",10:"GPSMeasureMode",11:"GPSDOP",12:"GPSSpeedRef",13:"GPSSpeed",14:"GPSTrackRef",15:"GPSTrack",16:"GPSImgDirectionRef",17:"GPSImgDirection",18:"GPSMapDatum",19:"GPSDestLatitudeRef",20:"GPSDestLatitude",21:"GPSDestLongitudeRef",22:"GPSDestLongitude",23:"GPSDestBearingRef",24:"GPSDestBearing",25:"GPSDestDistanceRef",26:"GPSDestDistance",27:"GPSProcessingMethod",28:"GPSAreaInformation",29:"GPSDateStamp",30:"GPSDifferential"},e.ExifMap.prototype.stringValues={ExposureProgram:{0:"Undefined",1:"Manual",2:"Normal program",3:"Aperture priority",4:"Shutter priority",5:"Creative program",6:"Action program",7:"Portrait mode",8:"Landscape mode"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{0:"Unknown",1:"Daylight",2:"Fluorescent",3:"Tungsten (incandescent light)",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 - 5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},SensingMethod:{1:"Undefined",2:"One-chip color area sensor",3:"Two-chip color area sensor",4:"Three-chip color area sensor",5:"Color sequential area sensor",7:"Trilinear sensor",8:"Color sequential linear sensor"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},SceneType:{1:"Directly photographed"},CustomRendered:{0:"Normal process",1:"Custom process"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},GainControl:{0:"None",1:"Low gain up",2:"High gain up",3:"Low gain down",4:"High gain down"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},SubjectDistanceRange:{0:"Unknown",1:"Macro",2:"Close view",3:"Distant view"},FileSource:{3:"DSC"},ComponentsConfiguration:{0:"",1:"Y",2:"Cb",3:"Cr",4:"R",5:"G",6:"B"},Orientation:{1:"top-left",2:"top-right",3:"bottom-right",4:"bottom-left",5:"left-top",6:"right-top",7:"right-bottom",8:"left-bottom"}},e.ExifMap.prototype.getText=function(e){var t=this.get(e);switch(e){case"LightSource":case"Flash":case"MeteringMode":case"ExposureProgram":case"SensingMethod":case"SceneCaptureType":case"SceneType":case"CustomRendered":case"WhiteBalance":case"GainControl":case"Contrast":case"Saturation":case"Sharpness":case"SubjectDistanceRange":case"FileSource":case"Orientation":return this.stringValues[e][t];case"ExifVersion":case"FlashpixVersion":return String.fromCharCode(t[0],t[1],t[2],t[3]);case"ComponentsConfiguration":return this.stringValues[e][t[0]]+this.stringValues[e][t[1]]+this.stringValues[e][t[2]]+this.stringValues[e][t[3]];case"GPSVersionID":return t[0]+"."+t[1]+"."+t[2]+"."+t[3]}return t+""},t=e.ExifMap.prototype.tags,i=e.ExifMap.prototype.map;for(a in t)t.hasOwnProperty(a)&&(i[t[a]]=a);e.ExifMap.prototype.getAll=function(){var e,i,a={};for(e in this)this.hasOwnProperty(e)&&(i=t[e],i&&(a[i]=this.getText(i)));return a}});
\ No newline at end of file
+(function(e){"use strict";var t=function(e,i,a){var n,r,o=document.createElement("img");if(o.onerror=i,o.onload=function(){!r||a&&a.noRevoke||t.revokeObjectURL(r),i&&i(t.scale(o,a))},t.isInstanceOf("Blob",e)||t.isInstanceOf("File",e))n=r=t.createObjectURL(e),o._type=e.type;else{if("string"!=typeof e)return!1;n=e,a&&a.crossOrigin&&(o.crossOrigin=a.crossOrigin)}return n?(o.src=n,o):t.readFile(e,function(e){var t=e.target;t&&t.result?o.src=t.result:i&&i(e)})},i=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;t.isInstanceOf=function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},t.transformCoordinates=function(e,t){var i=e.getContext("2d"),a=e.width,n=e.height;switch(t>4&&(e.width=n,e.height=a),t){case 2:i.translate(a,0),i.scale(-1,1);break;case 3:i.translate(a,n),i.rotate(Math.PI);break;case 4:i.translate(0,n),i.scale(1,-1);break;case 5:i.rotate(.5*Math.PI),i.scale(1,-1);break;case 6:i.rotate(.5*Math.PI),i.translate(0,-n);break;case 7:i.rotate(.5*Math.PI),i.translate(a,-n),i.scale(-1,1);break;case 8:i.rotate(-.5*Math.PI),i.translate(-a,0)}},t.renderImageToCanvas=function(e,t,i,a,n,r,o,s,d,l){return e.getContext("2d").drawImage(t,i,a,n,r,o,s,d,l),e},t.scale=function(e,i){i=i||{};var a,n,r,o,s,d,l,c=document.createElement("canvas"),u=e.getContext||(i.canvas||i.crop||i.orientation)&&c.getContext,g=e.width,f=e.height,h=g,m=f,p=0,S=0,x=0,b=0;return u&&i.orientation>4?(a=i.maxHeight,n=i.maxWidth,r=i.minHeight,o=i.minWidth):(a=i.maxWidth,n=i.maxHeight,r=i.minWidth,o=i.minHeight),u&&a&&n&&i.crop?(s=a,d=n,a/n>g/f?(m=n*g/a,S=(f-m)/2):(h=a*f/n,p=(g-h)/2)):(s=g,d=f,l=Math.max((r||s)/s,(o||d)/d),l>1&&(s=Math.ceil(s*l),d=Math.ceil(d*l)),l=Math.min((a||s)/s,(n||d)/d),1>l&&(s=Math.ceil(s*l),d=Math.ceil(d*l))),u?(c.width=s,c.height=d,t.transformCoordinates(c,i.orientation),t.renderImageToCanvas(c,e,p,S,h,m,x,b,s,d)):(e.width=s,e.height=d,e)},t.createObjectURL=function(e){return i?i.createObjectURL(e):!1},t.revokeObjectURL=function(e){return i?i.revokeObjectURL(e):!1},t.readFile=function(e,t,i){if(window.FileReader){var a=new FileReader;if(a.onload=a.onerror=t,i=i||"readAsDataURL",a[i])return a[i](e),a}return!1},"function"==typeof define&&define.amd?define(function(){return t}):e.loadImage=t})(this),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image"],e):e(window.loadImage)}(function(e){"use strict";if(window.navigator&&window.navigator.platform&&/iP(hone|od|ad)/.test(window.navigator.platform)){var t=e.renderImageToCanvas;e.detectSubsampling=function(e){var t,i;return e.width*e.height>1048576?(t=document.createElement("canvas"),t.width=t.height=1,i=t.getContext("2d"),i.drawImage(e,-e.width+1,0),0===i.getImageData(0,0,1,1).data[3]):!1},e.detectVerticalSquash=function(e,t){var i,a,n,r,o,s=document.createElement("canvas"),d=s.getContext("2d");for(s.width=1,s.height=t,d.drawImage(e,0,0),i=d.getImageData(0,0,1,t).data,a=0,n=t,r=t;r>a;)o=i[4*(r-1)+3],0===o?n=r:a=r,r=n+a>>1;return r/t||1},e.renderImageToCanvas=function(i,a,n,r,o,s,d,l,c,u){if("image/jpeg"===a._type){var g,f,h,m,p=i.getContext("2d"),S=document.createElement("canvas"),x=1024,b=S.getContext("2d");if(S.width=x,S.height=x,p.save(),g=e.detectSubsampling(a),g&&(o/=2,s/=2),f=e.detectVerticalSquash(a,s),g&&1!==f){for(c=Math.ceil(x*c/o),u=Math.ceil(x*u/s/f),l=0,m=0;s>m;){for(d=0,h=0;o>h;)b.clearRect(0,0,x,x),b.drawImage(a,n,r,o,s,-h,-m,o,s),p.drawImage(S,0,0,x,x,d,l,c,u),h+=x,d+=c;m+=x,l+=u}return p.restore(),i}}return t(i,a,n,r,o,s,d,l,c,u)}}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image"],e):e(window.loadImage)}(function(e){"use strict";var t=window.Blob&&(Blob.prototype.slice||Blob.prototype.webkitSlice||Blob.prototype.mozSlice);e.blobSlice=t&&function(){var e=this.slice||this.webkitSlice||this.mozSlice;return e.apply(this,arguments)},e.metaDataParsers={jpeg:{65505:[]}},e.parseMetaData=function(t,i,a){a=a||{};var n=this,r={},o=!(window.DataView&&t&&t.size>=12&&"image/jpeg"===t.type&&e.blobSlice);(o||!e.readFile(e.blobSlice.call(t,0,131072),function(t){var o,s,d,l,c=t.target.result,u=new DataView(c),g=2,f=u.byteLength-4,h=g;if(65496===u.getUint16(0)){for(;f>g&&(o=u.getUint16(g),o>=65504&&65519>=o||65534===o);)if(s=u.getUint16(g+2)+2,g+s>u.byteLength)console.log("Invalid meta data: Invalid segment size.");else{if(d=e.metaDataParsers.jpeg[o])for(l=0;d.length>l;l+=1)d[l].call(n,u,g,s,r,a);g+=s,h=g}!a.disableImageHead&&h>6&&(r.imageHead=c.slice?c.slice(0,h):new Uint8Array(c).subarray(0,h))}else console.log("Invalid JPEG file: Missing JPEG marker.");i(r)},"readAsArrayBuffer"))&&i(r)}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-meta"],e):e(window.loadImage)}(function(e){"use strict";e.ExifMap=function(){return this},e.ExifMap.prototype.map={Orientation:274},e.ExifMap.prototype.get=function(e){return this[e]||this[this.map[e]]},e.getExifThumbnail=function(e,t,i){var a,n,r;if(!i||t+i>e.byteLength)return console.log("Invalid Exif data: Invalid thumbnail data."),void 0;for(a=[],n=0;i>n;n+=1)r=e.getUint8(t+n),a.push((16>r?"0":"")+r.toString(16));return"data:image/jpeg,%"+a.join("%")},e.exifTagTypes={1:{getValue:function(e,t){return e.getUint8(t)},size:1},2:{getValue:function(e,t){return String.fromCharCode(e.getUint8(t))},size:1,ascii:!0},3:{getValue:function(e,t,i){return e.getUint16(t,i)},size:2},4:{getValue:function(e,t,i){return e.getUint32(t,i)},size:4},5:{getValue:function(e,t,i){return e.getUint32(t,i)/e.getUint32(t+4,i)},size:8},9:{getValue:function(e,t,i){return e.getInt32(t,i)},size:4},10:{getValue:function(e,t,i){return e.getInt32(t,i)/e.getInt32(t+4,i)},size:8}},e.exifTagTypes[7]=e.exifTagTypes[1],e.getExifValue=function(t,i,a,n,r,o){var s,d,l,c,u,g,f=e.exifTagTypes[n];if(!f)return console.log("Invalid Exif data: Invalid tag type."),void 0;if(s=f.size*r,d=s>4?i+t.getUint32(a+8,o):a+8,d+s>t.byteLength)return console.log("Invalid Exif data: Invalid data offset."),void 0;if(1===r)return f.getValue(t,d,o);for(l=[],c=0;r>c;c+=1)l[c]=f.getValue(t,d+c*f.size,o);if(f.ascii){for(u="",c=0;l.length>c&&(g=l[c],"\0"!==g);c+=1)u+=g;return u}return l},e.parseExifTag=function(t,i,a,n,r){var o=t.getUint16(a,n);r.exif[o]=e.getExifValue(t,i,a,t.getUint16(a+2,n),t.getUint32(a+4,n),n)},e.parseExifTags=function(e,t,i,a,n){var r,o,s;if(i+6>e.byteLength)return console.log("Invalid Exif data: Invalid directory offset."),void 0;if(r=e.getUint16(i,a),o=i+2+12*r,o+4>e.byteLength)return console.log("Invalid Exif data: Invalid directory size."),void 0;for(s=0;r>s;s+=1)this.parseExifTag(e,t,i+2+12*s,a,n);return e.getUint32(o,a)},e.parseExifData=function(t,i,a,n,r){if(!r.disableExif){var o,s,d,l=i+10;if(1165519206===t.getUint32(i+4)){if(l+8>t.byteLength)return console.log("Invalid Exif data: Invalid segment size."),void 0;if(0!==t.getUint16(i+8))return console.log("Invalid Exif data: Missing byte alignment offset."),void 0;switch(t.getUint16(l)){case 18761:o=!0;break;case 19789:o=!1;break;default:return console.log("Invalid Exif data: Invalid byte alignment marker."),void 0}if(42!==t.getUint16(l+2,o))return console.log("Invalid Exif data: Missing TIFF marker."),void 0;s=t.getUint32(l+4,o),n.exif=new e.ExifMap,s=e.parseExifTags(t,l,l+s,o,n),s&&!r.disableExifThumbnail&&(d={exif:{}},s=e.parseExifTags(t,l,l+s,o,d),d.exif[513]&&(n.exif.Thumbnail=e.getExifThumbnail(t,l+d.exif[513],d.exif[514]))),n.exif[34665]&&!r.disableExifSub&&e.parseExifTags(t,l,l+n.exif[34665],o,n),n.exif[34853]&&!r.disableExifGps&&e.parseExifTags(t,l,l+n.exif[34853],o,n)}}},e.metaDataParsers.jpeg[65505].push(e.parseExifData)}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-exif"],e):e(window.loadImage)}(function(e){"use strict";var t,i,a;e.ExifMap.prototype.tags={256:"ImageWidth",257:"ImageHeight",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer",40965:"InteroperabilityIFDPointer",258:"BitsPerSample",259:"Compression",262:"PhotometricInterpretation",274:"Orientation",277:"SamplesPerPixel",284:"PlanarConfiguration",530:"YCbCrSubSampling",531:"YCbCrPositioning",282:"XResolution",283:"YResolution",296:"ResolutionUnit",273:"StripOffsets",278:"RowsPerStrip",279:"StripByteCounts",513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength",301:"TransferFunction",318:"WhitePoint",319:"PrimaryChromaticities",529:"YCbCrCoefficients",532:"ReferenceBlackWhite",306:"DateTime",270:"ImageDescription",271:"Make",272:"Model",305:"Software",315:"Artist",33432:"Copyright",36864:"ExifVersion",40960:"FlashpixVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",37121:"ComponentsConfiguration",37122:"CompressedBitsPerPixel",37500:"MakerNote",37510:"UserComment",40964:"RelatedSoundFile",36867:"DateTimeOriginal",36868:"DateTimeDigitized",37520:"SubsecTime",37521:"SubsecTimeOriginal",37522:"SubsecTimeDigitized",33434:"ExposureTime",33437:"FNumber",34850:"ExposureProgram",34852:"SpectralSensitivity",34855:"ISOSpeedRatings",34856:"OECF",37377:"ShutterSpeedValue",37378:"ApertureValue",37379:"BrightnessValue",37380:"ExposureBias",37381:"MaxApertureValue",37382:"SubjectDistance",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37396:"SubjectArea",37386:"FocalLength",41483:"FlashEnergy",41484:"SpatialFrequencyResponse",41486:"FocalPlaneXResolution",41487:"FocalPlaneYResolution",41488:"FocalPlaneResolutionUnit",41492:"SubjectLocation",41493:"ExposureIndex",41495:"SensingMethod",41728:"FileSource",41729:"SceneType",41730:"CFAPattern",41985:"CustomRendered",41986:"ExposureMode",41987:"WhiteBalance",41988:"DigitalZoomRation",41989:"FocalLengthIn35mmFilm",41990:"SceneCaptureType",41991:"GainControl",41992:"Contrast",41993:"Saturation",41994:"Sharpness",41995:"DeviceSettingDescription",41996:"SubjectDistanceRange",42016:"ImageUniqueID",0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude",5:"GPSAltitudeRef",6:"GPSAltitude",7:"GPSTimeStamp",8:"GPSSatellites",9:"GPSStatus",10:"GPSMeasureMode",11:"GPSDOP",12:"GPSSpeedRef",13:"GPSSpeed",14:"GPSTrackRef",15:"GPSTrack",16:"GPSImgDirectionRef",17:"GPSImgDirection",18:"GPSMapDatum",19:"GPSDestLatitudeRef",20:"GPSDestLatitude",21:"GPSDestLongitudeRef",22:"GPSDestLongitude",23:"GPSDestBearingRef",24:"GPSDestBearing",25:"GPSDestDistanceRef",26:"GPSDestDistance",27:"GPSProcessingMethod",28:"GPSAreaInformation",29:"GPSDateStamp",30:"GPSDifferential"},e.ExifMap.prototype.stringValues={ExposureProgram:{0:"Undefined",1:"Manual",2:"Normal program",3:"Aperture priority",4:"Shutter priority",5:"Creative program",6:"Action program",7:"Portrait mode",8:"Landscape mode"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{0:"Unknown",1:"Daylight",2:"Fluorescent",3:"Tungsten (incandescent light)",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 - 5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},SensingMethod:{1:"Undefined",2:"One-chip color area sensor",3:"Two-chip color area sensor",4:"Three-chip color area sensor",5:"Color sequential area sensor",7:"Trilinear sensor",8:"Color sequential linear sensor"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},SceneType:{1:"Directly photographed"},CustomRendered:{0:"Normal process",1:"Custom process"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},GainControl:{0:"None",1:"Low gain up",2:"High gain up",3:"Low gain down",4:"High gain down"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},SubjectDistanceRange:{0:"Unknown",1:"Macro",2:"Close view",3:"Distant view"},FileSource:{3:"DSC"},ComponentsConfiguration:{0:"",1:"Y",2:"Cb",3:"Cr",4:"R",5:"G",6:"B"},Orientation:{1:"top-left",2:"top-right",3:"bottom-right",4:"bottom-left",5:"left-top",6:"right-top",7:"right-bottom",8:"left-bottom"}},e.ExifMap.prototype.getText=function(e){var t=this.get(e);switch(e){case"LightSource":case"Flash":case"MeteringMode":case"ExposureProgram":case"SensingMethod":case"SceneCaptureType":case"SceneType":case"CustomRendered":case"WhiteBalance":case"GainControl":case"Contrast":case"Saturation":case"Sharpness":case"SubjectDistanceRange":case"FileSource":case"Orientation":return this.stringValues[e][t];case"ExifVersion":case"FlashpixVersion":return String.fromCharCode(t[0],t[1],t[2],t[3]);case"ComponentsConfiguration":return this.stringValues[e][t[0]]+this.stringValues[e][t[1]]+this.stringValues[e][t[2]]+this.stringValues[e][t[3]];case"GPSVersionID":return t[0]+"."+t[1]+"."+t[2]+"."+t[3]}return t+""},t=e.ExifMap.prototype.tags,i=e.ExifMap.prototype.map;for(a in t)t.hasOwnProperty(a)&&(i[t[a]]=a);e.ExifMap.prototype.getAll=function(){var e,i,a={};for(e in this)this.hasOwnProperty(e)&&(i=t[e],i&&(a[i]=this.getText(i)));return a}});
\ No newline at end of file
From e6f48c13ea8fbb6afd76285236033598f753a35e Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Sun, 16 Jun 2013 22:25:20 -0500
Subject: [PATCH 036/386] Break out of the loop if the marker length exceeds
the data view length.
Use 256 KiB by default to parse the image meta data, which can be
overriden by the new configuration option maxMetaDataSize.
---
README.md | 3 ++-
load-image-meta.js | 9 +++++----
load-image.min.js | 2 +-
package.json | 2 +-
4 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 3c02e5d..7bfb891 100644
--- a/README.md
+++ b/README.md
@@ -160,12 +160,13 @@ loadImage.parseMetaData(
], {type: resizedImage.type});
},
{
+ maxMetaDataSize: 262144,
disableImageHead: false
}
);
```
-The third argument is an options object which allows to disable the imageHead creation and is also passed along to segment parsers registered via loadImage extensions, e.g. the Exif parser.
+The third argument is an options object which defines the maximum number of bytes to parse for the image meta data, allows to disable the imageHead creation and is also passed along to segment parsers registered via loadImage extensions, e.g. the Exif parser.
**Note:**
Blob objects of resized images can be created via [canvas.toBlob()](https://github.com/blueimp/JavaScript-Canvas-to-Blob).
diff --git a/load-image-meta.js b/load-image-meta.js
index 9e0f25f..c7e5a20 100644
--- a/load-image-meta.js
+++ b/load-image-meta.js
@@ -1,5 +1,5 @@
/*
- * JavaScript Load Image Meta 1.0
+ * JavaScript Load Image Meta 1.0.1
* https://github.com/blueimp/JavaScript-Load-Image
*
* Copyright 2013, Sebastian Tschan
@@ -50,12 +50,13 @@
loadImage.parseMetaData = function (file, callback, options) {
options = options || {};
var that = this,
+ // 256 KiB should contain all EXIF/ICC/IPTC segments:
+ maxMetaDataSize = options.maxMetaDataSize || 262144,
data = {},
noMetaData = !(window.DataView && file && file.size >= 12 &&
file.type === 'image/jpeg' && loadImage.blobSlice);
if (noMetaData || !loadImage.readFile(
- // 128 KiB should contain all EXIF/ICC/IPTC segments:
- loadImage.blobSlice.call(file, 0, 131072),
+ loadImage.blobSlice.call(file, 0, maxMetaDataSize),
function (e) {
// Note on endianness:
// Since the marker and length bytes in JPEG files are always
@@ -86,7 +87,7 @@
markerLength = dataView.getUint16(offset + 2) + 2;
if (offset + markerLength > dataView.byteLength) {
console.log('Invalid meta data: Invalid segment size.');
- continue;
+ break;
}
parsers = loadImage.metaDataParsers.jpeg[markerBytes];
if (parsers) {
diff --git a/load-image.min.js b/load-image.min.js
index b58f4e9..a752fb3 100644
--- a/load-image.min.js
+++ b/load-image.min.js
@@ -1 +1 @@
-(function(e){"use strict";var t=function(e,i,a){var n,r,o=document.createElement("img");if(o.onerror=i,o.onload=function(){!r||a&&a.noRevoke||t.revokeObjectURL(r),i&&i(t.scale(o,a))},t.isInstanceOf("Blob",e)||t.isInstanceOf("File",e))n=r=t.createObjectURL(e),o._type=e.type;else{if("string"!=typeof e)return!1;n=e,a&&a.crossOrigin&&(o.crossOrigin=a.crossOrigin)}return n?(o.src=n,o):t.readFile(e,function(e){var t=e.target;t&&t.result?o.src=t.result:i&&i(e)})},i=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;t.isInstanceOf=function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},t.transformCoordinates=function(e,t){var i=e.getContext("2d"),a=e.width,n=e.height;switch(t>4&&(e.width=n,e.height=a),t){case 2:i.translate(a,0),i.scale(-1,1);break;case 3:i.translate(a,n),i.rotate(Math.PI);break;case 4:i.translate(0,n),i.scale(1,-1);break;case 5:i.rotate(.5*Math.PI),i.scale(1,-1);break;case 6:i.rotate(.5*Math.PI),i.translate(0,-n);break;case 7:i.rotate(.5*Math.PI),i.translate(a,-n),i.scale(-1,1);break;case 8:i.rotate(-.5*Math.PI),i.translate(-a,0)}},t.renderImageToCanvas=function(e,t,i,a,n,r,o,s,d,l){return e.getContext("2d").drawImage(t,i,a,n,r,o,s,d,l),e},t.scale=function(e,i){i=i||{};var a,n,r,o,s,d,l,c=document.createElement("canvas"),u=e.getContext||(i.canvas||i.crop||i.orientation)&&c.getContext,g=e.width,f=e.height,h=g,m=f,p=0,S=0,x=0,b=0;return u&&i.orientation>4?(a=i.maxHeight,n=i.maxWidth,r=i.minHeight,o=i.minWidth):(a=i.maxWidth,n=i.maxHeight,r=i.minWidth,o=i.minHeight),u&&a&&n&&i.crop?(s=a,d=n,a/n>g/f?(m=n*g/a,S=(f-m)/2):(h=a*f/n,p=(g-h)/2)):(s=g,d=f,l=Math.max((r||s)/s,(o||d)/d),l>1&&(s=Math.ceil(s*l),d=Math.ceil(d*l)),l=Math.min((a||s)/s,(n||d)/d),1>l&&(s=Math.ceil(s*l),d=Math.ceil(d*l))),u?(c.width=s,c.height=d,t.transformCoordinates(c,i.orientation),t.renderImageToCanvas(c,e,p,S,h,m,x,b,s,d)):(e.width=s,e.height=d,e)},t.createObjectURL=function(e){return i?i.createObjectURL(e):!1},t.revokeObjectURL=function(e){return i?i.revokeObjectURL(e):!1},t.readFile=function(e,t,i){if(window.FileReader){var a=new FileReader;if(a.onload=a.onerror=t,i=i||"readAsDataURL",a[i])return a[i](e),a}return!1},"function"==typeof define&&define.amd?define(function(){return t}):e.loadImage=t})(this),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image"],e):e(window.loadImage)}(function(e){"use strict";if(window.navigator&&window.navigator.platform&&/iP(hone|od|ad)/.test(window.navigator.platform)){var t=e.renderImageToCanvas;e.detectSubsampling=function(e){var t,i;return e.width*e.height>1048576?(t=document.createElement("canvas"),t.width=t.height=1,i=t.getContext("2d"),i.drawImage(e,-e.width+1,0),0===i.getImageData(0,0,1,1).data[3]):!1},e.detectVerticalSquash=function(e,t){var i,a,n,r,o,s=document.createElement("canvas"),d=s.getContext("2d");for(s.width=1,s.height=t,d.drawImage(e,0,0),i=d.getImageData(0,0,1,t).data,a=0,n=t,r=t;r>a;)o=i[4*(r-1)+3],0===o?n=r:a=r,r=n+a>>1;return r/t||1},e.renderImageToCanvas=function(i,a,n,r,o,s,d,l,c,u){if("image/jpeg"===a._type){var g,f,h,m,p=i.getContext("2d"),S=document.createElement("canvas"),x=1024,b=S.getContext("2d");if(S.width=x,S.height=x,p.save(),g=e.detectSubsampling(a),g&&(o/=2,s/=2),f=e.detectVerticalSquash(a,s),g&&1!==f){for(c=Math.ceil(x*c/o),u=Math.ceil(x*u/s/f),l=0,m=0;s>m;){for(d=0,h=0;o>h;)b.clearRect(0,0,x,x),b.drawImage(a,n,r,o,s,-h,-m,o,s),p.drawImage(S,0,0,x,x,d,l,c,u),h+=x,d+=c;m+=x,l+=u}return p.restore(),i}}return t(i,a,n,r,o,s,d,l,c,u)}}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image"],e):e(window.loadImage)}(function(e){"use strict";var t=window.Blob&&(Blob.prototype.slice||Blob.prototype.webkitSlice||Blob.prototype.mozSlice);e.blobSlice=t&&function(){var e=this.slice||this.webkitSlice||this.mozSlice;return e.apply(this,arguments)},e.metaDataParsers={jpeg:{65505:[]}},e.parseMetaData=function(t,i,a){a=a||{};var n=this,r={},o=!(window.DataView&&t&&t.size>=12&&"image/jpeg"===t.type&&e.blobSlice);(o||!e.readFile(e.blobSlice.call(t,0,131072),function(t){var o,s,d,l,c=t.target.result,u=new DataView(c),g=2,f=u.byteLength-4,h=g;if(65496===u.getUint16(0)){for(;f>g&&(o=u.getUint16(g),o>=65504&&65519>=o||65534===o);)if(s=u.getUint16(g+2)+2,g+s>u.byteLength)console.log("Invalid meta data: Invalid segment size.");else{if(d=e.metaDataParsers.jpeg[o])for(l=0;d.length>l;l+=1)d[l].call(n,u,g,s,r,a);g+=s,h=g}!a.disableImageHead&&h>6&&(r.imageHead=c.slice?c.slice(0,h):new Uint8Array(c).subarray(0,h))}else console.log("Invalid JPEG file: Missing JPEG marker.");i(r)},"readAsArrayBuffer"))&&i(r)}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-meta"],e):e(window.loadImage)}(function(e){"use strict";e.ExifMap=function(){return this},e.ExifMap.prototype.map={Orientation:274},e.ExifMap.prototype.get=function(e){return this[e]||this[this.map[e]]},e.getExifThumbnail=function(e,t,i){var a,n,r;if(!i||t+i>e.byteLength)return console.log("Invalid Exif data: Invalid thumbnail data."),void 0;for(a=[],n=0;i>n;n+=1)r=e.getUint8(t+n),a.push((16>r?"0":"")+r.toString(16));return"data:image/jpeg,%"+a.join("%")},e.exifTagTypes={1:{getValue:function(e,t){return e.getUint8(t)},size:1},2:{getValue:function(e,t){return String.fromCharCode(e.getUint8(t))},size:1,ascii:!0},3:{getValue:function(e,t,i){return e.getUint16(t,i)},size:2},4:{getValue:function(e,t,i){return e.getUint32(t,i)},size:4},5:{getValue:function(e,t,i){return e.getUint32(t,i)/e.getUint32(t+4,i)},size:8},9:{getValue:function(e,t,i){return e.getInt32(t,i)},size:4},10:{getValue:function(e,t,i){return e.getInt32(t,i)/e.getInt32(t+4,i)},size:8}},e.exifTagTypes[7]=e.exifTagTypes[1],e.getExifValue=function(t,i,a,n,r,o){var s,d,l,c,u,g,f=e.exifTagTypes[n];if(!f)return console.log("Invalid Exif data: Invalid tag type."),void 0;if(s=f.size*r,d=s>4?i+t.getUint32(a+8,o):a+8,d+s>t.byteLength)return console.log("Invalid Exif data: Invalid data offset."),void 0;if(1===r)return f.getValue(t,d,o);for(l=[],c=0;r>c;c+=1)l[c]=f.getValue(t,d+c*f.size,o);if(f.ascii){for(u="",c=0;l.length>c&&(g=l[c],"\0"!==g);c+=1)u+=g;return u}return l},e.parseExifTag=function(t,i,a,n,r){var o=t.getUint16(a,n);r.exif[o]=e.getExifValue(t,i,a,t.getUint16(a+2,n),t.getUint32(a+4,n),n)},e.parseExifTags=function(e,t,i,a,n){var r,o,s;if(i+6>e.byteLength)return console.log("Invalid Exif data: Invalid directory offset."),void 0;if(r=e.getUint16(i,a),o=i+2+12*r,o+4>e.byteLength)return console.log("Invalid Exif data: Invalid directory size."),void 0;for(s=0;r>s;s+=1)this.parseExifTag(e,t,i+2+12*s,a,n);return e.getUint32(o,a)},e.parseExifData=function(t,i,a,n,r){if(!r.disableExif){var o,s,d,l=i+10;if(1165519206===t.getUint32(i+4)){if(l+8>t.byteLength)return console.log("Invalid Exif data: Invalid segment size."),void 0;if(0!==t.getUint16(i+8))return console.log("Invalid Exif data: Missing byte alignment offset."),void 0;switch(t.getUint16(l)){case 18761:o=!0;break;case 19789:o=!1;break;default:return console.log("Invalid Exif data: Invalid byte alignment marker."),void 0}if(42!==t.getUint16(l+2,o))return console.log("Invalid Exif data: Missing TIFF marker."),void 0;s=t.getUint32(l+4,o),n.exif=new e.ExifMap,s=e.parseExifTags(t,l,l+s,o,n),s&&!r.disableExifThumbnail&&(d={exif:{}},s=e.parseExifTags(t,l,l+s,o,d),d.exif[513]&&(n.exif.Thumbnail=e.getExifThumbnail(t,l+d.exif[513],d.exif[514]))),n.exif[34665]&&!r.disableExifSub&&e.parseExifTags(t,l,l+n.exif[34665],o,n),n.exif[34853]&&!r.disableExifGps&&e.parseExifTags(t,l,l+n.exif[34853],o,n)}}},e.metaDataParsers.jpeg[65505].push(e.parseExifData)}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-exif"],e):e(window.loadImage)}(function(e){"use strict";var t,i,a;e.ExifMap.prototype.tags={256:"ImageWidth",257:"ImageHeight",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer",40965:"InteroperabilityIFDPointer",258:"BitsPerSample",259:"Compression",262:"PhotometricInterpretation",274:"Orientation",277:"SamplesPerPixel",284:"PlanarConfiguration",530:"YCbCrSubSampling",531:"YCbCrPositioning",282:"XResolution",283:"YResolution",296:"ResolutionUnit",273:"StripOffsets",278:"RowsPerStrip",279:"StripByteCounts",513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength",301:"TransferFunction",318:"WhitePoint",319:"PrimaryChromaticities",529:"YCbCrCoefficients",532:"ReferenceBlackWhite",306:"DateTime",270:"ImageDescription",271:"Make",272:"Model",305:"Software",315:"Artist",33432:"Copyright",36864:"ExifVersion",40960:"FlashpixVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",37121:"ComponentsConfiguration",37122:"CompressedBitsPerPixel",37500:"MakerNote",37510:"UserComment",40964:"RelatedSoundFile",36867:"DateTimeOriginal",36868:"DateTimeDigitized",37520:"SubsecTime",37521:"SubsecTimeOriginal",37522:"SubsecTimeDigitized",33434:"ExposureTime",33437:"FNumber",34850:"ExposureProgram",34852:"SpectralSensitivity",34855:"ISOSpeedRatings",34856:"OECF",37377:"ShutterSpeedValue",37378:"ApertureValue",37379:"BrightnessValue",37380:"ExposureBias",37381:"MaxApertureValue",37382:"SubjectDistance",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37396:"SubjectArea",37386:"FocalLength",41483:"FlashEnergy",41484:"SpatialFrequencyResponse",41486:"FocalPlaneXResolution",41487:"FocalPlaneYResolution",41488:"FocalPlaneResolutionUnit",41492:"SubjectLocation",41493:"ExposureIndex",41495:"SensingMethod",41728:"FileSource",41729:"SceneType",41730:"CFAPattern",41985:"CustomRendered",41986:"ExposureMode",41987:"WhiteBalance",41988:"DigitalZoomRation",41989:"FocalLengthIn35mmFilm",41990:"SceneCaptureType",41991:"GainControl",41992:"Contrast",41993:"Saturation",41994:"Sharpness",41995:"DeviceSettingDescription",41996:"SubjectDistanceRange",42016:"ImageUniqueID",0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude",5:"GPSAltitudeRef",6:"GPSAltitude",7:"GPSTimeStamp",8:"GPSSatellites",9:"GPSStatus",10:"GPSMeasureMode",11:"GPSDOP",12:"GPSSpeedRef",13:"GPSSpeed",14:"GPSTrackRef",15:"GPSTrack",16:"GPSImgDirectionRef",17:"GPSImgDirection",18:"GPSMapDatum",19:"GPSDestLatitudeRef",20:"GPSDestLatitude",21:"GPSDestLongitudeRef",22:"GPSDestLongitude",23:"GPSDestBearingRef",24:"GPSDestBearing",25:"GPSDestDistanceRef",26:"GPSDestDistance",27:"GPSProcessingMethod",28:"GPSAreaInformation",29:"GPSDateStamp",30:"GPSDifferential"},e.ExifMap.prototype.stringValues={ExposureProgram:{0:"Undefined",1:"Manual",2:"Normal program",3:"Aperture priority",4:"Shutter priority",5:"Creative program",6:"Action program",7:"Portrait mode",8:"Landscape mode"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{0:"Unknown",1:"Daylight",2:"Fluorescent",3:"Tungsten (incandescent light)",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 - 5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},SensingMethod:{1:"Undefined",2:"One-chip color area sensor",3:"Two-chip color area sensor",4:"Three-chip color area sensor",5:"Color sequential area sensor",7:"Trilinear sensor",8:"Color sequential linear sensor"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},SceneType:{1:"Directly photographed"},CustomRendered:{0:"Normal process",1:"Custom process"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},GainControl:{0:"None",1:"Low gain up",2:"High gain up",3:"Low gain down",4:"High gain down"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},SubjectDistanceRange:{0:"Unknown",1:"Macro",2:"Close view",3:"Distant view"},FileSource:{3:"DSC"},ComponentsConfiguration:{0:"",1:"Y",2:"Cb",3:"Cr",4:"R",5:"G",6:"B"},Orientation:{1:"top-left",2:"top-right",3:"bottom-right",4:"bottom-left",5:"left-top",6:"right-top",7:"right-bottom",8:"left-bottom"}},e.ExifMap.prototype.getText=function(e){var t=this.get(e);switch(e){case"LightSource":case"Flash":case"MeteringMode":case"ExposureProgram":case"SensingMethod":case"SceneCaptureType":case"SceneType":case"CustomRendered":case"WhiteBalance":case"GainControl":case"Contrast":case"Saturation":case"Sharpness":case"SubjectDistanceRange":case"FileSource":case"Orientation":return this.stringValues[e][t];case"ExifVersion":case"FlashpixVersion":return String.fromCharCode(t[0],t[1],t[2],t[3]);case"ComponentsConfiguration":return this.stringValues[e][t[0]]+this.stringValues[e][t[1]]+this.stringValues[e][t[2]]+this.stringValues[e][t[3]];case"GPSVersionID":return t[0]+"."+t[1]+"."+t[2]+"."+t[3]}return t+""},t=e.ExifMap.prototype.tags,i=e.ExifMap.prototype.map;for(a in t)t.hasOwnProperty(a)&&(i[t[a]]=a);e.ExifMap.prototype.getAll=function(){var e,i,a={};for(e in this)this.hasOwnProperty(e)&&(i=t[e],i&&(a[i]=this.getText(i)));return a}});
\ No newline at end of file
+(function(e){"use strict";var t=function(e,i,a){var n,r,o=document.createElement("img");if(o.onerror=i,o.onload=function(){!r||a&&a.noRevoke||t.revokeObjectURL(r),i&&i(t.scale(o,a))},t.isInstanceOf("Blob",e)||t.isInstanceOf("File",e))n=r=t.createObjectURL(e),o._type=e.type;else{if("string"!=typeof e)return!1;n=e,a&&a.crossOrigin&&(o.crossOrigin=a.crossOrigin)}return n?(o.src=n,o):t.readFile(e,function(e){var t=e.target;t&&t.result?o.src=t.result:i&&i(e)})},i=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;t.isInstanceOf=function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},t.transformCoordinates=function(e,t){var i=e.getContext("2d"),a=e.width,n=e.height;switch(t>4&&(e.width=n,e.height=a),t){case 2:i.translate(a,0),i.scale(-1,1);break;case 3:i.translate(a,n),i.rotate(Math.PI);break;case 4:i.translate(0,n),i.scale(1,-1);break;case 5:i.rotate(.5*Math.PI),i.scale(1,-1);break;case 6:i.rotate(.5*Math.PI),i.translate(0,-n);break;case 7:i.rotate(.5*Math.PI),i.translate(a,-n),i.scale(-1,1);break;case 8:i.rotate(-.5*Math.PI),i.translate(-a,0)}},t.renderImageToCanvas=function(e,t,i,a,n,r,o,s,d,l){return e.getContext("2d").drawImage(t,i,a,n,r,o,s,d,l),e},t.scale=function(e,i){i=i||{};var a,n,r,o,s,d,l,c=document.createElement("canvas"),u=e.getContext||(i.canvas||i.crop||i.orientation)&&c.getContext,g=e.width,f=e.height,h=g,m=f,p=0,S=0,x=0,b=0;return u&&i.orientation>4?(a=i.maxHeight,n=i.maxWidth,r=i.minHeight,o=i.minWidth):(a=i.maxWidth,n=i.maxHeight,r=i.minWidth,o=i.minHeight),u&&a&&n&&i.crop?(s=a,d=n,a/n>g/f?(m=n*g/a,S=(f-m)/2):(h=a*f/n,p=(g-h)/2)):(s=g,d=f,l=Math.max((r||s)/s,(o||d)/d),l>1&&(s=Math.ceil(s*l),d=Math.ceil(d*l)),l=Math.min((a||s)/s,(n||d)/d),1>l&&(s=Math.ceil(s*l),d=Math.ceil(d*l))),u?(c.width=s,c.height=d,t.transformCoordinates(c,i.orientation),t.renderImageToCanvas(c,e,p,S,h,m,x,b,s,d)):(e.width=s,e.height=d,e)},t.createObjectURL=function(e){return i?i.createObjectURL(e):!1},t.revokeObjectURL=function(e){return i?i.revokeObjectURL(e):!1},t.readFile=function(e,t,i){if(window.FileReader){var a=new FileReader;if(a.onload=a.onerror=t,i=i||"readAsDataURL",a[i])return a[i](e),a}return!1},"function"==typeof define&&define.amd?define(function(){return t}):e.loadImage=t})(this),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image"],e):e(window.loadImage)}(function(e){"use strict";if(window.navigator&&window.navigator.platform&&/iP(hone|od|ad)/.test(window.navigator.platform)){var t=e.renderImageToCanvas;e.detectSubsampling=function(e){var t,i;return e.width*e.height>1048576?(t=document.createElement("canvas"),t.width=t.height=1,i=t.getContext("2d"),i.drawImage(e,-e.width+1,0),0===i.getImageData(0,0,1,1).data[3]):!1},e.detectVerticalSquash=function(e,t){var i,a,n,r,o,s=document.createElement("canvas"),d=s.getContext("2d");for(s.width=1,s.height=t,d.drawImage(e,0,0),i=d.getImageData(0,0,1,t).data,a=0,n=t,r=t;r>a;)o=i[4*(r-1)+3],0===o?n=r:a=r,r=n+a>>1;return r/t||1},e.renderImageToCanvas=function(i,a,n,r,o,s,d,l,c,u){if("image/jpeg"===a._type){var g,f,h,m,p=i.getContext("2d"),S=document.createElement("canvas"),x=1024,b=S.getContext("2d");if(S.width=x,S.height=x,p.save(),g=e.detectSubsampling(a),g&&(o/=2,s/=2),f=e.detectVerticalSquash(a,s),g&&1!==f){for(c=Math.ceil(x*c/o),u=Math.ceil(x*u/s/f),l=0,m=0;s>m;){for(d=0,h=0;o>h;)b.clearRect(0,0,x,x),b.drawImage(a,n,r,o,s,-h,-m,o,s),p.drawImage(S,0,0,x,x,d,l,c,u),h+=x,d+=c;m+=x,l+=u}return p.restore(),i}}return t(i,a,n,r,o,s,d,l,c,u)}}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image"],e):e(window.loadImage)}(function(e){"use strict";var t=window.Blob&&(Blob.prototype.slice||Blob.prototype.webkitSlice||Blob.prototype.mozSlice);e.blobSlice=t&&function(){var e=this.slice||this.webkitSlice||this.mozSlice;return e.apply(this,arguments)},e.metaDataParsers={jpeg:{65505:[]}},e.parseMetaData=function(t,i,a){a=a||{};var n=this,r=a.maxMetaDataSize||262144,o={},s=!(window.DataView&&t&&t.size>=12&&"image/jpeg"===t.type&&e.blobSlice);(s||!e.readFile(e.blobSlice.call(t,0,r),function(t){var r,s,d,l,c=t.target.result,u=new DataView(c),g=2,f=u.byteLength-4,h=g;if(65496===u.getUint16(0)){for(;f>g&&(r=u.getUint16(g),r>=65504&&65519>=r||65534===r);){if(s=u.getUint16(g+2)+2,g+s>u.byteLength){console.log("Invalid meta data: Invalid segment size.");break}if(d=e.metaDataParsers.jpeg[r])for(l=0;d.length>l;l+=1)d[l].call(n,u,g,s,o,a);g+=s,h=g}!a.disableImageHead&&h>6&&(o.imageHead=c.slice?c.slice(0,h):new Uint8Array(c).subarray(0,h))}else console.log("Invalid JPEG file: Missing JPEG marker.");i(o)},"readAsArrayBuffer"))&&i(o)}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-meta"],e):e(window.loadImage)}(function(e){"use strict";e.ExifMap=function(){return this},e.ExifMap.prototype.map={Orientation:274},e.ExifMap.prototype.get=function(e){return this[e]||this[this.map[e]]},e.getExifThumbnail=function(e,t,i){var a,n,r;if(!i||t+i>e.byteLength)return console.log("Invalid Exif data: Invalid thumbnail data."),void 0;for(a=[],n=0;i>n;n+=1)r=e.getUint8(t+n),a.push((16>r?"0":"")+r.toString(16));return"data:image/jpeg,%"+a.join("%")},e.exifTagTypes={1:{getValue:function(e,t){return e.getUint8(t)},size:1},2:{getValue:function(e,t){return String.fromCharCode(e.getUint8(t))},size:1,ascii:!0},3:{getValue:function(e,t,i){return e.getUint16(t,i)},size:2},4:{getValue:function(e,t,i){return e.getUint32(t,i)},size:4},5:{getValue:function(e,t,i){return e.getUint32(t,i)/e.getUint32(t+4,i)},size:8},9:{getValue:function(e,t,i){return e.getInt32(t,i)},size:4},10:{getValue:function(e,t,i){return e.getInt32(t,i)/e.getInt32(t+4,i)},size:8}},e.exifTagTypes[7]=e.exifTagTypes[1],e.getExifValue=function(t,i,a,n,r,o){var s,d,l,c,u,g,f=e.exifTagTypes[n];if(!f)return console.log("Invalid Exif data: Invalid tag type."),void 0;if(s=f.size*r,d=s>4?i+t.getUint32(a+8,o):a+8,d+s>t.byteLength)return console.log("Invalid Exif data: Invalid data offset."),void 0;if(1===r)return f.getValue(t,d,o);for(l=[],c=0;r>c;c+=1)l[c]=f.getValue(t,d+c*f.size,o);if(f.ascii){for(u="",c=0;l.length>c&&(g=l[c],"\0"!==g);c+=1)u+=g;return u}return l},e.parseExifTag=function(t,i,a,n,r){var o=t.getUint16(a,n);r.exif[o]=e.getExifValue(t,i,a,t.getUint16(a+2,n),t.getUint32(a+4,n),n)},e.parseExifTags=function(e,t,i,a,n){var r,o,s;if(i+6>e.byteLength)return console.log("Invalid Exif data: Invalid directory offset."),void 0;if(r=e.getUint16(i,a),o=i+2+12*r,o+4>e.byteLength)return console.log("Invalid Exif data: Invalid directory size."),void 0;for(s=0;r>s;s+=1)this.parseExifTag(e,t,i+2+12*s,a,n);return e.getUint32(o,a)},e.parseExifData=function(t,i,a,n,r){if(!r.disableExif){var o,s,d,l=i+10;if(1165519206===t.getUint32(i+4)){if(l+8>t.byteLength)return console.log("Invalid Exif data: Invalid segment size."),void 0;if(0!==t.getUint16(i+8))return console.log("Invalid Exif data: Missing byte alignment offset."),void 0;switch(t.getUint16(l)){case 18761:o=!0;break;case 19789:o=!1;break;default:return console.log("Invalid Exif data: Invalid byte alignment marker."),void 0}if(42!==t.getUint16(l+2,o))return console.log("Invalid Exif data: Missing TIFF marker."),void 0;s=t.getUint32(l+4,o),n.exif=new e.ExifMap,s=e.parseExifTags(t,l,l+s,o,n),s&&!r.disableExifThumbnail&&(d={exif:{}},s=e.parseExifTags(t,l,l+s,o,d),d.exif[513]&&(n.exif.Thumbnail=e.getExifThumbnail(t,l+d.exif[513],d.exif[514]))),n.exif[34665]&&!r.disableExifSub&&e.parseExifTags(t,l,l+n.exif[34665],o,n),n.exif[34853]&&!r.disableExifGps&&e.parseExifTags(t,l,l+n.exif[34853],o,n)}}},e.metaDataParsers.jpeg[65505].push(e.parseExifData)}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-exif"],e):e(window.loadImage)}(function(e){"use strict";var t,i,a;e.ExifMap.prototype.tags={256:"ImageWidth",257:"ImageHeight",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer",40965:"InteroperabilityIFDPointer",258:"BitsPerSample",259:"Compression",262:"PhotometricInterpretation",274:"Orientation",277:"SamplesPerPixel",284:"PlanarConfiguration",530:"YCbCrSubSampling",531:"YCbCrPositioning",282:"XResolution",283:"YResolution",296:"ResolutionUnit",273:"StripOffsets",278:"RowsPerStrip",279:"StripByteCounts",513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength",301:"TransferFunction",318:"WhitePoint",319:"PrimaryChromaticities",529:"YCbCrCoefficients",532:"ReferenceBlackWhite",306:"DateTime",270:"ImageDescription",271:"Make",272:"Model",305:"Software",315:"Artist",33432:"Copyright",36864:"ExifVersion",40960:"FlashpixVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",37121:"ComponentsConfiguration",37122:"CompressedBitsPerPixel",37500:"MakerNote",37510:"UserComment",40964:"RelatedSoundFile",36867:"DateTimeOriginal",36868:"DateTimeDigitized",37520:"SubsecTime",37521:"SubsecTimeOriginal",37522:"SubsecTimeDigitized",33434:"ExposureTime",33437:"FNumber",34850:"ExposureProgram",34852:"SpectralSensitivity",34855:"ISOSpeedRatings",34856:"OECF",37377:"ShutterSpeedValue",37378:"ApertureValue",37379:"BrightnessValue",37380:"ExposureBias",37381:"MaxApertureValue",37382:"SubjectDistance",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37396:"SubjectArea",37386:"FocalLength",41483:"FlashEnergy",41484:"SpatialFrequencyResponse",41486:"FocalPlaneXResolution",41487:"FocalPlaneYResolution",41488:"FocalPlaneResolutionUnit",41492:"SubjectLocation",41493:"ExposureIndex",41495:"SensingMethod",41728:"FileSource",41729:"SceneType",41730:"CFAPattern",41985:"CustomRendered",41986:"ExposureMode",41987:"WhiteBalance",41988:"DigitalZoomRation",41989:"FocalLengthIn35mmFilm",41990:"SceneCaptureType",41991:"GainControl",41992:"Contrast",41993:"Saturation",41994:"Sharpness",41995:"DeviceSettingDescription",41996:"SubjectDistanceRange",42016:"ImageUniqueID",0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude",5:"GPSAltitudeRef",6:"GPSAltitude",7:"GPSTimeStamp",8:"GPSSatellites",9:"GPSStatus",10:"GPSMeasureMode",11:"GPSDOP",12:"GPSSpeedRef",13:"GPSSpeed",14:"GPSTrackRef",15:"GPSTrack",16:"GPSImgDirectionRef",17:"GPSImgDirection",18:"GPSMapDatum",19:"GPSDestLatitudeRef",20:"GPSDestLatitude",21:"GPSDestLongitudeRef",22:"GPSDestLongitude",23:"GPSDestBearingRef",24:"GPSDestBearing",25:"GPSDestDistanceRef",26:"GPSDestDistance",27:"GPSProcessingMethod",28:"GPSAreaInformation",29:"GPSDateStamp",30:"GPSDifferential"},e.ExifMap.prototype.stringValues={ExposureProgram:{0:"Undefined",1:"Manual",2:"Normal program",3:"Aperture priority",4:"Shutter priority",5:"Creative program",6:"Action program",7:"Portrait mode",8:"Landscape mode"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{0:"Unknown",1:"Daylight",2:"Fluorescent",3:"Tungsten (incandescent light)",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 - 5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},SensingMethod:{1:"Undefined",2:"One-chip color area sensor",3:"Two-chip color area sensor",4:"Three-chip color area sensor",5:"Color sequential area sensor",7:"Trilinear sensor",8:"Color sequential linear sensor"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},SceneType:{1:"Directly photographed"},CustomRendered:{0:"Normal process",1:"Custom process"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},GainControl:{0:"None",1:"Low gain up",2:"High gain up",3:"Low gain down",4:"High gain down"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},SubjectDistanceRange:{0:"Unknown",1:"Macro",2:"Close view",3:"Distant view"},FileSource:{3:"DSC"},ComponentsConfiguration:{0:"",1:"Y",2:"Cb",3:"Cr",4:"R",5:"G",6:"B"},Orientation:{1:"top-left",2:"top-right",3:"bottom-right",4:"bottom-left",5:"left-top",6:"right-top",7:"right-bottom",8:"left-bottom"}},e.ExifMap.prototype.getText=function(e){var t=this.get(e);switch(e){case"LightSource":case"Flash":case"MeteringMode":case"ExposureProgram":case"SensingMethod":case"SceneCaptureType":case"SceneType":case"CustomRendered":case"WhiteBalance":case"GainControl":case"Contrast":case"Saturation":case"Sharpness":case"SubjectDistanceRange":case"FileSource":case"Orientation":return this.stringValues[e][t];case"ExifVersion":case"FlashpixVersion":return String.fromCharCode(t[0],t[1],t[2],t[3]);case"ComponentsConfiguration":return this.stringValues[e][t[0]]+this.stringValues[e][t[1]]+this.stringValues[e][t[2]]+this.stringValues[e][t[3]];case"GPSVersionID":return t[0]+"."+t[1]+"."+t[2]+"."+t[3]}return t+""},t=e.ExifMap.prototype.tags,i=e.ExifMap.prototype.map;for(a in t)t.hasOwnProperty(a)&&(i[t[a]]=a);e.ExifMap.prototype.getAll=function(){var e,i,a={};for(e in this)this.hasOwnProperty(e)&&(i=t[e],i&&(a[i]=this.getText(i)));return a}});
\ No newline at end of file
diff --git a/package.json b/package.json
index 1c652b3..881e64e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "blueimp-load-image",
- "version": "1.7.0",
+ "version": "1.7.1",
"title": "JavaScript Load Image",
"description": "JavaScript Load Image is a library to load images provided as File or Blob objects or via URL. It returns an optionally scaled and/or cropped HTML img or canvas element. It also provides a method to parse image meta data to extract Exif tags and thumbnails and to restore the complete image header after resizing.",
"keywords": [
From 7ad3b0b41d326c15949838c24ae5fc9edadf8cc6 Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Sun, 16 Jun 2013 22:28:00 -0500
Subject: [PATCH 037/386] Added comment for the maxMetaDataSize option.
---
load-image-meta.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/load-image-meta.js b/load-image-meta.js
index c7e5a20..ab45210 100644
--- a/load-image-meta.js
+++ b/load-image-meta.js
@@ -46,6 +46,7 @@
// with the following properties:
// * imageHead: The complete image head as ArrayBuffer (Uint8Array for IE10)
// The options arguments accepts an object and supports the following properties:
+ // * maxMetaDataSize: Defines the maximum number of bytes to parse.
// * disableImageHead: Disables creating the imageHead property.
loadImage.parseMetaData = function (file, callback, options) {
options = options || {};
From aea610a96cb65dd5eb703f449b91383170f57d9f Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Mon, 17 Jun 2013 09:22:33 -0500
Subject: [PATCH 038/386] Added missing tags for Exif version 2.3. Fixes #25.
---
load-image-exif-map.js | 28 +++++++++++++++++++++-------
load-image.min.js | 2 +-
package.json | 2 +-
3 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/load-image-exif-map.js b/load-image-exif-map.js
index cddc7b0..ef8c6c7 100644
--- a/load-image-exif-map.js
+++ b/load-image-exif-map.js
@@ -1,5 +1,5 @@
/*
- * JavaScript Load Image Exif Map 1.0
+ * JavaScript Load Image Exif Map 1.0.1
* https://github.com/blueimp/JavaScript-Load-Image
*
* Copyright 2013, Sebastian Tschan
@@ -75,6 +75,7 @@
0xA001: 'ColorSpace', // Color space information tag
0xA002: 'PixelXDimension', // Valid width of meaningful image
0xA003: 'PixelYDimension', // Valid height of meaningful image
+ 0xA500: 'Gamma',
0x9101: 'ComponentsConfiguration', // Information about channels
0x9102: 'CompressedBitsPerPixel', // Compressed bits per pixel
0x927C: 'MakerNote', // Any desired information written by the manufacturer
@@ -82,15 +83,21 @@
0xA004: 'RelatedSoundFile', // Name of related sound file
0x9003: 'DateTimeOriginal', // Date and time when the original image was generated
0x9004: 'DateTimeDigitized', // Date and time when the image was stored digitally
- 0x9290: 'SubsecTime', // Fractions of seconds for DateTime
- 0x9291: 'SubsecTimeOriginal', // Fractions of seconds for DateTimeOriginal
- 0x9292: 'SubsecTimeDigitized', // Fractions of seconds for DateTimeDigitized
+ 0x9290: 'SubSecTime', // Fractions of seconds for DateTime
+ 0x9291: 'SubSecTimeOriginal', // Fractions of seconds for DateTimeOriginal
+ 0x9292: 'SubSecTimeDigitized', // Fractions of seconds for DateTimeDigitized
0x829A: 'ExposureTime', // Exposure time (in seconds)
0x829D: 'FNumber',
0x8822: 'ExposureProgram', // Exposure program
0x8824: 'SpectralSensitivity', // Spectral sensitivity
- 0x8827: 'ISOSpeedRatings', // ISO speed rating
+ 0x8827: 'PhotographicSensitivity', // EXIF 2.3, ISOSpeedRatings in EXIF 2.2
0x8828: 'OECF', // Optoelectric conversion factor
+ 0x8830: 'SensitivityType',
+ 0x8831: 'StandardOutputSensitivity',
+ 0x8832: 'RecommendedExposureIndex',
+ 0x8833: 'ISOSpeed',
+ 0x8834: 'ISOSpeedLatitudeyyy',
+ 0x8835: 'ISOSpeedLatitudezzz',
0x9201: 'ShutterSpeedValue', // Shutter speed
0x9202: 'ApertureValue', // Lens aperture
0x9203: 'BrightnessValue', // Value of brightness
@@ -116,7 +123,7 @@
0xA401: 'CustomRendered', // Special processing
0xA402: 'ExposureMode', // Exposure mode
0xA403: 'WhiteBalance', // 1 = auto white balance, 2 = manual
- 0xA404: 'DigitalZoomRation', // Digital zoom ratio
+ 0xA404: 'DigitalZoomRatio', // Digital zoom ratio
0xA405: 'FocalLengthIn35mmFilm',
0xA406: 'SceneCaptureType', // Type of scene
0xA407: 'GainControl', // Degree of overall image gain adjustment
@@ -126,6 +133,12 @@
0xA40B: 'DeviceSettingDescription',
0xA40C: 'SubjectDistanceRange', // Distance to subject
0xA420: 'ImageUniqueID', // Identifier assigned uniquely to each image
+ 0xA430: 'CameraOwnerName',
+ 0xA431: 'BodySerialNumber',
+ 0xA432: 'LensSpecification',
+ 0xA433: 'LensMake',
+ 0xA434: 'LensModel',
+ 0xA435: 'LensSerialNumber',
// ==============
// GPS Info tags:
// ==============
@@ -159,7 +172,8 @@
0x001B: 'GPSProcessingMethod',
0x001C: 'GPSAreaInformation',
0x001D: 'GPSDateStamp',
- 0x001E: 'GPSDifferential'
+ 0x001E: 'GPSDifferential',
+ 0x001F: 'GPSHPositioningError'
};
loadImage.ExifMap.prototype.stringValues = {
diff --git a/load-image.min.js b/load-image.min.js
index a752fb3..11a1ae5 100644
--- a/load-image.min.js
+++ b/load-image.min.js
@@ -1 +1 @@
-(function(e){"use strict";var t=function(e,i,a){var n,r,o=document.createElement("img");if(o.onerror=i,o.onload=function(){!r||a&&a.noRevoke||t.revokeObjectURL(r),i&&i(t.scale(o,a))},t.isInstanceOf("Blob",e)||t.isInstanceOf("File",e))n=r=t.createObjectURL(e),o._type=e.type;else{if("string"!=typeof e)return!1;n=e,a&&a.crossOrigin&&(o.crossOrigin=a.crossOrigin)}return n?(o.src=n,o):t.readFile(e,function(e){var t=e.target;t&&t.result?o.src=t.result:i&&i(e)})},i=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;t.isInstanceOf=function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},t.transformCoordinates=function(e,t){var i=e.getContext("2d"),a=e.width,n=e.height;switch(t>4&&(e.width=n,e.height=a),t){case 2:i.translate(a,0),i.scale(-1,1);break;case 3:i.translate(a,n),i.rotate(Math.PI);break;case 4:i.translate(0,n),i.scale(1,-1);break;case 5:i.rotate(.5*Math.PI),i.scale(1,-1);break;case 6:i.rotate(.5*Math.PI),i.translate(0,-n);break;case 7:i.rotate(.5*Math.PI),i.translate(a,-n),i.scale(-1,1);break;case 8:i.rotate(-.5*Math.PI),i.translate(-a,0)}},t.renderImageToCanvas=function(e,t,i,a,n,r,o,s,d,l){return e.getContext("2d").drawImage(t,i,a,n,r,o,s,d,l),e},t.scale=function(e,i){i=i||{};var a,n,r,o,s,d,l,c=document.createElement("canvas"),u=e.getContext||(i.canvas||i.crop||i.orientation)&&c.getContext,g=e.width,f=e.height,h=g,m=f,p=0,S=0,x=0,b=0;return u&&i.orientation>4?(a=i.maxHeight,n=i.maxWidth,r=i.minHeight,o=i.minWidth):(a=i.maxWidth,n=i.maxHeight,r=i.minWidth,o=i.minHeight),u&&a&&n&&i.crop?(s=a,d=n,a/n>g/f?(m=n*g/a,S=(f-m)/2):(h=a*f/n,p=(g-h)/2)):(s=g,d=f,l=Math.max((r||s)/s,(o||d)/d),l>1&&(s=Math.ceil(s*l),d=Math.ceil(d*l)),l=Math.min((a||s)/s,(n||d)/d),1>l&&(s=Math.ceil(s*l),d=Math.ceil(d*l))),u?(c.width=s,c.height=d,t.transformCoordinates(c,i.orientation),t.renderImageToCanvas(c,e,p,S,h,m,x,b,s,d)):(e.width=s,e.height=d,e)},t.createObjectURL=function(e){return i?i.createObjectURL(e):!1},t.revokeObjectURL=function(e){return i?i.revokeObjectURL(e):!1},t.readFile=function(e,t,i){if(window.FileReader){var a=new FileReader;if(a.onload=a.onerror=t,i=i||"readAsDataURL",a[i])return a[i](e),a}return!1},"function"==typeof define&&define.amd?define(function(){return t}):e.loadImage=t})(this),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image"],e):e(window.loadImage)}(function(e){"use strict";if(window.navigator&&window.navigator.platform&&/iP(hone|od|ad)/.test(window.navigator.platform)){var t=e.renderImageToCanvas;e.detectSubsampling=function(e){var t,i;return e.width*e.height>1048576?(t=document.createElement("canvas"),t.width=t.height=1,i=t.getContext("2d"),i.drawImage(e,-e.width+1,0),0===i.getImageData(0,0,1,1).data[3]):!1},e.detectVerticalSquash=function(e,t){var i,a,n,r,o,s=document.createElement("canvas"),d=s.getContext("2d");for(s.width=1,s.height=t,d.drawImage(e,0,0),i=d.getImageData(0,0,1,t).data,a=0,n=t,r=t;r>a;)o=i[4*(r-1)+3],0===o?n=r:a=r,r=n+a>>1;return r/t||1},e.renderImageToCanvas=function(i,a,n,r,o,s,d,l,c,u){if("image/jpeg"===a._type){var g,f,h,m,p=i.getContext("2d"),S=document.createElement("canvas"),x=1024,b=S.getContext("2d");if(S.width=x,S.height=x,p.save(),g=e.detectSubsampling(a),g&&(o/=2,s/=2),f=e.detectVerticalSquash(a,s),g&&1!==f){for(c=Math.ceil(x*c/o),u=Math.ceil(x*u/s/f),l=0,m=0;s>m;){for(d=0,h=0;o>h;)b.clearRect(0,0,x,x),b.drawImage(a,n,r,o,s,-h,-m,o,s),p.drawImage(S,0,0,x,x,d,l,c,u),h+=x,d+=c;m+=x,l+=u}return p.restore(),i}}return t(i,a,n,r,o,s,d,l,c,u)}}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image"],e):e(window.loadImage)}(function(e){"use strict";var t=window.Blob&&(Blob.prototype.slice||Blob.prototype.webkitSlice||Blob.prototype.mozSlice);e.blobSlice=t&&function(){var e=this.slice||this.webkitSlice||this.mozSlice;return e.apply(this,arguments)},e.metaDataParsers={jpeg:{65505:[]}},e.parseMetaData=function(t,i,a){a=a||{};var n=this,r=a.maxMetaDataSize||262144,o={},s=!(window.DataView&&t&&t.size>=12&&"image/jpeg"===t.type&&e.blobSlice);(s||!e.readFile(e.blobSlice.call(t,0,r),function(t){var r,s,d,l,c=t.target.result,u=new DataView(c),g=2,f=u.byteLength-4,h=g;if(65496===u.getUint16(0)){for(;f>g&&(r=u.getUint16(g),r>=65504&&65519>=r||65534===r);){if(s=u.getUint16(g+2)+2,g+s>u.byteLength){console.log("Invalid meta data: Invalid segment size.");break}if(d=e.metaDataParsers.jpeg[r])for(l=0;d.length>l;l+=1)d[l].call(n,u,g,s,o,a);g+=s,h=g}!a.disableImageHead&&h>6&&(o.imageHead=c.slice?c.slice(0,h):new Uint8Array(c).subarray(0,h))}else console.log("Invalid JPEG file: Missing JPEG marker.");i(o)},"readAsArrayBuffer"))&&i(o)}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-meta"],e):e(window.loadImage)}(function(e){"use strict";e.ExifMap=function(){return this},e.ExifMap.prototype.map={Orientation:274},e.ExifMap.prototype.get=function(e){return this[e]||this[this.map[e]]},e.getExifThumbnail=function(e,t,i){var a,n,r;if(!i||t+i>e.byteLength)return console.log("Invalid Exif data: Invalid thumbnail data."),void 0;for(a=[],n=0;i>n;n+=1)r=e.getUint8(t+n),a.push((16>r?"0":"")+r.toString(16));return"data:image/jpeg,%"+a.join("%")},e.exifTagTypes={1:{getValue:function(e,t){return e.getUint8(t)},size:1},2:{getValue:function(e,t){return String.fromCharCode(e.getUint8(t))},size:1,ascii:!0},3:{getValue:function(e,t,i){return e.getUint16(t,i)},size:2},4:{getValue:function(e,t,i){return e.getUint32(t,i)},size:4},5:{getValue:function(e,t,i){return e.getUint32(t,i)/e.getUint32(t+4,i)},size:8},9:{getValue:function(e,t,i){return e.getInt32(t,i)},size:4},10:{getValue:function(e,t,i){return e.getInt32(t,i)/e.getInt32(t+4,i)},size:8}},e.exifTagTypes[7]=e.exifTagTypes[1],e.getExifValue=function(t,i,a,n,r,o){var s,d,l,c,u,g,f=e.exifTagTypes[n];if(!f)return console.log("Invalid Exif data: Invalid tag type."),void 0;if(s=f.size*r,d=s>4?i+t.getUint32(a+8,o):a+8,d+s>t.byteLength)return console.log("Invalid Exif data: Invalid data offset."),void 0;if(1===r)return f.getValue(t,d,o);for(l=[],c=0;r>c;c+=1)l[c]=f.getValue(t,d+c*f.size,o);if(f.ascii){for(u="",c=0;l.length>c&&(g=l[c],"\0"!==g);c+=1)u+=g;return u}return l},e.parseExifTag=function(t,i,a,n,r){var o=t.getUint16(a,n);r.exif[o]=e.getExifValue(t,i,a,t.getUint16(a+2,n),t.getUint32(a+4,n),n)},e.parseExifTags=function(e,t,i,a,n){var r,o,s;if(i+6>e.byteLength)return console.log("Invalid Exif data: Invalid directory offset."),void 0;if(r=e.getUint16(i,a),o=i+2+12*r,o+4>e.byteLength)return console.log("Invalid Exif data: Invalid directory size."),void 0;for(s=0;r>s;s+=1)this.parseExifTag(e,t,i+2+12*s,a,n);return e.getUint32(o,a)},e.parseExifData=function(t,i,a,n,r){if(!r.disableExif){var o,s,d,l=i+10;if(1165519206===t.getUint32(i+4)){if(l+8>t.byteLength)return console.log("Invalid Exif data: Invalid segment size."),void 0;if(0!==t.getUint16(i+8))return console.log("Invalid Exif data: Missing byte alignment offset."),void 0;switch(t.getUint16(l)){case 18761:o=!0;break;case 19789:o=!1;break;default:return console.log("Invalid Exif data: Invalid byte alignment marker."),void 0}if(42!==t.getUint16(l+2,o))return console.log("Invalid Exif data: Missing TIFF marker."),void 0;s=t.getUint32(l+4,o),n.exif=new e.ExifMap,s=e.parseExifTags(t,l,l+s,o,n),s&&!r.disableExifThumbnail&&(d={exif:{}},s=e.parseExifTags(t,l,l+s,o,d),d.exif[513]&&(n.exif.Thumbnail=e.getExifThumbnail(t,l+d.exif[513],d.exif[514]))),n.exif[34665]&&!r.disableExifSub&&e.parseExifTags(t,l,l+n.exif[34665],o,n),n.exif[34853]&&!r.disableExifGps&&e.parseExifTags(t,l,l+n.exif[34853],o,n)}}},e.metaDataParsers.jpeg[65505].push(e.parseExifData)}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-exif"],e):e(window.loadImage)}(function(e){"use strict";var t,i,a;e.ExifMap.prototype.tags={256:"ImageWidth",257:"ImageHeight",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer",40965:"InteroperabilityIFDPointer",258:"BitsPerSample",259:"Compression",262:"PhotometricInterpretation",274:"Orientation",277:"SamplesPerPixel",284:"PlanarConfiguration",530:"YCbCrSubSampling",531:"YCbCrPositioning",282:"XResolution",283:"YResolution",296:"ResolutionUnit",273:"StripOffsets",278:"RowsPerStrip",279:"StripByteCounts",513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength",301:"TransferFunction",318:"WhitePoint",319:"PrimaryChromaticities",529:"YCbCrCoefficients",532:"ReferenceBlackWhite",306:"DateTime",270:"ImageDescription",271:"Make",272:"Model",305:"Software",315:"Artist",33432:"Copyright",36864:"ExifVersion",40960:"FlashpixVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",37121:"ComponentsConfiguration",37122:"CompressedBitsPerPixel",37500:"MakerNote",37510:"UserComment",40964:"RelatedSoundFile",36867:"DateTimeOriginal",36868:"DateTimeDigitized",37520:"SubsecTime",37521:"SubsecTimeOriginal",37522:"SubsecTimeDigitized",33434:"ExposureTime",33437:"FNumber",34850:"ExposureProgram",34852:"SpectralSensitivity",34855:"ISOSpeedRatings",34856:"OECF",37377:"ShutterSpeedValue",37378:"ApertureValue",37379:"BrightnessValue",37380:"ExposureBias",37381:"MaxApertureValue",37382:"SubjectDistance",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37396:"SubjectArea",37386:"FocalLength",41483:"FlashEnergy",41484:"SpatialFrequencyResponse",41486:"FocalPlaneXResolution",41487:"FocalPlaneYResolution",41488:"FocalPlaneResolutionUnit",41492:"SubjectLocation",41493:"ExposureIndex",41495:"SensingMethod",41728:"FileSource",41729:"SceneType",41730:"CFAPattern",41985:"CustomRendered",41986:"ExposureMode",41987:"WhiteBalance",41988:"DigitalZoomRation",41989:"FocalLengthIn35mmFilm",41990:"SceneCaptureType",41991:"GainControl",41992:"Contrast",41993:"Saturation",41994:"Sharpness",41995:"DeviceSettingDescription",41996:"SubjectDistanceRange",42016:"ImageUniqueID",0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude",5:"GPSAltitudeRef",6:"GPSAltitude",7:"GPSTimeStamp",8:"GPSSatellites",9:"GPSStatus",10:"GPSMeasureMode",11:"GPSDOP",12:"GPSSpeedRef",13:"GPSSpeed",14:"GPSTrackRef",15:"GPSTrack",16:"GPSImgDirectionRef",17:"GPSImgDirection",18:"GPSMapDatum",19:"GPSDestLatitudeRef",20:"GPSDestLatitude",21:"GPSDestLongitudeRef",22:"GPSDestLongitude",23:"GPSDestBearingRef",24:"GPSDestBearing",25:"GPSDestDistanceRef",26:"GPSDestDistance",27:"GPSProcessingMethod",28:"GPSAreaInformation",29:"GPSDateStamp",30:"GPSDifferential"},e.ExifMap.prototype.stringValues={ExposureProgram:{0:"Undefined",1:"Manual",2:"Normal program",3:"Aperture priority",4:"Shutter priority",5:"Creative program",6:"Action program",7:"Portrait mode",8:"Landscape mode"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{0:"Unknown",1:"Daylight",2:"Fluorescent",3:"Tungsten (incandescent light)",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 - 5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},SensingMethod:{1:"Undefined",2:"One-chip color area sensor",3:"Two-chip color area sensor",4:"Three-chip color area sensor",5:"Color sequential area sensor",7:"Trilinear sensor",8:"Color sequential linear sensor"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},SceneType:{1:"Directly photographed"},CustomRendered:{0:"Normal process",1:"Custom process"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},GainControl:{0:"None",1:"Low gain up",2:"High gain up",3:"Low gain down",4:"High gain down"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},SubjectDistanceRange:{0:"Unknown",1:"Macro",2:"Close view",3:"Distant view"},FileSource:{3:"DSC"},ComponentsConfiguration:{0:"",1:"Y",2:"Cb",3:"Cr",4:"R",5:"G",6:"B"},Orientation:{1:"top-left",2:"top-right",3:"bottom-right",4:"bottom-left",5:"left-top",6:"right-top",7:"right-bottom",8:"left-bottom"}},e.ExifMap.prototype.getText=function(e){var t=this.get(e);switch(e){case"LightSource":case"Flash":case"MeteringMode":case"ExposureProgram":case"SensingMethod":case"SceneCaptureType":case"SceneType":case"CustomRendered":case"WhiteBalance":case"GainControl":case"Contrast":case"Saturation":case"Sharpness":case"SubjectDistanceRange":case"FileSource":case"Orientation":return this.stringValues[e][t];case"ExifVersion":case"FlashpixVersion":return String.fromCharCode(t[0],t[1],t[2],t[3]);case"ComponentsConfiguration":return this.stringValues[e][t[0]]+this.stringValues[e][t[1]]+this.stringValues[e][t[2]]+this.stringValues[e][t[3]];case"GPSVersionID":return t[0]+"."+t[1]+"."+t[2]+"."+t[3]}return t+""},t=e.ExifMap.prototype.tags,i=e.ExifMap.prototype.map;for(a in t)t.hasOwnProperty(a)&&(i[t[a]]=a);e.ExifMap.prototype.getAll=function(){var e,i,a={};for(e in this)this.hasOwnProperty(e)&&(i=t[e],i&&(a[i]=this.getText(i)));return a}});
\ No newline at end of file
+(function(e){"use strict";var t=function(e,i,a){var n,r,o=document.createElement("img");if(o.onerror=i,o.onload=function(){!r||a&&a.noRevoke||t.revokeObjectURL(r),i&&i(t.scale(o,a))},t.isInstanceOf("Blob",e)||t.isInstanceOf("File",e))n=r=t.createObjectURL(e),o._type=e.type;else{if("string"!=typeof e)return!1;n=e,a&&a.crossOrigin&&(o.crossOrigin=a.crossOrigin)}return n?(o.src=n,o):t.readFile(e,function(e){var t=e.target;t&&t.result?o.src=t.result:i&&i(e)})},i=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;t.isInstanceOf=function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},t.transformCoordinates=function(e,t){var i=e.getContext("2d"),a=e.width,n=e.height;switch(t>4&&(e.width=n,e.height=a),t){case 2:i.translate(a,0),i.scale(-1,1);break;case 3:i.translate(a,n),i.rotate(Math.PI);break;case 4:i.translate(0,n),i.scale(1,-1);break;case 5:i.rotate(.5*Math.PI),i.scale(1,-1);break;case 6:i.rotate(.5*Math.PI),i.translate(0,-n);break;case 7:i.rotate(.5*Math.PI),i.translate(a,-n),i.scale(-1,1);break;case 8:i.rotate(-.5*Math.PI),i.translate(-a,0)}},t.renderImageToCanvas=function(e,t,i,a,n,r,o,s,d,l){return e.getContext("2d").drawImage(t,i,a,n,r,o,s,d,l),e},t.scale=function(e,i){i=i||{};var a,n,r,o,s,d,l,c=document.createElement("canvas"),u=e.getContext||(i.canvas||i.crop||i.orientation)&&c.getContext,g=e.width,f=e.height,h=g,m=f,p=0,S=0,x=0,y=0;return u&&i.orientation>4?(a=i.maxHeight,n=i.maxWidth,r=i.minHeight,o=i.minWidth):(a=i.maxWidth,n=i.maxHeight,r=i.minWidth,o=i.minHeight),u&&a&&n&&i.crop?(s=a,d=n,a/n>g/f?(m=n*g/a,S=(f-m)/2):(h=a*f/n,p=(g-h)/2)):(s=g,d=f,l=Math.max((r||s)/s,(o||d)/d),l>1&&(s=Math.ceil(s*l),d=Math.ceil(d*l)),l=Math.min((a||s)/s,(n||d)/d),1>l&&(s=Math.ceil(s*l),d=Math.ceil(d*l))),u?(c.width=s,c.height=d,t.transformCoordinates(c,i.orientation),t.renderImageToCanvas(c,e,p,S,h,m,x,y,s,d)):(e.width=s,e.height=d,e)},t.createObjectURL=function(e){return i?i.createObjectURL(e):!1},t.revokeObjectURL=function(e){return i?i.revokeObjectURL(e):!1},t.readFile=function(e,t,i){if(window.FileReader){var a=new FileReader;if(a.onload=a.onerror=t,i=i||"readAsDataURL",a[i])return a[i](e),a}return!1},"function"==typeof define&&define.amd?define(function(){return t}):e.loadImage=t})(this),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image"],e):e(window.loadImage)}(function(e){"use strict";if(window.navigator&&window.navigator.platform&&/iP(hone|od|ad)/.test(window.navigator.platform)){var t=e.renderImageToCanvas;e.detectSubsampling=function(e){var t,i;return e.width*e.height>1048576?(t=document.createElement("canvas"),t.width=t.height=1,i=t.getContext("2d"),i.drawImage(e,-e.width+1,0),0===i.getImageData(0,0,1,1).data[3]):!1},e.detectVerticalSquash=function(e,t){var i,a,n,r,o,s=document.createElement("canvas"),d=s.getContext("2d");for(s.width=1,s.height=t,d.drawImage(e,0,0),i=d.getImageData(0,0,1,t).data,a=0,n=t,r=t;r>a;)o=i[4*(r-1)+3],0===o?n=r:a=r,r=n+a>>1;return r/t||1},e.renderImageToCanvas=function(i,a,n,r,o,s,d,l,c,u){if("image/jpeg"===a._type){var g,f,h,m,p=i.getContext("2d"),S=document.createElement("canvas"),x=1024,y=S.getContext("2d");if(S.width=x,S.height=x,p.save(),g=e.detectSubsampling(a),g&&(o/=2,s/=2),f=e.detectVerticalSquash(a,s),g&&1!==f){for(c=Math.ceil(x*c/o),u=Math.ceil(x*u/s/f),l=0,m=0;s>m;){for(d=0,h=0;o>h;)y.clearRect(0,0,x,x),y.drawImage(a,n,r,o,s,-h,-m,o,s),p.drawImage(S,0,0,x,x,d,l,c,u),h+=x,d+=c;m+=x,l+=u}return p.restore(),i}}return t(i,a,n,r,o,s,d,l,c,u)}}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image"],e):e(window.loadImage)}(function(e){"use strict";var t=window.Blob&&(Blob.prototype.slice||Blob.prototype.webkitSlice||Blob.prototype.mozSlice);e.blobSlice=t&&function(){var e=this.slice||this.webkitSlice||this.mozSlice;return e.apply(this,arguments)},e.metaDataParsers={jpeg:{65505:[]}},e.parseMetaData=function(t,i,a){a=a||{};var n=this,r=a.maxMetaDataSize||262144,o={},s=!(window.DataView&&t&&t.size>=12&&"image/jpeg"===t.type&&e.blobSlice);(s||!e.readFile(e.blobSlice.call(t,0,r),function(t){var r,s,d,l,c=t.target.result,u=new DataView(c),g=2,f=u.byteLength-4,h=g;if(65496===u.getUint16(0)){for(;f>g&&(r=u.getUint16(g),r>=65504&&65519>=r||65534===r);){if(s=u.getUint16(g+2)+2,g+s>u.byteLength){console.log("Invalid meta data: Invalid segment size.");break}if(d=e.metaDataParsers.jpeg[r])for(l=0;d.length>l;l+=1)d[l].call(n,u,g,s,o,a);g+=s,h=g}!a.disableImageHead&&h>6&&(o.imageHead=c.slice?c.slice(0,h):new Uint8Array(c).subarray(0,h))}else console.log("Invalid JPEG file: Missing JPEG marker.");i(o)},"readAsArrayBuffer"))&&i(o)}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-meta"],e):e(window.loadImage)}(function(e){"use strict";e.ExifMap=function(){return this},e.ExifMap.prototype.map={Orientation:274},e.ExifMap.prototype.get=function(e){return this[e]||this[this.map[e]]},e.getExifThumbnail=function(e,t,i){var a,n,r;if(!i||t+i>e.byteLength)return console.log("Invalid Exif data: Invalid thumbnail data."),void 0;for(a=[],n=0;i>n;n+=1)r=e.getUint8(t+n),a.push((16>r?"0":"")+r.toString(16));return"data:image/jpeg,%"+a.join("%")},e.exifTagTypes={1:{getValue:function(e,t){return e.getUint8(t)},size:1},2:{getValue:function(e,t){return String.fromCharCode(e.getUint8(t))},size:1,ascii:!0},3:{getValue:function(e,t,i){return e.getUint16(t,i)},size:2},4:{getValue:function(e,t,i){return e.getUint32(t,i)},size:4},5:{getValue:function(e,t,i){return e.getUint32(t,i)/e.getUint32(t+4,i)},size:8},9:{getValue:function(e,t,i){return e.getInt32(t,i)},size:4},10:{getValue:function(e,t,i){return e.getInt32(t,i)/e.getInt32(t+4,i)},size:8}},e.exifTagTypes[7]=e.exifTagTypes[1],e.getExifValue=function(t,i,a,n,r,o){var s,d,l,c,u,g,f=e.exifTagTypes[n];if(!f)return console.log("Invalid Exif data: Invalid tag type."),void 0;if(s=f.size*r,d=s>4?i+t.getUint32(a+8,o):a+8,d+s>t.byteLength)return console.log("Invalid Exif data: Invalid data offset."),void 0;if(1===r)return f.getValue(t,d,o);for(l=[],c=0;r>c;c+=1)l[c]=f.getValue(t,d+c*f.size,o);if(f.ascii){for(u="",c=0;l.length>c&&(g=l[c],"\0"!==g);c+=1)u+=g;return u}return l},e.parseExifTag=function(t,i,a,n,r){var o=t.getUint16(a,n);r.exif[o]=e.getExifValue(t,i,a,t.getUint16(a+2,n),t.getUint32(a+4,n),n)},e.parseExifTags=function(e,t,i,a,n){var r,o,s;if(i+6>e.byteLength)return console.log("Invalid Exif data: Invalid directory offset."),void 0;if(r=e.getUint16(i,a),o=i+2+12*r,o+4>e.byteLength)return console.log("Invalid Exif data: Invalid directory size."),void 0;for(s=0;r>s;s+=1)this.parseExifTag(e,t,i+2+12*s,a,n);return e.getUint32(o,a)},e.parseExifData=function(t,i,a,n,r){if(!r.disableExif){var o,s,d,l=i+10;if(1165519206===t.getUint32(i+4)){if(l+8>t.byteLength)return console.log("Invalid Exif data: Invalid segment size."),void 0;if(0!==t.getUint16(i+8))return console.log("Invalid Exif data: Missing byte alignment offset."),void 0;switch(t.getUint16(l)){case 18761:o=!0;break;case 19789:o=!1;break;default:return console.log("Invalid Exif data: Invalid byte alignment marker."),void 0}if(42!==t.getUint16(l+2,o))return console.log("Invalid Exif data: Missing TIFF marker."),void 0;s=t.getUint32(l+4,o),n.exif=new e.ExifMap,s=e.parseExifTags(t,l,l+s,o,n),s&&!r.disableExifThumbnail&&(d={exif:{}},s=e.parseExifTags(t,l,l+s,o,d),d.exif[513]&&(n.exif.Thumbnail=e.getExifThumbnail(t,l+d.exif[513],d.exif[514]))),n.exif[34665]&&!r.disableExifSub&&e.parseExifTags(t,l,l+n.exif[34665],o,n),n.exif[34853]&&!r.disableExifGps&&e.parseExifTags(t,l,l+n.exif[34853],o,n)}}},e.metaDataParsers.jpeg[65505].push(e.parseExifData)}),function(e){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-exif"],e):e(window.loadImage)}(function(e){"use strict";var t,i,a;e.ExifMap.prototype.tags={256:"ImageWidth",257:"ImageHeight",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer",40965:"InteroperabilityIFDPointer",258:"BitsPerSample",259:"Compression",262:"PhotometricInterpretation",274:"Orientation",277:"SamplesPerPixel",284:"PlanarConfiguration",530:"YCbCrSubSampling",531:"YCbCrPositioning",282:"XResolution",283:"YResolution",296:"ResolutionUnit",273:"StripOffsets",278:"RowsPerStrip",279:"StripByteCounts",513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength",301:"TransferFunction",318:"WhitePoint",319:"PrimaryChromaticities",529:"YCbCrCoefficients",532:"ReferenceBlackWhite",306:"DateTime",270:"ImageDescription",271:"Make",272:"Model",305:"Software",315:"Artist",33432:"Copyright",36864:"ExifVersion",40960:"FlashpixVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",42240:"Gamma",37121:"ComponentsConfiguration",37122:"CompressedBitsPerPixel",37500:"MakerNote",37510:"UserComment",40964:"RelatedSoundFile",36867:"DateTimeOriginal",36868:"DateTimeDigitized",37520:"SubSecTime",37521:"SubSecTimeOriginal",37522:"SubSecTimeDigitized",33434:"ExposureTime",33437:"FNumber",34850:"ExposureProgram",34852:"SpectralSensitivity",34855:"PhotographicSensitivity",34856:"OECF",34864:"SensitivityType",34865:"StandardOutputSensitivity",34866:"RecommendedExposureIndex",34867:"ISOSpeed",34868:"ISOSpeedLatitudeyyy",34869:"ISOSpeedLatitudezzz",37377:"ShutterSpeedValue",37378:"ApertureValue",37379:"BrightnessValue",37380:"ExposureBias",37381:"MaxApertureValue",37382:"SubjectDistance",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37396:"SubjectArea",37386:"FocalLength",41483:"FlashEnergy",41484:"SpatialFrequencyResponse",41486:"FocalPlaneXResolution",41487:"FocalPlaneYResolution",41488:"FocalPlaneResolutionUnit",41492:"SubjectLocation",41493:"ExposureIndex",41495:"SensingMethod",41728:"FileSource",41729:"SceneType",41730:"CFAPattern",41985:"CustomRendered",41986:"ExposureMode",41987:"WhiteBalance",41988:"DigitalZoomRatio",41989:"FocalLengthIn35mmFilm",41990:"SceneCaptureType",41991:"GainControl",41992:"Contrast",41993:"Saturation",41994:"Sharpness",41995:"DeviceSettingDescription",41996:"SubjectDistanceRange",42016:"ImageUniqueID",42032:"CameraOwnerName",42033:"BodySerialNumber",42034:"LensSpecification",42035:"LensMake",42036:"LensModel",42037:"LensSerialNumber",0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude",5:"GPSAltitudeRef",6:"GPSAltitude",7:"GPSTimeStamp",8:"GPSSatellites",9:"GPSStatus",10:"GPSMeasureMode",11:"GPSDOP",12:"GPSSpeedRef",13:"GPSSpeed",14:"GPSTrackRef",15:"GPSTrack",16:"GPSImgDirectionRef",17:"GPSImgDirection",18:"GPSMapDatum",19:"GPSDestLatitudeRef",20:"GPSDestLatitude",21:"GPSDestLongitudeRef",22:"GPSDestLongitude",23:"GPSDestBearingRef",24:"GPSDestBearing",25:"GPSDestDistanceRef",26:"GPSDestDistance",27:"GPSProcessingMethod",28:"GPSAreaInformation",29:"GPSDateStamp",30:"GPSDifferential",31:"GPSHPositioningError"},e.ExifMap.prototype.stringValues={ExposureProgram:{0:"Undefined",1:"Manual",2:"Normal program",3:"Aperture priority",4:"Shutter priority",5:"Creative program",6:"Action program",7:"Portrait mode",8:"Landscape mode"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{0:"Unknown",1:"Daylight",2:"Fluorescent",3:"Tungsten (incandescent light)",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 - 5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},SensingMethod:{1:"Undefined",2:"One-chip color area sensor",3:"Two-chip color area sensor",4:"Three-chip color area sensor",5:"Color sequential area sensor",7:"Trilinear sensor",8:"Color sequential linear sensor"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},SceneType:{1:"Directly photographed"},CustomRendered:{0:"Normal process",1:"Custom process"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},GainControl:{0:"None",1:"Low gain up",2:"High gain up",3:"Low gain down",4:"High gain down"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},SubjectDistanceRange:{0:"Unknown",1:"Macro",2:"Close view",3:"Distant view"},FileSource:{3:"DSC"},ComponentsConfiguration:{0:"",1:"Y",2:"Cb",3:"Cr",4:"R",5:"G",6:"B"},Orientation:{1:"top-left",2:"top-right",3:"bottom-right",4:"bottom-left",5:"left-top",6:"right-top",7:"right-bottom",8:"left-bottom"}},e.ExifMap.prototype.getText=function(e){var t=this.get(e);switch(e){case"LightSource":case"Flash":case"MeteringMode":case"ExposureProgram":case"SensingMethod":case"SceneCaptureType":case"SceneType":case"CustomRendered":case"WhiteBalance":case"GainControl":case"Contrast":case"Saturation":case"Sharpness":case"SubjectDistanceRange":case"FileSource":case"Orientation":return this.stringValues[e][t];case"ExifVersion":case"FlashpixVersion":return String.fromCharCode(t[0],t[1],t[2],t[3]);case"ComponentsConfiguration":return this.stringValues[e][t[0]]+this.stringValues[e][t[1]]+this.stringValues[e][t[2]]+this.stringValues[e][t[3]];case"GPSVersionID":return t[0]+"."+t[1]+"."+t[2]+"."+t[3]}return t+""},t=e.ExifMap.prototype.tags,i=e.ExifMap.prototype.map;for(a in t)t.hasOwnProperty(a)&&(i[t[a]]=a);e.ExifMap.prototype.getAll=function(){var e,i,a={};for(e in this)this.hasOwnProperty(e)&&(i=t[e],i&&(a[i]=this.getText(i)));return a}});
\ No newline at end of file
diff --git a/package.json b/package.json
index 881e64e..66ec75b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "blueimp-load-image",
- "version": "1.7.1",
+ "version": "1.7.2",
"title": "JavaScript Load Image",
"description": "JavaScript Load Image is a library to load images provided as File or Blob objects or via URL. It returns an optionally scaled and/or cropped HTML img or canvas element. It also provides a method to parse image meta data to extract Exif tags and thumbnails and to restore the complete image header after resizing.",
"keywords": [
From adacaf4e37698979dd13bb7db2790f9c841dd53a Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Wed, 26 Jun 2013 18:35:32 -0500
Subject: [PATCH 039/386] Refactored demo implementation.
Added bower.json.
---
Makefile | 4 +-
README.md | 17 +-
bower.json | 49 +++++
css/demo.css | 71 +++++++
index.html | 180 ++++--------------
js/demo.js | 91 +++++++++
.../load-image-exif-map.js | 0
load-image-exif.js => js/load-image-exif.js | 0
load-image-ios.js => js/load-image-ios.js | 0
load-image-meta.js => js/load-image-meta.js | 0
load-image.js => js/load-image.js | 0
load-image.min.js => js/load-image.min.js | 0
package.json | 6 +-
test/index.html | 16 +-
14 files changed, 272 insertions(+), 162 deletions(-)
create mode 100644 bower.json
create mode 100644 css/demo.css
create mode 100644 js/demo.js
rename load-image-exif-map.js => js/load-image-exif-map.js (100%)
rename load-image-exif.js => js/load-image-exif.js (100%)
rename load-image-ios.js => js/load-image-ios.js (100%)
rename load-image-meta.js => js/load-image-meta.js (100%)
rename load-image.js => js/load-image.js (100%)
rename load-image.min.js => js/load-image.min.js (100%)
diff --git a/Makefile b/Makefile
index 75bdbde..8f917de 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
.PHONY: js
-MINIFY_LIST=load-image.js load-image-ios.js load-image-meta.js load-image-exif.js load-image-exif-map.js
+MINIFY_LIST=js/load-image.js js/load-image-ios.js js/load-image-meta.js js/load-image-exif.js js/load-image-exif-map.js
js:
- node_modules/.bin/uglifyjs ${MINIFY_LIST} -c -m -o load-image.min.js
+ node_modules/.bin/uglifyjs ${MINIFY_LIST} -c -m -o js/load-image.min.js
diff --git a/README.md b/README.md
index 7bfb891..0ea7d3d 100644
--- a/README.md
+++ b/README.md
@@ -3,21 +3,26 @@
## Demo
[JavaScript Load Image Demo](http://blueimp.github.io/JavaScript-Load-Image/)
+## Description
+JavaScript Load Image is a library to load images provided as File or Blob objects or via URL.
+It returns an optionally scaled and/or cropped HTML img or canvas element.
+It also provides a method to parse image meta data to extract Exif tags and thumbnails and to restore the complete image header after resizing.
+
## Setup
Include the (minified) JavaScript Load Image script in your HTML markup:
```html
-
+
```
Or alternatively, choose which components you want to include:
```html
-
-
-
-
-
+
+
+
+
+
```
## Usage
diff --git a/bower.json b/bower.json
new file mode 100644
index 0000000..be9bb7e
--- /dev/null
+++ b/bower.json
@@ -0,0 +1,49 @@
+{
+ "name": "blueimp-load-image",
+ "version": "1.7.3",
+ "title": "JavaScript Load Image",
+ "description": "JavaScript Load Image is a library to load images provided as File or Blob objects or via URL. It returns an optionally scaled and/or cropped HTML img or canvas element. It also provides a method to parse image meta data to extract Exif tags and thumbnails and to restore the complete image header after resizing.",
+ "keywords": [
+ "javascript",
+ "load",
+ "loading",
+ "image",
+ "file",
+ "blob",
+ "url",
+ "scale",
+ "crop",
+ "img",
+ "canvas",
+ "meta",
+ "exif",
+ "thumbnail",
+ "resizing"
+ ],
+ "homepage": "https://github.com/blueimp/JavaScript-Load-Image",
+ "author": {
+ "name": "Sebastian Tschan",
+ "url": "https://blueimp.net/"
+ },
+ "maintainers": [
+ {
+ "name": "Sebastian Tschan",
+ "url": "https://blueimp.net/"
+ }
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/blueimp/JavaScript-Load-Image.git"
+ },
+ "devDependencies": {
+ "uglify-js": "2.3.6"
+ },
+ "bugs": "https://github.com/blueimp/JavaScript-Load-Image/issues",
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": "http://www.opensource.org/licenses/MIT"
+ }
+ ],
+ "main": "js/load-image.js"
+}
diff --git a/css/demo.css b/css/demo.css
new file mode 100644
index 0000000..6916292
--- /dev/null
+++ b/css/demo.css
@@ -0,0 +1,71 @@
+/*
+ * JavaScript Load Image Demo CSS 1.7.3
+ * https://github.com/blueimp/JavaScript-Load-Image
+ *
+ * Copyright 2013, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+body {
+ max-width: 750px;
+ margin: 0 auto;
+ padding: 1em;
+ font-family: 'Lucida Grande', 'Lucida Sans Unicode', Arial, sans-serif;
+ font-size: 1em;
+ line-height: 1.4em;
+ background: #222;
+ color: #fff;
+ -webkit-text-size-adjust: 100%;
+ -ms-text-size-adjust: 100%;
+}
+a {
+ color: orange;
+ text-decoration: none;
+}
+img {
+ border: 0;
+ vertical-align: middle;
+}
+h1 {
+ line-height: 1em;
+}
+table {
+ width: 100%;
+ word-wrap: break-word;
+ table-layout: fixed;
+ border-collapse: collapse;
+}
+tr {
+ background: #fff;
+ color: #222;
+}
+tr:nth-child(odd) {
+ background: #eee;
+ color: #222;
+}
+td {
+ padding: 10px;
+}
+.result,
+.thumbnail {
+ padding: 20px;
+ background: #fff;
+ color: #222;
+ text-align: center;
+}
+
+@media (min-width: 481px) {
+ .navigation {
+ list-style: none;
+ padding: 0;
+ }
+ .navigation li {
+ display: inline-block;
+ }
+ .navigation li:not(:first-child):before {
+ content: '| ';
+ }
+}
diff --git a/index.html b/index.html
index 1207e0e..9faef1f 100644
--- a/index.html
+++ b/index.html
@@ -1,7 +1,7 @@
-
+
JavaScript Load Image
-
-
-
-
+
-
-
+
JavaScript Load Image Demo
+
JavaScript Load Image is a library to load images provided as File or Blob objects or via URL.
+It returns an optionally scaled and/or cropped HTML img or canvas element.
+It also provides a method to parse image meta data to extract Exif tags and thumbnails and to restore the complete image header after resizing.
+
+
Select an image file
+
+
Or drag & drop an image file onto this webpage.
+
+
Result
+
+
This demo works only in browsers with support for the URL or FileReader API.
-
-
-
- JavaScript Load Image is a library to load images provided as File or Blob objects or via URL.
- It returns an optionally scaled and/or cropped HTML img or canvas element.
- It also provides a method to parse image meta data to extract Exif tags and thumbnails and to restore the complete image header after resizing.
-
-
-
-
-
Select an image file
-
-
Notice Or drag & drop an image file onto this webpage.
-
-
-
-
-
Result
-
Notice This demo works only in browsers with support for the URL or FileReader API.
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
diff --git a/js/demo.js b/js/demo.js
new file mode 100644
index 0000000..124386b
--- /dev/null
+++ b/js/demo.js
@@ -0,0 +1,91 @@
+/*
+ * JavaScript Load Image Demo JS 1.7.3
+ * https://github.com/blueimp/JavaScript-Load-Image
+ *
+ * Copyright 2013, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+/*global window, document, HTMLCanvasElement, $ */
+
+$(function () {
+ 'use strict';
+
+ var result = $('#result'),
+ exifNode = $('#exif'),
+ thumbNode = $('#thumbnail'),
+ displayImage = function (file, options) {
+ if (!window.loadImage(
+ file,
+ function (img) {
+ if (!(img.src || img instanceof HTMLCanvasElement)) {
+ img = $('
Loading image file failed ');
+ }
+ result.children().replaceWith(img);
+ },
+ options
+ )) {
+ result.children().replaceWith(
+ $('
Your browser does not support the URL or FileReader API. ')
+ );
+ }
+ },
+ displayExifData = function (exif) {
+ var thumbnail = exif.get('Thumbnail'),
+ tags = exif.getAll(),
+ table = exifNode.find('table').empty(),
+ row = $('
'),
+ cell = $('
'),
+ prop;
+ if (thumbnail) {
+ thumbNode.empty();
+ window.loadImage(thumbnail, function (img) {
+ thumbNode.append(img).show();
+ }, {orientation: exif.get('Orientation')});
+ }
+ for (prop in tags) {
+ if (tags.hasOwnProperty(prop)) {
+ table.append(
+ row.clone()
+ .append(cell.clone().text(prop))
+ .append(cell.clone().text(tags[prop]))
+ );
+ }
+ }
+ exifNode.show();
+ },
+ dropChangeHandler = function (e) {
+ e.preventDefault();
+ e = e.originalEvent;
+ var target = e.dataTransfer || e.target,
+ file = target && target.files && target.files[0],
+ options = {
+ maxWidth: result.children().outerWidth(),
+ canvas: true
+ };
+ if (!file) {
+ return;
+ }
+ exifNode.hide();
+ thumbNode.hide();
+ window.loadImage.parseMetaData(file, function (data) {
+ if (data.exif) {
+ options.orientation = data.exif.get('Orientation');
+ displayExifData(data.exif);
+ }
+ displayImage(file, options);
+ });
+ };
+ $(document)
+ .on('dragover', function (e) {
+ e.preventDefault();
+ e = e.originalEvent;
+ e.dataTransfer.dropEffect = 'copy';
+ })
+ .on('drop', dropChangeHandler);
+ $('#file-input').on('change', dropChangeHandler);
+
+});
diff --git a/load-image-exif-map.js b/js/load-image-exif-map.js
similarity index 100%
rename from load-image-exif-map.js
rename to js/load-image-exif-map.js
diff --git a/load-image-exif.js b/js/load-image-exif.js
similarity index 100%
rename from load-image-exif.js
rename to js/load-image-exif.js
diff --git a/load-image-ios.js b/js/load-image-ios.js
similarity index 100%
rename from load-image-ios.js
rename to js/load-image-ios.js
diff --git a/load-image-meta.js b/js/load-image-meta.js
similarity index 100%
rename from load-image-meta.js
rename to js/load-image-meta.js
diff --git a/load-image.js b/js/load-image.js
similarity index 100%
rename from load-image.js
rename to js/load-image.js
diff --git a/load-image.min.js b/js/load-image.min.js
similarity index 100%
rename from load-image.min.js
rename to js/load-image.min.js
diff --git a/package.json b/package.json
index 66ec75b..be9bb7e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "blueimp-load-image",
- "version": "1.7.2",
+ "version": "1.7.3",
"title": "JavaScript Load Image",
"description": "JavaScript Load Image is a library to load images provided as File or Blob objects or via URL. It returns an optionally scaled and/or cropped HTML img or canvas element. It also provides a method to parse image meta data to extract Exif tags and thumbnails and to restore the complete image header after resizing.",
"keywords": [
@@ -36,7 +36,7 @@
"url": "git://github.com/blueimp/JavaScript-Load-Image.git"
},
"devDependencies": {
- "uglify-js": "2.2.5"
+ "uglify-js": "2.3.6"
},
"bugs": "https://github.com/blueimp/JavaScript-Load-Image/issues",
"licenses": [
@@ -45,5 +45,5 @@
"url": "http://www.opensource.org/licenses/MIT"
}
],
- "main": "load-image.js"
+ "main": "js/load-image.js"
}
diff --git a/test/index.html b/test/index.html
index f23a10a..77c45e7 100644
--- a/test/index.html
+++ b/test/index.html
@@ -1,7 +1,7 @@
-
+
JavaScript Load Image Test
@@ -31,11 +33,11 @@
});
-
-
-
-
-
+
+
+
+
+
From 75eb5b4b0fa4189152ed07ce45421cf0660b045d Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Wed, 26 Jun 2013 18:49:13 -0500
Subject: [PATCH 040/386] Updated path to canvas.toBlob polyfill library.
---
test/index.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/index.html b/test/index.html
index 77c45e7..441e5c6 100644
--- a/test/index.html
+++ b/test/index.html
@@ -32,7 +32,7 @@
mocha.run();
});
-
+
From 9803142efb33de3c6d35dd78708c4b38ce93a840 Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Wed, 3 Jul 2013 14:34:11 -0500
Subject: [PATCH 041/386] Added contain and cover options. Closes #30.
---
README.md | 15 ++--
bower.json | 10 ++-
css/demo.css | 2 +-
index.html | 2 +-
js/demo.js | 2 +-
js/load-image-exif.js | 2 +-
js/load-image-ios.js | 2 +-
js/load-image.js | 48 +++++++----
js/load-image.min.js | 2 +-
package.json | 4 +-
test/index.html | 10 +--
test/test.js | 193 ++++++++++++++++++++++++++----------------
12 files changed, 180 insertions(+), 112 deletions(-)
diff --git a/README.md b/README.md
index 0ea7d3d..ff191e2 100644
--- a/README.md
+++ b/README.md
@@ -117,9 +117,15 @@ The optional third argument to **loadImage()** is a map of options:
* **maxHeight**: Defines the maximum height of the img/canvas element.
* **minWidth**: Defines the minimum width of the img/canvas element.
* **minHeight**: Defines the minimum height of the img/canvas element.
-* **crop**: Defines if the canvas element should be cropped to the maxWidth/maxHeight constraints.
-* **orientation**: Allows to transform the canvas coordinates according to the EXIF orientation specification.
-* **canvas**: Defines if the returned element should be a [canvas](https://developer.mozilla.org/en/HTML/Canvas) element.
+* **contain**: Scales the image up/down to contain it in the max dimensions if set to *true*.
+This emulates the CSS feature [background-image: contain](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Scaling_background_images#contain).
+* **cover**: Scales the image up/down to cover the max dimensions with the image dimensions if set to *true*.
+This emulates the CSS feature [background-image: cover](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Scaling_background_images#cover).
+* **crop**: Crops the image to the maxWidth/maxHeight constraints if set to *true*.
+This feature assumes *canvas: true*.
+* **orientation**: Allows to transform the canvas coordinates according to the EXIF orientation specification.
+This feature assumes *canvas: true*.
+* **canvas**: Returns the image as [canvas](https://developer.mozilla.org/en/HTML/Canvas) element if set to *true*.
* **crossOrigin**: Sets the crossOrigin property on the img element for loading [CORS enabled images](https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image).
* **noRevoke**: By default, the [created object URL](https://developer.mozilla.org/en/DOM/window.URL.createObjectURL) is revoked after the image has been loaded, except when this option is set to *true*.
@@ -136,8 +142,7 @@ loadImage(
maxHeight: 300,
minWidth: 100,
minHeight: 50,
- canvas: true,
- noRevoke: true
+ canvas: true
}
);
```
diff --git a/bower.json b/bower.json
index be9bb7e..197d395 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
{
"name": "blueimp-load-image",
- "version": "1.7.3",
+ "version": "1.8.0",
"title": "JavaScript Load Image",
"description": "JavaScript Load Image is a library to load images provided as File or Blob objects or via URL. It returns an optionally scaled and/or cropped HTML img or canvas element. It also provides a method to parse image meta data to extract Exif tags and thumbnails and to restore the complete image header after resizing.",
"keywords": [
@@ -45,5 +45,11 @@
"url": "http://www.opensource.org/licenses/MIT"
}
],
- "main": "js/load-image.js"
+ "main": [
+ "./js/load-image.js",
+ "./js/load-image-ios.js",
+ "./js/load-image-meta.js",
+ "./js/load-image-exif.js",
+ "./js/load-image-exif-map.js"
+ ]
}
diff --git a/css/demo.css b/css/demo.css
index 6916292..2e2da2c 100644
--- a/css/demo.css
+++ b/css/demo.css
@@ -1,5 +1,5 @@
/*
- * JavaScript Load Image Demo CSS 1.7.3
+ * JavaScript Load Image Demo CSS 1.8.0
* https://github.com/blueimp/JavaScript-Load-Image
*
* Copyright 2013, Sebastian Tschan
diff --git a/index.html b/index.html
index 9faef1f..017b1e5 100644
--- a/index.html
+++ b/index.html
@@ -1,7 +1,7 @@
+
@@ -34,11 +36,16 @@ JavaScript Load Image Demo
Test
© Sebastian Tschan
+
Select an image file
Or drag & drop an image file onto this webpage.
Result
+
+ Edit
+ Crop
+
This demo works only in browsers with support for the URL or FileReader API.
@@ -51,11 +58,13 @@ Exif meta data
+
-
+
+