| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471 | /* piexifjsThe MIT License (MIT)Copyright (c) 2014, 2015 hMatoba(https://github.com/hMatoba)Permission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in allcopies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, 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 THESOFTWARE.*/(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;    }})();
 |