OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 const EXIF_MARK_SOI = 0xffd8; // Start of image data. | 5 const EXIF_MARK_SOI = 0xffd8; // Start of image data. |
6 const EXIF_MARK_SOS = 0xffda; // Start of "stream" (the actual image data). | 6 const EXIF_MARK_SOS = 0xffda; // Start of "stream" (the actual image data). |
7 const EXIF_MARK_SOF = 0xffc0; // Start of "frame" | 7 const EXIF_MARK_SOF = 0xffc0; // Start of "frame" |
8 const EXIF_MARK_EXIF = 0xffe1; // Start of exif block. | 8 const EXIF_MARK_EXIF = 0xffe1; // Start of exif block. |
9 | 9 |
10 const EXIF_ALIGN_LITTLE = 0x4949; // Indicates little endian exif data. | 10 const EXIF_ALIGN_LITTLE = 0x4949; // Indicates little endian exif data. |
11 const EXIF_ALIGN_BIG = 0x4d4d; // Indicates big endian exif data. | 11 const EXIF_ALIGN_BIG = 0x4d4d; // Indicates big endian exif data. |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 if (filePos + br.tell() + markLength > file.size) { | 88 if (filePos + br.tell() + markLength > file.size) { |
89 throw new Error( | 89 throw new Error( |
90 'Invalid section length @' + (filePos + br.tell() - 2)); | 90 'Invalid section length @' + (filePos + br.tell() - 2)); |
91 } | 91 } |
92 reread(-4, markLength + 4); | 92 reread(-4, markLength + 4); |
93 return; | 93 return; |
94 } | 94 } |
95 | 95 |
96 if (mark == EXIF_MARK_EXIF) { | 96 if (mark == EXIF_MARK_EXIF) { |
97 this.parseExifSection(metadata, buf, br); | 97 this.parseExifSection(metadata, buf, br); |
98 } else if ((mark & ~0xF) == EXIF_MARK_SOF) { | 98 } else if (ExifParser.isSOF_(mark)) { |
99 // The most reliable size information is encoded in the SOF section. | 99 // The most reliable size information is encoded in the SOF section. |
100 // There are 16 variants of the SOF format distinguished by the last | |
101 // hex digit of the mark, but the part we want is always the same. | |
102 br.seek(1, ByteReader.SEEK_CUR); // Skip the precision byte. | 100 br.seek(1, ByteReader.SEEK_CUR); // Skip the precision byte. |
103 var height = br.readScalar(2); | 101 var height = br.readScalar(2); |
104 var width = br.readScalar(2); | 102 var width = br.readScalar(2); |
105 ExifParser.setImageSize(metadata, width, height); | 103 ExifParser.setImageSize(metadata, width, height); |
106 callback(metadata); // We are done! | 104 callback(metadata); // We are done! |
107 return; | 105 return; |
108 } | 106 } |
109 | 107 |
110 br.seek(nextSectionStart, ByteReader.SEEK_BEG); | 108 br.seek(nextSectionStart, ByteReader.SEEK_BEG); |
111 } | 109 } |
112 } catch (e) { | 110 } catch (e) { |
113 errorCallback(e.toString()); | 111 errorCallback(e.toString()); |
114 } | 112 } |
115 }; | 113 }; |
116 | 114 |
| 115 ExifParser.isSOF_ = function(mark) { |
| 116 // There are 13 variants of SOF fragment format distinguished by the last |
| 117 // hex digit of the mark, but the part we want is always the same. |
| 118 if ((mark & ~0xF) != EXIF_MARK_SOF) return false; |
| 119 |
| 120 // If the last digit is 4, 8 or 12 it is not really a SOF. |
| 121 var type = mark & 0xF; |
| 122 return (type != 4 && type != 8 && type != 12); |
| 123 }; |
| 124 |
117 ExifParser.prototype.parseExifSection = function(metadata, buf, br) { | 125 ExifParser.prototype.parseExifSection = function(metadata, buf, br) { |
118 var magic = br.readString(6); | 126 var magic = br.readString(6); |
119 if (magic != 'Exif\0\0') { | 127 if (magic != 'Exif\0\0') { |
120 // Some JPEG files may have sections marked with EXIF_MARK_EXIF | 128 // Some JPEG files may have sections marked with EXIF_MARK_EXIF |
121 // but containing something else (e.g. XML text). Ignore such sections. | 129 // but containing something else (e.g. XML text). Ignore such sections. |
122 this.vlog('Invalid EXIF magic: ' + magic + br.readString(100)); | 130 this.vlog('Invalid EXIF magic: ' + magic + br.readString(100)); |
123 return; | 131 return; |
124 } | 132 } |
125 | 133 |
126 // Offsets inside the EXIF block are based after the magic string. | 134 // Offsets inside the EXIF block are based after the magic string. |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 return { | 356 return { |
349 scaleX: ExifParser.SCALEX[index], | 357 scaleX: ExifParser.SCALEX[index], |
350 scaleY: ExifParser.SCALEY[index], | 358 scaleY: ExifParser.SCALEY[index], |
351 rotate90: ExifParser.ROTATE90[index] | 359 rotate90: ExifParser.ROTATE90[index] |
352 } | 360 } |
353 } | 361 } |
354 return null; | 362 return null; |
355 }; | 363 }; |
356 | 364 |
357 MetadataDispatcher.registerParserClass(ExifParser); | 365 MetadataDispatcher.registerParserClass(ExifParser); |
OLD | NEW |