fix-orientation
Version:
Rotate images if their exif data says so.
1,735 lines (1,634 loc) • 53.7 kB
JavaScript
;(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
var fixOrientation = require('..');
var input = document.createElement('input');
input.type = 'file';
input.accept = 'image/*';
input.capture = 'camera';
window.onload = function () {
document.body.appendChild(input);
};
input.onchange = function (ev) {
var file = ev.target.files[0];
var reader = new FileReader();
reader.onload = function (ev) {
var url = ev.target.result;
fixOrientation(url, { image: true }, function (fixed, image) {
var img = new Image();
img.src = fixed;
document.body.appendChild(img);
document.body.appendChild(image);
});
}
reader.readAsDataURL(file);
};
},{"..":2}],2:[function(require,module,exports){
(function(){var process = require('process');
var exif = require('exif-component');
var toArray = require('data-uri-to-u8');
var rotate = require('rotate-component');
var resize = require('./lib/resize');
var urlToImage = require('./lib/url-to-image');
var size = {
'image/png': require('png-size'),
'image/jpeg': require('jpeg-size')
};
module.exports = fixOrientation;
function fixOrientation (url, opts, fn) {
if (typeof opts == 'function') {
fn = opts;
opts = {};
}
var buf = toArray(url);
var tags = {};
try { tags = exif(buf.buffer) } catch (err) {}
var toRotate = tags.Orientation
&& typeof tags.Orientation.value == 'number'
&& tags.Orientation.value == 6;
alert(toRotate);
if (!toRotate) {
process.nextTick(function () {
fn(url, opts.image && urlToImage(url));
});
return;
}
var s = size[buf.type](buf);
var max = Math.max(s.width, s.height);
var half = max / 2;
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = max;
rotate(ctx, { x: half, y: half, degrees: 90 });
urlToImage(url, function (img) {
ctx.drawImage(img, 0, max / 4);
rotate(ctx, { x: half, y: half, degrees: -90 });
resize(canvas, {
max: max,
width: s.height,
height: s.width
});
var url = canvas.toDataURL();
fn(url, opts.image && urlToImage(url));
});
}
})()
},{"./lib/resize":3,"./lib/url-to-image":4,"data-uri-to-u8":5,"exif-component":6,"jpeg-size":8,"png-size":9,"process":12,"rotate-component":10}],3:[function(require,module,exports){
module.exports = resize;
function resize (canvas, o) {
var ctx = canvas.getContext('2d');
var imgData = ctx.getImageData(0, 0, o.max, o.max);
canvas.width = o.width;
canvas.height = o.height;
ctx.putImageData(imgData, 0, 0);
}
},{}],4:[function(require,module,exports){
module.exports = urlToImage;
function urlToImage (url, fn) {
var img = new Image();
if (fn) img.onload = fn.bind(null, img);
img.src = url;
return img;
}
},{}],5:[function(require,module,exports){
/**
* Return a `Blob` for the given data `uri`.
*
* @param {String} uri
* @return {Blob}
* @api public
*/
module.exports = function(uri){
var data = uri.split(',')[1];
var bytes = atob(data);
var buf = new ArrayBuffer(bytes.length);
var arr = new Uint8Array(buf);
for (var i = 0; i < bytes.length; i++) {
arr[i] = bytes.charCodeAt(i);
}
arr.type = mime(uri);
return arr;
};
/**
* Return data uri mime type.
*/
function mime(uri) {
return uri.split(';')[0].slice(5);
}
},{}],6:[function(require,module,exports){
/**
* Module dependencies.
*/
var ExifReader = require('./js/ExifReader').ExifReader;
/**
* Parse EXIF tags in `buf`.
*
* @param {ArrayBuffer} buf
* @return {Object}
* @api public
*/
module.exports = function(buf){
var exif = new ExifReader;
exif.load(buf);
return exif.getAllTags();
};
},{"./js/ExifReader":7}],7:[function(require,module,exports){
(function(){(function() {
/*
# ExifReader 0.1
# http://github.com/mattiasw/exifreader
# Copyright (C) 2011 Mattias Wallander <mattias@wallander.eu>
# Licensed under the GNU Lesser General Public License version 3 or later
# See license text at http://www.gnu.org/licenses/lgpl.txt
*/ var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
(typeof exports !== "undefined" && exports !== null ? exports : this).ExifReader = (function() {
ExifReader.prototype._tiffHeaderOffset = 0x0c;
function ExifReader() {
this._getTagValueAt = {
1: __bind(function(offset) {
return this._getByteAt(offset);
}, this),
2: __bind(function(offset) {
return this._getAsciiAt(offset);
}, this),
3: __bind(function(offset) {
return this._getShortAt(offset);
}, this),
4: __bind(function(offset) {
return this._getLongAt(offset);
}, this),
5: __bind(function(offset) {
return this._getRationalAt(offset);
}, this),
7: __bind(function(offset) {
return this._getUndefinedAt(offset);
}, this),
9: __bind(function(offset) {
return this._getSlongAt(offset);
}, this),
10: __bind(function(offset) {
return this._getSrationalAt(offset);
}, this)
};
}
/*
# 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() {
if (this._dataView.byteLength < 12 || this._dataView.getUint32(0, false) !== 0xffd8ffe1 || this._dataView.getUint32(6, false) !== 0x45786966 || this._dataView.getUint16(10, false) !== 0x0000) {
throw 'Invalid image format or 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, _results;
numberOfFields = this._getShortAt(offset);
offset += 2;
_results = [];
for (fieldIndex = 0; 0 <= numberOfFields ? fieldIndex < numberOfFields : fieldIndex > numberOfFields; 0 <= numberOfFields ? fieldIndex++ : fieldIndex--) {
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 _results;
_results = [];
for (valueIndex = 0; 0 <= count ? valueIndex < count : valueIndex > count; 0 <= count ? valueIndex++ : valueIndex--) {
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];
break;
case 3:
return "Circle; X: " + value[0] + ", Y: " + value[1] + ", diameter: " + value[2];
break;
case 4:
return "Rectangle; X: " + value[0] + ", Y: " + value[1] + ", width: " + value[2] + ", height: " + value[3];
break;
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, _ref2;
if ((value[0] === (_ref = value[1]) && _ref === 2) && (value[2] === (_ref2 = value[3]) && _ref2 === 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 _ref, _results;
_results = [];
for (i = 0, _ref = 2 - ('' + Math.floor(num)).length; 0 <= _ref ? i < _ref : i > _ref; 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);
})()
},{}],8:[function(require,module,exports){
(function(){
module.exports = size;
/**
* Start of frame markers.
*/
var sof = {
0xc0: true,
0xc1: true,
0xc2: true,
0xc3: true,
0xc5: true,
0xc6: true,
0xc7: true,
0xc9: true,
0xca: true,
0xcb: true,
0xcd: true,
0xce: true,
0xcf: true
};
/**
* Uint16BE.
*/
function u16(buf, o) {
return buf[o] << 8 | buf[o + 1];
}
/**
* Return dimensions from jpeg `buf`.
*
* @param {Buffer} buf
* @return {Object} or undefined
* @api public
*/
function size(buf) {
var len = buf.length;
var o = 0;
// magick
var jpeg = 0xff == buf[0] && 0xd8 == buf[1];
if (!jpeg) return;
o += 2;
while (o < len) {
// find next marker
while (0xff != buf[o]) o++;
// skip marker
while (0xff == buf[o]) o++;
// non-SOF jump to the next marker
if (!sof[buf[o]]) {
o += u16(buf, ++o);
continue;
}
var w = u16(buf, o + 6);
var h = u16(buf, o + 4);
return { width: w, height: h };
}
}
})()
},{}],9:[function(require,module,exports){
(function(){
/**
* Expose `size`.
*/
module.exports = size;
/**
* Uint32BE.
*/
function u32(buf, o) {
return buf[o] << 24
| buf[o + 1] << 16
| buf[o + 2] << 8
| buf[o + 3];
}
/**
* Return dimensions from png `buf`.
*
* @param {Buffer} buf
* @return {Object}
* @api public
*/
function size(buf) {
return {
width: u32(buf, 16),
height: u32(buf, 16 + 4)
}
}
})()
},{}],10:[function(require,module,exports){
module.exports = function(ctx, o){
var x = o.x || 0;
var y = o.y || 0;
if (o.degrees) {
o.radians = o.degrees * (Math.PI / 180);
}
ctx.translate(x, y);
ctx.rotate(o.radians);
ctx.translate(-x, -y);
};
},{}],11:[function(require,module,exports){
(function(process){function filter (xs, fn) {
var res = [];
for (var i = 0; i < xs.length; i++) {
if (fn(xs[i], i, xs)) res.push(xs[i]);
}
return res;
}
// resolves . and .. elements in a path array with directory names there
// must be no slashes, empty elements, or device names (c:\) in the array
// (so also no leading and trailing slashes - it does not distinguish
// relative and absolute paths)
function normalizeArray(parts, allowAboveRoot) {
// if the path tries to go above the root, `up` ends up > 0
var up = 0;
for (var i = parts.length; i >= 0; i--) {
var last = parts[i];
if (last == '.') {
parts.splice(i, 1);
} else if (last === '..') {
parts.splice(i, 1);
up++;
} else if (up) {
parts.splice(i, 1);
up--;
}
}
// if the path is allowed to go above the root, restore leading ..s
if (allowAboveRoot) {
for (; up--; up) {
parts.unshift('..');
}
}
return parts;
}
// Regex to split a filename into [*, dir, basename, ext]
// posix version
var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;
// path.resolve([from ...], to)
// posix version
exports.resolve = function() {
var resolvedPath = '',
resolvedAbsolute = false;
for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) {
var path = (i >= 0)
? arguments[i]
: process.cwd();
// Skip empty and invalid entries
if (typeof path !== 'string' || !path) {
continue;
}
resolvedPath = path + '/' + resolvedPath;
resolvedAbsolute = path.charAt(0) === '/';
}
// At this point the path should be resolved to a full absolute path, but
// handle relative paths to be safe (might happen when process.cwd() fails)
// Normalize the path
resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
return !!p;
}), !resolvedAbsolute).join('/');
return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
};
// path.normalize(path)
// posix version
exports.normalize = function(path) {
var isAbsolute = path.charAt(0) === '/',
trailingSlash = path.slice(-1) === '/';
// Normalize the path
path = normalizeArray(filter(path.split('/'), function(p) {
return !!p;
}), !isAbsolute).join('/');
if (!path && !isAbsolute) {
path = '.';
}
if (path && trailingSlash) {
path += '/';
}
return (isAbsolute ? '/' : '') + path;
};
// posix version
exports.join = function() {
var paths = Array.prototype.slice.call(arguments, 0);
return exports.normalize(filter(paths, function(p, index) {
return p && typeof p === 'string';
}).join('/'));
};
exports.dirname = function(path) {
var dir = splitPathRe.exec(path)[1] || '';
var isWindows = false;
if (!dir) {
// No dirname
return '.';
} else if (dir.length === 1 ||
(isWindows && dir.length <= 3 && dir.charAt(1) === ':')) {
// It is just a slash or a drive letter with a slash
return dir;
} else {
// It is a full dirname, strip trailing slash
return dir.substring(0, dir.length - 1);
}
};
exports.basename = function(path, ext) {
var f = splitPathRe.exec(path)[2] || '';
// TODO: make this comparison case-insensitive on windows?
if (ext && f.substr(-1 * ext.length) === ext) {
f = f.substr(0, f.length - ext.length);
}
return f;
};
exports.extname = function(path) {
return splitPathRe.exec(path)[3] || '';
};
exports.relative = function(from, to) {
from = exports.resolve(from).substr(1);
to = exports.resolve(to).substr(1);
function trim(arr) {
var start = 0;
for (; start < arr.length; start++) {
if (arr[start] !== '') break;
}
var end = arr.length - 1;
for (; end >= 0; end--) {
if (arr[end] !== '') break;
}
if (start > end) return [];
return arr.slice(start, end - start + 1);
}
var fromParts = trim(from.split('/'));
var toParts = trim(to.split('/'));
var length = Math.min(fromParts.length, toParts.length);
var samePartsLength = length;
for (var i = 0; i < length; i++) {
if (fromParts[i] !== toParts[i]) {
samePartsLength = i;
break;
}
}
var outputParts = [];
for (var i = samePartsLength; i < fromParts.length; i++) {
outputParts.push('..');
}
outputParts = outputParts.concat(toParts.slice(samePartsLength));
return outputParts.join('/');
};
})(require("__browserify_process"))
},{"__browserify_process":14}],12:[function(require,module,exports){
(function(){var process = module.exports = {};
process.nextTick = (function () {
var canSetImmediate = typeof window !== 'undefined'
&& window.setImmediate;
var canPost = typeof window !== 'undefined'
&& window.postMessage && window.addEventListener
;
if (canSetImmediate) {
return function (f) { return window.setImmediate(f) };
}
if (canPost) {
var queue = [];
window.addEventListener('message', function (ev) {
if (ev.source === window && ev.data === 'browserify-tick') {
ev.stopPropagation();
if (queue.length > 0) {
var fn = queue.shift();
fn();
}
}
}, true);
return function nextTick(fn) {
queue.push(fn);
window.postMessage('browserify-tick', '*');
};
}
return function nextTick(fn) {
setTimeout(fn, 0);
};
})();
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.binding = function (name) {
if (name === 'evals') return (require)('vm')
else throw new Error('No such module. (Possibly not yet loaded)')
};
(function () {
var cwd = '/';
var path;
process.cwd = function () { return cwd };
process.chdir = function (dir) {
if (!path) path = require('path');
cwd = path.resolve(dir, cwd);
};
})();
})()
},{"path"