123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- /*jslint browser: true, devel: true, bitwise: false, debug: true, eqeq: false, es5: true, evil: false, forin: false, newcap: false, nomen: true, plusplus: true, regexp: false, unparam: false, sloppy: true, stupid: false, sub: false, todo: true, vars: true, white: true */
- var jpeg = require('./jpeg'),
- exif = require('./exif'),
- simplify = require('./simplify');
- function ExifResult(startMarker, tags, imageSize, thumbnailOffset, thumbnailLength, thumbnailType, app1Offset) {
- this.startMarker = startMarker;
- this.tags = tags;
- this.imageSize = imageSize;
- this.thumbnailOffset = thumbnailOffset;
- this.thumbnailLength = thumbnailLength;
- this.thumbnailType = thumbnailType;
- this.app1Offset = app1Offset;
- }
- ExifResult.prototype = {
- hasThumbnail: function(mime) {
- if(!this.thumbnailOffset || !this.thumbnailLength) {
- return false;
- }
- if(typeof mime !== 'string') {
- return true;
- }
- if(mime.toLowerCase().trim() === 'image/jpeg') {
- return this.thumbnailType === 6;
- }
- if(mime.toLowerCase().trim() === 'image/tiff') {
- return this.thumbnailType === 1;
- }
- return false;
- },
- getThumbnailOffset: function() {
- return this.app1Offset + 6 + this.thumbnailOffset;
- },
- getThumbnailLength: function() {
- return this.thumbnailLength;
- },
- getThumbnailBuffer: function() {
- return this._getThumbnailStream().nextBuffer(this.thumbnailLength);
- },
- _getThumbnailStream: function() {
- return this.startMarker.openWithOffset(this.getThumbnailOffset());
- },
- getImageSize: function() {
- return this.imageSize;
- },
- getThumbnailSize: function() {
- var stream = this._getThumbnailStream(), size;
- jpeg.parseSections(stream, function(sectionType, sectionStream) {
- if(jpeg.getSectionName(sectionType).name === 'SOF') {
- size = jpeg.getSizeFromSOFSection(sectionStream);
- }
- });
- return size;
- }
- };
- function Parser(stream) {
- this.stream = stream;
- this.flags = {
- readBinaryTags: false,
- resolveTagNames: true,
- simplifyValues: true,
- imageSize: true,
- hidePointers: true,
- returnTags: true
- };
- }
- Parser.prototype = {
- enableBinaryFields: function(enable) {
- this.flags.readBinaryTags = !!enable;
- return this;
- },
- enablePointers: function(enable) {
- this.flags.hidePointers = !enable;
- return this;
- },
- enableTagNames: function(enable) {
- this.flags.resolveTagNames = !!enable;
- return this;
- },
- enableImageSize: function(enable) {
- this.flags.imageSize = !!enable;
- return this;
- },
- enableReturnTags: function(enable) {
- this.flags.returnTags = !!enable;
- return this;
- },
- enableSimpleValues: function(enable) {
- this.flags.simplifyValues = !!enable;
- return this;
- },
- parse: function() {
- var start = this.stream.mark(),
- stream = start.openWithOffset(0),
- flags = this.flags,
- tags,
- imageSize,
- thumbnailOffset,
- thumbnailLength,
- thumbnailType,
- app1Offset,
- tagNames,
- getTagValue, setTagValue;
- if(flags.resolveTagNames) {
- tagNames = require('./exif-tags');
- }
- if(flags.resolveTagNames) {
- tags = {};
- getTagValue = function(t) {
- return tags[t.name];
- };
- setTagValue = function(t, value) {
- tags[t.name] = value;
- };
- } else {
- tags = [];
- getTagValue = function(t) {
- var i;
- for(i = 0; i < tags.length; ++i) {
- if(tags[i].type === t.type && tags[i].section === t.section) {
- return tags.value;
- }
- }
- };
- setTagValue = function(t, value) {
- var i;
- for(i = 0; i < tags.length; ++i) {
- if(tags[i].type === t.type && tags[i].section === t.section) {
- tags.value = value;
- return;
- }
- }
- };
- }
- jpeg.parseSections(stream, function(sectionType, sectionStream) {
- var validExifHeaders, sectionOffset = sectionStream.offsetFrom(start);
- if(sectionType === 0xE1) {
- validExifHeaders = exif.parseTags(sectionStream, function(ifdSection, tagType, value, format) {
- //ignore binary fields if disabled
- if(!flags.readBinaryTags && format === 7) {
- return;
- }
- if(tagType === 0x0201) {
- thumbnailOffset = value[0];
- if(flags.hidePointers) {return;}
- } else if(tagType === 0x0202) {
- thumbnailLength = value[0];
- if(flags.hidePointers) {return;}
- } else if(tagType === 0x0103) {
- thumbnailType = value[0];
- if(flags.hidePointers) {return;}
- }
- //if flag is set to not store tags, return here after storing pointers
- if(!flags.returnTags) {
- return;
- }
- if(flags.simplifyValues) {
- value = simplify.simplifyValue(value, format);
- }
- if(flags.resolveTagNames) {
- var sectionTagNames = ifdSection === exif.GPSIFD ? tagNames.gps : tagNames.exif;
- var name = sectionTagNames[tagType];
- if(!name) {
- name = tagNames.exif[tagType];
- }
- if (!tags.hasOwnProperty(name)) {
- tags[name] = value;
- }
- } else {
- tags.push({
- section: ifdSection,
- type: tagType,
- value: value
- });
- }
- });
- if(validExifHeaders) {
- app1Offset = sectionOffset;
- }
- }
- else if(flags.imageSize && jpeg.getSectionName(sectionType).name === 'SOF') {
- imageSize = jpeg.getSizeFromSOFSection(sectionStream);
- }
- });
- if(flags.simplifyValues) {
- simplify.castDegreeValues(getTagValue, setTagValue);
- simplify.castDateValues(getTagValue, setTagValue);
- }
- return new ExifResult(start, tags, imageSize, thumbnailOffset, thumbnailLength, thumbnailType, app1Offset);
- }
- };
- module.exports = Parser;
|