UNPKG

fix-orientation

Version:

Rotate images if their exif data says so.

1,735 lines (1,634 loc) 53.7 kB
;(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"