You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DS7/DSWeb/Areas/SoftMng/Content/bootstrap-fileinput-master/js/plugins/piexif.js

2472 lines
74 KiB
JavaScript

3 years ago
/* 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.03";
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 ("Given data is not jpeg.");
}
var segments = splitIntoSegments(jpeg);
if (segments[1].slice(0, 2) == "\xff\xe1" &&
segments[1].slice(4, 10) == "Exif\x00\x00") {
segments = [segments[0]].concat(segments.slice(2));
} else if (segments[2].slice(0, 2) == "\xff\xe1" &&
segments[2].slice(4, 10) == "Exif\x00\x00") {
segments = segments.slice(0, 2).concat(segments.slice(3));
} else {
throw("Exif not found.");
}
var new_data = segments.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 ("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 ("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 ("'load' gots invalid file data.");
}
} else {
throw ("'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 ("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 ("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 == 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 ("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 ("'pack' error. Got invalid type argument.");
}
if ((mark.length - 1) != array.length) {
throw ("'pack' error. " + (mark.length - 1) + " marks, " + array.length + " elements.");
}
var littleEndian;
if (mark[0] == "<") {
littleEndian = true;
} else if (mark[0] == ">") {
littleEndian = false;
} else {
throw ("");
}
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 ("'pack' error.");
} else {
valStr = String.fromCharCode(val);
}
} else if (c == "H") {
val = array[p - 1];
if ((val > 0xffff) || (val < 0)) {
throw ("'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 ("'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 ("'pack' error.");
}
packed += valStr;
p += 1;
}
return packed;
}
function unpack(mark, str) {
if (typeof (str) != "string") {
throw ("'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 ("'unpack' error. Got invalid mark.");
}
}
if (l != str.length) {
throw ("'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 ("'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 ("'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 ("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 ("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) {
if (segments[1].slice(0, 2) == "\xff\xe0" &&
(segments[2].slice(0, 2) == "\xff\xe1" &&
segments[2].slice(4, 10) == "Exif\x00\x00")) {
if (exif) {
segments[2] = exif;
segments = ["\xff\xd8"].concat(segments.slice(2));
} else if (exif == null) {
segments = segments.slice(0, 2).concat(segments.slice(3));
} else {
segments = segments.slice(0).concat(segments.slice(2));
}
} else if (segments[1].slice(0, 2) == "\xff\xe0") {
if (exif) {
segments[1] = exif;
}
} else if (segments[1].slice(0, 2) == "\xff\xe1" &&
segments[1].slice(4, 10) == "Exif\x00\x00") {
if (exif) {
segments[1] = exif;
} else if (exif == null) {
segments = segments.slice(0).concat(segments.slice(2));
}
} else {
if (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 minFloat = degFloat % 1 * 60;
var secFloat = minFloat % 1 * 60;
var deg = Math.floor(degFloat);
var min = Math.floor(minFloat);
var sec = Math.round(secFloat * 100);
return [[deg, 1], [min, 1], [sec, 100]];
}
};
if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = that;
}
exports.piexif = that;
} else {
window.piexif = that;
}
})();