2482 lines
75 KiB
JavaScript
2482 lines
75 KiB
JavaScript
/* 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;
|
|
}
|
|
|
|
})();
|