Index: trunk/phase3/resources/mediawiki.libs/mediawiki.libs.jpegmeta.js |
— | — | @@ -1,731 +0,0 @@ |
2 | | -/* This is JsJpegMeta 1.0, ported to MediaWiki ResourceLoader by Bryan Tong Minh */ |
3 | | -/* The following lines where changed with respect to the original: 54, 625-627 */ |
4 | | - |
5 | | -(function( $ ) { |
6 | | - |
7 | | - /* JsJpegMeta starts here */ |
8 | | - |
9 | | - /* |
10 | | - Copyright (c) 2009 Ben Leslie |
11 | | - |
12 | | - Permission is hereby granted, free of charge, to any person obtaining a copy |
13 | | - of this software and associated documentation files (the "Software"), to deal |
14 | | - in the Software without restriction, including without limitation the rights |
15 | | - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
16 | | - copies of the Software, and to permit persons to whom the Software is |
17 | | - furnished to do so, subject to the following conditions: |
18 | | - |
19 | | - The above copyright notice and this permission notice shall be included in |
20 | | - all copies or substantial portions of the Software. |
21 | | - |
22 | | - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
23 | | - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
24 | | - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
25 | | - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
26 | | - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
27 | | - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
28 | | - THE SOFTWARE. |
29 | | - */ |
30 | | - |
31 | | - /* |
32 | | - This JavaScript library is used to parse meta-data from files |
33 | | - with mime-type image/jpeg. |
34 | | - |
35 | | - Include it with something like: |
36 | | - |
37 | | - <script type="text/javascript" src="jpegmeta.js"></script> |
38 | | - |
39 | | - This adds a single 'module' object called 'JpegMeta' to the global |
40 | | - namespace. |
41 | | - |
42 | | - Public Functions |
43 | | - ---------------- |
44 | | - JpegMeta.parseNum - parse unsigned integers from binary data |
45 | | - JpegMeta.parseSnum - parse signed integers from binary data |
46 | | - |
47 | | - Public Classes |
48 | | - -------------- |
49 | | - JpegMeta.Rational - A rational number class |
50 | | - JpegMeta.JfifSegment |
51 | | - JpegMeta.ExifSegment |
52 | | - JpegMeta.JpegFile - Primary class for Javascript parsing |
53 | | - */ |
54 | | - |
55 | | - var JpegMeta = {}; |
56 | | - this.JpegMeta = JpegMeta; // I have no clue why I need this magic... -- Bryan |
57 | | - |
58 | | - /* |
59 | | - parse an unsigned number of size bytes at offset in some binary string data. |
60 | | - If endian |
61 | | - is "<" parse the data as little endian, if endian |
62 | | - is ">" parse as big-endian. |
63 | | - */ |
64 | | - JpegMeta.parseNum = function parseNum(endian, data, offset, size) { |
65 | | - var i; |
66 | | - var ret; |
67 | | - var big_endian = (endian === ">"); |
68 | | - if (offset === undefined) offset = 0; |
69 | | - if (size === undefined) size = data.length - offset; |
70 | | - for (big_endian ? i = offset : i = offset + size - 1; |
71 | | - big_endian ? i < offset + size : i >= offset; |
72 | | - big_endian ? i++ : i--) { |
73 | | - ret <<= 8; |
74 | | - ret += data.charCodeAt(i); |
75 | | - } |
76 | | - return ret; |
77 | | - }; |
78 | | - |
79 | | - /* |
80 | | - parse an signed number of size bytes at offset in some binary string data. |
81 | | - If endian |
82 | | - is "<" parse the data as little endian, if endian |
83 | | - is ">" parse as big-endian. |
84 | | - */ |
85 | | - JpegMeta.parseSnum = function parseSnum(endian, data, offset, size) { |
86 | | - var i; |
87 | | - var ret; |
88 | | - var neg; |
89 | | - var big_endian = (endian === ">"); |
90 | | - if (offset === undefined) offset = 0; |
91 | | - if (size === undefined) size = data.length - offset; |
92 | | - for (big_endian ? i = offset : i = offset + size - 1; |
93 | | - big_endian ? i < offset + size : i >= offset; |
94 | | - big_endian ? i++ : i--) { |
95 | | - if (neg === undefined) { |
96 | | - /* Negative if top bit is set */ |
97 | | - neg = (data.charCodeAt(i) & 0x80) === 0x80; |
98 | | - } |
99 | | - ret <<= 8; |
100 | | - /* If it is negative we invert the bits */ |
101 | | - ret += neg ? ~data.charCodeAt(i) & 0xff: data.charCodeAt(i); |
102 | | - } |
103 | | - if (neg) { |
104 | | - /* If it is negative we do two's complement */ |
105 | | - ret += 1; |
106 | | - ret *= -1; |
107 | | - } |
108 | | - return ret; |
109 | | - }; |
110 | | - |
111 | | - /* Rational number class */ |
112 | | - JpegMeta.Rational = function Rational(num, den) |
113 | | - { |
114 | | - this.num = num; |
115 | | - this.den = den || 1; |
116 | | - return this; |
117 | | - }; |
118 | | - |
119 | | - /* Rational number methods */ |
120 | | - JpegMeta.Rational.prototype.toString = function toString() { |
121 | | - if (this.num === 0) { |
122 | | - return "" + this.num |
123 | | - } |
124 | | - if (this.den === 1) { |
125 | | - return "" + this.num; |
126 | | - } |
127 | | - if (this.num === 1) { |
128 | | - return this.num + " / " + this.den; |
129 | | - } |
130 | | - return this.num / this.den; // + "/" + this.den; |
131 | | - }; |
132 | | - |
133 | | - JpegMeta.Rational.prototype.asFloat = function asFloat() { |
134 | | - return this.num / this.den; |
135 | | - }; |
136 | | - |
137 | | - /* MetaGroup class */ |
138 | | - JpegMeta.MetaGroup = function MetaGroup(fieldName, description) { |
139 | | - this.fieldName = fieldName; |
140 | | - this.description = description; |
141 | | - this.metaProps = {}; |
142 | | - return this; |
143 | | - }; |
144 | | - |
145 | | - JpegMeta.MetaGroup.prototype._addProperty = function _addProperty(fieldName, description, value) { |
146 | | - var property = new JpegMeta.MetaProp(fieldName, description, value); |
147 | | - this[property.fieldName] = property; |
148 | | - this.metaProps[property.fieldName] = property; |
149 | | - }; |
150 | | - |
151 | | - JpegMeta.MetaGroup.prototype.toString = function toString() { |
152 | | - return "[MetaGroup " + this.description + "]"; |
153 | | - }; |
154 | | - |
155 | | - /* MetaProp class */ |
156 | | - JpegMeta.MetaProp = function MetaProp(fieldName, description, value) { |
157 | | - this.fieldName = fieldName; |
158 | | - this.description = description; |
159 | | - this.value = value; |
160 | | - return this; |
161 | | - }; |
162 | | - |
163 | | - JpegMeta.MetaProp.prototype.toString = function toString() { |
164 | | - return "" + this.value; |
165 | | - }; |
166 | | - |
167 | | - /* JpegFile class */ |
168 | | - JpegMeta.JpegFile = function JpegFile(binary_data, filename) { |
169 | | - /* Change this to EOI if we want to parse. */ |
170 | | - var break_segment = this._SOS; |
171 | | - |
172 | | - this.metaGroups = {}; |
173 | | - this._binary_data = binary_data; |
174 | | - this.filename = filename; |
175 | | - |
176 | | - /* Go through and parse. */ |
177 | | - var pos = 0; |
178 | | - var pos_start_of_segment = 0; |
179 | | - var delim; |
180 | | - var mark; |
181 | | - var _mark; |
182 | | - var segsize; |
183 | | - var headersize; |
184 | | - var mark_code; |
185 | | - var mark_fn; |
186 | | - |
187 | | - /* Check to see if this looks like a JPEG file */ |
188 | | - if (this._binary_data.slice(0, 2) !== this._SOI_MARKER) { |
189 | | - throw new Error("Doesn't look like a JPEG file. First two bytes are " + |
190 | | - this._binary_data.charCodeAt(0) + "," + |
191 | | - this._binary_data.charCodeAt(1) + "."); |
192 | | - } |
193 | | - |
194 | | - pos += 2; |
195 | | - |
196 | | - while (pos < this._binary_data.length) { |
197 | | - delim = this._binary_data.charCodeAt(pos++); |
198 | | - mark = this._binary_data.charCodeAt(pos++); |
199 | | - |
200 | | - pos_start_of_segment = pos; |
201 | | - |
202 | | - if (delim != this._DELIM) { |
203 | | - break; |
204 | | - } |
205 | | - |
206 | | - if (mark === break_segment) { |
207 | | - break; |
208 | | - } |
209 | | - |
210 | | - headersize = JpegMeta.parseNum(">", this._binary_data, pos, 2); |
211 | | - |
212 | | - /* Find the end */ |
213 | | - pos += headersize; |
214 | | - while (pos < this._binary_data.length) { |
215 | | - delim = this._binary_data.charCodeAt(pos++); |
216 | | - if (delim == this._DELIM) { |
217 | | - _mark = this._binary_data.charCodeAt(pos++); |
218 | | - if (_mark != 0x0) { |
219 | | - pos -= 2; |
220 | | - break; |
221 | | - } |
222 | | - } |
223 | | - } |
224 | | - |
225 | | - segsize = pos - pos_start_of_segment; |
226 | | - |
227 | | - if (this._markers[mark]) { |
228 | | - mark_code = this._markers[mark][0]; |
229 | | - mark_fn = this._markers[mark][1]; |
230 | | - } else { |
231 | | - mark_code = "UNKN"; |
232 | | - mark_fn = undefined; |
233 | | - } |
234 | | - |
235 | | - if (mark_fn) { |
236 | | - this[mark_fn](mark, pos_start_of_segment + 2); |
237 | | - } |
238 | | - |
239 | | - } |
240 | | - |
241 | | - if (this.general === undefined) { |
242 | | - throw Error("Invalid JPEG file."); |
243 | | - } |
244 | | - |
245 | | - return this; |
246 | | - }; |
247 | | - |
248 | | - this.JpegMeta.JpegFile.prototype.toString = function () { |
249 | | - return "[JpegFile " + this.filename + " " + |
250 | | - this.general.type + " " + |
251 | | - this.general.pixelWidth + "x" + |
252 | | - this.general.pixelHeight + |
253 | | - " Depth: " + this.general.depth + "]"; |
254 | | - }; |
255 | | - |
256 | | - /* Some useful constants */ |
257 | | - this.JpegMeta.JpegFile.prototype._SOI_MARKER = '\xff\xd8'; |
258 | | - this.JpegMeta.JpegFile.prototype._DELIM = 0xff; |
259 | | - this.JpegMeta.JpegFile.prototype._EOI = 0xd9; |
260 | | - this.JpegMeta.JpegFile.prototype._SOS = 0xda; |
261 | | - |
262 | | - this.JpegMeta.JpegFile.prototype._sofHandler = function _sofHandler (mark, pos) { |
263 | | - if (this.general !== undefined) { |
264 | | - throw Error("Unexpected multiple-frame image"); |
265 | | - } |
266 | | - |
267 | | - this._addMetaGroup("general", "General"); |
268 | | - this.general._addProperty("depth", "Depth", JpegMeta.parseNum(">", this._binary_data, pos, 1)); |
269 | | - this.general._addProperty("pixelHeight", "Pixel Height", JpegMeta.parseNum(">", this._binary_data, pos + 1, 2)); |
270 | | - this.general._addProperty("pixelWidth", "Pixel Width",JpegMeta.parseNum(">", this._binary_data, pos + 3, 2)); |
271 | | - this.general._addProperty("type", "Type", this._markers[mark][2]); |
272 | | - }; |
273 | | - |
274 | | - /* JFIF idents */ |
275 | | - this.JpegMeta.JpegFile.prototype._JFIF_IDENT = "JFIF\x00"; |
276 | | - this.JpegMeta.JpegFile.prototype._JFXX_IDENT = "JFXX\x00"; |
277 | | - |
278 | | - /* EXIF idents */ |
279 | | - this.JpegMeta.JpegFile.prototype._EXIF_IDENT = "Exif\x00"; |
280 | | - |
281 | | - /* TIFF types */ |
282 | | - this.JpegMeta.JpegFile.prototype._types = { |
283 | | - /* The format is identifier : ["type name", type_size_in_bytes ] */ |
284 | | - 1 : ["BYTE", 1], |
285 | | - 2 : ["ASCII", 1], |
286 | | - 3 : ["SHORT", 2], |
287 | | - 4 : ["LONG", 4], |
288 | | - 5 : ["RATIONAL", 8], |
289 | | - 6 : ["SBYTE", 1], |
290 | | - 7 : ["UNDEFINED", 1], |
291 | | - 8 : ["SSHORT", 2], |
292 | | - 9 : ["SLONG", 4], |
293 | | - 10 : ["SRATIONAL", 8], |
294 | | - 11 : ["FLOAT", 4], |
295 | | - 12 : ["DOUBLE", 8], |
296 | | - }; |
297 | | - |
298 | | - this.JpegMeta.JpegFile.prototype._tifftags = { |
299 | | - /* A. Tags relating to image data structure */ |
300 | | - 256 : ["Image width", "ImageWidth"], |
301 | | - 257 : ["Image height", "ImageLength"], |
302 | | - 258 : ["Number of bits per component", "BitsPerSample"], |
303 | | - 259 : ["Compression scheme", "Compression", |
304 | | - {1 : "uncompressed", 6 : "JPEG compression" }], |
305 | | - 262 : ["Pixel composition", "PhotmetricInerpretation", |
306 | | - {2 : "RGB", 6 : "YCbCr"}], |
307 | | - 274 : ["Orientation of image", "Orientation", |
308 | | - /* FIXME: Check the mirror-image / reverse encoding and rotation */ |
309 | | - {1 : "Normal", 2 : "Reverse?", |
310 | | - 3 : "Upside-down", 4 : "Upside-down Reverse", |
311 | | - 5 : "90 degree CW", 6 : "90 degree CW reverse", |
312 | | - 7 : "90 degree CCW", 8 : "90 degree CCW reverse",}], |
313 | | - 277 : ["Number of components", "SamplesPerPixel"], |
314 | | - 284 : ["Image data arrangement", "PlanarConfiguration", |
315 | | - {1 : "chunky format", 2 : "planar format"}], |
316 | | - 530 : ["Subsampling ratio of Y to C", "YCbCrSubSampling"], |
317 | | - 531 : ["Y and C positioning", "YCbCrPositioning", |
318 | | - {1 : "centered", 2 : "co-sited"}], |
319 | | - 282 : ["X Resolution", "XResolution"], |
320 | | - 283 : ["Y Resolution", "YResolution"], |
321 | | - 296 : ["Resolution Unit", "ResolutionUnit", |
322 | | - {2 : "inches", 3 : "centimeters"}], |
323 | | - /* B. Tags realting to recording offset */ |
324 | | - 273 : ["Image data location", "StripOffsets"], |
325 | | - 278 : ["Number of rows per strip", "RowsPerStrip"], |
326 | | - 279 : ["Bytes per compressed strip", "StripByteCounts"], |
327 | | - 513 : ["Offset to JPEG SOI", "JPEGInterchangeFormat"], |
328 | | - 514 : ["Bytes of JPEG Data", "JPEGInterchangeFormatLength"], |
329 | | - /* C. Tags relating to image data characteristics */ |
330 | | - 301 : ["Transfer function", "TransferFunction"], |
331 | | - 318 : ["White point chromaticity", "WhitePoint"], |
332 | | - 319 : ["Chromaticities of primaries", "PrimaryChromaticities"], |
333 | | - 529 : ["Color space transformation matrix coefficients", "YCbCrCoefficients"], |
334 | | - 532 : ["Pair of black and white reference values", "ReferenceBlackWhite"], |
335 | | - /* D. Other tags */ |
336 | | - 306 : ["Date and time", "DateTime"], |
337 | | - 270 : ["Image title", "ImageDescription"], |
338 | | - 271 : ["Make", "Make"], |
339 | | - 272 : ["Model", "Model"], |
340 | | - 305 : ["Software", "Software"], |
341 | | - 315 : ["Person who created the image", "Artist"], |
342 | | - 316 : ["Host Computer", "HostComputer"], |
343 | | - 33432 : ["Copyright holder", "Copyright"], |
344 | | - |
345 | | - 34665 : ["Exif tag", "ExifIfdPointer"], |
346 | | - 34853 : ["GPS tag", "GPSInfoIfdPointer"], |
347 | | - }; |
348 | | - |
349 | | - this.JpegMeta.JpegFile.prototype._exiftags = { |
350 | | - /* Tag Support Levels (2) - 0th IFX Exif Private Tags */ |
351 | | - /* A. Tags Relating to Version */ |
352 | | - 36864 : ["Exif Version", "ExifVersion"], |
353 | | - 40960 : ["FlashPix Version", "FlashpixVersion"], |
354 | | - |
355 | | - /* B. Tag Relating to Image Data Characteristics */ |
356 | | - 40961 : ["Color Space", "ColorSpace"], |
357 | | - |
358 | | - /* C. Tags Relating to Image Configuration */ |
359 | | - 37121 : ["Meaning of each component", "ComponentsConfiguration"], |
360 | | - 37122 : ["Compressed Bits Per Pixel", "CompressedBitsPerPixel"], |
361 | | - 40962 : ["Pixel X Dimension", "PixelXDimension"], |
362 | | - 40963 : ["Pixel Y Dimension", "PixelYDimension"], |
363 | | - |
364 | | - /* D. Tags Relating to User Information */ |
365 | | - 37500 : ["Manufacturer notes", "MakerNote"], |
366 | | - 37510 : ["User comments", "UserComment"], |
367 | | - |
368 | | - /* E. Tag Relating to Related File Information */ |
369 | | - 40964 : ["Related audio file", "RelatedSoundFile"], |
370 | | - |
371 | | - /* F. Tags Relating to Date and Time */ |
372 | | - 36867 : ["Date Time Original", "DateTimeOriginal"], |
373 | | - 36868 : ["Date Time Digitized", "DateTimeDigitized"], |
374 | | - 37520 : ["DateTime subseconds", "SubSecTime"], |
375 | | - 37521 : ["DateTimeOriginal subseconds", "SubSecTimeOriginal"], |
376 | | - 37522 : ["DateTimeDigitized subseconds", "SubSecTimeDigitized"], |
377 | | - |
378 | | - /* G. Tags Relating to Picture-Taking Conditions */ |
379 | | - 33434 : ["Exposure time", "ExposureTime"], |
380 | | - 33437 : ["FNumber", "FNumber"], |
381 | | - 34850 : ["Exposure program", "ExposureProgram"], |
382 | | - 34852 : ["Spectral sensitivity", "SpectralSensitivity"], |
383 | | - 34855 : ["ISO Speed Ratings", "ISOSpeedRatings"], |
384 | | - 34856 : ["Optoelectric coefficient", "OECF"], |
385 | | - 37377 : ["Shutter Speed", "ShutterSpeedValue"], |
386 | | - 37378 : ["Aperture Value", "ApertureValue"], |
387 | | - 37379 : ["Brightness", "BrightnessValue"], |
388 | | - 37380 : ["Exposure Bias Value", "ExposureBiasValue"], |
389 | | - 37381 : ["Max Aperture Value", "MaxApertureValue"], |
390 | | - 37382 : ["Subject Distance", "SubjectDistance"], |
391 | | - 37383 : ["Metering Mode", "MeteringMode"], |
392 | | - 37384 : ["Light Source", "LightSource"], |
393 | | - 37385 : ["Flash", "Flash"], |
394 | | - 37386 : ["Focal Length", "FocalLength"], |
395 | | - 37396 : ["Subject Area", "SubjectArea"], |
396 | | - 41483 : ["Flash Energy", "FlashEnergy"], |
397 | | - 41484 : ["Spatial Frequency Response", "SpatialFrequencyResponse"], |
398 | | - 41486 : ["Focal Plane X Resolution", "FocalPlaneXResolution"], |
399 | | - 41487 : ["Focal Plane Y Resolution", "FocalPlaneYResolution"], |
400 | | - 41488 : ["Focal Plane Resolution Unit", "FocalPlaneResolutionUnit"], |
401 | | - 41492 : ["Subject Location", "SubjectLocation"], |
402 | | - 41493 : ["Exposure Index", "ExposureIndex"], |
403 | | - 41495 : ["Sensing Method", "SensingMethod"], |
404 | | - 41728 : ["File Source", "FileSource"], |
405 | | - 41729 : ["Scene Type", "SceneType"], |
406 | | - 41730 : ["CFA Pattern", "CFAPattern"], |
407 | | - 41985 : ["Custom Rendered", "CustomRendered"], |
408 | | - 41986 : ["Exposure Mode", "Exposure Mode"], |
409 | | - 41987 : ["White Balance", "WhiteBalance"], |
410 | | - 41988 : ["Digital Zoom Ratio", "DigitalZoomRatio"], |
411 | | - 41990 : ["Scene Capture Type", "SceneCaptureType"], |
412 | | - 41991 : ["Gain Control", "GainControl"], |
413 | | - 41992 : ["Contrast", "Contrast"], |
414 | | - 41993 : ["Saturation", "Saturation"], |
415 | | - 41994 : ["Sharpness", "Sharpness"], |
416 | | - 41995 : ["Device settings description", "DeviceSettingDescription"], |
417 | | - 41996 : ["Subject distance range", "SubjectDistanceRange"], |
418 | | - |
419 | | - /* H. Other Tags */ |
420 | | - 42016 : ["Unique image ID", "ImageUniqueID"], |
421 | | - |
422 | | - 40965 : ["Interoperability tag", "InteroperabilityIFDPointer"], |
423 | | - }; |
424 | | - |
425 | | - this.JpegMeta.JpegFile.prototype._gpstags = { |
426 | | - /* A. Tags Relating to GPS */ |
427 | | - 0 : ["GPS tag version", "GPSVersionID"], |
428 | | - 1 : ["North or South Latitude", "GPSLatitudeRef"], |
429 | | - 2 : ["Latitude", "GPSLatitude"], |
430 | | - 3 : ["East or West Longitude", "GPSLongitudeRef"], |
431 | | - 4 : ["Longitude", "GPSLongitude"], |
432 | | - 5 : ["Altitude reference", "GPSAltitudeRef"], |
433 | | - 6 : ["Altitude", "GPSAltitude"], |
434 | | - 7 : ["GPS time (atomic clock)", "GPSTimeStamp"], |
435 | | - 8 : ["GPS satellites usedd for measurement", "GPSSatellites"], |
436 | | - 9 : ["GPS receiver status", "GPSStatus"], |
437 | | - 10 : ["GPS mesaurement mode", "GPSMeasureMode"], |
438 | | - 11 : ["Measurement precision", "GPSDOP"], |
439 | | - 12 : ["Speed unit", "GPSSpeedRef"], |
440 | | - 13 : ["Speed of GPS receiver", "GPSSpeed"], |
441 | | - 14 : ["Reference for direction of movement", "GPSTrackRef"], |
442 | | - 15 : ["Direction of movement", "GPSTrack"], |
443 | | - 16 : ["Reference for direction of image", "GPSImgDirectionRef"], |
444 | | - 17 : ["Direction of image", "GPSImgDirection"], |
445 | | - 18 : ["Geodetic survey data used", "GPSMapDatum"], |
446 | | - 19 : ["Reference for latitude of destination", "GPSDestLatitudeRef"], |
447 | | - 20 : ["Latitude of destination", "GPSDestLatitude"], |
448 | | - 21 : ["Reference for longitude of destination", "GPSDestLongitudeRef"], |
449 | | - 22 : ["Longitude of destination", "GPSDestLongitude"], |
450 | | - 23 : ["Reference for bearing of destination", "GPSDestBearingRef"], |
451 | | - 24 : ["Bearing of destination", "GPSDestBearing"], |
452 | | - 25 : ["Reference for distance to destination", "GPSDestDistanceRef"], |
453 | | - 26 : ["Distance to destination", "GPSDestDistance"], |
454 | | - 27 : ["Name of GPS processing method", "GPSProcessingMethod"], |
455 | | - 28 : ["Name of GPS area", "GPSAreaInformation"], |
456 | | - 29 : ["GPS Date", "GPSDateStamp"], |
457 | | - 30 : ["GPS differential correction", "GPSDifferential"], |
458 | | - }; |
459 | | - |
460 | | - this.JpegMeta.JpegFile.prototype._markers = { |
461 | | - /* Start Of Frame markers, non-differential, Huffman coding */ |
462 | | - 0xc0: ["SOF0", "_sofHandler", "Baseline DCT"], |
463 | | - 0xc1: ["SOF1", "_sofHandler", "Extended sequential DCT"], |
464 | | - 0xc2: ["SOF2", "_sofHandler", "Progressive DCT"], |
465 | | - 0xc3: ["SOF3", "_sofHandler", "Lossless (sequential)"], |
466 | | - |
467 | | - /* Start Of Frame markers, differential, Huffman coding */ |
468 | | - 0xc5: ["SOF5", "_sofHandler", "Differential sequential DCT"], |
469 | | - 0xc6: ["SOF6", "_sofHandler", "Differential progressive DCT"], |
470 | | - 0xc7: ["SOF7", "_sofHandler", "Differential lossless (sequential)"], |
471 | | - |
472 | | - /* Start Of Frame markers, non-differential, arithmetic coding */ |
473 | | - 0xc8: ["JPG", null, "Reserved for JPEG extensions"], |
474 | | - 0xc9: ["SOF9", "_sofHandler", "Extended sequential DCT"], |
475 | | - 0xca: ["SOF10", "_sofHandler", "Progressive DCT"], |
476 | | - 0xcb: ["SOF11", "_sofHandler", "Lossless (sequential)"], |
477 | | - |
478 | | - /* Start Of Frame markers, differential, arithmetic coding */ |
479 | | - 0xcd: ["SOF13", "_sofHandler", "Differential sequential DCT"], |
480 | | - 0xce: ["SOF14", "_sofHandler", "Differential progressive DCT"], |
481 | | - 0xcf: ["SOF15", "_sofHandler", "Differential lossless (sequential)"], |
482 | | - |
483 | | - /* Huffman table specification */ |
484 | | - 0xc4: ["DHT", null, "Define Huffman table(s)"], |
485 | | - 0xcc: ["DAC", null, "Define arithmetic coding conditioning(s)"], |
486 | | - |
487 | | - /* Restart interval termination" */ |
488 | | - 0xd0: ["RST0", null, "Restart with modulo 8 count “0”"], |
489 | | - 0xd1: ["RST1", null, "Restart with modulo 8 count “1”"], |
490 | | - 0xd2: ["RST2", null, "Restart with modulo 8 count “2”"], |
491 | | - 0xd3: ["RST3", null, "Restart with modulo 8 count “3”"], |
492 | | - 0xd4: ["RST4", null, "Restart with modulo 8 count “4”"], |
493 | | - 0xd5: ["RST5", null, "Restart with modulo 8 count “5”"], |
494 | | - 0xd6: ["RST6", null, "Restart with modulo 8 count “6”"], |
495 | | - 0xd7: ["RST7", null, "Restart with modulo 8 count “7”"], |
496 | | - |
497 | | - /* Other markers */ |
498 | | - 0xd8: ["SOI", null, "Start of image"], |
499 | | - 0xd9: ["EOI", null, "End of image"], |
500 | | - 0xda: ["SOS", null, "Start of scan"], |
501 | | - 0xdb: ["DQT", null, "Define quantization table(s)"], |
502 | | - 0xdc: ["DNL", null, "Define number of lines"], |
503 | | - 0xdd: ["DRI", null, "Define restart interval"], |
504 | | - 0xde: ["DHP", null, "Define hierarchical progression"], |
505 | | - 0xdf: ["EXP", null, "Expand reference component(s)"], |
506 | | - 0xe0: ["APP0", "_app0Handler", "Reserved for application segments"], |
507 | | - 0xe1: ["APP1", "_app1Handler"], |
508 | | - 0xe2: ["APP2", null], |
509 | | - 0xe3: ["APP3", null], |
510 | | - 0xe4: ["APP4", null], |
511 | | - 0xe5: ["APP5", null], |
512 | | - 0xe6: ["APP6", null], |
513 | | - 0xe7: ["APP7", null], |
514 | | - 0xe8: ["APP8", null], |
515 | | - 0xe9: ["APP9", null], |
516 | | - 0xea: ["APP10", null], |
517 | | - 0xeb: ["APP11", null], |
518 | | - 0xec: ["APP12", null], |
519 | | - 0xed: ["APP13", null], |
520 | | - 0xee: ["APP14", null], |
521 | | - 0xef: ["APP15", null], |
522 | | - 0xf0: ["JPG0", null], /* Reserved for JPEG extensions */ |
523 | | - 0xf1: ["JPG1", null], |
524 | | - 0xf2: ["JPG2", null], |
525 | | - 0xf3: ["JPG3", null], |
526 | | - 0xf4: ["JPG4", null], |
527 | | - 0xf5: ["JPG5", null], |
528 | | - 0xf6: ["JPG6", null], |
529 | | - 0xf7: ["JPG7", null], |
530 | | - 0xf8: ["JPG8", null], |
531 | | - 0xf9: ["JPG9", null], |
532 | | - 0xfa: ["JPG10", null], |
533 | | - 0xfb: ["JPG11", null], |
534 | | - 0xfc: ["JPG12", null], |
535 | | - 0xfd: ["JPG13", null], |
536 | | - 0xfe: ["COM", null], /* Comment */ |
537 | | - |
538 | | - /* Reserved markers */ |
539 | | - 0x01: ["JPG13", null], /* For temporary private use in arithmetic coding */ |
540 | | - /* 02 -> bf are reserverd */ |
541 | | - }; |
542 | | - |
543 | | - /* Private methods */ |
544 | | - this.JpegMeta.JpegFile.prototype._addMetaGroup = function _addMetaGroup(name, description) { |
545 | | - var group = new JpegMeta.MetaGroup(name, description); |
546 | | - this[group.fieldName] = group; |
547 | | - this.metaGroups[group.fieldName] = group; |
548 | | - return group; |
549 | | - }; |
550 | | - |
551 | | - this.JpegMeta.JpegFile.prototype._parseIfd = function _parseIfd(endian, _binary_data, base, ifd_offset, tags, name, description) { |
552 | | - var num_fields = JpegMeta.parseNum(endian, _binary_data, base + ifd_offset, 2); |
553 | | - /* Per tag variables */ |
554 | | - var i, j; |
555 | | - var tag_base; |
556 | | - var tag_field; |
557 | | - var type, type_field, type_size; |
558 | | - var num_values; |
559 | | - var value_offset; |
560 | | - var value; |
561 | | - var _val; |
562 | | - var num; |
563 | | - var den; |
564 | | - |
565 | | - var group; |
566 | | - |
567 | | - group = this._addMetaGroup(name, description); |
568 | | - |
569 | | - for (var i = 0; i < num_fields; i++) { |
570 | | - /* parse the field */ |
571 | | - tag_base = base + ifd_offset + 2 + (i * 12); |
572 | | - tag_field = JpegMeta.parseNum(endian, _binary_data, tag_base, 2); |
573 | | - type_field = JpegMeta.parseNum(endian, _binary_data, tag_base + 2, 2); |
574 | | - num_values = JpegMeta.parseNum(endian, _binary_data, tag_base + 4, 4); |
575 | | - value_offset = JpegMeta.parseNum(endian, _binary_data, tag_base + 8, 4); |
576 | | - if (this._types[type_field] === undefined) { |
577 | | - continue; |
578 | | - } |
579 | | - type = this._types[type_field][0]; |
580 | | - type_size = this._types[type_field][1]; |
581 | | - |
582 | | - if (type_size * num_values <= 4) { |
583 | | - /* Data is in-line */ |
584 | | - value_offset = tag_base + 8; |
585 | | - } else { |
586 | | - value_offset = base + value_offset; |
587 | | - } |
588 | | - |
589 | | - /* Read the value */ |
590 | | - if (type == "UNDEFINED") { |
591 | | - value = _binary_data.slice(value_offset, value_offset + num_values); |
592 | | - } else if (type == "ASCII") { |
593 | | - value = _binary_data.slice(value_offset, value_offset + num_values); |
594 | | - value = value.split('\x00')[0]; |
595 | | - /* strip trail nul */ |
596 | | - } else { |
597 | | - value = new Array(); |
598 | | - for (j = 0; j < num_values; j++, value_offset += type_size) { |
599 | | - if (type == "BYTE" || type == "SHORT" || type == "LONG") { |
600 | | - value.push(JpegMeta.parseNum(endian, _binary_data, value_offset, type_size)); |
601 | | - } |
602 | | - if (type == "SBYTE" || type == "SSHORT" || type == "SLONG") { |
603 | | - value.push(JpegMeta.parseSnum(endian, _binary_data, value_offset, type_size)); |
604 | | - } |
605 | | - if (type == "RATIONAL") { |
606 | | - num = JpegMeta.parseNum(endian, _binary_data, value_offset, 4); |
607 | | - den = JpegMeta.parseNum(endian, _binary_data, value_offset + 4, 4); |
608 | | - value.push(new JpegMeta.Rational(num, den)); |
609 | | - } |
610 | | - if (type == "SRATIONAL") { |
611 | | - num = JpegMeta.parseSnum(endian, _binary_data, value_offset, 4); |
612 | | - den = JpegMeta.parseSnum(endian, _binary_data, value_offset + 4, 4); |
613 | | - value.push(new JpegMeta.Rational(num, den)); |
614 | | - } |
615 | | - value.push(); |
616 | | - } |
617 | | - if (num_values === 1) { |
618 | | - value = value[0]; |
619 | | - } |
620 | | - } |
621 | | - if (tags[tag_field] !== undefined) { |
622 | | - group._addProperty(tags[tag_field][1], tags[tag_field][0], value); |
623 | | - } |
624 | | - } |
625 | | - }; |
626 | | - |
627 | | - this.JpegMeta.JpegFile.prototype._jfifHandler = function _jfifHandler(mark, pos) { |
628 | | - if (this.jfif !== undefined) { |
629 | | - throw Error("Multiple JFIF segments found"); |
630 | | - } |
631 | | - this._addMetaGroup("jfif", "JFIF"); |
632 | | - this.jfif._addProperty("version_major", "Version Major", this._binary_data.charCodeAt(pos + 5)); |
633 | | - this.jfif._addProperty("version_minor", "Version Minor", this._binary_data.charCodeAt(pos + 6)); |
634 | | - this.jfif._addProperty("version", "JFIF Version", this.jfif.version_major.value + "." + this.jfif.version_minor.value); |
635 | | - this.jfif._addProperty("units", "Density Unit", this._binary_data.charCodeAt(pos + 7)); |
636 | | - this.jfif._addProperty("Xdensity", "X density", JpegMeta.parseNum(">", this._binary_data, pos + 8, 2)); |
637 | | - this.jfif._addProperty("Ydensity", "Y Density", JpegMeta.parseNum(">", this._binary_data, pos + 10, 2)); |
638 | | - this.jfif._addProperty("Xthumbnail", "X Thumbnail", JpegMeta.parseNum(">", this._binary_data, pos + 12, 1)); |
639 | | - this.jfif._addProperty("Ythumbnail", "Y Thumbnail", JpegMeta.parseNum(">", this._binary_data, pos + 13, 1)); |
640 | | - }; |
641 | | - |
642 | | - /* Handle app0 segments */ |
643 | | - this.JpegMeta.JpegFile.prototype._app0Handler = function app0Handler(mark, pos) { |
644 | | - var ident = this._binary_data.slice(pos, pos + 5); |
645 | | - if (ident == this._JFIF_IDENT) { |
646 | | - this._jfifHandler(mark, pos); |
647 | | - } else if (ident == this._JFXX_IDENT) { |
648 | | - /* Don't handle JFXX Ident yet */ |
649 | | - } else { |
650 | | - /* Don't know about other idents */ |
651 | | - } |
652 | | - }; |
653 | | - |
654 | | - /* Handle app1 segments */ |
655 | | - this.JpegMeta.JpegFile.prototype._app1Handler = function _app1Handler(mark, pos) { |
656 | | - var ident = this._binary_data.slice(pos, pos + 5); |
657 | | - if (ident == this._EXIF_IDENT) { |
658 | | - this._exifHandler(mark, pos + 6); |
659 | | - } else { |
660 | | - /* Don't know about other idents */ |
661 | | - } |
662 | | - }; |
663 | | - |
664 | | - /* Handle exif segments */ |
665 | | - JpegMeta.JpegFile.prototype._exifHandler = function _exifHandler(mark, pos) { |
666 | | - if (this.exif !== undefined) { |
667 | | - throw new Error("Multiple JFIF segments found"); |
668 | | - } |
669 | | - |
670 | | - /* Parse this TIFF header */ |
671 | | - var endian; |
672 | | - var magic_field; |
673 | | - var ifd_offset; |
674 | | - var primary_ifd, exif_ifd, gps_ifd; |
675 | | - var endian_field = this._binary_data.slice(pos, pos + 2); |
676 | | - |
677 | | - /* Trivia: This 'I' is for Intel, the 'M' is for Motorola */ |
678 | | - if (endian_field === "II") { |
679 | | - endian = "<"; |
680 | | - } else if (endian_field === "MM") { |
681 | | - endian = ">"; |
682 | | - } else { |
683 | | - throw new Error("Malformed TIFF meta-data. Unknown endianess: " + endian_field); |
684 | | - } |
685 | | - |
686 | | - magic_field = JpegMeta.parseNum(endian, this._binary_data, pos + 2, 2); |
687 | | - |
688 | | - if (magic_field !== 42) { |
689 | | - throw new Error("Malformed TIFF meta-data. Bad magic: " + magic_field); |
690 | | - } |
691 | | - |
692 | | - ifd_offset = JpegMeta.parseNum(endian, this._binary_data, pos + 4, 4); |
693 | | - |
694 | | - /* Parse 0th IFD */ |
695 | | - this._parseIfd(endian, this._binary_data, pos, ifd_offset, this._tifftags, "tiff", "TIFF"); |
696 | | - |
697 | | - if (this.tiff.ExifIfdPointer) { |
698 | | - this._parseIfd(endian, this._binary_data, pos, this.tiff.ExifIfdPointer.value, this._exiftags, "exif", "Exif"); |
699 | | - } |
700 | | - |
701 | | - if (this.tiff.GPSInfoIfdPointer) { |
702 | | - this._parseIfd(endian, this._binary_data, pos, this.tiff.GPSInfoIfdPointer.value, this._gpstags, "gps", "GPS"); |
703 | | - if (this.gps.GPSLatitude) { |
704 | | - var latitude; |
705 | | - latitude = this.gps.GPSLatitude.value[0].asFloat() + |
706 | | - (1 / 60) * this.gps.GPSLatitude.value[1].asFloat() + |
707 | | - (1 / 3600) * this.gps.GPSLatitude.value[2].asFloat(); |
708 | | - if (this.gps.GPSLatitudeRef.value === "S") { |
709 | | - latitude = -latitude; |
710 | | - } |
711 | | - this.gps._addProperty("latitude", "Dec. Latitude", latitude); |
712 | | - } |
713 | | - if (this.gps.GPSLongitude) { |
714 | | - var longitude; |
715 | | - longitude = this.gps.GPSLongitude.value[0].asFloat() + |
716 | | - (1 / 60) * this.gps.GPSLongitude.value[1].asFloat() + |
717 | | - (1 / 3600) * this.gps.GPSLongitude.value[2].asFloat(); |
718 | | - if (this.gps.GPSLongitudeRef.value === "W") { |
719 | | - longitude = -longitude; |
720 | | - } |
721 | | - this.gps._addProperty("longitude", "Dec. Longitude", longitude); |
722 | | - } |
723 | | - } |
724 | | - }; |
725 | | - |
726 | | - /* JsJpegMeta ends here */ |
727 | | - |
728 | | - mw.libs.jpegmeta = function( fileReaderResult, fileName ) { |
729 | | - return new JpegMeta.JpegFile( fileReaderResult, fileName ); |
730 | | - }; |
731 | | - |
732 | | -} )( jQuery ); |
\ No newline at end of file |