From c9df5827491ea81979d5934abafb6439685a1548 Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Tue, 12 Mar 2013 00:47:13 +0100
Subject: [PATCH 001/380] Prevent division by zero.
See
https://github.com/stomita/ios-imagefile-megapixel/commit/5b2252cc14d412
24682f06c098c1b44fef0258d5
---
load-image.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/load-image.js b/load-image.js
index dc70408..22bde9f 100644
--- a/load-image.js
+++ b/load-image.js
@@ -106,7 +106,7 @@
}
py = (ey + sy) >> 1;
}
- return py / ih;
+ return (py / ih) || 1;
};
// Renders image to canvas while working around iOS image scaling bugs:
From 4a426d923ce53da512d60ef33fe3cb6460f0ab4d Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Tue, 12 Mar 2013 00:48:40 +0100
Subject: [PATCH 002/380] Use the faster bitwise operator instead of Math.floor
and parseInt.
See
https://github.com/stomita/ios-imagefile-megapixel/commit/a8a96e47bb25c6
ad59f84a9144a38198ce974cfc
and http://jsperf.com/math-floor-vs-math-round-vs-parseint/33
---
load-image.js | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/load-image.js b/load-image.js
index 22bde9f..8abc77f 100644
--- a/load-image.js
+++ b/load-image.js
@@ -145,8 +145,8 @@
0,
sw,
sh,
- Math.floor(sx * width / iw),
- Math.floor(sy * height / ih / vertSquashRatio),
+ (sx * width / iw) << 0,
+ (sy * height / ih / vertSquashRatio) << 0,
Math.ceil(sw * width / iw),
Math.ceil(sh * height / ih / vertSquashRatio)
);
@@ -173,16 +173,16 @@
(options.minHeight || height) / height
);
if (scale > 1) {
- width = parseInt(width * scale, 10);
- height = parseInt(height * scale, 10);
+ width = (width * scale) << 0;
+ height = (height * scale) << 0;
}
scale = Math.min(
(options.maxWidth || width) / width,
(options.maxHeight || height) / height
);
if (scale < 1) {
- width = parseInt(width * scale, 10);
- height = parseInt(height * scale, 10);
+ width = (width * scale) << 0;
+ height = (height * scale) << 0;
}
if (img.getContext || (options.canvas && canvas.getContext)) {
canvas.width = width;
From 501069034f963d246b99ff80499c45ed4e6441aa Mon Sep 17 00:00:00 2001
From: Sebastian Tschan
Date: Wed, 13 Mar 2013 10:09:45 +0100
Subject: [PATCH 003/380] Update demo jQuery version to 1.9.1.
---
index.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/index.html b/index.html
index 7440537..f19eee5 100644
--- a/index.html
+++ b/index.html
@@ -71,7 +71,7 @@ Result
-
+
+
@@ -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 016/380] 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 017/380] 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 018/380] 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 019/380] 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 020/380] 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 021/380] 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 022/380] 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 023/380] 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 024/380] 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 025/380] 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
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+