From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../third_party/piexif/LICENSE.txt | 21 + .../third_party/piexif/piexif.js | 2482 ++++++++++++++++++++ 2 files changed, 2503 insertions(+) create mode 100644 testing/web-platform/tests/density-size-correction/third_party/piexif/LICENSE.txt create mode 100644 testing/web-platform/tests/density-size-correction/third_party/piexif/piexif.js (limited to 'testing/web-platform/tests/density-size-correction/third_party/piexif') diff --git a/testing/web-platform/tests/density-size-correction/third_party/piexif/LICENSE.txt b/testing/web-platform/tests/density-size-correction/third_party/piexif/LICENSE.txt new file mode 100644 index 0000000000..73bd9746b2 --- /dev/null +++ b/testing/web-platform/tests/density-size-correction/third_party/piexif/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Hiroaki Matoba + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/testing/web-platform/tests/density-size-correction/third_party/piexif/piexif.js b/testing/web-platform/tests/density-size-correction/third_party/piexif/piexif.js new file mode 100644 index 0000000000..01b4e8f108 --- /dev/null +++ b/testing/web-platform/tests/density-size-correction/third_party/piexif/piexif.js @@ -0,0 +1,2482 @@ +/* piexifjs + +The MIT License (MIT) + +Copyright (c) 2014, 2015 hMatoba(https://github.com/hMatoba) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +(function () { + "use strict"; + var that = {}; + that.version = "1.0.4"; + + that.remove = function (jpeg) { + var b64 = false; + if (jpeg.slice(0, 2) == "\xff\xd8") { + } else if (jpeg.slice(0, 23) == "data:image/jpeg;base64," || jpeg.slice(0, 22) == "data:image/jpg;base64,") { + jpeg = atob(jpeg.split(",")[1]); + b64 = true; + } else { + throw new Error("Given data is not jpeg."); + } + + var segments = splitIntoSegments(jpeg); + var newSegments = segments.filter(function(seg){ + return !(seg.slice(0, 2) == "\xff\xe1" && + seg.slice(4, 10) == "Exif\x00\x00"); + }); + + var new_data = newSegments.join(""); + if (b64) { + new_data = "data:image/jpeg;base64," + btoa(new_data); + } + + return new_data; + }; + + + that.insert = function (exif, jpeg) { + var b64 = false; + if (exif.slice(0, 6) != "\x45\x78\x69\x66\x00\x00") { + throw new Error("Given data is not exif."); + } + if (jpeg.slice(0, 2) == "\xff\xd8") { + } else if (jpeg.slice(0, 23) == "data:image/jpeg;base64," || jpeg.slice(0, 22) == "data:image/jpg;base64,") { + jpeg = atob(jpeg.split(",")[1]); + b64 = true; + } else { + throw new Error("Given data is not jpeg."); + } + + var exifStr = "\xff\xe1" + pack(">H", [exif.length + 2]) + exif; + var segments = splitIntoSegments(jpeg); + var new_data = mergeSegments(segments, exifStr); + if (b64) { + new_data = "data:image/jpeg;base64," + btoa(new_data); + } + + return new_data; + }; + + + that.load = function (data) { + var input_data; + if (typeof (data) == "string") { + if (data.slice(0, 2) == "\xff\xd8") { + input_data = data; + } else if (data.slice(0, 23) == "data:image/jpeg;base64," || data.slice(0, 22) == "data:image/jpg;base64,") { + input_data = atob(data.split(",")[1]); + } else if (data.slice(0, 4) == "Exif") { + input_data = data.slice(6); + } else { + throw new Error("'load' gots invalid file data."); + } + } else { + throw new Error("'load' gots invalid type argument."); + } + + var exifDict = {}; + var exif_dict = { + "0th": {}, + "Exif": {}, + "GPS": {}, + "Interop": {}, + "1st": {}, + "thumbnail": null + }; + var exifReader = new ExifReader(input_data); + if (exifReader.tiftag === null) { + return exif_dict; + } + + if (exifReader.tiftag.slice(0, 2) == "\x49\x49") { + exifReader.endian_mark = "<"; + } else { + exifReader.endian_mark = ">"; + } + + var pointer = unpack(exifReader.endian_mark + "L", + exifReader.tiftag.slice(4, 8))[0]; + exif_dict["0th"] = exifReader.get_ifd(pointer, "0th"); + + var first_ifd_pointer = exif_dict["0th"]["first_ifd_pointer"]; + delete exif_dict["0th"]["first_ifd_pointer"]; + + if (34665 in exif_dict["0th"]) { + pointer = exif_dict["0th"][34665]; + exif_dict["Exif"] = exifReader.get_ifd(pointer, "Exif"); + } + if (34853 in exif_dict["0th"]) { + pointer = exif_dict["0th"][34853]; + exif_dict["GPS"] = exifReader.get_ifd(pointer, "GPS"); + } + if (40965 in exif_dict["Exif"]) { + pointer = exif_dict["Exif"][40965]; + exif_dict["Interop"] = exifReader.get_ifd(pointer, "Interop"); + } + if (first_ifd_pointer != "\x00\x00\x00\x00") { + pointer = unpack(exifReader.endian_mark + "L", + first_ifd_pointer)[0]; + exif_dict["1st"] = exifReader.get_ifd(pointer, "1st"); + if ((513 in exif_dict["1st"]) && (514 in exif_dict["1st"])) { + var end = exif_dict["1st"][513] + exif_dict["1st"][514]; + var thumb = exifReader.tiftag.slice(exif_dict["1st"][513], end); + exif_dict["thumbnail"] = thumb; + } + } + + return exif_dict; + }; + + + that.dump = function (exif_dict_original) { + var TIFF_HEADER_LENGTH = 8; + + var exif_dict = copy(exif_dict_original); + var header = "Exif\x00\x00\x4d\x4d\x00\x2a\x00\x00\x00\x08"; + var exif_is = false; + var gps_is = false; + var interop_is = false; + var first_is = false; + + var zeroth_ifd, + exif_ifd, + interop_ifd, + gps_ifd, + first_ifd; + + if ("0th" in exif_dict) { + zeroth_ifd = exif_dict["0th"]; + } else { + zeroth_ifd = {}; + } + + if ((("Exif" in exif_dict) && (Object.keys(exif_dict["Exif"]).length)) || + (("Interop" in exif_dict) && (Object.keys(exif_dict["Interop"]).length))) { + zeroth_ifd[34665] = 1; + exif_is = true; + exif_ifd = exif_dict["Exif"]; + if (("Interop" in exif_dict) && Object.keys(exif_dict["Interop"]).length) { + exif_ifd[40965] = 1; + interop_is = true; + interop_ifd = exif_dict["Interop"]; + } else if (Object.keys(exif_ifd).indexOf(that.ExifIFD.InteroperabilityTag.toString()) > -1) { + delete exif_ifd[40965]; + } + } else if (Object.keys(zeroth_ifd).indexOf(that.ImageIFD.ExifTag.toString()) > -1) { + delete zeroth_ifd[34665]; + } + + if (("GPS" in exif_dict) && (Object.keys(exif_dict["GPS"]).length)) { + zeroth_ifd[that.ImageIFD.GPSTag] = 1; + gps_is = true; + gps_ifd = exif_dict["GPS"]; + } else if (Object.keys(zeroth_ifd).indexOf(that.ImageIFD.GPSTag.toString()) > -1) { + delete zeroth_ifd[that.ImageIFD.GPSTag]; + } + + if (("1st" in exif_dict) && + ("thumbnail" in exif_dict) && + (exif_dict["thumbnail"] != null)) { + first_is = true; + exif_dict["1st"][513] = 1; + exif_dict["1st"][514] = 1; + first_ifd = exif_dict["1st"]; + } + + var zeroth_set = _dict_to_bytes(zeroth_ifd, "0th", 0); + var zeroth_length = (zeroth_set[0].length + exif_is * 12 + gps_is * 12 + 4 + + zeroth_set[1].length); + + var exif_set, + exif_bytes = "", + exif_length = 0, + gps_set, + gps_bytes = "", + gps_length = 0, + interop_set, + interop_bytes = "", + interop_length = 0, + first_set, + first_bytes = "", + thumbnail; + if (exif_is) { + exif_set = _dict_to_bytes(exif_ifd, "Exif", zeroth_length); + exif_length = exif_set[0].length + interop_is * 12 + exif_set[1].length; + } + if (gps_is) { + gps_set = _dict_to_bytes(gps_ifd, "GPS", zeroth_length + exif_length); + gps_bytes = gps_set.join(""); + gps_length = gps_bytes.length; + } + if (interop_is) { + var offset = zeroth_length + exif_length + gps_length; + interop_set = _dict_to_bytes(interop_ifd, "Interop", offset); + interop_bytes = interop_set.join(""); + interop_length = interop_bytes.length; + } + if (first_is) { + var offset = zeroth_length + exif_length + gps_length + interop_length; + first_set = _dict_to_bytes(first_ifd, "1st", offset); + thumbnail = _get_thumbnail(exif_dict["thumbnail"]); + if (thumbnail.length > 64000) { + throw new Error("Given thumbnail is too large. max 64kB"); + } + } + + var exif_pointer = "", + gps_pointer = "", + interop_pointer = "", + first_ifd_pointer = "\x00\x00\x00\x00"; + if (exif_is) { + var pointer_value = TIFF_HEADER_LENGTH + zeroth_length; + var pointer_str = pack(">L", [pointer_value]); + var key = 34665; + var key_str = pack(">H", [key]); + var type_str = pack(">H", [TYPES["Long"]]); + var length_str = pack(">L", [1]); + exif_pointer = key_str + type_str + length_str + pointer_str; + } + if (gps_is) { + var pointer_value = TIFF_HEADER_LENGTH + zeroth_length + exif_length; + var pointer_str = pack(">L", [pointer_value]); + var key = 34853; + var key_str = pack(">H", [key]); + var type_str = pack(">H", [TYPES["Long"]]); + var length_str = pack(">L", [1]); + gps_pointer = key_str + type_str + length_str + pointer_str; + } + if (interop_is) { + var pointer_value = (TIFF_HEADER_LENGTH + + zeroth_length + exif_length + gps_length); + var pointer_str = pack(">L", [pointer_value]); + var key = 40965; + var key_str = pack(">H", [key]); + var type_str = pack(">H", [TYPES["Long"]]); + var length_str = pack(">L", [1]); + interop_pointer = key_str + type_str + length_str + pointer_str; + } + if (first_is) { + var pointer_value = (TIFF_HEADER_LENGTH + zeroth_length + + exif_length + gps_length + interop_length); + first_ifd_pointer = pack(">L", [pointer_value]); + var thumbnail_pointer = (pointer_value + first_set[0].length + 24 + + 4 + first_set[1].length); + var thumbnail_p_bytes = ("\x02\x01\x00\x04\x00\x00\x00\x01" + + pack(">L", [thumbnail_pointer])); + var thumbnail_length_bytes = ("\x02\x02\x00\x04\x00\x00\x00\x01" + + pack(">L", [thumbnail.length])); + first_bytes = (first_set[0] + thumbnail_p_bytes + + thumbnail_length_bytes + "\x00\x00\x00\x00" + + first_set[1] + thumbnail); + } + + var zeroth_bytes = (zeroth_set[0] + exif_pointer + gps_pointer + + first_ifd_pointer + zeroth_set[1]); + if (exif_is) { + exif_bytes = exif_set[0] + interop_pointer + exif_set[1]; + } + + return (header + zeroth_bytes + exif_bytes + gps_bytes + + interop_bytes + first_bytes); + }; + + + function copy(obj) { + return JSON.parse(JSON.stringify(obj)); + } + + + function _get_thumbnail(jpeg) { + var segments = splitIntoSegments(jpeg); + while (("\xff\xe0" <= segments[1].slice(0, 2)) && (segments[1].slice(0, 2) <= "\xff\xef")) { + segments = [segments[0]].concat(segments.slice(2)); + } + return segments.join(""); + } + + + function _pack_byte(array) { + return pack(">" + nStr("B", array.length), array); + } + + + function _pack_short(array) { + return pack(">" + nStr("H", array.length), array); + } + + + function _pack_long(array) { + return pack(">" + nStr("L", array.length), array); + } + + + function _value_to_bytes(raw_value, value_type, offset) { + var four_bytes_over = ""; + var value_str = ""; + var length, + new_value, + num, + den; + + if (value_type == "Byte") { + length = raw_value.length; + if (length <= 4) { + value_str = (_pack_byte(raw_value) + + nStr("\x00", 4 - length)); + } else { + value_str = pack(">L", [offset]); + four_bytes_over = _pack_byte(raw_value); + } + } else if (value_type == "Short") { + length = raw_value.length; + if (length <= 2) { + value_str = (_pack_short(raw_value) + + nStr("\x00\x00", 2 - length)); + } else { + value_str = pack(">L", [offset]); + four_bytes_over = _pack_short(raw_value); + } + } else if (value_type == "Long") { + length = raw_value.length; + if (length <= 1) { + value_str = _pack_long(raw_value); + } else { + value_str = pack(">L", [offset]); + four_bytes_over = _pack_long(raw_value); + } + } else if (value_type == "Ascii") { + new_value = raw_value + "\x00"; + length = new_value.length; + if (length > 4) { + value_str = pack(">L", [offset]); + four_bytes_over = new_value; + } else { + value_str = new_value + nStr("\x00", 4 - length); + } + } else if (value_type == "Rational") { + if (typeof (raw_value[0]) == "number") { + length = 1; + num = raw_value[0]; + den = raw_value[1]; + new_value = pack(">L", [num]) + pack(">L", [den]); + } else { + length = raw_value.length; + new_value = ""; + for (var n = 0; n < length; n++) { + num = raw_value[n][0]; + den = raw_value[n][1]; + new_value += (pack(">L", [num]) + + pack(">L", [den])); + } + } + value_str = pack(">L", [offset]); + four_bytes_over = new_value; + } else if (value_type == "SRational") { + if (typeof (raw_value[0]) == "number") { + length = 1; + num = raw_value[0]; + den = raw_value[1]; + new_value = pack(">l", [num]) + pack(">l", [den]); + } else { + length = raw_value.length; + new_value = ""; + for (var n = 0; n < length; n++) { + num = raw_value[n][0]; + den = raw_value[n][1]; + new_value += (pack(">l", [num]) + + pack(">l", [den])); + } + } + value_str = pack(">L", [offset]); + four_bytes_over = new_value; + } else if (value_type == "Undefined") { + length = raw_value.length; + if (length > 4) { + value_str = pack(">L", [offset]); + four_bytes_over = raw_value; + } else { + value_str = raw_value + nStr("\x00", 4 - length); + } + } + + var length_str = pack(">L", [length]); + + return [length_str, value_str, four_bytes_over]; + } + + function _dict_to_bytes(ifd_dict, ifd, ifd_offset) { + var TIFF_HEADER_LENGTH = 8; + var tag_count = Object.keys(ifd_dict).length; + var entry_header = pack(">H", [tag_count]); + var entries_length; + if (["0th", "1st"].indexOf(ifd) > -1) { + entries_length = 2 + tag_count * 12 + 4; + } else { + entries_length = 2 + tag_count * 12; + } + var entries = ""; + var values = ""; + var key; + + for (var key in ifd_dict) { + if (typeof (key) == "string") { + key = parseInt(key); + } + if ((ifd == "0th") && ([34665, 34853].indexOf(key) > -1)) { + continue; + } else if ((ifd == "Exif") && (key == 40965)) { + continue; + } else if ((ifd == "1st") && ([513, 514].indexOf(key) > -1)) { + continue; + } + + var raw_value = ifd_dict[key]; + var key_str = pack(">H", [key]); + var value_type = TAGS[ifd][key]["type"]; + var type_str = pack(">H", [TYPES[value_type]]); + + if (typeof (raw_value) == "number") { + raw_value = [raw_value]; + } + var offset = TIFF_HEADER_LENGTH + entries_length + ifd_offset + values.length; + var b = _value_to_bytes(raw_value, value_type, offset); + var length_str = b[0]; + var value_str = b[1]; + var four_bytes_over = b[2]; + + entries += key_str + type_str + length_str + value_str; + values += four_bytes_over; + } + + return [entry_header + entries, values]; + } + + + + function ExifReader(data) { + var segments, + app1; + if (data.slice(0, 2) == "\xff\xd8") { // JPEG + segments = splitIntoSegments(data); + app1 = getExifSeg(segments); + if (app1) { + this.tiftag = app1.slice(10); + } else { + this.tiftag = null; + } + } else if (["\x49\x49", "\x4d\x4d"].indexOf(data.slice(0, 2)) > -1) { // TIFF + this.tiftag = data; + } else if (data.slice(0, 4) == "Exif") { // Exif + this.tiftag = data.slice(6); + } else { + throw new Error("Given file is neither JPEG nor TIFF."); + } + } + + ExifReader.prototype = { + get_ifd: function (pointer, ifd_name) { + var ifd_dict = {}; + var tag_count = unpack(this.endian_mark + "H", + this.tiftag.slice(pointer, pointer + 2))[0]; + var offset = pointer + 2; + var t; + if (["0th", "1st"].indexOf(ifd_name) > -1) { + t = "Image"; + } else { + t = ifd_name; + } + + for (var x = 0; x < tag_count; x++) { + pointer = offset + 12 * x; + var tag = unpack(this.endian_mark + "H", + this.tiftag.slice(pointer, pointer + 2))[0]; + var value_type = unpack(this.endian_mark + "H", + this.tiftag.slice(pointer + 2, pointer + 4))[0]; + var value_num = unpack(this.endian_mark + "L", + this.tiftag.slice(pointer + 4, pointer + 8))[0]; + var value = this.tiftag.slice(pointer + 8, pointer + 12); + + var v_set = [value_type, value_num, value]; + if (tag in TAGS[t]) { + ifd_dict[tag] = this.convert_value(v_set); + } + } + + if (ifd_name == "0th") { + pointer = offset + 12 * tag_count; + ifd_dict["first_ifd_pointer"] = this.tiftag.slice(pointer, pointer + 4); + } + + return ifd_dict; + }, + + convert_value: function (val) { + var data = null; + var t = val[0]; + var length = val[1]; + var value = val[2]; + var pointer; + + if (t == 1) { // BYTE + if (length > 4) { + pointer = unpack(this.endian_mark + "L", value)[0]; + data = unpack(this.endian_mark + nStr("B", length), + this.tiftag.slice(pointer, pointer + length)); + } else { + data = unpack(this.endian_mark + nStr("B", length), value.slice(0, length)); + } + } else if (t == 2) { // ASCII + if (length > 4) { + pointer = unpack(this.endian_mark + "L", value)[0]; + data = this.tiftag.slice(pointer, pointer + length - 1); + } else { + data = value.slice(0, length - 1); + } + } else if (t == 3) { // SHORT + if (length > 2) { + pointer = unpack(this.endian_mark + "L", value)[0]; + data = unpack(this.endian_mark + nStr("H", length), + this.tiftag.slice(pointer, pointer + length * 2)); + } else { + data = unpack(this.endian_mark + nStr("H", length), + value.slice(0, length * 2)); + } + } else if (t == 4) { // LONG + if (length > 1) { + pointer = unpack(this.endian_mark + "L", value)[0]; + data = unpack(this.endian_mark + nStr("L", length), + this.tiftag.slice(pointer, pointer + length * 4)); + } else { + data = unpack(this.endian_mark + nStr("L", length), + value); + } + } else if (t == 5) { // RATIONAL + pointer = unpack(this.endian_mark + "L", value)[0]; + if (length > 1) { + data = []; + for (var x = 0; x < length; x++) { + data.push([unpack(this.endian_mark + "L", + this.tiftag.slice(pointer + x * 8, pointer + 4 + x * 8))[0], + unpack(this.endian_mark + "L", + this.tiftag.slice(pointer + 4 + x * 8, pointer + 8 + x * 8))[0] + ]); + } + } else { + data = [unpack(this.endian_mark + "L", + this.tiftag.slice(pointer, pointer + 4))[0], + unpack(this.endian_mark + "L", + this.tiftag.slice(pointer + 4, pointer + 8))[0] + ]; + } + } else if (t == 7) { // UNDEFINED BYTES + if (length > 4) { + pointer = unpack(this.endian_mark + "L", value)[0]; + data = this.tiftag.slice(pointer, pointer + length); + } else { + data = value.slice(0, length); + } + } else if (t == 9) { // SLONG + if (length > 1) { + pointer = unpack(this.endian_mark + "L", value)[0]; + data = unpack(this.endian_mark + nStr("l", length), + this.tiftag.slice(pointer, pointer + length * 4)); + } else { + data = unpack(this.endian_mark + nStr("l", length), + value); + } + } else if (t == 10) { // SRATIONAL + pointer = unpack(this.endian_mark + "L", value)[0]; + if (length > 1) { + data = []; + for (var x = 0; x < length; x++) { + data.push([unpack(this.endian_mark + "l", + this.tiftag.slice(pointer + x * 8, pointer + 4 + x * 8))[0], + unpack(this.endian_mark + "l", + this.tiftag.slice(pointer + 4 + x * 8, pointer + 8 + x * 8))[0] + ]); + } + } else { + data = [unpack(this.endian_mark + "l", + this.tiftag.slice(pointer, pointer + 4))[0], + unpack(this.endian_mark + "l", + this.tiftag.slice(pointer + 4, pointer + 8))[0] + ]; + } + } else { + throw new Error("Exif might be wrong. Got incorrect value " + + "type to decode. type:" + t); + } + + if ((data instanceof Array) && (data.length == 1)) { + return data[0]; + } else { + return data; + } + }, + }; + + + if (typeof window !== "undefined" && typeof window.btoa === "function") { + var btoa = window.btoa; + } + if (typeof btoa === "undefined") { + var btoa = function (input) { var output = ""; + var chr1, chr2, chr3, enc1, enc2, enc3, enc4; + var i = 0; + var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + + while (i < input.length) { + + chr1 = input.charCodeAt(i++); + chr2 = input.charCodeAt(i++); + chr3 = input.charCodeAt(i++); + + enc1 = chr1 >> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2)) { + enc3 = enc4 = 64; + } else if (isNaN(chr3)) { + enc4 = 64; + } + + output = output + + keyStr.charAt(enc1) + keyStr.charAt(enc2) + + keyStr.charAt(enc3) + keyStr.charAt(enc4); + + } + + return output; + }; + } + + + if (typeof window !== "undefined" && typeof window.atob === "function") { + var atob = window.atob; + } + if (typeof atob === "undefined") { + var atob = function (input) { + var output = ""; + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0; + var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + while (i < input.length) { + + enc1 = keyStr.indexOf(input.charAt(i++)); + enc2 = keyStr.indexOf(input.charAt(i++)); + enc3 = keyStr.indexOf(input.charAt(i++)); + enc4 = keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output = output + String.fromCharCode(chr1); + + if (enc3 != 64) { + output = output + String.fromCharCode(chr2); + } + if (enc4 != 64) { + output = output + String.fromCharCode(chr3); + } + + } + + return output; + }; + } + + + function getImageSize(imageArray) { + var segments = slice2Segments(imageArray); + var seg, + width, + height, + SOF = [192, 193, 194, 195, 197, 198, 199, 201, 202, 203, 205, 206, 207]; + + for (var x = 0; x < segments.length; x++) { + seg = segments[x]; + if (SOF.indexOf(seg[1]) >= 0) { + height = seg[5] * 256 + seg[6]; + width = seg[7] * 256 + seg[8]; + break; + } + } + return [width, height]; + } + + + function pack(mark, array) { + if (!(array instanceof Array)) { + throw new Error("'pack' error. Got invalid type argument."); + } + if ((mark.length - 1) != array.length) { + throw new Error("'pack' error. " + (mark.length - 1) + " marks, " + array.length + " elements."); + } + + var littleEndian; + if (mark[0] == "<") { + littleEndian = true; + } else if (mark[0] == ">") { + littleEndian = false; + } else { + throw new Error(""); + } + var packed = ""; + var p = 1; + var val = null; + var c = null; + var valStr = null; + + while (c = mark[p]) { + if (c.toLowerCase() == "b") { + val = array[p - 1]; + if ((c == "b") && (val < 0)) { + val += 0x100; + } + if ((val > 0xff) || (val < 0)) { + throw new Error("'pack' error."); + } else { + valStr = String.fromCharCode(val); + } + } else if (c == "H") { + val = array[p - 1]; + if ((val > 0xffff) || (val < 0)) { + throw new Error("'pack' error."); + } else { + valStr = String.fromCharCode(Math.floor((val % 0x10000) / 0x100)) + + String.fromCharCode(val % 0x100); + if (littleEndian) { + valStr = valStr.split("").reverse().join(""); + } + } + } else if (c.toLowerCase() == "l") { + val = array[p - 1]; + if ((c == "l") && (val < 0)) { + val += 0x100000000; + } + if ((val > 0xffffffff) || (val < 0)) { + throw new Error("'pack' error."); + } else { + valStr = String.fromCharCode(Math.floor(val / 0x1000000)) + + String.fromCharCode(Math.floor((val % 0x1000000) / 0x10000)) + + String.fromCharCode(Math.floor((val % 0x10000) / 0x100)) + + String.fromCharCode(val % 0x100); + if (littleEndian) { + valStr = valStr.split("").reverse().join(""); + } + } + } else { + throw new Error("'pack' error."); + } + + packed += valStr; + p += 1; + } + + return packed; + } + + function unpack(mark, str) { + if (typeof (str) != "string") { + throw new Error("'unpack' error. Got invalid type argument."); + } + var l = 0; + for (var markPointer = 1; markPointer < mark.length; markPointer++) { + if (mark[markPointer].toLowerCase() == "b") { + l += 1; + } else if (mark[markPointer].toLowerCase() == "h") { + l += 2; + } else if (mark[markPointer].toLowerCase() == "l") { + l += 4; + } else { + throw new Error("'unpack' error. Got invalid mark."); + } + } + + if (l != str.length) { + throw new Error("'unpack' error. Mismatch between symbol and string length. " + l + ":" + str.length); + } + + var littleEndian; + if (mark[0] == "<") { + littleEndian = true; + } else if (mark[0] == ">") { + littleEndian = false; + } else { + throw new Error("'unpack' error."); + } + var unpacked = []; + var strPointer = 0; + var p = 1; + var val = null; + var c = null; + var length = null; + var sliced = ""; + + while (c = mark[p]) { + if (c.toLowerCase() == "b") { + length = 1; + sliced = str.slice(strPointer, strPointer + length); + val = sliced.charCodeAt(0); + if ((c == "b") && (val >= 0x80)) { + val -= 0x100; + } + } else if (c == "H") { + length = 2; + sliced = str.slice(strPointer, strPointer + length); + if (littleEndian) { + sliced = sliced.split("").reverse().join(""); + } + val = sliced.charCodeAt(0) * 0x100 + + sliced.charCodeAt(1); + } else if (c.toLowerCase() == "l") { + length = 4; + sliced = str.slice(strPointer, strPointer + length); + if (littleEndian) { + sliced = sliced.split("").reverse().join(""); + } + val = sliced.charCodeAt(0) * 0x1000000 + + sliced.charCodeAt(1) * 0x10000 + + sliced.charCodeAt(2) * 0x100 + + sliced.charCodeAt(3); + if ((c == "l") && (val >= 0x80000000)) { + val -= 0x100000000; + } + } else { + throw new Error("'unpack' error. " + c); + } + + unpacked.push(val); + strPointer += length; + p += 1; + } + + return unpacked; + } + + function nStr(ch, num) { + var str = ""; + for (var i = 0; i < num; i++) { + str += ch; + } + return str; + } + + function splitIntoSegments(data) { + if (data.slice(0, 2) != "\xff\xd8") { + throw new Error("Given data isn't JPEG."); + } + + var head = 2; + var segments = ["\xff\xd8"]; + while (true) { + if (data.slice(head, head + 2) == "\xff\xda") { + segments.push(data.slice(head)); + break; + } else { + var length = unpack(">H", data.slice(head + 2, head + 4))[0]; + var endPoint = head + length + 2; + segments.push(data.slice(head, endPoint)); + head = endPoint; + } + + if (head >= data.length) { + throw new Error("Wrong JPEG data."); + } + } + return segments; + } + + + function getExifSeg(segments) { + var seg; + for (var i = 0; i < segments.length; i++) { + seg = segments[i]; + if (seg.slice(0, 2) == "\xff\xe1" && + seg.slice(4, 10) == "Exif\x00\x00") { + return seg; + } + } + return null; + } + + + function mergeSegments(segments, exif) { + var hasExifSegment = false; + var additionalAPP1ExifSegments = []; + + segments.forEach(function(segment, i) { + // Replace first occurence of APP1:Exif segment + if (segment.slice(0, 2) == "\xff\xe1" && + segment.slice(4, 10) == "Exif\x00\x00" + ) { + if (!hasExifSegment) { + segments[i] = exif; + hasExifSegment = true; + } else { + additionalAPP1ExifSegments.unshift(i); + } + } + }); + + // Remove additional occurences of APP1:Exif segment + additionalAPP1ExifSegments.forEach(function(segmentIndex) { + segments.splice(segmentIndex, 1); + }); + + if (!hasExifSegment && exif) { + segments = [segments[0], exif].concat(segments.slice(1)); + } + + return segments.join(""); + } + + + function toHex(str) { + var hexStr = ""; + for (var i = 0; i < str.length; i++) { + var h = str.charCodeAt(i); + var hex = ((h < 10) ? "0" : "") + h.toString(16); + hexStr += hex + " "; + } + return hexStr; + } + + + var TYPES = { + "Byte": 1, + "Ascii": 2, + "Short": 3, + "Long": 4, + "Rational": 5, + "Undefined": 7, + "SLong": 9, + "SRational": 10 + }; + + + var TAGS = { + 'Image': { + 11: { + 'name': 'ProcessingSoftware', + 'type': 'Ascii' + }, + 254: { + 'name': 'NewSubfileType', + 'type': 'Long' + }, + 255: { + 'name': 'SubfileType', + 'type': 'Short' + }, + 256: { + 'name': 'ImageWidth', + 'type': 'Long' + }, + 257: { + 'name': 'ImageLength', + 'type': 'Long' + }, + 258: { + 'name': 'BitsPerSample', + 'type': 'Short' + }, + 259: { + 'name': 'Compression', + 'type': 'Short' + }, + 262: { + 'name': 'PhotometricInterpretation', + 'type': 'Short' + }, + 263: { + 'name': 'Threshholding', + 'type': 'Short' + }, + 264: { + 'name': 'CellWidth', + 'type': 'Short' + }, + 265: { + 'name': 'CellLength', + 'type': 'Short' + }, + 266: { + 'name': 'FillOrder', + 'type': 'Short' + }, + 269: { + 'name': 'DocumentName', + 'type': 'Ascii' + }, + 270: { + 'name': 'ImageDescription', + 'type': 'Ascii' + }, + 271: { + 'name': 'Make', + 'type': 'Ascii' + }, + 272: { + 'name': 'Model', + 'type': 'Ascii' + }, + 273: { + 'name': 'StripOffsets', + 'type': 'Long' + }, + 274: { + 'name': 'Orientation', + 'type': 'Short' + }, + 277: { + 'name': 'SamplesPerPixel', + 'type': 'Short' + }, + 278: { + 'name': 'RowsPerStrip', + 'type': 'Long' + }, + 279: { + 'name': 'StripByteCounts', + 'type': 'Long' + }, + 282: { + 'name': 'XResolution', + 'type': 'Rational' + }, + 283: { + 'name': 'YResolution', + 'type': 'Rational' + }, + 284: { + 'name': 'PlanarConfiguration', + 'type': 'Short' + }, + 290: { + 'name': 'GrayResponseUnit', + 'type': 'Short' + }, + 291: { + 'name': 'GrayResponseCurve', + 'type': 'Short' + }, + 292: { + 'name': 'T4Options', + 'type': 'Long' + }, + 293: { + 'name': 'T6Options', + 'type': 'Long' + }, + 296: { + 'name': 'ResolutionUnit', + 'type': 'Short' + }, + 301: { + 'name': 'TransferFunction', + 'type': 'Short' + }, + 305: { + 'name': 'Software', + 'type': 'Ascii' + }, + 306: { + 'name': 'DateTime', + 'type': 'Ascii' + }, + 315: { + 'name': 'Artist', + 'type': 'Ascii' + }, + 316: { + 'name': 'HostComputer', + 'type': 'Ascii' + }, + 317: { + 'name': 'Predictor', + 'type': 'Short' + }, + 318: { + 'name': 'WhitePoint', + 'type': 'Rational' + }, + 319: { + 'name': 'PrimaryChromaticities', + 'type': 'Rational' + }, + 320: { + 'name': 'ColorMap', + 'type': 'Short' + }, + 321: { + 'name': 'HalftoneHints', + 'type': 'Short' + }, + 322: { + 'name': 'TileWidth', + 'type': 'Short' + }, + 323: { + 'name': 'TileLength', + 'type': 'Short' + }, + 324: { + 'name': 'TileOffsets', + 'type': 'Short' + }, + 325: { + 'name': 'TileByteCounts', + 'type': 'Short' + }, + 330: { + 'name': 'SubIFDs', + 'type': 'Long' + }, + 332: { + 'name': 'InkSet', + 'type': 'Short' + }, + 333: { + 'name': 'InkNames', + 'type': 'Ascii' + }, + 334: { + 'name': 'NumberOfInks', + 'type': 'Short' + }, + 336: { + 'name': 'DotRange', + 'type': 'Byte' + }, + 337: { + 'name': 'TargetPrinter', + 'type': 'Ascii' + }, + 338: { + 'name': 'ExtraSamples', + 'type': 'Short' + }, + 339: { + 'name': 'SampleFormat', + 'type': 'Short' + }, + 340: { + 'name': 'SMinSampleValue', + 'type': 'Short' + }, + 341: { + 'name': 'SMaxSampleValue', + 'type': 'Short' + }, + 342: { + 'name': 'TransferRange', + 'type': 'Short' + }, + 343: { + 'name': 'ClipPath', + 'type': 'Byte' + }, + 344: { + 'name': 'XClipPathUnits', + 'type': 'Long' + }, + 345: { + 'name': 'YClipPathUnits', + 'type': 'Long' + }, + 346: { + 'name': 'Indexed', + 'type': 'Short' + }, + 347: { + 'name': 'JPEGTables', + 'type': 'Undefined' + }, + 351: { + 'name': 'OPIProxy', + 'type': 'Short' + }, + 512: { + 'name': 'JPEGProc', + 'type': 'Long' + }, + 513: { + 'name': 'JPEGInterchangeFormat', + 'type': 'Long' + }, + 514: { + 'name': 'JPEGInterchangeFormatLength', + 'type': 'Long' + }, + 515: { + 'name': 'JPEGRestartInterval', + 'type': 'Short' + }, + 517: { + 'name': 'JPEGLosslessPredictors', + 'type': 'Short' + }, + 518: { + 'name': 'JPEGPointTransforms', + 'type': 'Short' + }, + 519: { + 'name': 'JPEGQTables', + 'type': 'Long' + }, + 520: { + 'name': 'JPEGDCTables', + 'type': 'Long' + }, + 521: { + 'name': 'JPEGACTables', + 'type': 'Long' + }, + 529: { + 'name': 'YCbCrCoefficients', + 'type': 'Rational' + }, + 530: { + 'name': 'YCbCrSubSampling', + 'type': 'Short' + }, + 531: { + 'name': 'YCbCrPositioning', + 'type': 'Short' + }, + 532: { + 'name': 'ReferenceBlackWhite', + 'type': 'Rational' + }, + 700: { + 'name': 'XMLPacket', + 'type': 'Byte' + }, + 18246: { + 'name': 'Rating', + 'type': 'Short' + }, + 18249: { + 'name': 'RatingPercent', + 'type': 'Short' + }, + 32781: { + 'name': 'ImageID', + 'type': 'Ascii' + }, + 33421: { + 'name': 'CFARepeatPatternDim', + 'type': 'Short' + }, + 33422: { + 'name': 'CFAPattern', + 'type': 'Byte' + }, + 33423: { + 'name': 'BatteryLevel', + 'type': 'Rational' + }, + 33432: { + 'name': 'Copyright', + 'type': 'Ascii' + }, + 33434: { + 'name': 'ExposureTime', + 'type': 'Rational' + }, + 34377: { + 'name': 'ImageResources', + 'type': 'Byte' + }, + 34665: { + 'name': 'ExifTag', + 'type': 'Long' + }, + 34675: { + 'name': 'InterColorProfile', + 'type': 'Undefined' + }, + 34853: { + 'name': 'GPSTag', + 'type': 'Long' + }, + 34857: { + 'name': 'Interlace', + 'type': 'Short' + }, + 34858: { + 'name': 'TimeZoneOffset', + 'type': 'Long' + }, + 34859: { + 'name': 'SelfTimerMode', + 'type': 'Short' + }, + 37387: { + 'name': 'FlashEnergy', + 'type': 'Rational' + }, + 37388: { + 'name': 'SpatialFrequencyResponse', + 'type': 'Undefined' + }, + 37389: { + 'name': 'Noise', + 'type': 'Undefined' + }, + 37390: { + 'name': 'FocalPlaneXResolution', + 'type': 'Rational' + }, + 37391: { + 'name': 'FocalPlaneYResolution', + 'type': 'Rational' + }, + 37392: { + 'name': 'FocalPlaneResolutionUnit', + 'type': 'Short' + }, + 37393: { + 'name': 'ImageNumber', + 'type': 'Long' + }, + 37394: { + 'name': 'SecurityClassification', + 'type': 'Ascii' + }, + 37395: { + 'name': 'ImageHistory', + 'type': 'Ascii' + }, + 37397: { + 'name': 'ExposureIndex', + 'type': 'Rational' + }, + 37398: { + 'name': 'TIFFEPStandardID', + 'type': 'Byte' + }, + 37399: { + 'name': 'SensingMethod', + 'type': 'Short' + }, + 40091: { + 'name': 'XPTitle', + 'type': 'Byte' + }, + 40092: { + 'name': 'XPComment', + 'type': 'Byte' + }, + 40093: { + 'name': 'XPAuthor', + 'type': 'Byte' + }, + 40094: { + 'name': 'XPKeywords', + 'type': 'Byte' + }, + 40095: { + 'name': 'XPSubject', + 'type': 'Byte' + }, + 50341: { + 'name': 'PrintImageMatching', + 'type': 'Undefined' + }, + 50706: { + 'name': 'DNGVersion', + 'type': 'Byte' + }, + 50707: { + 'name': 'DNGBackwardVersion', + 'type': 'Byte' + }, + 50708: { + 'name': 'UniqueCameraModel', + 'type': 'Ascii' + }, + 50709: { + 'name': 'LocalizedCameraModel', + 'type': 'Byte' + }, + 50710: { + 'name': 'CFAPlaneColor', + 'type': 'Byte' + }, + 50711: { + 'name': 'CFALayout', + 'type': 'Short' + }, + 50712: { + 'name': 'LinearizationTable', + 'type': 'Short' + }, + 50713: { + 'name': 'BlackLevelRepeatDim', + 'type': 'Short' + }, + 50714: { + 'name': 'BlackLevel', + 'type': 'Rational' + }, + 50715: { + 'name': 'BlackLevelDeltaH', + 'type': 'SRational' + }, + 50716: { + 'name': 'BlackLevelDeltaV', + 'type': 'SRational' + }, + 50717: { + 'name': 'WhiteLevel', + 'type': 'Short' + }, + 50718: { + 'name': 'DefaultScale', + 'type': 'Rational' + }, + 50719: { + 'name': 'DefaultCropOrigin', + 'type': 'Short' + }, + 50720: { + 'name': 'DefaultCropSize', + 'type': 'Short' + }, + 50721: { + 'name': 'ColorMatrix1', + 'type': 'SRational' + }, + 50722: { + 'name': 'ColorMatrix2', + 'type': 'SRational' + }, + 50723: { + 'name': 'CameraCalibration1', + 'type': 'SRational' + }, + 50724: { + 'name': 'CameraCalibration2', + 'type': 'SRational' + }, + 50725: { + 'name': 'ReductionMatrix1', + 'type': 'SRational' + }, + 50726: { + 'name': 'ReductionMatrix2', + 'type': 'SRational' + }, + 50727: { + 'name': 'AnalogBalance', + 'type': 'Rational' + }, + 50728: { + 'name': 'AsShotNeutral', + 'type': 'Short' + }, + 50729: { + 'name': 'AsShotWhiteXY', + 'type': 'Rational' + }, + 50730: { + 'name': 'BaselineExposure', + 'type': 'SRational' + }, + 50731: { + 'name': 'BaselineNoise', + 'type': 'Rational' + }, + 50732: { + 'name': 'BaselineSharpness', + 'type': 'Rational' + }, + 50733: { + 'name': 'BayerGreenSplit', + 'type': 'Long' + }, + 50734: { + 'name': 'LinearResponseLimit', + 'type': 'Rational' + }, + 50735: { + 'name': 'CameraSerialNumber', + 'type': 'Ascii' + }, + 50736: { + 'name': 'LensInfo', + 'type': 'Rational' + }, + 50737: { + 'name': 'ChromaBlurRadius', + 'type': 'Rational' + }, + 50738: { + 'name': 'AntiAliasStrength', + 'type': 'Rational' + }, + 50739: { + 'name': 'ShadowScale', + 'type': 'SRational' + }, + 50740: { + 'name': 'DNGPrivateData', + 'type': 'Byte' + }, + 50741: { + 'name': 'MakerNoteSafety', + 'type': 'Short' + }, + 50778: { + 'name': 'CalibrationIlluminant1', + 'type': 'Short' + }, + 50779: { + 'name': 'CalibrationIlluminant2', + 'type': 'Short' + }, + 50780: { + 'name': 'BestQualityScale', + 'type': 'Rational' + }, + 50781: { + 'name': 'RawDataUniqueID', + 'type': 'Byte' + }, + 50827: { + 'name': 'OriginalRawFileName', + 'type': 'Byte' + }, + 50828: { + 'name': 'OriginalRawFileData', + 'type': 'Undefined' + }, + 50829: { + 'name': 'ActiveArea', + 'type': 'Short' + }, + 50830: { + 'name': 'MaskedAreas', + 'type': 'Short' + }, + 50831: { + 'name': 'AsShotICCProfile', + 'type': 'Undefined' + }, + 50832: { + 'name': 'AsShotPreProfileMatrix', + 'type': 'SRational' + }, + 50833: { + 'name': 'CurrentICCProfile', + 'type': 'Undefined' + }, + 50834: { + 'name': 'CurrentPreProfileMatrix', + 'type': 'SRational' + }, + 50879: { + 'name': 'ColorimetricReference', + 'type': 'Short' + }, + 50931: { + 'name': 'CameraCalibrationSignature', + 'type': 'Byte' + }, + 50932: { + 'name': 'ProfileCalibrationSignature', + 'type': 'Byte' + }, + 50934: { + 'name': 'AsShotProfileName', + 'type': 'Byte' + }, + 50935: { + 'name': 'NoiseReductionApplied', + 'type': 'Rational' + }, + 50936: { + 'name': 'ProfileName', + 'type': 'Byte' + }, + 50937: { + 'name': 'ProfileHueSatMapDims', + 'type': 'Long' + }, + 50938: { + 'name': 'ProfileHueSatMapData1', + 'type': 'Float' + }, + 50939: { + 'name': 'ProfileHueSatMapData2', + 'type': 'Float' + }, + 50940: { + 'name': 'ProfileToneCurve', + 'type': 'Float' + }, + 50941: { + 'name': 'ProfileEmbedPolicy', + 'type': 'Long' + }, + 50942: { + 'name': 'ProfileCopyright', + 'type': 'Byte' + }, + 50964: { + 'name': 'ForwardMatrix1', + 'type': 'SRational' + }, + 50965: { + 'name': 'ForwardMatrix2', + 'type': 'SRational' + }, + 50966: { + 'name': 'PreviewApplicationName', + 'type': 'Byte' + }, + 50967: { + 'name': 'PreviewApplicationVersion', + 'type': 'Byte' + }, + 50968: { + 'name': 'PreviewSettingsName', + 'type': 'Byte' + }, + 50969: { + 'name': 'PreviewSettingsDigest', + 'type': 'Byte' + }, + 50970: { + 'name': 'PreviewColorSpace', + 'type': 'Long' + }, + 50971: { + 'name': 'PreviewDateTime', + 'type': 'Ascii' + }, + 50972: { + 'name': 'RawImageDigest', + 'type': 'Undefined' + }, + 50973: { + 'name': 'OriginalRawFileDigest', + 'type': 'Undefined' + }, + 50974: { + 'name': 'SubTileBlockSize', + 'type': 'Long' + }, + 50975: { + 'name': 'RowInterleaveFactor', + 'type': 'Long' + }, + 50981: { + 'name': 'ProfileLookTableDims', + 'type': 'Long' + }, + 50982: { + 'name': 'ProfileLookTableData', + 'type': 'Float' + }, + 51008: { + 'name': 'OpcodeList1', + 'type': 'Undefined' + }, + 51009: { + 'name': 'OpcodeList2', + 'type': 'Undefined' + }, + 51022: { + 'name': 'OpcodeList3', + 'type': 'Undefined' + } + }, + 'Exif': { + 33434: { + 'name': 'ExposureTime', + 'type': 'Rational' + }, + 33437: { + 'name': 'FNumber', + 'type': 'Rational' + }, + 34850: { + 'name': 'ExposureProgram', + 'type': 'Short' + }, + 34852: { + 'name': 'SpectralSensitivity', + 'type': 'Ascii' + }, + 34855: { + 'name': 'ISOSpeedRatings', + 'type': 'Short' + }, + 34856: { + 'name': 'OECF', + 'type': 'Undefined' + }, + 34864: { + 'name': 'SensitivityType', + 'type': 'Short' + }, + 34865: { + 'name': 'StandardOutputSensitivity', + 'type': 'Long' + }, + 34866: { + 'name': 'RecommendedExposureIndex', + 'type': 'Long' + }, + 34867: { + 'name': 'ISOSpeed', + 'type': 'Long' + }, + 34868: { + 'name': 'ISOSpeedLatitudeyyy', + 'type': 'Long' + }, + 34869: { + 'name': 'ISOSpeedLatitudezzz', + 'type': 'Long' + }, + 36864: { + 'name': 'ExifVersion', + 'type': 'Undefined' + }, + 36867: { + 'name': 'DateTimeOriginal', + 'type': 'Ascii' + }, + 36868: { + 'name': 'DateTimeDigitized', + 'type': 'Ascii' + }, + 37121: { + 'name': 'ComponentsConfiguration', + 'type': 'Undefined' + }, + 37122: { + 'name': 'CompressedBitsPerPixel', + 'type': 'Rational' + }, + 37377: { + 'name': 'ShutterSpeedValue', + 'type': 'SRational' + }, + 37378: { + 'name': 'ApertureValue', + 'type': 'Rational' + }, + 37379: { + 'name': 'BrightnessValue', + 'type': 'SRational' + }, + 37380: { + 'name': 'ExposureBiasValue', + 'type': 'SRational' + }, + 37381: { + 'name': 'MaxApertureValue', + 'type': 'Rational' + }, + 37382: { + 'name': 'SubjectDistance', + 'type': 'Rational' + }, + 37383: { + 'name': 'MeteringMode', + 'type': 'Short' + }, + 37384: { + 'name': 'LightSource', + 'type': 'Short' + }, + 37385: { + 'name': 'Flash', + 'type': 'Short' + }, + 37386: { + 'name': 'FocalLength', + 'type': 'Rational' + }, + 37396: { + 'name': 'SubjectArea', + 'type': 'Short' + }, + 37500: { + 'name': 'MakerNote', + 'type': 'Undefined' + }, + 37510: { + 'name': 'UserComment', + 'type': 'Ascii' + }, + 37520: { + 'name': 'SubSecTime', + 'type': 'Ascii' + }, + 37521: { + 'name': 'SubSecTimeOriginal', + 'type': 'Ascii' + }, + 37522: { + 'name': 'SubSecTimeDigitized', + 'type': 'Ascii' + }, + 40960: { + 'name': 'FlashpixVersion', + 'type': 'Undefined' + }, + 40961: { + 'name': 'ColorSpace', + 'type': 'Short' + }, + 40962: { + 'name': 'PixelXDimension', + 'type': 'Long' + }, + 40963: { + 'name': 'PixelYDimension', + 'type': 'Long' + }, + 40964: { + 'name': 'RelatedSoundFile', + 'type': 'Ascii' + }, + 40965: { + 'name': 'InteroperabilityTag', + 'type': 'Long' + }, + 41483: { + 'name': 'FlashEnergy', + 'type': 'Rational' + }, + 41484: { + 'name': 'SpatialFrequencyResponse', + 'type': 'Undefined' + }, + 41486: { + 'name': 'FocalPlaneXResolution', + 'type': 'Rational' + }, + 41487: { + 'name': 'FocalPlaneYResolution', + 'type': 'Rational' + }, + 41488: { + 'name': 'FocalPlaneResolutionUnit', + 'type': 'Short' + }, + 41492: { + 'name': 'SubjectLocation', + 'type': 'Short' + }, + 41493: { + 'name': 'ExposureIndex', + 'type': 'Rational' + }, + 41495: { + 'name': 'SensingMethod', + 'type': 'Short' + }, + 41728: { + 'name': 'FileSource', + 'type': 'Undefined' + }, + 41729: { + 'name': 'SceneType', + 'type': 'Undefined' + }, + 41730: { + 'name': 'CFAPattern', + 'type': 'Undefined' + }, + 41985: { + 'name': 'CustomRendered', + 'type': 'Short' + }, + 41986: { + 'name': 'ExposureMode', + 'type': 'Short' + }, + 41987: { + 'name': 'WhiteBalance', + 'type': 'Short' + }, + 41988: { + 'name': 'DigitalZoomRatio', + 'type': 'Rational' + }, + 41989: { + 'name': 'FocalLengthIn35mmFilm', + 'type': 'Short' + }, + 41990: { + 'name': 'SceneCaptureType', + 'type': 'Short' + }, + 41991: { + 'name': 'GainControl', + 'type': 'Short' + }, + 41992: { + 'name': 'Contrast', + 'type': 'Short' + }, + 41993: { + 'name': 'Saturation', + 'type': 'Short' + }, + 41994: { + 'name': 'Sharpness', + 'type': 'Short' + }, + 41995: { + 'name': 'DeviceSettingDescription', + 'type': 'Undefined' + }, + 41996: { + 'name': 'SubjectDistanceRange', + 'type': 'Short' + }, + 42016: { + 'name': 'ImageUniqueID', + 'type': 'Ascii' + }, + 42032: { + 'name': 'CameraOwnerName', + 'type': 'Ascii' + }, + 42033: { + 'name': 'BodySerialNumber', + 'type': 'Ascii' + }, + 42034: { + 'name': 'LensSpecification', + 'type': 'Rational' + }, + 42035: { + 'name': 'LensMake', + 'type': 'Ascii' + }, + 42036: { + 'name': 'LensModel', + 'type': 'Ascii' + }, + 42037: { + 'name': 'LensSerialNumber', + 'type': 'Ascii' + }, + 42240: { + 'name': 'Gamma', + 'type': 'Rational' + } + }, + 'GPS': { + 0: { + 'name': 'GPSVersionID', + 'type': 'Byte' + }, + 1: { + 'name': 'GPSLatitudeRef', + 'type': 'Ascii' + }, + 2: { + 'name': 'GPSLatitude', + 'type': 'Rational' + }, + 3: { + 'name': 'GPSLongitudeRef', + 'type': 'Ascii' + }, + 4: { + 'name': 'GPSLongitude', + 'type': 'Rational' + }, + 5: { + 'name': 'GPSAltitudeRef', + 'type': 'Byte' + }, + 6: { + 'name': 'GPSAltitude', + 'type': 'Rational' + }, + 7: { + 'name': 'GPSTimeStamp', + 'type': 'Rational' + }, + 8: { + 'name': 'GPSSatellites', + 'type': 'Ascii' + }, + 9: { + 'name': 'GPSStatus', + 'type': 'Ascii' + }, + 10: { + 'name': 'GPSMeasureMode', + 'type': 'Ascii' + }, + 11: { + 'name': 'GPSDOP', + 'type': 'Rational' + }, + 12: { + 'name': 'GPSSpeedRef', + 'type': 'Ascii' + }, + 13: { + 'name': 'GPSSpeed', + 'type': 'Rational' + }, + 14: { + 'name': 'GPSTrackRef', + 'type': 'Ascii' + }, + 15: { + 'name': 'GPSTrack', + 'type': 'Rational' + }, + 16: { + 'name': 'GPSImgDirectionRef', + 'type': 'Ascii' + }, + 17: { + 'name': 'GPSImgDirection', + 'type': 'Rational' + }, + 18: { + 'name': 'GPSMapDatum', + 'type': 'Ascii' + }, + 19: { + 'name': 'GPSDestLatitudeRef', + 'type': 'Ascii' + }, + 20: { + 'name': 'GPSDestLatitude', + 'type': 'Rational' + }, + 21: { + 'name': 'GPSDestLongitudeRef', + 'type': 'Ascii' + }, + 22: { + 'name': 'GPSDestLongitude', + 'type': 'Rational' + }, + 23: { + 'name': 'GPSDestBearingRef', + 'type': 'Ascii' + }, + 24: { + 'name': 'GPSDestBearing', + 'type': 'Rational' + }, + 25: { + 'name': 'GPSDestDistanceRef', + 'type': 'Ascii' + }, + 26: { + 'name': 'GPSDestDistance', + 'type': 'Rational' + }, + 27: { + 'name': 'GPSProcessingMethod', + 'type': 'Undefined' + }, + 28: { + 'name': 'GPSAreaInformation', + 'type': 'Undefined' + }, + 29: { + 'name': 'GPSDateStamp', + 'type': 'Ascii' + }, + 30: { + 'name': 'GPSDifferential', + 'type': 'Short' + }, + 31: { + 'name': 'GPSHPositioningError', + 'type': 'Rational' + } + }, + 'Interop': { + 1: { + 'name': 'InteroperabilityIndex', + 'type': 'Ascii' + } + }, + }; + TAGS["0th"] = TAGS["Image"]; + TAGS["1st"] = TAGS["Image"]; + that.TAGS = TAGS; + + + that.ImageIFD = { + ProcessingSoftware:11, + NewSubfileType:254, + SubfileType:255, + ImageWidth:256, + ImageLength:257, + BitsPerSample:258, + Compression:259, + PhotometricInterpretation:262, + Threshholding:263, + CellWidth:264, + CellLength:265, + FillOrder:266, + DocumentName:269, + ImageDescription:270, + Make:271, + Model:272, + StripOffsets:273, + Orientation:274, + SamplesPerPixel:277, + RowsPerStrip:278, + StripByteCounts:279, + XResolution:282, + YResolution:283, + PlanarConfiguration:284, + GrayResponseUnit:290, + GrayResponseCurve:291, + T4Options:292, + T6Options:293, + ResolutionUnit:296, + TransferFunction:301, + Software:305, + DateTime:306, + Artist:315, + HostComputer:316, + Predictor:317, + WhitePoint:318, + PrimaryChromaticities:319, + ColorMap:320, + HalftoneHints:321, + TileWidth:322, + TileLength:323, + TileOffsets:324, + TileByteCounts:325, + SubIFDs:330, + InkSet:332, + InkNames:333, + NumberOfInks:334, + DotRange:336, + TargetPrinter:337, + ExtraSamples:338, + SampleFormat:339, + SMinSampleValue:340, + SMaxSampleValue:341, + TransferRange:342, + ClipPath:343, + XClipPathUnits:344, + YClipPathUnits:345, + Indexed:346, + JPEGTables:347, + OPIProxy:351, + JPEGProc:512, + JPEGInterchangeFormat:513, + JPEGInterchangeFormatLength:514, + JPEGRestartInterval:515, + JPEGLosslessPredictors:517, + JPEGPointTransforms:518, + JPEGQTables:519, + JPEGDCTables:520, + JPEGACTables:521, + YCbCrCoefficients:529, + YCbCrSubSampling:530, + YCbCrPositioning:531, + ReferenceBlackWhite:532, + XMLPacket:700, + Rating:18246, + RatingPercent:18249, + ImageID:32781, + CFARepeatPatternDim:33421, + CFAPattern:33422, + BatteryLevel:33423, + Copyright:33432, + ExposureTime:33434, + ImageResources:34377, + ExifTag:34665, + InterColorProfile:34675, + GPSTag:34853, + Interlace:34857, + TimeZoneOffset:34858, + SelfTimerMode:34859, + FlashEnergy:37387, + SpatialFrequencyResponse:37388, + Noise:37389, + FocalPlaneXResolution:37390, + FocalPlaneYResolution:37391, + FocalPlaneResolutionUnit:37392, + ImageNumber:37393, + SecurityClassification:37394, + ImageHistory:37395, + ExposureIndex:37397, + TIFFEPStandardID:37398, + SensingMethod:37399, + XPTitle:40091, + XPComment:40092, + XPAuthor:40093, + XPKeywords:40094, + XPSubject:40095, + PrintImageMatching:50341, + DNGVersion:50706, + DNGBackwardVersion:50707, + UniqueCameraModel:50708, + LocalizedCameraModel:50709, + CFAPlaneColor:50710, + CFALayout:50711, + LinearizationTable:50712, + BlackLevelRepeatDim:50713, + BlackLevel:50714, + BlackLevelDeltaH:50715, + BlackLevelDeltaV:50716, + WhiteLevel:50717, + DefaultScale:50718, + DefaultCropOrigin:50719, + DefaultCropSize:50720, + ColorMatrix1:50721, + ColorMatrix2:50722, + CameraCalibration1:50723, + CameraCalibration2:50724, + ReductionMatrix1:50725, + ReductionMatrix2:50726, + AnalogBalance:50727, + AsShotNeutral:50728, + AsShotWhiteXY:50729, + BaselineExposure:50730, + BaselineNoise:50731, + BaselineSharpness:50732, + BayerGreenSplit:50733, + LinearResponseLimit:50734, + CameraSerialNumber:50735, + LensInfo:50736, + ChromaBlurRadius:50737, + AntiAliasStrength:50738, + ShadowScale:50739, + DNGPrivateData:50740, + MakerNoteSafety:50741, + CalibrationIlluminant1:50778, + CalibrationIlluminant2:50779, + BestQualityScale:50780, + RawDataUniqueID:50781, + OriginalRawFileName:50827, + OriginalRawFileData:50828, + ActiveArea:50829, + MaskedAreas:50830, + AsShotICCProfile:50831, + AsShotPreProfileMatrix:50832, + CurrentICCProfile:50833, + CurrentPreProfileMatrix:50834, + ColorimetricReference:50879, + CameraCalibrationSignature:50931, + ProfileCalibrationSignature:50932, + AsShotProfileName:50934, + NoiseReductionApplied:50935, + ProfileName:50936, + ProfileHueSatMapDims:50937, + ProfileHueSatMapData1:50938, + ProfileHueSatMapData2:50939, + ProfileToneCurve:50940, + ProfileEmbedPolicy:50941, + ProfileCopyright:50942, + ForwardMatrix1:50964, + ForwardMatrix2:50965, + PreviewApplicationName:50966, + PreviewApplicationVersion:50967, + PreviewSettingsName:50968, + PreviewSettingsDigest:50969, + PreviewColorSpace:50970, + PreviewDateTime:50971, + RawImageDigest:50972, + OriginalRawFileDigest:50973, + SubTileBlockSize:50974, + RowInterleaveFactor:50975, + ProfileLookTableDims:50981, + ProfileLookTableData:50982, + OpcodeList1:51008, + OpcodeList2:51009, + OpcodeList3:51022, + NoiseProfile:51041, + }; + + + that.ExifIFD = { + ExposureTime:33434, + FNumber:33437, + ExposureProgram:34850, + SpectralSensitivity:34852, + ISOSpeedRatings:34855, + OECF:34856, + SensitivityType:34864, + StandardOutputSensitivity:34865, + RecommendedExposureIndex:34866, + ISOSpeed:34867, + ISOSpeedLatitudeyyy:34868, + ISOSpeedLatitudezzz:34869, + ExifVersion:36864, + DateTimeOriginal:36867, + DateTimeDigitized:36868, + ComponentsConfiguration:37121, + CompressedBitsPerPixel:37122, + ShutterSpeedValue:37377, + ApertureValue:37378, + BrightnessValue:37379, + ExposureBiasValue:37380, + MaxApertureValue:37381, + SubjectDistance:37382, + MeteringMode:37383, + LightSource:37384, + Flash:37385, + FocalLength:37386, + SubjectArea:37396, + MakerNote:37500, + UserComment:37510, + SubSecTime:37520, + SubSecTimeOriginal:37521, + SubSecTimeDigitized:37522, + FlashpixVersion:40960, + ColorSpace:40961, + PixelXDimension:40962, + PixelYDimension:40963, + RelatedSoundFile:40964, + InteroperabilityTag:40965, + FlashEnergy:41483, + SpatialFrequencyResponse:41484, + FocalPlaneXResolution:41486, + FocalPlaneYResolution:41487, + FocalPlaneResolutionUnit:41488, + SubjectLocation:41492, + ExposureIndex:41493, + SensingMethod:41495, + FileSource:41728, + SceneType:41729, + CFAPattern:41730, + CustomRendered:41985, + ExposureMode:41986, + WhiteBalance:41987, + DigitalZoomRatio:41988, + FocalLengthIn35mmFilm:41989, + SceneCaptureType:41990, + GainControl:41991, + Contrast:41992, + Saturation:41993, + Sharpness:41994, + DeviceSettingDescription:41995, + SubjectDistanceRange:41996, + ImageUniqueID:42016, + CameraOwnerName:42032, + BodySerialNumber:42033, + LensSpecification:42034, + LensMake:42035, + LensModel:42036, + LensSerialNumber:42037, + Gamma:42240, + }; + + + that.GPSIFD = { + GPSVersionID:0, + GPSLatitudeRef:1, + GPSLatitude:2, + GPSLongitudeRef:3, + GPSLongitude:4, + GPSAltitudeRef:5, + GPSAltitude:6, + GPSTimeStamp:7, + GPSSatellites:8, + GPSStatus:9, + GPSMeasureMode:10, + GPSDOP:11, + GPSSpeedRef:12, + GPSSpeed:13, + GPSTrackRef:14, + GPSTrack:15, + GPSImgDirectionRef:16, + GPSImgDirection:17, + GPSMapDatum:18, + GPSDestLatitudeRef:19, + GPSDestLatitude:20, + GPSDestLongitudeRef:21, + GPSDestLongitude:22, + GPSDestBearingRef:23, + GPSDestBearing:24, + GPSDestDistanceRef:25, + GPSDestDistance:26, + GPSProcessingMethod:27, + GPSAreaInformation:28, + GPSDateStamp:29, + GPSDifferential:30, + GPSHPositioningError:31, + }; + + + that.InteropIFD = { + InteroperabilityIndex:1, + }; + + that.GPSHelper = { + degToDmsRational:function (degFloat) { + var degAbs = Math.abs(degFloat); + var minFloat = degAbs % 1 * 60; + var secFloat = minFloat % 1 * 60; + var deg = Math.floor(degAbs); + var min = Math.floor(minFloat); + var sec = Math.round(secFloat * 100); + + return [[deg, 1], [min, 1], [sec, 100]]; + }, + + dmsRationalToDeg:function (dmsArray, ref) { + var sign = (ref === 'S' || ref === 'W') ? -1.0 : 1.0; + var deg = dmsArray[0][0] / dmsArray[0][1] + + dmsArray[1][0] / dmsArray[1][1] / 60.0 + + dmsArray[2][0] / dmsArray[2][1] / 3600.0; + + return deg * sign; + } + }; + + + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = that; + } + exports.piexif = that; + } else { + window.piexif = that; + } + +})(); \ No newline at end of file -- cgit v1.2.3