Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
6056 efrain 1
/* piexifjs
2
 
3
The MIT License (MIT)
4
 
5
Copyright (c) 2014, 2015 hMatoba(https://github.com/hMatoba)
6
 
7
Permission is hereby granted, free of charge, to any person obtaining a copy
8
of this software and associated documentation files (the "Software"), to deal
9
in the Software without restriction, including without limitation the rights
10
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
copies of the Software, and to permit persons to whom the Software is
12
furnished to do so, subject to the following conditions:
13
 
14
The above copyright notice and this permission notice shall be included in all
15
copies or substantial portions of the Software.
16
 
17
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
SOFTWARE.
24
*/
25
 
26
(function () {
27
    "use strict";
28
    var that = {};
29
    that.version = "1.03";
30
 
31
    that.remove = function (jpeg) {
32
        var b64 = false;
33
        if (jpeg.slice(0, 2) == "\xff\xd8") {
34
        } else if (jpeg.slice(0, 23) == "data:image/jpeg;base64," || jpeg.slice(0, 22) == "data:image/jpg;base64,") {
35
            jpeg = atob(jpeg.split(",")[1]);
36
            b64 = true;
37
        } else {
38
            throw ("Given data is not jpeg.");
39
        }
40
 
41
        var segments = splitIntoSegments(jpeg);
42
        if (segments[1].slice(0, 2) == "\xff\xe1" &&
43
               segments[1].slice(4, 10) == "Exif\x00\x00") {
44
            segments = [segments[0]].concat(segments.slice(2));
45
        } else if (segments[2].slice(0, 2) == "\xff\xe1" &&
46
                   segments[2].slice(4, 10) == "Exif\x00\x00") {
47
            segments = segments.slice(0, 2).concat(segments.slice(3));
48
        } else {
49
            throw("Exif not found.");
50
        }
51
 
52
        var new_data = segments.join("");
53
        if (b64) {
54
            new_data = "data:image/jpeg;base64," + btoa(new_data);
55
        }
56
 
57
        return new_data;
58
    };
59
 
60
 
61
    that.insert = function (exif, jpeg) {
62
        var b64 = false;
63
        if (exif.slice(0, 6) != "\x45\x78\x69\x66\x00\x00") {
64
            throw ("Given data is not exif.");
65
        }
66
        if (jpeg.slice(0, 2) == "\xff\xd8") {
67
        } else if (jpeg.slice(0, 23) == "data:image/jpeg;base64," || jpeg.slice(0, 22) == "data:image/jpg;base64,") {
68
            jpeg = atob(jpeg.split(",")[1]);
69
            b64 = true;
70
        } else {
71
            throw ("Given data is not jpeg.");
72
        }
73
 
74
        var exifStr = "\xff\xe1" + pack(">H", [exif.length + 2]) + exif;
75
        var segments = splitIntoSegments(jpeg);
76
        var new_data = mergeSegments(segments, exifStr);
77
        if (b64) {
78
            new_data = "data:image/jpeg;base64," + btoa(new_data);
79
        }
80
 
81
        return new_data;
82
    };
83
 
84
 
85
    that.load = function (data) {
86
        var input_data;
87
        if (typeof (data) == "string") {
88
            if (data.slice(0, 2) == "\xff\xd8") {
89
                input_data = data;
90
            } else if (data.slice(0, 23) == "data:image/jpeg;base64," || data.slice(0, 22) == "data:image/jpg;base64,") {
91
                input_data = atob(data.split(",")[1]);
92
            } else if (data.slice(0, 4) == "Exif") {
93
                input_data = data.slice(6);
94
            } else {
95
                throw ("'load' gots invalid file data.");
96
            }
97
        } else {
98
            throw ("'load' gots invalid type argument.");
99
        }
100
 
101
        var exifDict = {};
102
        var exif_dict = {
103
            "0th": {},
104
            "Exif": {},
105
            "GPS": {},
106
            "Interop": {},
107
            "1st": {},
108
            "thumbnail": null
109
        };
110
        var exifReader = new ExifReader(input_data);
111
        if (exifReader.tiftag === null) {
112
            return exif_dict;
113
        }
114
 
115
        if (exifReader.tiftag.slice(0, 2) == "\x49\x49") {
116
            exifReader.endian_mark = "<";
117
        } else {
118
            exifReader.endian_mark = ">";
119
        }
120
 
121
        var pointer = unpack(exifReader.endian_mark + "L",
122
            exifReader.tiftag.slice(4, 8))[0];
123
        exif_dict["0th"] = exifReader.get_ifd(pointer, "0th");
124
 
125
        var first_ifd_pointer = exif_dict["0th"]["first_ifd_pointer"];
126
        delete exif_dict["0th"]["first_ifd_pointer"];
127
 
128
        if (34665 in exif_dict["0th"]) {
129
            pointer = exif_dict["0th"][34665];
130
            exif_dict["Exif"] = exifReader.get_ifd(pointer, "Exif");
131
        }
132
        if (34853 in exif_dict["0th"]) {
133
            pointer = exif_dict["0th"][34853];
134
            exif_dict["GPS"] = exifReader.get_ifd(pointer, "GPS");
135
        }
136
        if (40965 in exif_dict["Exif"]) {
137
            pointer = exif_dict["Exif"][40965];
138
            exif_dict["Interop"] = exifReader.get_ifd(pointer, "Interop");
139
        }
140
        if (first_ifd_pointer != "\x00\x00\x00\x00") {
141
            pointer = unpack(exifReader.endian_mark + "L",
142
                first_ifd_pointer)[0];
143
            exif_dict["1st"] = exifReader.get_ifd(pointer, "1st");
144
            if ((513 in exif_dict["1st"]) && (514 in exif_dict["1st"])) {
145
                var end = exif_dict["1st"][513] + exif_dict["1st"][514];
146
                var thumb = exifReader.tiftag.slice(exif_dict["1st"][513], end);
147
                exif_dict["thumbnail"] = thumb;
148
            }
149
        }
150
 
151
        return exif_dict;
152
    };
153
 
154
 
155
    that.dump = function (exif_dict_original) {
156
        var TIFF_HEADER_LENGTH = 8;
157
 
158
        var exif_dict = copy(exif_dict_original);
159
        var header = "Exif\x00\x00\x4d\x4d\x00\x2a\x00\x00\x00\x08";
160
        var exif_is = false;
161
        var gps_is = false;
162
        var interop_is = false;
163
        var first_is = false;
164
 
165
        var zeroth_ifd,
166
            exif_ifd,
167
            interop_ifd,
168
            gps_ifd,
169
            first_ifd;
170
 
171
        if ("0th" in exif_dict) {
172
            zeroth_ifd = exif_dict["0th"];
173
        } else {
174
            zeroth_ifd = {};
175
        }
176
 
177
        if ((("Exif" in exif_dict) && (Object.keys(exif_dict["Exif"]).length)) ||
178
            (("Interop" in exif_dict) && (Object.keys(exif_dict["Interop"]).length))) {
179
            zeroth_ifd[34665] = 1;
180
            exif_is = true;
181
            exif_ifd = exif_dict["Exif"];
182
            if (("Interop" in exif_dict) && Object.keys(exif_dict["Interop"]).length) {
183
                exif_ifd[40965] = 1;
184
                interop_is = true;
185
                interop_ifd = exif_dict["Interop"];
186
            } else if (Object.keys(exif_ifd).indexOf(that.ExifIFD.InteroperabilityTag.toString()) > -1) {
187
                delete exif_ifd[40965];
188
            }
189
        } else if (Object.keys(zeroth_ifd).indexOf(that.ImageIFD.ExifTag.toString()) > -1) {
190
            delete zeroth_ifd[34665];
191
        }
192
 
193
        if (("GPS" in exif_dict) && (Object.keys(exif_dict["GPS"]).length)) {
194
            zeroth_ifd[that.ImageIFD.GPSTag] = 1;
195
            gps_is = true;
196
            gps_ifd = exif_dict["GPS"];
197
        } else if (Object.keys(zeroth_ifd).indexOf(that.ImageIFD.GPSTag.toString()) > -1) {
198
            delete zeroth_ifd[that.ImageIFD.GPSTag];
199
        }
200
 
201
        if (("1st" in exif_dict) &&
202
            ("thumbnail" in exif_dict) &&
203
            (exif_dict["thumbnail"] != null)) {
204
            first_is = true;
205
            exif_dict["1st"][513] = 1;
206
            exif_dict["1st"][514] = 1;
207
            first_ifd = exif_dict["1st"];
208
        }
209
 
210
        var zeroth_set = _dict_to_bytes(zeroth_ifd, "0th", 0);
211
        var zeroth_length = (zeroth_set[0].length + exif_is * 12 + gps_is * 12 + 4 +
212
            zeroth_set[1].length);
213
 
214
        var exif_set,
215
            exif_bytes = "",
216
            exif_length = 0,
217
            gps_set,
218
            gps_bytes = "",
219
            gps_length = 0,
220
            interop_set,
221
            interop_bytes = "",
222
            interop_length = 0,
223
            first_set,
224
            first_bytes = "",
225
            thumbnail;
226
        if (exif_is) {
227
            exif_set = _dict_to_bytes(exif_ifd, "Exif", zeroth_length);
228
            exif_length = exif_set[0].length + interop_is * 12 + exif_set[1].length;
229
        }
230
        if (gps_is) {
231
            gps_set = _dict_to_bytes(gps_ifd, "GPS", zeroth_length + exif_length);
232
            gps_bytes = gps_set.join("");
233
            gps_length = gps_bytes.length;
234
        }
235
        if (interop_is) {
236
            var offset = zeroth_length + exif_length + gps_length;
237
            interop_set = _dict_to_bytes(interop_ifd, "Interop", offset);
238
            interop_bytes = interop_set.join("");
239
            interop_length = interop_bytes.length;
240
        }
241
        if (first_is) {
242
            var offset = zeroth_length + exif_length + gps_length + interop_length;
243
            first_set = _dict_to_bytes(first_ifd, "1st", offset);
244
            thumbnail = _get_thumbnail(exif_dict["thumbnail"]);
245
            if (thumbnail.length > 64000) {
246
                throw ("Given thumbnail is too large. max 64kB");
247
            }
248
        }
249
 
250
        var exif_pointer = "",
251
            gps_pointer = "",
252
            interop_pointer = "",
253
            first_ifd_pointer = "\x00\x00\x00\x00";
254
        if (exif_is) {
255
            var pointer_value = TIFF_HEADER_LENGTH + zeroth_length;
256
            var pointer_str = pack(">L", [pointer_value]);
257
            var key = 34665;
258
            var key_str = pack(">H", [key]);
259
            var type_str = pack(">H", [TYPES["Long"]]);
260
            var length_str = pack(">L", [1]);
261
            exif_pointer = key_str + type_str + length_str + pointer_str;
262
        }
263
        if (gps_is) {
264
            var pointer_value = TIFF_HEADER_LENGTH + zeroth_length + exif_length;
265
            var pointer_str = pack(">L", [pointer_value]);
266
            var key = 34853;
267
            var key_str = pack(">H", [key]);
268
            var type_str = pack(">H", [TYPES["Long"]]);
269
            var length_str = pack(">L", [1]);
270
            gps_pointer = key_str + type_str + length_str + pointer_str;
271
        }
272
        if (interop_is) {
273
            var pointer_value = (TIFF_HEADER_LENGTH +
274
                zeroth_length + exif_length + gps_length);
275
            var pointer_str = pack(">L", [pointer_value]);
276
            var key = 40965;
277
            var key_str = pack(">H", [key]);
278
            var type_str = pack(">H", [TYPES["Long"]]);
279
            var length_str = pack(">L", [1]);
280
            interop_pointer = key_str + type_str + length_str + pointer_str;
281
        }
282
        if (first_is) {
283
            var pointer_value = (TIFF_HEADER_LENGTH + zeroth_length +
284
                exif_length + gps_length + interop_length);
285
            first_ifd_pointer = pack(">L", [pointer_value]);
286
            var thumbnail_pointer = (pointer_value + first_set[0].length + 24 +
287
                4 + first_set[1].length);
288
            var thumbnail_p_bytes = ("\x02\x01\x00\x04\x00\x00\x00\x01" +
289
                pack(">L", [thumbnail_pointer]));
290
            var thumbnail_length_bytes = ("\x02\x02\x00\x04\x00\x00\x00\x01" +
291
                pack(">L", [thumbnail.length]));
292
            first_bytes = (first_set[0] + thumbnail_p_bytes +
293
                thumbnail_length_bytes + "\x00\x00\x00\x00" +
294
                first_set[1] + thumbnail);
295
        }
296
 
297
        var zeroth_bytes = (zeroth_set[0] + exif_pointer + gps_pointer +
298
            first_ifd_pointer + zeroth_set[1]);
299
        if (exif_is) {
300
            exif_bytes = exif_set[0] + interop_pointer + exif_set[1];
301
        }
302
 
303
        return (header + zeroth_bytes + exif_bytes + gps_bytes +
304
            interop_bytes + first_bytes);
305
    };
306
 
307
 
308
    function copy(obj) {
309
        return JSON.parse(JSON.stringify(obj));
310
    }
311
 
312
 
313
    function _get_thumbnail(jpeg) {
314
        var segments = splitIntoSegments(jpeg);
315
        while (("\xff\xe0" <= segments[1].slice(0, 2)) && (segments[1].slice(0, 2) <= "\xff\xef")) {
316
            segments = [segments[0]].concat(segments.slice(2));
317
        }
318
        return segments.join("");
319
    }
320
 
321
 
322
    function _pack_byte(array) {
323
        return pack(">" + nStr("B", array.length), array);
324
    }
325
 
326
 
327
    function _pack_short(array) {
328
        return pack(">" + nStr("H", array.length), array);
329
    }
330
 
331
 
332
    function _pack_long(array) {
333
        return pack(">" + nStr("L", array.length), array);
334
    }
335
 
336
 
337
    function _value_to_bytes(raw_value, value_type, offset) {
338
        var four_bytes_over = "";
339
        var value_str = "";
340
        var length,
341
            new_value,
342
            num,
343
            den;
344
 
345
        if (value_type == "Byte") {
346
            length = raw_value.length;
347
            if (length <= 4) {
348
                value_str = (_pack_byte(raw_value) +
349
                    nStr("\x00", 4 - length));
350
            } else {
351
                value_str = pack(">L", [offset]);
352
                four_bytes_over = _pack_byte(raw_value);
353
            }
354
        } else if (value_type == "Short") {
355
            length = raw_value.length;
356
            if (length <= 2) {
357
                value_str = (_pack_short(raw_value) +
358
                    nStr("\x00\x00", 2 - length));
359
            } else {
360
                value_str = pack(">L", [offset]);
361
                four_bytes_over = _pack_short(raw_value);
362
            }
363
        } else if (value_type == "Long") {
364
            length = raw_value.length;
365
            if (length <= 1) {
366
                value_str = _pack_long(raw_value);
367
            } else {
368
                value_str = pack(">L", [offset]);
369
                four_bytes_over = _pack_long(raw_value);
370
            }
371
        } else if (value_type == "Ascii") {
372
            new_value = raw_value + "\x00";
373
            length = new_value.length;
374
            if (length > 4) {
375
                value_str = pack(">L", [offset]);
376
                four_bytes_over = new_value;
377
            } else {
378
                value_str = new_value + nStr("\x00", 4 - length);
379
            }
380
        } else if (value_type == "Rational") {
381
            if (typeof (raw_value[0]) == "number") {
382
                length = 1;
383
                num = raw_value[0];
384
                den = raw_value[1];
385
                new_value = pack(">L", [num]) + pack(">L", [den]);
386
            } else {
387
                length = raw_value.length;
388
                new_value = "";
389
                for (var n = 0; n < length; n++) {
390
                    num = raw_value[n][0];
391
                    den = raw_value[n][1];
392
                    new_value += (pack(">L", [num]) +
393
                        pack(">L", [den]));
394
                }
395
            }
396
            value_str = pack(">L", [offset]);
397
            four_bytes_over = new_value;
398
        } else if (value_type == "SRational") {
399
            if (typeof (raw_value[0]) == "number") {
400
                length = 1;
401
                num = raw_value[0];
402
                den = raw_value[1];
403
                new_value = pack(">l", [num]) + pack(">l", [den]);
404
            } else {
405
                length = raw_value.length;
406
                new_value = "";
407
                for (var n = 0; n < length; n++) {
408
                    num = raw_value[n][0];
409
                    den = raw_value[n][1];
410
                    new_value += (pack(">l", [num]) +
411
                        pack(">l", [den]));
412
                }
413
            }
414
            value_str = pack(">L", [offset]);
415
            four_bytes_over = new_value;
416
        } else if (value_type == "Undefined") {
417
            length = raw_value.length;
418
            if (length > 4) {
419
                value_str = pack(">L", [offset]);
420
                four_bytes_over = raw_value;
421
            } else {
422
                value_str = raw_value + nStr("\x00", 4 - length);
423
            }
424
        }
425
 
426
        var length_str = pack(">L", [length]);
427
 
428
        return [length_str, value_str, four_bytes_over];
429
    }
430
 
431
    function _dict_to_bytes(ifd_dict, ifd, ifd_offset) {
432
        var TIFF_HEADER_LENGTH = 8;
433
        var tag_count = Object.keys(ifd_dict).length;
434
        var entry_header = pack(">H", [tag_count]);
435
        var entries_length;
436
        if (["0th", "1st"].indexOf(ifd) > -1) {
437
            entries_length = 2 + tag_count * 12 + 4;
438
        } else {
439
            entries_length = 2 + tag_count * 12;
440
        }
441
        var entries = "";
442
        var values = "";
443
        var key;
444
 
445
        for (var key in ifd_dict) {
446
            if (typeof (key) == "string") {
447
                key = parseInt(key);
448
            }
449
            if ((ifd == "0th") && ([34665, 34853].indexOf(key) > -1)) {
450
                continue;
451
            } else if ((ifd == "Exif") && (key == 40965)) {
452
                continue;
453
            } else if ((ifd == "1st") && ([513, 514].indexOf(key) > -1)) {
454
                continue;
455
            }
456
 
457
            var raw_value = ifd_dict[key];
458
            var key_str = pack(">H", [key]);
459
            var value_type = TAGS[ifd][key]["type"];
460
            var type_str = pack(">H", [TYPES[value_type]]);
461
 
462
            if (typeof (raw_value) == "number") {
463
                raw_value = [raw_value];
464
            }
465
            var offset = TIFF_HEADER_LENGTH + entries_length + ifd_offset + values.length;
466
            var b = _value_to_bytes(raw_value, value_type, offset);
467
            var length_str = b[0];
468
            var value_str = b[1];
469
            var four_bytes_over = b[2];
470
 
471
            entries += key_str + type_str + length_str + value_str;
472
            values += four_bytes_over;
473
        }
474
 
475
        return [entry_header + entries, values];
476
    }
477
 
478
 
479
 
480
    function ExifReader(data) {
481
        var segments,
482
            app1;
483
        if (data.slice(0, 2) == "\xff\xd8") { // JPEG
484
            segments = splitIntoSegments(data);
485
            app1 = getExifSeg(segments);
486
            if (app1) {
487
                this.tiftag = app1.slice(10);
488
            } else {
489
                this.tiftag = null;
490
            }
491
        } else if (["\x49\x49", "\x4d\x4d"].indexOf(data.slice(0, 2)) > -1) { // TIFF
492
            this.tiftag = data;
493
        } else if (data.slice(0, 4) == "Exif") { // Exif
494
            this.tiftag = data.slice(6);
495
        } else {
496
            throw ("Given file is neither JPEG nor TIFF.");
497
        }
498
    }
499
 
500
    ExifReader.prototype = {
501
        get_ifd: function (pointer, ifd_name) {
502
            var ifd_dict = {};
503
            var tag_count = unpack(this.endian_mark + "H",
504
                this.tiftag.slice(pointer, pointer + 2))[0];
505
            var offset = pointer + 2;
506
            var t;
507
            if (["0th", "1st"].indexOf(ifd_name) > -1) {
508
                t = "Image";
509
            } else {
510
                t = ifd_name;
511
            }
512
 
513
            for (var x = 0; x < tag_count; x++) {
514
                pointer = offset + 12 * x;
515
                var tag = unpack(this.endian_mark + "H",
516
                    this.tiftag.slice(pointer, pointer + 2))[0];
517
                var value_type = unpack(this.endian_mark + "H",
518
                    this.tiftag.slice(pointer + 2, pointer + 4))[0];
519
                var value_num = unpack(this.endian_mark + "L",
520
                    this.tiftag.slice(pointer + 4, pointer + 8))[0];
521
                var value = this.tiftag.slice(pointer + 8, pointer + 12);
522
 
523
                var v_set = [value_type, value_num, value];
524
                if (tag in TAGS[t]) {
525
                    ifd_dict[tag] = this.convert_value(v_set);
526
                }
527
            }
528
 
529
            if (ifd_name == "0th") {
530
                pointer = offset + 12 * tag_count;
531
                ifd_dict["first_ifd_pointer"] = this.tiftag.slice(pointer, pointer + 4);
532
            }
533
 
534
            return ifd_dict;
535
        },
536
 
537
        convert_value: function (val) {
538
            var data = null;
539
            var t = val[0];
540
            var length = val[1];
541
            var value = val[2];
542
            var pointer;
543
 
544
            if (t == 1) { // BYTE
545
                if (length > 4) {
546
                    pointer = unpack(this.endian_mark + "L", value)[0];
547
                    data = unpack(this.endian_mark + nStr("B", length),
548
                        this.tiftag.slice(pointer, pointer + length));
549
                } else {
550
                    data = unpack(this.endian_mark + nStr("B", length), value.slice(0, length));
551
                }
552
            } else if (t == 2) { // ASCII
553
                if (length > 4) {
554
                    pointer = unpack(this.endian_mark + "L", value)[0];
555
                    data = this.tiftag.slice(pointer, pointer + length - 1);
556
                } else {
557
                    data = value.slice(0, length - 1);
558
                }
559
            } else if (t == 3) { // SHORT
560
                if (length > 2) {
561
                    pointer = unpack(this.endian_mark + "L", value)[0];
562
                    data = unpack(this.endian_mark + nStr("H", length),
563
                        this.tiftag.slice(pointer, pointer + length * 2));
564
                } else {
565
                    data = unpack(this.endian_mark + nStr("H", length),
566
                        value.slice(0, length * 2));
567
                }
568
            } else if (t == 4) { // LONG
569
                if (length > 1) {
570
                    pointer = unpack(this.endian_mark + "L", value)[0];
571
                    data = unpack(this.endian_mark + nStr("L", length),
572
                        this.tiftag.slice(pointer, pointer + length * 4));
573
                } else {
574
                    data = unpack(this.endian_mark + nStr("L", length),
575
                        value);
576
                }
577
            } else if (t == 5) { // RATIONAL
578
                pointer = unpack(this.endian_mark + "L", value)[0];
579
                if (length > 1) {
580
                    data = [];
581
                    for (var x = 0; x < length; x++) {
582
                        data.push([unpack(this.endian_mark + "L",
583
                                this.tiftag.slice(pointer + x * 8, pointer + 4 + x * 8))[0],
584
                                   unpack(this.endian_mark + "L",
585
                                this.tiftag.slice(pointer + 4 + x * 8, pointer + 8 + x * 8))[0]
586
                                   ]);
587
                    }
588
                } else {
589
                    data = [unpack(this.endian_mark + "L",
590
                            this.tiftag.slice(pointer, pointer + 4))[0],
591
                            unpack(this.endian_mark + "L",
592
                            this.tiftag.slice(pointer + 4, pointer + 8))[0]
593
                            ];
594
                }
595
            } else if (t == 7) { // UNDEFINED BYTES
596
                if (length > 4) {
597
                    pointer = unpack(this.endian_mark + "L", value)[0];
598
                    data = this.tiftag.slice(pointer, pointer + length);
599
                } else {
600
                    data = value.slice(0, length);
601
                }
602
            } else if (t == 10) { // SRATIONAL
603
                pointer = unpack(this.endian_mark + "L", value)[0];
604
                if (length > 1) {
605
                    data = [];
606
                    for (var x = 0; x < length; x++) {
607
                        data.push([unpack(this.endian_mark + "l",
608
                                this.tiftag.slice(pointer + x * 8, pointer + 4 + x * 8))[0],
609
                                   unpack(this.endian_mark + "l",
610
                                this.tiftag.slice(pointer + 4 + x * 8, pointer + 8 + x * 8))[0]
611
                                  ]);
612
                    }
613
                } else {
614
                    data = [unpack(this.endian_mark + "l",
615
                            this.tiftag.slice(pointer, pointer + 4))[0],
616
                            unpack(this.endian_mark + "l",
617
                            this.tiftag.slice(pointer + 4, pointer + 8))[0]
618
                           ];
619
                }
620
            } else {
621
                throw ("Exif might be wrong. Got incorrect value " +
622
                    "type to decode. type:" + t);
623
            }
624
 
625
            if ((data instanceof Array) && (data.length == 1)) {
626
                return data[0];
627
            } else {
628
                return data;
629
            }
630
        },
631
    };
632
 
633
 
634
    if (typeof window !== "undefined" && typeof window.btoa === "function") {
635
        var btoa = window.btoa;
636
    }
637
    if (typeof btoa === "undefined") {
638
        var btoa = function (input) {        var output = "";
639
            var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
640
            var i = 0;
641
            var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
642
 
643
            while (i < input.length) {
644
 
645
                chr1 = input.charCodeAt(i++);
646
                chr2 = input.charCodeAt(i++);
647
                chr3 = input.charCodeAt(i++);
648
 
649
                enc1 = chr1 >> 2;
650
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
651
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
652
                enc4 = chr3 & 63;
653
 
654
                if (isNaN(chr2)) {
655
                    enc3 = enc4 = 64;
656
                } else if (isNaN(chr3)) {
657
                    enc4 = 64;
658
                }
659
 
660
                output = output +
661
                keyStr.charAt(enc1) + keyStr.charAt(enc2) +
662
                keyStr.charAt(enc3) + keyStr.charAt(enc4);
663
 
664
            }
665
 
666
            return output;
667
        };
668
    }
669
 
670
 
671
    if (typeof window !== "undefined" && typeof window.atob === "function") {
672
        var atob = window.atob;
673
    }
674
    if (typeof atob === "undefined") {
675
        var atob = function (input) {
676
            var output = "";
677
            var chr1, chr2, chr3;
678
            var enc1, enc2, enc3, enc4;
679
            var i = 0;
680
            var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
681
 
682
            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
683
 
684
            while (i < input.length) {
685
 
686
                enc1 = keyStr.indexOf(input.charAt(i++));
687
                enc2 = keyStr.indexOf(input.charAt(i++));
688
                enc3 = keyStr.indexOf(input.charAt(i++));
689
                enc4 = keyStr.indexOf(input.charAt(i++));
690
 
691
                chr1 = (enc1 << 2) | (enc2 >> 4);
692
                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
693
                chr3 = ((enc3 & 3) << 6) | enc4;
694
 
695
                output = output + String.fromCharCode(chr1);
696
 
697
                if (enc3 != 64) {
698
                    output = output + String.fromCharCode(chr2);
699
                }
700
                if (enc4 != 64) {
701
                    output = output + String.fromCharCode(chr3);
702
                }
703
 
704
            }
705
 
706
            return output;
707
        };
708
    }
709
 
710
 
711
    function getImageSize(imageArray) {
712
        var segments = slice2Segments(imageArray);
713
        var seg,
714
            width,
715
            height,
716
            SOF = [192, 193, 194, 195, 197, 198, 199, 201, 202, 203, 205, 206, 207];
717
 
718
        for (var x = 0; x < segments.length; x++) {
719
            seg = segments[x];
720
            if (SOF.indexOf(seg[1]) >= 0) {
721
                height = seg[5] * 256 + seg[6];
722
                width = seg[7] * 256 + seg[8];
723
                break;
724
            }
725
        }
726
        return [width, height];
727
    }
728
 
729
 
730
    function pack(mark, array) {
731
        if (!(array instanceof Array)) {
732
            throw ("'pack' error. Got invalid type argument.");
733
        }
734
        if ((mark.length - 1) != array.length) {
735
            throw ("'pack' error. " + (mark.length - 1) + " marks, " + array.length + " elements.");
736
        }
737
 
738
        var littleEndian;
739
        if (mark[0] == "<") {
740
            littleEndian = true;
741
        } else if (mark[0] == ">") {
742
            littleEndian = false;
743
        } else {
744
            throw ("");
745
        }
746
        var packed = "";
747
        var p = 1;
748
        var val = null;
749
        var c = null;
750
        var valStr = null;
751
 
752
        while (c = mark[p]) {
753
            if (c.toLowerCase() == "b") {
754
                val = array[p - 1];
755
                if ((c == "b") && (val < 0)) {
756
                    val += 0x100;
757
                }
758
                if ((val > 0xff) || (val < 0)) {
759
                    throw ("'pack' error.");
760
                } else {
761
                    valStr = String.fromCharCode(val);
762
                }
763
            } else if (c == "H") {
764
                val = array[p - 1];
765
                if ((val > 0xffff) || (val < 0)) {
766
                    throw ("'pack' error.");
767
                } else {
768
                    valStr = String.fromCharCode(Math.floor((val % 0x10000) / 0x100)) +
769
                        String.fromCharCode(val % 0x100);
770
                    if (littleEndian) {
771
                        valStr = valStr.split("").reverse().join("");
772
                    }
773
                }
774
            } else if (c.toLowerCase() == "l") {
775
                val = array[p - 1];
776
                if ((c == "l") && (val < 0)) {
777
                    val += 0x100000000;
778
                }
779
                if ((val > 0xffffffff) || (val < 0)) {
780
                    throw ("'pack' error.");
781
                } else {
782
                    valStr = String.fromCharCode(Math.floor(val / 0x1000000)) +
783
                        String.fromCharCode(Math.floor((val % 0x1000000) / 0x10000)) +
784
                        String.fromCharCode(Math.floor((val % 0x10000) / 0x100)) +
785
                        String.fromCharCode(val % 0x100);
786
                    if (littleEndian) {
787
                        valStr = valStr.split("").reverse().join("");
788
                    }
789
                }
790
            } else {
791
                throw ("'pack' error.");
792
            }
793
 
794
            packed += valStr;
795
            p += 1;
796
        }
797
 
798
        return packed;
799
    }
800
 
801
    function unpack(mark, str) {
802
        if (typeof (str) != "string") {
803
            throw ("'unpack' error. Got invalid type argument.");
804
        }
805
        var l = 0;
806
        for (var markPointer = 1; markPointer < mark.length; markPointer++) {
807
            if (mark[markPointer].toLowerCase() == "b") {
808
                l += 1;
809
            } else if (mark[markPointer].toLowerCase() == "h") {
810
                l += 2;
811
            } else if (mark[markPointer].toLowerCase() == "l") {
812
                l += 4;
813
            } else {
814
                throw ("'unpack' error. Got invalid mark.");
815
            }
816
        }
817
 
818
        if (l != str.length) {
819
            throw ("'unpack' error. Mismatch between symbol and string length. " + l + ":" + str.length);
820
        }
821
 
822
        var littleEndian;
823
        if (mark[0] == "<") {
824
            littleEndian = true;
825
        } else if (mark[0] == ">") {
826
            littleEndian = false;
827
        } else {
828
            throw ("'unpack' error.");
829
        }
830
        var unpacked = [];
831
        var strPointer = 0;
832
        var p = 1;
833
        var val = null;
834
        var c = null;
835
        var length = null;
836
        var sliced = "";
837
 
838
        while (c = mark[p]) {
839
            if (c.toLowerCase() == "b") {
840
                length = 1;
841
                sliced = str.slice(strPointer, strPointer + length);
842
                val = sliced.charCodeAt(0);
843
                if ((c == "b") && (val >= 0x80)) {
844
                    val -= 0x100;
845
                }
846
            } else if (c == "H") {
847
                length = 2;
848
                sliced = str.slice(strPointer, strPointer + length);
849
                if (littleEndian) {
850
                    sliced = sliced.split("").reverse().join("");
851
                }
852
                val = sliced.charCodeAt(0) * 0x100 +
853
                    sliced.charCodeAt(1);
854
            } else if (c.toLowerCase() == "l") {
855
                length = 4;
856
                sliced = str.slice(strPointer, strPointer + length);
857
                if (littleEndian) {
858
                    sliced = sliced.split("").reverse().join("");
859
                }
860
                val = sliced.charCodeAt(0) * 0x1000000 +
861
                    sliced.charCodeAt(1) * 0x10000 +
862
                    sliced.charCodeAt(2) * 0x100 +
863
                    sliced.charCodeAt(3);
864
                if ((c == "l") && (val >= 0x80000000)) {
865
                    val -= 0x100000000;
866
                }
867
            } else {
868
                throw ("'unpack' error. " + c);
869
            }
870
 
871
            unpacked.push(val);
872
            strPointer += length;
873
            p += 1;
874
        }
875
 
876
        return unpacked;
877
    }
878
 
879
    function nStr(ch, num) {
880
        var str = "";
881
        for (var i = 0; i < num; i++) {
882
            str += ch;
883
        }
884
        return str;
885
    }
886
 
887
    function splitIntoSegments(data) {
888
        if (data.slice(0, 2) != "\xff\xd8") {
889
            throw ("Given data isn't JPEG.");
890
        }
891
 
892
        var head = 2;
893
        var segments = ["\xff\xd8"];
894
        while (true) {
895
            if (data.slice(head, head + 2) == "\xff\xda") {
896
                segments.push(data.slice(head));
897
                break;
898
            } else {
899
                var length = unpack(">H", data.slice(head + 2, head + 4))[0];
900
                var endPoint = head + length + 2;
901
                segments.push(data.slice(head, endPoint));
902
                head = endPoint;
903
            }
904
 
905
            if (head >= data.length) {
906
                throw ("Wrong JPEG data.");
907
            }
908
        }
909
        return segments;
910
    }
911
 
912
 
913
    function getExifSeg(segments) {
914
        var seg;
915
        for (var i = 0; i < segments.length; i++) {
916
            seg = segments[i];
917
            if (seg.slice(0, 2) == "\xff\xe1" &&
918
                   seg.slice(4, 10) == "Exif\x00\x00") {
919
                return seg;
920
            }
921
        }
922
        return null;
923
    }
924
 
925
 
926
    function mergeSegments(segments, exif) {
927
 
928
        if (segments[1].slice(0, 2) == "\xff\xe0" &&
929
            (segments[2].slice(0, 2) == "\xff\xe1" &&
930
             segments[2].slice(4, 10) == "Exif\x00\x00")) {
931
            if (exif) {
932
                segments[2] = exif;
933
                segments = ["\xff\xd8"].concat(segments.slice(2));
934
            } else if (exif == null) {
935
                segments = segments.slice(0, 2).concat(segments.slice(3));
936
            } else {
937
                segments = segments.slice(0).concat(segments.slice(2));
938
            }
939
        } else if (segments[1].slice(0, 2) == "\xff\xe0") {
940
            if (exif) {
941
                segments[1] = exif;
942
            }
943
        } else if (segments[1].slice(0, 2) == "\xff\xe1" &&
944
                   segments[1].slice(4, 10) == "Exif\x00\x00") {
945
            if (exif) {
946
                segments[1] = exif;
947
            } else if (exif == null) {
948
                segments = segments.slice(0).concat(segments.slice(2));
949
            }
950
        } else {
951
            if (exif) {
952
                segments = [segments[0], exif].concat(segments.slice(1));
953
            }
954
        }
955
 
956
        return segments.join("");
957
    }
958
 
959
 
960
    function toHex(str) {
961
        var hexStr = "";
962
        for (var i = 0; i < str.length; i++) {
963
            var h = str.charCodeAt(i);
964
            var hex = ((h < 10) ? "0" : "") + h.toString(16);
965
            hexStr += hex + " ";
966
        }
967
        return hexStr;
968
    }
969
 
970
 
971
    var TYPES = {
972
        "Byte": 1,
973
        "Ascii": 2,
974
        "Short": 3,
975
        "Long": 4,
976
        "Rational": 5,
977
        "Undefined": 7,
978
        "SLong": 9,
979
        "SRational": 10
980
    };
981
 
982
 
983
    var TAGS = {
984
        'Image': {
985
            11: {
986
                'name': 'ProcessingSoftware',
987
                'type': 'Ascii'
988
            },
989
            254: {
990
                'name': 'NewSubfileType',
991
                'type': 'Long'
992
            },
993
            255: {
994
                'name': 'SubfileType',
995
                'type': 'Short'
996
            },
997
            256: {
998
                'name': 'ImageWidth',
999
                'type': 'Long'
1000
            },
1001
            257: {
1002
                'name': 'ImageLength',
1003
                'type': 'Long'
1004
            },
1005
            258: {
1006
                'name': 'BitsPerSample',
1007
                'type': 'Short'
1008
            },
1009
            259: {
1010
                'name': 'Compression',
1011
                'type': 'Short'
1012
            },
1013
            262: {
1014
                'name': 'PhotometricInterpretation',
1015
                'type': 'Short'
1016
            },
1017
            263: {
1018
                'name': 'Threshholding',
1019
                'type': 'Short'
1020
            },
1021
            264: {
1022
                'name': 'CellWidth',
1023
                'type': 'Short'
1024
            },
1025
            265: {
1026
                'name': 'CellLength',
1027
                'type': 'Short'
1028
            },
1029
            266: {
1030
                'name': 'FillOrder',
1031
                'type': 'Short'
1032
            },
1033
            269: {
1034
                'name': 'DocumentName',
1035
                'type': 'Ascii'
1036
            },
1037
            270: {
1038
                'name': 'ImageDescription',
1039
                'type': 'Ascii'
1040
            },
1041
            271: {
1042
                'name': 'Make',
1043
                'type': 'Ascii'
1044
            },
1045
            272: {
1046
                'name': 'Model',
1047
                'type': 'Ascii'
1048
            },
1049
            273: {
1050
                'name': 'StripOffsets',
1051
                'type': 'Long'
1052
            },
1053
            274: {
1054
                'name': 'Orientation',
1055
                'type': 'Short'
1056
            },
1057
            277: {
1058
                'name': 'SamplesPerPixel',
1059
                'type': 'Short'
1060
            },
1061
            278: {
1062
                'name': 'RowsPerStrip',
1063
                'type': 'Long'
1064
            },
1065
            279: {
1066
                'name': 'StripByteCounts',
1067
                'type': 'Long'
1068
            },
1069
            282: {
1070
                'name': 'XResolution',
1071
                'type': 'Rational'
1072
            },
1073
            283: {
1074
                'name': 'YResolution',
1075
                'type': 'Rational'
1076
            },
1077
            284: {
1078
                'name': 'PlanarConfiguration',
1079
                'type': 'Short'
1080
            },
1081
            290: {
1082
                'name': 'GrayResponseUnit',
1083
                'type': 'Short'
1084
            },
1085
            291: {
1086
                'name': 'GrayResponseCurve',
1087
                'type': 'Short'
1088
            },
1089
            292: {
1090
                'name': 'T4Options',
1091
                'type': 'Long'
1092
            },
1093
            293: {
1094
                'name': 'T6Options',
1095
                'type': 'Long'
1096
            },
1097
            296: {
1098
                'name': 'ResolutionUnit',
1099
                'type': 'Short'
1100
            },
1101
            301: {
1102
                'name': 'TransferFunction',
1103
                'type': 'Short'
1104
            },
1105
            305: {
1106
                'name': 'Software',
1107
                'type': 'Ascii'
1108
            },
1109
            306: {
1110
                'name': 'DateTime',
1111
                'type': 'Ascii'
1112
            },
1113
            315: {
1114
                'name': 'Artist',
1115
                'type': 'Ascii'
1116
            },
1117
            316: {
1118
                'name': 'HostComputer',
1119
                'type': 'Ascii'
1120
            },
1121
            317: {
1122
                'name': 'Predictor',
1123
                'type': 'Short'
1124
            },
1125
            318: {
1126
                'name': 'WhitePoint',
1127
                'type': 'Rational'
1128
            },
1129
            319: {
1130
                'name': 'PrimaryChromaticities',
1131
                'type': 'Rational'
1132
            },
1133
            320: {
1134
                'name': 'ColorMap',
1135
                'type': 'Short'
1136
            },
1137
            321: {
1138
                'name': 'HalftoneHints',
1139
                'type': 'Short'
1140
            },
1141
            322: {
1142
                'name': 'TileWidth',
1143
                'type': 'Short'
1144
            },
1145
            323: {
1146
                'name': 'TileLength',
1147
                'type': 'Short'
1148
            },
1149
            324: {
1150
                'name': 'TileOffsets',
1151
                'type': 'Short'
1152
            },
1153
            325: {
1154
                'name': 'TileByteCounts',
1155
                'type': 'Short'
1156
            },
1157
            330: {
1158
                'name': 'SubIFDs',
1159
                'type': 'Long'
1160
            },
1161
            332: {
1162
                'name': 'InkSet',
1163
                'type': 'Short'
1164
            },
1165
            333: {
1166
                'name': 'InkNames',
1167
                'type': 'Ascii'
1168
            },
1169
            334: {
1170
                'name': 'NumberOfInks',
1171
                'type': 'Short'
1172
            },
1173
            336: {
1174
                'name': 'DotRange',
1175
                'type': 'Byte'
1176
            },
1177
            337: {
1178
                'name': 'TargetPrinter',
1179
                'type': 'Ascii'
1180
            },
1181
            338: {
1182
                'name': 'ExtraSamples',
1183
                'type': 'Short'
1184
            },
1185
            339: {
1186
                'name': 'SampleFormat',
1187
                'type': 'Short'
1188
            },
1189
            340: {
1190
                'name': 'SMinSampleValue',
1191
                'type': 'Short'
1192
            },
1193
            341: {
1194
                'name': 'SMaxSampleValue',
1195
                'type': 'Short'
1196
            },
1197
            342: {
1198
                'name': 'TransferRange',
1199
                'type': 'Short'
1200
            },
1201
            343: {
1202
                'name': 'ClipPath',
1203
                'type': 'Byte'
1204
            },
1205
            344: {
1206
                'name': 'XClipPathUnits',
1207
                'type': 'Long'
1208
            },
1209
            345: {
1210
                'name': 'YClipPathUnits',
1211
                'type': 'Long'
1212
            },
1213
            346: {
1214
                'name': 'Indexed',
1215
                'type': 'Short'
1216
            },
1217
            347: {
1218
                'name': 'JPEGTables',
1219
                'type': 'Undefined'
1220
            },
1221
            351: {
1222
                'name': 'OPIProxy',
1223
                'type': 'Short'
1224
            },
1225
            512: {
1226
                'name': 'JPEGProc',
1227
                'type': 'Long'
1228
            },
1229
            513: {
1230
                'name': 'JPEGInterchangeFormat',
1231
                'type': 'Long'
1232
            },
1233
            514: {
1234
                'name': 'JPEGInterchangeFormatLength',
1235
                'type': 'Long'
1236
            },
1237
            515: {
1238
                'name': 'JPEGRestartInterval',
1239
                'type': 'Short'
1240
            },
1241
            517: {
1242
                'name': 'JPEGLosslessPredictors',
1243
                'type': 'Short'
1244
            },
1245
            518: {
1246
                'name': 'JPEGPointTransforms',
1247
                'type': 'Short'
1248
            },
1249
            519: {
1250
                'name': 'JPEGQTables',
1251
                'type': 'Long'
1252
            },
1253
            520: {
1254
                'name': 'JPEGDCTables',
1255
                'type': 'Long'
1256
            },
1257
            521: {
1258
                'name': 'JPEGACTables',
1259
                'type': 'Long'
1260
            },
1261
            529: {
1262
                'name': 'YCbCrCoefficients',
1263
                'type': 'Rational'
1264
            },
1265
            530: {
1266
                'name': 'YCbCrSubSampling',
1267
                'type': 'Short'
1268
            },
1269
            531: {
1270
                'name': 'YCbCrPositioning',
1271
                'type': 'Short'
1272
            },
1273
            532: {
1274
                'name': 'ReferenceBlackWhite',
1275
                'type': 'Rational'
1276
            },
1277
            700: {
1278
                'name': 'XMLPacket',
1279
                'type': 'Byte'
1280
            },
1281
            18246: {
1282
                'name': 'Rating',
1283
                'type': 'Short'
1284
            },
1285
            18249: {
1286
                'name': 'RatingPercent',
1287
                'type': 'Short'
1288
            },
1289
            32781: {
1290
                'name': 'ImageID',
1291
                'type': 'Ascii'
1292
            },
1293
            33421: {
1294
                'name': 'CFARepeatPatternDim',
1295
                'type': 'Short'
1296
            },
1297
            33422: {
1298
                'name': 'CFAPattern',
1299
                'type': 'Byte'
1300
            },
1301
            33423: {
1302
                'name': 'BatteryLevel',
1303
                'type': 'Rational'
1304
            },
1305
            33432: {
1306
                'name': 'Copyright',
1307
                'type': 'Ascii'
1308
            },
1309
            33434: {
1310
                'name': 'ExposureTime',
1311
                'type': 'Rational'
1312
            },
1313
            34377: {
1314
                'name': 'ImageResources',
1315
                'type': 'Byte'
1316
            },
1317
            34665: {
1318
                'name': 'ExifTag',
1319
                'type': 'Long'
1320
            },
1321
            34675: {
1322
                'name': 'InterColorProfile',
1323
                'type': 'Undefined'
1324
            },
1325
            34853: {
1326
                'name': 'GPSTag',
1327
                'type': 'Long'
1328
            },
1329
            34857: {
1330
                'name': 'Interlace',
1331
                'type': 'Short'
1332
            },
1333
            34858: {
1334
                'name': 'TimeZoneOffset',
1335
                'type': 'Long'
1336
            },
1337
            34859: {
1338
                'name': 'SelfTimerMode',
1339
                'type': 'Short'
1340
            },
1341
            37387: {
1342
                'name': 'FlashEnergy',
1343
                'type': 'Rational'
1344
            },
1345
            37388: {
1346
                'name': 'SpatialFrequencyResponse',
1347
                'type': 'Undefined'
1348
            },
1349
            37389: {
1350
                'name': 'Noise',
1351
                'type': 'Undefined'
1352
            },
1353
            37390: {
1354
                'name': 'FocalPlaneXResolution',
1355
                'type': 'Rational'
1356
            },
1357
            37391: {
1358
                'name': 'FocalPlaneYResolution',
1359
                'type': 'Rational'
1360
            },
1361
            37392: {
1362
                'name': 'FocalPlaneResolutionUnit',
1363
                'type': 'Short'
1364
            },
1365
            37393: {
1366
                'name': 'ImageNumber',
1367
                'type': 'Long'
1368
            },
1369
            37394: {
1370
                'name': 'SecurityClassification',
1371
                'type': 'Ascii'
1372
            },
1373
            37395: {
1374
                'name': 'ImageHistory',
1375
                'type': 'Ascii'
1376
            },
1377
            37397: {
1378
                'name': 'ExposureIndex',
1379
                'type': 'Rational'
1380
            },
1381
            37398: {
1382
                'name': 'TIFFEPStandardID',
1383
                'type': 'Byte'
1384
            },
1385
            37399: {
1386
                'name': 'SensingMethod',
1387
                'type': 'Short'
1388
            },
1389
            40091: {
1390
                'name': 'XPTitle',
1391
                'type': 'Byte'
1392
            },
1393
            40092: {
1394
                'name': 'XPComment',
1395
                'type': 'Byte'
1396
            },
1397
            40093: {
1398
                'name': 'XPAuthor',
1399
                'type': 'Byte'
1400
            },
1401
            40094: {
1402
                'name': 'XPKeywords',
1403
                'type': 'Byte'
1404
            },
1405
            40095: {
1406
                'name': 'XPSubject',
1407
                'type': 'Byte'
1408
            },
1409
            50341: {
1410
                'name': 'PrintImageMatching',
1411
                'type': 'Undefined'
1412
            },
1413
            50706: {
1414
                'name': 'DNGVersion',
1415
                'type': 'Byte'
1416
            },
1417
            50707: {
1418
                'name': 'DNGBackwardVersion',
1419
                'type': 'Byte'
1420
            },
1421
            50708: {
1422
                'name': 'UniqueCameraModel',
1423
                'type': 'Ascii'
1424
            },
1425
            50709: {
1426
                'name': 'LocalizedCameraModel',
1427
                'type': 'Byte'
1428
            },
1429
            50710: {
1430
                'name': 'CFAPlaneColor',
1431
                'type': 'Byte'
1432
            },
1433
            50711: {
1434
                'name': 'CFALayout',
1435
                'type': 'Short'
1436
            },
1437
            50712: {
1438
                'name': 'LinearizationTable',
1439
                'type': 'Short'
1440
            },
1441
            50713: {
1442
                'name': 'BlackLevelRepeatDim',
1443
                'type': 'Short'
1444
            },
1445
            50714: {
1446
                'name': 'BlackLevel',
1447
                'type': 'Rational'
1448
            },
1449
            50715: {
1450
                'name': 'BlackLevelDeltaH',
1451
                'type': 'SRational'
1452
            },
1453
            50716: {
1454
                'name': 'BlackLevelDeltaV',
1455
                'type': 'SRational'
1456
            },
1457
            50717: {
1458
                'name': 'WhiteLevel',
1459
                'type': 'Short'
1460
            },
1461
            50718: {
1462
                'name': 'DefaultScale',
1463
                'type': 'Rational'
1464
            },
1465
            50719: {
1466
                'name': 'DefaultCropOrigin',
1467
                'type': 'Short'
1468
            },
1469
            50720: {
1470
                'name': 'DefaultCropSize',
1471
                'type': 'Short'
1472
            },
1473
            50721: {
1474
                'name': 'ColorMatrix1',
1475
                'type': 'SRational'
1476
            },
1477
            50722: {
1478
                'name': 'ColorMatrix2',
1479
                'type': 'SRational'
1480
            },
1481
            50723: {
1482
                'name': 'CameraCalibration1',
1483
                'type': 'SRational'
1484
            },
1485
            50724: {
1486
                'name': 'CameraCalibration2',
1487
                'type': 'SRational'
1488
            },
1489
            50725: {
1490
                'name': 'ReductionMatrix1',
1491
                'type': 'SRational'
1492
            },
1493
            50726: {
1494
                'name': 'ReductionMatrix2',
1495
                'type': 'SRational'
1496
            },
1497
            50727: {
1498
                'name': 'AnalogBalance',
1499
                'type': 'Rational'
1500
            },
1501
            50728: {
1502
                'name': 'AsShotNeutral',
1503
                'type': 'Short'
1504
            },
1505
            50729: {
1506
                'name': 'AsShotWhiteXY',
1507
                'type': 'Rational'
1508
            },
1509
            50730: {
1510
                'name': 'BaselineExposure',
1511
                'type': 'SRational'
1512
            },
1513
            50731: {
1514
                'name': 'BaselineNoise',
1515
                'type': 'Rational'
1516
            },
1517
            50732: {
1518
                'name': 'BaselineSharpness',
1519
                'type': 'Rational'
1520
            },
1521
            50733: {
1522
                'name': 'BayerGreenSplit',
1523
                'type': 'Long'
1524
            },
1525
            50734: {
1526
                'name': 'LinearResponseLimit',
1527
                'type': 'Rational'
1528
            },
1529
            50735: {
1530
                'name': 'CameraSerialNumber',
1531
                'type': 'Ascii'
1532
            },
1533
            50736: {
1534
                'name': 'LensInfo',
1535
                'type': 'Rational'
1536
            },
1537
            50737: {
1538
                'name': 'ChromaBlurRadius',
1539
                'type': 'Rational'
1540
            },
1541
            50738: {
1542
                'name': 'AntiAliasStrength',
1543
                'type': 'Rational'
1544
            },
1545
            50739: {
1546
                'name': 'ShadowScale',
1547
                'type': 'SRational'
1548
            },
1549
            50740: {
1550
                'name': 'DNGPrivateData',
1551
                'type': 'Byte'
1552
            },
1553
            50741: {
1554
                'name': 'MakerNoteSafety',
1555
                'type': 'Short'
1556
            },
1557
            50778: {
1558
                'name': 'CalibrationIlluminant1',
1559
                'type': 'Short'
1560
            },
1561
            50779: {
1562
                'name': 'CalibrationIlluminant2',
1563
                'type': 'Short'
1564
            },
1565
            50780: {
1566
                'name': 'BestQualityScale',
1567
                'type': 'Rational'
1568
            },
1569
            50781: {
1570
                'name': 'RawDataUniqueID',
1571
                'type': 'Byte'
1572
            },
1573
            50827: {
1574
                'name': 'OriginalRawFileName',
1575
                'type': 'Byte'
1576
            },
1577
            50828: {
1578
                'name': 'OriginalRawFileData',
1579
                'type': 'Undefined'
1580
            },
1581
            50829: {
1582
                'name': 'ActiveArea',
1583
                'type': 'Short'
1584
            },
1585
            50830: {
1586
                'name': 'MaskedAreas',
1587
                'type': 'Short'
1588
            },
1589
            50831: {
1590
                'name': 'AsShotICCProfile',
1591
                'type': 'Undefined'
1592
            },
1593
            50832: {
1594
                'name': 'AsShotPreProfileMatrix',
1595
                'type': 'SRational'
1596
            },
1597
            50833: {
1598
                'name': 'CurrentICCProfile',
1599
                'type': 'Undefined'
1600
            },
1601
            50834: {
1602
                'name': 'CurrentPreProfileMatrix',
1603
                'type': 'SRational'
1604
            },
1605
            50879: {
1606
                'name': 'ColorimetricReference',
1607
                'type': 'Short'
1608
            },
1609
            50931: {
1610
                'name': 'CameraCalibrationSignature',
1611
                'type': 'Byte'
1612
            },
1613
            50932: {
1614
                'name': 'ProfileCalibrationSignature',
1615
                'type': 'Byte'
1616
            },
1617
            50934: {
1618
                'name': 'AsShotProfileName',
1619
                'type': 'Byte'
1620
            },
1621
            50935: {
1622
                'name': 'NoiseReductionApplied',
1623
                'type': 'Rational'
1624
            },
1625
            50936: {
1626
                'name': 'ProfileName',
1627
                'type': 'Byte'
1628
            },
1629
            50937: {
1630
                'name': 'ProfileHueSatMapDims',
1631
                'type': 'Long'
1632
            },
1633
            50938: {
1634
                'name': 'ProfileHueSatMapData1',
1635
                'type': 'Float'
1636
            },
1637
            50939: {
1638
                'name': 'ProfileHueSatMapData2',
1639
                'type': 'Float'
1640
            },
1641
            50940: {
1642
                'name': 'ProfileToneCurve',
1643
                'type': 'Float'
1644
            },
1645
            50941: {
1646
                'name': 'ProfileEmbedPolicy',
1647
                'type': 'Long'
1648
            },
1649
            50942: {
1650
                'name': 'ProfileCopyright',
1651
                'type': 'Byte'
1652
            },
1653
            50964: {
1654
                'name': 'ForwardMatrix1',
1655
                'type': 'SRational'
1656
            },
1657
            50965: {
1658
                'name': 'ForwardMatrix2',
1659
                'type': 'SRational'
1660
            },
1661
            50966: {
1662
                'name': 'PreviewApplicationName',
1663
                'type': 'Byte'
1664
            },
1665
            50967: {
1666
                'name': 'PreviewApplicationVersion',
1667
                'type': 'Byte'
1668
            },
1669
            50968: {
1670
                'name': 'PreviewSettingsName',
1671
                'type': 'Byte'
1672
            },
1673
            50969: {
1674
                'name': 'PreviewSettingsDigest',
1675
                'type': 'Byte'
1676
            },
1677
            50970: {
1678
                'name': 'PreviewColorSpace',
1679
                'type': 'Long'
1680
            },
1681
            50971: {
1682
                'name': 'PreviewDateTime',
1683
                'type': 'Ascii'
1684
            },
1685
            50972: {
1686
                'name': 'RawImageDigest',
1687
                'type': 'Undefined'
1688
            },
1689
            50973: {
1690
                'name': 'OriginalRawFileDigest',
1691
                'type': 'Undefined'
1692
            },
1693
            50974: {
1694
                'name': 'SubTileBlockSize',
1695
                'type': 'Long'
1696
            },
1697
            50975: {
1698
                'name': 'RowInterleaveFactor',
1699
                'type': 'Long'
1700
            },
1701
            50981: {
1702
                'name': 'ProfileLookTableDims',
1703
                'type': 'Long'
1704
            },
1705
            50982: {
1706
                'name': 'ProfileLookTableData',
1707
                'type': 'Float'
1708
            },
1709
            51008: {
1710
                'name': 'OpcodeList1',
1711
                'type': 'Undefined'
1712
            },
1713
            51009: {
1714
                'name': 'OpcodeList2',
1715
                'type': 'Undefined'
1716
            },
1717
            51022: {
1718
                'name': 'OpcodeList3',
1719
                'type': 'Undefined'
1720
            }
1721
        },
1722
        'Exif': {
1723
            33434: {
1724
                'name': 'ExposureTime',
1725
                'type': 'Rational'
1726
            },
1727
            33437: {
1728
                'name': 'FNumber',
1729
                'type': 'Rational'
1730
            },
1731
            34850: {
1732
                'name': 'ExposureProgram',
1733
                'type': 'Short'
1734
            },
1735
            34852: {
1736
                'name': 'SpectralSensitivity',
1737
                'type': 'Ascii'
1738
            },
1739
            34855: {
1740
                'name': 'ISOSpeedRatings',
1741
                'type': 'Short'
1742
            },
1743
            34856: {
1744
                'name': 'OECF',
1745
                'type': 'Undefined'
1746
            },
1747
            34864: {
1748
                'name': 'SensitivityType',
1749
                'type': 'Short'
1750
            },
1751
            34865: {
1752
                'name': 'StandardOutputSensitivity',
1753
                'type': 'Long'
1754
            },
1755
            34866: {
1756
                'name': 'RecommendedExposureIndex',
1757
                'type': 'Long'
1758
            },
1759
            34867: {
1760
                'name': 'ISOSpeed',
1761
                'type': 'Long'
1762
            },
1763
            34868: {
1764
                'name': 'ISOSpeedLatitudeyyy',
1765
                'type': 'Long'
1766
            },
1767
            34869: {
1768
                'name': 'ISOSpeedLatitudezzz',
1769
                'type': 'Long'
1770
            },
1771
            36864: {
1772
                'name': 'ExifVersion',
1773
                'type': 'Undefined'
1774
            },
1775
            36867: {
1776
                'name': 'DateTimeOriginal',
1777
                'type': 'Ascii'
1778
            },
1779
            36868: {
1780
                'name': 'DateTimeDigitized',
1781
                'type': 'Ascii'
1782
            },
1783
            37121: {
1784
                'name': 'ComponentsConfiguration',
1785
                'type': 'Undefined'
1786
            },
1787
            37122: {
1788
                'name': 'CompressedBitsPerPixel',
1789
                'type': 'Rational'
1790
            },
1791
            37377: {
1792
                'name': 'ShutterSpeedValue',
1793
                'type': 'SRational'
1794
            },
1795
            37378: {
1796
                'name': 'ApertureValue',
1797
                'type': 'Rational'
1798
            },
1799
            37379: {
1800
                'name': 'BrightnessValue',
1801
                'type': 'SRational'
1802
            },
1803
            37380: {
1804
                'name': 'ExposureBiasValue',
1805
                'type': 'SRational'
1806
            },
1807
            37381: {
1808
                'name': 'MaxApertureValue',
1809
                'type': 'Rational'
1810
            },
1811
            37382: {
1812
                'name': 'SubjectDistance',
1813
                'type': 'Rational'
1814
            },
1815
            37383: {
1816
                'name': 'MeteringMode',
1817
                'type': 'Short'
1818
            },
1819
            37384: {
1820
                'name': 'LightSource',
1821
                'type': 'Short'
1822
            },
1823
            37385: {
1824
                'name': 'Flash',
1825
                'type': 'Short'
1826
            },
1827
            37386: {
1828
                'name': 'FocalLength',
1829
                'type': 'Rational'
1830
            },
1831
            37396: {
1832
                'name': 'SubjectArea',
1833
                'type': 'Short'
1834
            },
1835
            37500: {
1836
                'name': 'MakerNote',
1837
                'type': 'Undefined'
1838
            },
1839
            37510: {
1840
                'name': 'UserComment',
1841
                'type': 'Ascii'
1842
            },
1843
            37520: {
1844
                'name': 'SubSecTime',
1845
                'type': 'Ascii'
1846
            },
1847
            37521: {
1848
                'name': 'SubSecTimeOriginal',
1849
                'type': 'Ascii'
1850
            },
1851
            37522: {
1852
                'name': 'SubSecTimeDigitized',
1853
                'type': 'Ascii'
1854
            },
1855
            40960: {
1856
                'name': 'FlashpixVersion',
1857
                'type': 'Undefined'
1858
            },
1859
            40961: {
1860
                'name': 'ColorSpace',
1861
                'type': 'Short'
1862
            },
1863
            40962: {
1864
                'name': 'PixelXDimension',
1865
                'type': 'Long'
1866
            },
1867
            40963: {
1868
                'name': 'PixelYDimension',
1869
                'type': 'Long'
1870
            },
1871
            40964: {
1872
                'name': 'RelatedSoundFile',
1873
                'type': 'Ascii'
1874
            },
1875
            40965: {
1876
                'name': 'InteroperabilityTag',
1877
                'type': 'Long'
1878
            },
1879
            41483: {
1880
                'name': 'FlashEnergy',
1881
                'type': 'Rational'
1882
            },
1883
            41484: {
1884
                'name': 'SpatialFrequencyResponse',
1885
                'type': 'Undefined'
1886
            },
1887
            41486: {
1888
                'name': 'FocalPlaneXResolution',
1889
                'type': 'Rational'
1890
            },
1891
            41487: {
1892
                'name': 'FocalPlaneYResolution',
1893
                'type': 'Rational'
1894
            },
1895
            41488: {
1896
                'name': 'FocalPlaneResolutionUnit',
1897
                'type': 'Short'
1898
            },
1899
            41492: {
1900
                'name': 'SubjectLocation',
1901
                'type': 'Short'
1902
            },
1903
            41493: {
1904
                'name': 'ExposureIndex',
1905
                'type': 'Rational'
1906
            },
1907
            41495: {
1908
                'name': 'SensingMethod',
1909
                'type': 'Short'
1910
            },
1911
            41728: {
1912
                'name': 'FileSource',
1913
                'type': 'Undefined'
1914
            },
1915
            41729: {
1916
                'name': 'SceneType',
1917
                'type': 'Undefined'
1918
            },
1919
            41730: {
1920
                'name': 'CFAPattern',
1921
                'type': 'Undefined'
1922
            },
1923
            41985: {
1924
                'name': 'CustomRendered',
1925
                'type': 'Short'
1926
            },
1927
            41986: {
1928
                'name': 'ExposureMode',
1929
                'type': 'Short'
1930
            },
1931
            41987: {
1932
                'name': 'WhiteBalance',
1933
                'type': 'Short'
1934
            },
1935
            41988: {
1936
                'name': 'DigitalZoomRatio',
1937
                'type': 'Rational'
1938
            },
1939
            41989: {
1940
                'name': 'FocalLengthIn35mmFilm',
1941
                'type': 'Short'
1942
            },
1943
            41990: {
1944
                'name': 'SceneCaptureType',
1945
                'type': 'Short'
1946
            },
1947
            41991: {
1948
                'name': 'GainControl',
1949
                'type': 'Short'
1950
            },
1951
            41992: {
1952
                'name': 'Contrast',
1953
                'type': 'Short'
1954
            },
1955
            41993: {
1956
                'name': 'Saturation',
1957
                'type': 'Short'
1958
            },
1959
            41994: {
1960
                'name': 'Sharpness',
1961
                'type': 'Short'
1962
            },
1963
            41995: {
1964
                'name': 'DeviceSettingDescription',
1965
                'type': 'Undefined'
1966
            },
1967
            41996: {
1968
                'name': 'SubjectDistanceRange',
1969
                'type': 'Short'
1970
            },
1971
            42016: {
1972
                'name': 'ImageUniqueID',
1973
                'type': 'Ascii'
1974
            },
1975
            42032: {
1976
                'name': 'CameraOwnerName',
1977
                'type': 'Ascii'
1978
            },
1979
            42033: {
1980
                'name': 'BodySerialNumber',
1981
                'type': 'Ascii'
1982
            },
1983
            42034: {
1984
                'name': 'LensSpecification',
1985
                'type': 'Rational'
1986
            },
1987
            42035: {
1988
                'name': 'LensMake',
1989
                'type': 'Ascii'
1990
            },
1991
            42036: {
1992
                'name': 'LensModel',
1993
                'type': 'Ascii'
1994
            },
1995
            42037: {
1996
                'name': 'LensSerialNumber',
1997
                'type': 'Ascii'
1998
            },
1999
            42240: {
2000
                'name': 'Gamma',
2001
                'type': 'Rational'
2002
            }
2003
        },
2004
        'GPS': {
2005
            0: {
2006
                'name': 'GPSVersionID',
2007
                'type': 'Byte'
2008
            },
2009
            1: {
2010
                'name': 'GPSLatitudeRef',
2011
                'type': 'Ascii'
2012
            },
2013
            2: {
2014
                'name': 'GPSLatitude',
2015
                'type': 'Rational'
2016
            },
2017
            3: {
2018
                'name': 'GPSLongitudeRef',
2019
                'type': 'Ascii'
2020
            },
2021
            4: {
2022
                'name': 'GPSLongitude',
2023
                'type': 'Rational'
2024
            },
2025
            5: {
2026
                'name': 'GPSAltitudeRef',
2027
                'type': 'Byte'
2028
            },
2029
            6: {
2030
                'name': 'GPSAltitude',
2031
                'type': 'Rational'
2032
            },
2033
            7: {
2034
                'name': 'GPSTimeStamp',
2035
                'type': 'Rational'
2036
            },
2037
            8: {
2038
                'name': 'GPSSatellites',
2039
                'type': 'Ascii'
2040
            },
2041
            9: {
2042
                'name': 'GPSStatus',
2043
                'type': 'Ascii'
2044
            },
2045
            10: {
2046
                'name': 'GPSMeasureMode',
2047
                'type': 'Ascii'
2048
            },
2049
            11: {
2050
                'name': 'GPSDOP',
2051
                'type': 'Rational'
2052
            },
2053
            12: {
2054
                'name': 'GPSSpeedRef',
2055
                'type': 'Ascii'
2056
            },
2057
            13: {
2058
                'name': 'GPSSpeed',
2059
                'type': 'Rational'
2060
            },
2061
            14: {
2062
                'name': 'GPSTrackRef',
2063
                'type': 'Ascii'
2064
            },
2065
            15: {
2066
                'name': 'GPSTrack',
2067
                'type': 'Rational'
2068
            },
2069
            16: {
2070
                'name': 'GPSImgDirectionRef',
2071
                'type': 'Ascii'
2072
            },
2073
            17: {
2074
                'name': 'GPSImgDirection',
2075
                'type': 'Rational'
2076
            },
2077
            18: {
2078
                'name': 'GPSMapDatum',
2079
                'type': 'Ascii'
2080
            },
2081
            19: {
2082
                'name': 'GPSDestLatitudeRef',
2083
                'type': 'Ascii'
2084
            },
2085
            20: {
2086
                'name': 'GPSDestLatitude',
2087
                'type': 'Rational'
2088
            },
2089
            21: {
2090
                'name': 'GPSDestLongitudeRef',
2091
                'type': 'Ascii'
2092
            },
2093
            22: {
2094
                'name': 'GPSDestLongitude',
2095
                'type': 'Rational'
2096
            },
2097
            23: {
2098
                'name': 'GPSDestBearingRef',
2099
                'type': 'Ascii'
2100
            },
2101
            24: {
2102
                'name': 'GPSDestBearing',
2103
                'type': 'Rational'
2104
            },
2105
            25: {
2106
                'name': 'GPSDestDistanceRef',
2107
                'type': 'Ascii'
2108
            },
2109
            26: {
2110
                'name': 'GPSDestDistance',
2111
                'type': 'Rational'
2112
            },
2113
            27: {
2114
                'name': 'GPSProcessingMethod',
2115
                'type': 'Undefined'
2116
            },
2117
            28: {
2118
                'name': 'GPSAreaInformation',
2119
                'type': 'Undefined'
2120
            },
2121
            29: {
2122
                'name': 'GPSDateStamp',
2123
                'type': 'Ascii'
2124
            },
2125
            30: {
2126
                'name': 'GPSDifferential',
2127
                'type': 'Short'
2128
            },
2129
            31: {
2130
                'name': 'GPSHPositioningError',
2131
                'type': 'Rational'
2132
            }
2133
        },
2134
        'Interop': {
2135
            1: {
2136
                'name': 'InteroperabilityIndex',
2137
                'type': 'Ascii'
2138
            }
2139
        },
2140
    };
2141
    TAGS["0th"] = TAGS["Image"];
2142
    TAGS["1st"] = TAGS["Image"];
2143
    that.TAGS = TAGS;
2144
 
2145
 
2146
    that.ImageIFD = {
2147
        ProcessingSoftware:11,
2148
        NewSubfileType:254,
2149
        SubfileType:255,
2150
        ImageWidth:256,
2151
        ImageLength:257,
2152
        BitsPerSample:258,
2153
        Compression:259,
2154
        PhotometricInterpretation:262,
2155
        Threshholding:263,
2156
        CellWidth:264,
2157
        CellLength:265,
2158
        FillOrder:266,
2159
        DocumentName:269,
2160
        ImageDescription:270,
2161
        Make:271,
2162
        Model:272,
2163
        StripOffsets:273,
2164
        Orientation:274,
2165
        SamplesPerPixel:277,
2166
        RowsPerStrip:278,
2167
        StripByteCounts:279,
2168
        XResolution:282,
2169
        YResolution:283,
2170
        PlanarConfiguration:284,
2171
        GrayResponseUnit:290,
2172
        GrayResponseCurve:291,
2173
        T4Options:292,
2174
        T6Options:293,
2175
        ResolutionUnit:296,
2176
        TransferFunction:301,
2177
        Software:305,
2178
        DateTime:306,
2179
        Artist:315,
2180
        HostComputer:316,
2181
        Predictor:317,
2182
        WhitePoint:318,
2183
        PrimaryChromaticities:319,
2184
        ColorMap:320,
2185
        HalftoneHints:321,
2186
        TileWidth:322,
2187
        TileLength:323,
2188
        TileOffsets:324,
2189
        TileByteCounts:325,
2190
        SubIFDs:330,
2191
        InkSet:332,
2192
        InkNames:333,
2193
        NumberOfInks:334,
2194
        DotRange:336,
2195
        TargetPrinter:337,
2196
        ExtraSamples:338,
2197
        SampleFormat:339,
2198
        SMinSampleValue:340,
2199
        SMaxSampleValue:341,
2200
        TransferRange:342,
2201
        ClipPath:343,
2202
        XClipPathUnits:344,
2203
        YClipPathUnits:345,
2204
        Indexed:346,
2205
        JPEGTables:347,
2206
        OPIProxy:351,
2207
        JPEGProc:512,
2208
        JPEGInterchangeFormat:513,
2209
        JPEGInterchangeFormatLength:514,
2210
        JPEGRestartInterval:515,
2211
        JPEGLosslessPredictors:517,
2212
        JPEGPointTransforms:518,
2213
        JPEGQTables:519,
2214
        JPEGDCTables:520,
2215
        JPEGACTables:521,
2216
        YCbCrCoefficients:529,
2217
        YCbCrSubSampling:530,
2218
        YCbCrPositioning:531,
2219
        ReferenceBlackWhite:532,
2220
        XMLPacket:700,
2221
        Rating:18246,
2222
        RatingPercent:18249,
2223
        ImageID:32781,
2224
        CFARepeatPatternDim:33421,
2225
        CFAPattern:33422,
2226
        BatteryLevel:33423,
2227
        Copyright:33432,
2228
        ExposureTime:33434,
2229
        ImageResources:34377,
2230
        ExifTag:34665,
2231
        InterColorProfile:34675,
2232
        GPSTag:34853,
2233
        Interlace:34857,
2234
        TimeZoneOffset:34858,
2235
        SelfTimerMode:34859,
2236
        FlashEnergy:37387,
2237
        SpatialFrequencyResponse:37388,
2238
        Noise:37389,
2239
        FocalPlaneXResolution:37390,
2240
        FocalPlaneYResolution:37391,
2241
        FocalPlaneResolutionUnit:37392,
2242
        ImageNumber:37393,
2243
        SecurityClassification:37394,
2244
        ImageHistory:37395,
2245
        ExposureIndex:37397,
2246
        TIFFEPStandardID:37398,
2247
        SensingMethod:37399,
2248
        XPTitle:40091,
2249
        XPComment:40092,
2250
        XPAuthor:40093,
2251
        XPKeywords:40094,
2252
        XPSubject:40095,
2253
        PrintImageMatching:50341,
2254
        DNGVersion:50706,
2255
        DNGBackwardVersion:50707,
2256
        UniqueCameraModel:50708,
2257
        LocalizedCameraModel:50709,
2258
        CFAPlaneColor:50710,
2259
        CFALayout:50711,
2260
        LinearizationTable:50712,
2261
        BlackLevelRepeatDim:50713,
2262
        BlackLevel:50714,
2263
        BlackLevelDeltaH:50715,
2264
        BlackLevelDeltaV:50716,
2265
        WhiteLevel:50717,
2266
        DefaultScale:50718,
2267
        DefaultCropOrigin:50719,
2268
        DefaultCropSize:50720,
2269
        ColorMatrix1:50721,
2270
        ColorMatrix2:50722,
2271
        CameraCalibration1:50723,
2272
        CameraCalibration2:50724,
2273
        ReductionMatrix1:50725,
2274
        ReductionMatrix2:50726,
2275
        AnalogBalance:50727,
2276
        AsShotNeutral:50728,
2277
        AsShotWhiteXY:50729,
2278
        BaselineExposure:50730,
2279
        BaselineNoise:50731,
2280
        BaselineSharpness:50732,
2281
        BayerGreenSplit:50733,
2282
        LinearResponseLimit:50734,
2283
        CameraSerialNumber:50735,
2284
        LensInfo:50736,
2285
        ChromaBlurRadius:50737,
2286
        AntiAliasStrength:50738,
2287
        ShadowScale:50739,
2288
        DNGPrivateData:50740,
2289
        MakerNoteSafety:50741,
2290
        CalibrationIlluminant1:50778,
2291
        CalibrationIlluminant2:50779,
2292
        BestQualityScale:50780,
2293
        RawDataUniqueID:50781,
2294
        OriginalRawFileName:50827,
2295
        OriginalRawFileData:50828,
2296
        ActiveArea:50829,
2297
        MaskedAreas:50830,
2298
        AsShotICCProfile:50831,
2299
        AsShotPreProfileMatrix:50832,
2300
        CurrentICCProfile:50833,
2301
        CurrentPreProfileMatrix:50834,
2302
        ColorimetricReference:50879,
2303
        CameraCalibrationSignature:50931,
2304
        ProfileCalibrationSignature:50932,
2305
        AsShotProfileName:50934,
2306
        NoiseReductionApplied:50935,
2307
        ProfileName:50936,
2308
        ProfileHueSatMapDims:50937,
2309
        ProfileHueSatMapData1:50938,
2310
        ProfileHueSatMapData2:50939,
2311
        ProfileToneCurve:50940,
2312
        ProfileEmbedPolicy:50941,
2313
        ProfileCopyright:50942,
2314
        ForwardMatrix1:50964,
2315
        ForwardMatrix2:50965,
2316
        PreviewApplicationName:50966,
2317
        PreviewApplicationVersion:50967,
2318
        PreviewSettingsName:50968,
2319
        PreviewSettingsDigest:50969,
2320
        PreviewColorSpace:50970,
2321
        PreviewDateTime:50971,
2322
        RawImageDigest:50972,
2323
        OriginalRawFileDigest:50973,
2324
        SubTileBlockSize:50974,
2325
        RowInterleaveFactor:50975,
2326
        ProfileLookTableDims:50981,
2327
        ProfileLookTableData:50982,
2328
        OpcodeList1:51008,
2329
        OpcodeList2:51009,
2330
        OpcodeList3:51022,
2331
        NoiseProfile:51041,
2332
    };
2333
 
2334
 
2335
    that.ExifIFD = {
2336
        ExposureTime:33434,
2337
        FNumber:33437,
2338
        ExposureProgram:34850,
2339
        SpectralSensitivity:34852,
2340
        ISOSpeedRatings:34855,
2341
        OECF:34856,
2342
        SensitivityType:34864,
2343
        StandardOutputSensitivity:34865,
2344
        RecommendedExposureIndex:34866,
2345
        ISOSpeed:34867,
2346
        ISOSpeedLatitudeyyy:34868,
2347
        ISOSpeedLatitudezzz:34869,
2348
        ExifVersion:36864,
2349
        DateTimeOriginal:36867,
2350
        DateTimeDigitized:36868,
2351
        ComponentsConfiguration:37121,
2352
        CompressedBitsPerPixel:37122,
2353
        ShutterSpeedValue:37377,
2354
        ApertureValue:37378,
2355
        BrightnessValue:37379,
2356
        ExposureBiasValue:37380,
2357
        MaxApertureValue:37381,
2358
        SubjectDistance:37382,
2359
        MeteringMode:37383,
2360
        LightSource:37384,
2361
        Flash:37385,
2362
        FocalLength:37386,
2363
        SubjectArea:37396,
2364
        MakerNote:37500,
2365
        UserComment:37510,
2366
        SubSecTime:37520,
2367
        SubSecTimeOriginal:37521,
2368
        SubSecTimeDigitized:37522,
2369
        FlashpixVersion:40960,
2370
        ColorSpace:40961,
2371
        PixelXDimension:40962,
2372
        PixelYDimension:40963,
2373
        RelatedSoundFile:40964,
2374
        InteroperabilityTag:40965,
2375
        FlashEnergy:41483,
2376
        SpatialFrequencyResponse:41484,
2377
        FocalPlaneXResolution:41486,
2378
        FocalPlaneYResolution:41487,
2379
        FocalPlaneResolutionUnit:41488,
2380
        SubjectLocation:41492,
2381
        ExposureIndex:41493,
2382
        SensingMethod:41495,
2383
        FileSource:41728,
2384
        SceneType:41729,
2385
        CFAPattern:41730,
2386
        CustomRendered:41985,
2387
        ExposureMode:41986,
2388
        WhiteBalance:41987,
2389
        DigitalZoomRatio:41988,
2390
        FocalLengthIn35mmFilm:41989,
2391
        SceneCaptureType:41990,
2392
        GainControl:41991,
2393
        Contrast:41992,
2394
        Saturation:41993,
2395
        Sharpness:41994,
2396
        DeviceSettingDescription:41995,
2397
        SubjectDistanceRange:41996,
2398
        ImageUniqueID:42016,
2399
        CameraOwnerName:42032,
2400
        BodySerialNumber:42033,
2401
        LensSpecification:42034,
2402
        LensMake:42035,
2403
        LensModel:42036,
2404
        LensSerialNumber:42037,
2405
        Gamma:42240,
2406
    };
2407
 
2408
 
2409
    that.GPSIFD = {
2410
        GPSVersionID:0,
2411
        GPSLatitudeRef:1,
2412
        GPSLatitude:2,
2413
        GPSLongitudeRef:3,
2414
        GPSLongitude:4,
2415
        GPSAltitudeRef:5,
2416
        GPSAltitude:6,
2417
        GPSTimeStamp:7,
2418
        GPSSatellites:8,
2419
        GPSStatus:9,
2420
        GPSMeasureMode:10,
2421
        GPSDOP:11,
2422
        GPSSpeedRef:12,
2423
        GPSSpeed:13,
2424
        GPSTrackRef:14,
2425
        GPSTrack:15,
2426
        GPSImgDirectionRef:16,
2427
        GPSImgDirection:17,
2428
        GPSMapDatum:18,
2429
        GPSDestLatitudeRef:19,
2430
        GPSDestLatitude:20,
2431
        GPSDestLongitudeRef:21,
2432
        GPSDestLongitude:22,
2433
        GPSDestBearingRef:23,
2434
        GPSDestBearing:24,
2435
        GPSDestDistanceRef:25,
2436
        GPSDestDistance:26,
2437
        GPSProcessingMethod:27,
2438
        GPSAreaInformation:28,
2439
        GPSDateStamp:29,
2440
        GPSDifferential:30,
2441
        GPSHPositioningError:31,
2442
    };
2443
 
2444
 
2445
    that.InteropIFD = {
2446
        InteroperabilityIndex:1,
2447
    };
2448
 
2449
    that.GPSHelper = {
2450
        degToDmsRational:function (degFloat) {
2451
            var minFloat = degFloat % 1 * 60;
2452
            var secFloat = minFloat % 1 * 60;
2453
            var deg = Math.floor(degFloat);
2454
            var min = Math.floor(minFloat);
2455
            var sec = Math.round(secFloat * 100);
2456
 
2457
            return [[deg, 1], [min, 1], [sec, 100]];
2458
        }
2459
    };
2460
 
2461
 
2462
    if (typeof exports !== 'undefined') {
2463
        if (typeof module !== 'undefined' && module.exports) {
2464
            exports = module.exports = that;
2465
        }
2466
        exports.piexif = that;
2467
    } else {
2468
        window.piexif = that;
2469
    }
2470
 
2471
})();