From be83336cf7f7d71f49d4bb4e3971defe53456524 Mon Sep 17 00:00:00 2001 From: JeLuF Date: Mon, 21 Aug 2023 09:58:26 +0200 Subject: [PATCH] WebP metadata support (#1511) * WebP metadata support - Replace piexif.js by Exif-Reader - Merge plugin html/css to index.html/main.css * Add webp to tooltip message --- 3rd-PARTY-LICENSES | 380 +++ ui/index.html | 15 +- ui/media/css/image-editor.css | 25 +- ui/media/css/main.css | 14 + ui/media/js/exif-reader.js | 2 + .../ui/image-editor-improvements.plugin.js | 2577 +---------------- 6 files changed, 459 insertions(+), 2554 deletions(-) create mode 100644 ui/media/js/exif-reader.js diff --git a/3rd-PARTY-LICENSES b/3rd-PARTY-LICENSES index 78bfe3bb..05ba4541 100644 --- a/3rd-PARTY-LICENSES +++ b/3rd-PARTY-LICENSES @@ -740,3 +740,383 @@ croppr.js is licensed under the MIT license: 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. + +ExifReader +========== +https://github.com/mattiasw/ExifReader + +ExifReader is licensed under the Mozilla Public License: + + Mozilla Public License Version 2.0 + ================================== + + 1. Definitions + -------------- + + 1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + + 1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + + 1.3. "Contribution" + means Covered Software of a particular Contributor. + + 1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + + 1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + + 1.6. "Executable Form" + means any form of the work other than Source Code Form. + + 1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + + 1.8. "License" + means this document. + + 1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + + 1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + + 1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + + 1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + + 1.13. "Source Code Form" + means the form of the work preferred for making modifications. + + 1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + + 2. License Grants and Conditions + -------------------------------- + + 2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + (a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + + (b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + + 2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. + + 2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: + + (a) for any code that a Contributor has removed from Covered Software; + or + + (b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + (c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). + + 2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). + + 2.5. Representation + + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights + to grant the rights to its Contributions conveyed by this License. + + 2.6. Fair Use + + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. + + 2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted + in Section 2.1. + + 3. Responsibilities + ------------------- + + 3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. + + 3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + (a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + + (b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + + 3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). + + 3.4. Notices + + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, + or limitations of liability) contained within the Source Code Form of + the Covered Software, except that You may alter any license notices to + the extent required to remedy known factual inaccuracies. + + 3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + + 4. Inability to Comply Due to Statute or Regulation + --------------------------------------------------- + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Software due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description must + be placed in a text file included with all distributions of the Covered + Software under this License. Except to the extent prohibited by statute + or regulation, such description must be sufficiently detailed for a + recipient of ordinary skill to be able to understand it. + + 5. Termination + -------------- + + 5.1. The rights granted under this License will terminate automatically + if You fail to comply with any of its terms. However, if You become + compliant, then the rights granted under this License from a particular + Contributor are reinstated (a) provisionally, unless and until such + Contributor explicitly and finally terminates Your grants, and (b) on an + ongoing basis, if such Contributor fails to notify You of the + non-compliance by some reasonable means prior to 60 days after You have + come back into compliance. Moreover, Your grants from a particular + Contributor are reinstated on an ongoing basis if such Contributor + notifies You of the non-compliance by some reasonable means, this is the + first time You have received notice of non-compliance with this License + from such Contributor, and You become compliant prior to 30 days after + Your receipt of the notice. + + 5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. + + 5.3. In the event of termination under Sections 5.1 or 5.2 above, all + end user license agreements (excluding distributors and resellers) which + have been validly granted by You or Your distributors under this License + prior to termination shall survive termination. + + ************************************************************************ + * * + * 6. Disclaimer of Warranty * + * ------------------------- * + * * + * Covered Software is provided under this License on an "as is" * + * basis, without warranty of any kind, either expressed, implied, or * + * statutory, including, without limitation, warranties that the * + * Covered Software is free of defects, merchantable, fit for a * + * particular purpose or non-infringing. The entire risk as to the * + * quality and performance of the Covered Software is with You. * + * Should any Covered Software prove defective in any respect, You * + * (not any Contributor) assume the cost of any necessary servicing, * + * repair, or correction. This disclaimer of warranty constitutes an * + * essential part of this License. No use of any Covered Software is * + * authorized under this License except under this disclaimer. * + * * + ************************************************************************ + + ************************************************************************ + * * + * 7. Limitation of Liability * + * -------------------------- * + * * + * Under no circumstances and under no legal theory, whether tort * + * (including negligence), contract, or otherwise, shall any * + * Contributor, or anyone who distributes Covered Software as * + * permitted above, be liable to You for any direct, indirect, * + * special, incidental, or consequential damages of any character * + * including, without limitation, damages for lost profits, loss of * + * goodwill, work stoppage, computer failure or malfunction, or any * + * and all other commercial damages or losses, even if such party * + * shall have been informed of the possibility of such damages. This * + * limitation of liability shall not apply to liability for death or * + * personal injury resulting from such party's negligence to the * + * extent applicable law prohibits such limitation. Some * + * jurisdictions do not allow the exclusion or limitation of * + * incidental or consequential damages, so this exclusion and * + * limitation may not apply to You. * + * * + ************************************************************************ + + 8. Litigation + ------------- + + Any litigation relating to this License may be brought only in the + courts of a jurisdiction where the defendant maintains its principal + place of business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. + Nothing in this Section shall prevent a party's ability to bring + cross-claims or counter-claims. + + 9. Miscellaneous + ---------------- + + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides + that the language of a contract shall be construed against the drafter + shall not be used to construe this License against a Contributor. + + 10. Versions of the License + --------------------------- + + 10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + + 10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license + steward. + + 10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). + + 10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses + + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + + Exhibit A - Source Code Form License Notice + ------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to look + for such a notice. + + You may add additional accurate notices of copyright ownership. + + Exhibit B - "Incompatible With Secondary Licenses" Notice + --------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/ui/index.html b/ui/index.html index 32fdfbf0..05a83c57 100644 --- a/ui/index.html +++ b/ui/index.html @@ -26,6 +26,7 @@ +
@@ -61,7 +62,14 @@
- or + + or +
@@ -83,6 +91,11 @@
+ + Add img2img source image using the Browse button, via drag & drop from external file or browser image (incl. + rendered image) or by pasting an image from the clipboard using Ctrl+V.

+ You may also reload the metadata embedded in a PNG, WEBP or JPEG image (enable embedding from the Settings). +
diff --git a/ui/media/css/image-editor.css b/ui/media/css/image-editor.css index ba046383..46f49ebe 100644 --- a/ui/media/css/image-editor.css +++ b/ui/media/css/image-editor.css @@ -229,4 +229,27 @@ } .inpainter .load_mask { display: flex; -} \ No newline at end of file +} + +.editor-canvas-overlay { + cursor: none; +} + +.image-brush-preview { + position: fixed; + background: black; + opacity: 0.3; + borderRadius: 50%; + cursor: none; + pointer-events: none; + transform: translate(-50%, -50%); +} + +.editor-options-container > * > *:not(.active):not(.button) { + border: 1px dotted slategray; +} + +.image_editor_opacity .editor-options-container > * > *:not(.active):not(.button) { + border: 1px dotted slategray; +} + diff --git a/ui/media/css/main.css b/ui/media/css/main.css index 25602e8c..e9021ead 100644 --- a/ui/media/css/main.css +++ b/ui/media/css/main.css @@ -1927,6 +1927,20 @@ div#enlarge-buttons { width: 77%; } +.drop-area { + width: 45%; + height: 50px; + border: 2px dashed #ccc; + text-align: center; + line-height: 50px; + font-size: small; + color: #ccc; + border-radius: 10px; + display: none; + margin: 12px 10px; +} + + /* hack for fixing Image Modifier Improvements plugin */ #imageTagPopupContainer { position: absolute; diff --git a/ui/media/js/exif-reader.js b/ui/media/js/exif-reader.js new file mode 100644 index 00000000..6fdc7045 --- /dev/null +++ b/ui/media/js/exif-reader.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.ExifReader=t():e.ExifReader=t()}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={d:function(t,n){for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:1,get:n[r]})},o:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r:function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:1})}},t={};function n(e){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(e)}function r(e,t,n){for(var r=[],i=0;i=8){var t=l(e.slice(0,8));if("ASCII\0\0\0"===t)return l(e.slice(8));if("JIS\0\0\0\0\0"===t)return"[JIS encoded text]";if("UNICODE\0"===t)return"[Unicode encoded text]";if("\0\0\0\0\0\0\0\0"===t)return"[Undefined encoding]"}return"Undefined"}function p(e){return e[0][0]/e[0][1]+e[1][0]/e[1][1]/60+e[2][0]/e[2][1]/3600}var m=18761,g=m,v=function(e,t){if(e.getUint16(t)===m)return m;if(19789===e.getUint16(t))return 19789;throw Error("Illegal byte order value. Faulty image.")},h=65505;function y(e,t){return 65472===e.getUint16(t)}function S(e,t){return 65474===e.getUint16(t)}function b(e,t){return 65506===e.getUint16(t)&&"ICC_PROFILE\0"===r(e,t+4,12)}function C(e,t){return 65506===e.getUint16(t)&&"MPF\0"===r(e,t+4,4)}function A(e,t){return 65504===e.getUint16(t)&&"JFIF"===r(e,t+4,4)&&0===e.getUint8(t+4+4)}function I(e,t){return e.getUint16(t)===h&&"Exif"===r(e,t+4,4)&&0===e.getUint8(t+4+4)}function P(e,t){return e.getUint16(t)===h&&function(e,t){return"http://ns.adobe.com/xap/1.0/\0"===r(e,t+4,29)}(e,t)}function U(e,t){return e.getUint16(t)===h&&function(e,t){return"http://ns.adobe.com/xmp/extension/\0"===r(e,t+4,35)}(e,t)}function w(e,t){return{dataOffset:e+33,length:t-31}}function T(e,t){return{dataOffset:e+79,length:t-77}}function D(e,t){return 65517===e.getUint16(t)&&"Photoshop 3.0"===r(e,t+4,13)&&0===e.getUint8(t+4+13)}function x(e,t){var n=e.getUint16(t);return n>=65504&&n<=65519||65534===n||65472===n||65474===n||65476===n||65499===n||65501===n||65498===n}function M(e,t){return 65535===e.getUint16(t)}var O="‰PNG\r\n\n",F="iTXt",R="pHYs",L="tIME";function k(e,t){return"IHDR"===r(e,t+4,4)}function E(e,t){return"iTXt"===r(e,t+4,4)&&"XML:com.adobe.xmp\0"===r(e,t+8,18)}function N(e,t){var n=r(e,t+4,4);return"tEXt"===n||"iTXt"===n}function G(e,t){return"eXIf"===r(e,t+4,4)}function B(e,t){var n=[R,L],i=r(e,t+4,4);return n.includes(i)}function j(e,t){t+=28;for(var n=0;n<2&&t=4&&function(e){var t=e.getUint16(0)===g;return 42===e.getUint16(2,t)}(e)}(e))return{hasAppMarkers:1,tiffHeaderOffset:0};if(function(e){return!!e&&e.byteLength>=2&&65496===e.getUint16(0)}(e))return function(e){for(var t,n,r,i,o,a,u,c,f,s=2;s+4+5<=e.byteLength;){if(y(e,s))n=s+2;else if(S(e,s))r=s+2;else if(A(e,s))t=e.getUint16(s+2),i=s+2;else if(I(e,s))t=e.getUint16(s+2),o=s+10;else if(P(e,s))u||(u=[]),t=e.getUint16(s+2),u.push(w(s,t));else if(U(e,s))u||(u=[]),t=e.getUint16(s+2),u.push(T(s,t));else if(D(e,s))t=e.getUint16(s+2),a=s+18;else if(b(e,s)){var l=s+18,d=(t=e.getUint16(s+2))-16,p=e.getUint8(s+16),m=e.getUint8(s+17);c||(c=[]),c.push({offset:l,length:d,chunkNumber:p,chunksTotal:m})}else if(C(e,s))t=e.getUint16(s+2),f=s+8;else{if(!x(e,s)){if(M(e,s)){s++;continue}break}t=e.getUint16(s+2)}s+=2+t}return{hasAppMarkers:s>2,fileDataOffset:n||r,jfifDataOffset:i,tiffHeaderOffset:o,iptcDataOffset:a,xmpChunks:u,iccChunks:c,mpfDataOffset:f}}(e);if(function(e){return!!e&&r(e,0,8)===O}(e))return function(e){for(var t={hasAppMarkers:0},n=8;n+4+4<=e.byteLength;){if(k(e,n))t.hasAppMarkers=1,t.pngHeaderOffset=n+8;else if(E(e,n)){var i=j(e,n);void 0!==i&&(t.hasAppMarkers=1,t.xmpChunks=[{dataOffset:i,length:e.getUint32(n+0)-(i-(n+8))}])}else if(N(e,n)){t.hasAppMarkers=1;var o=r(e,n+4,4);t.pngTextChunks||(t.pngTextChunks=[]),t.pngTextChunks.push({length:e.getUint32(n+0),type:o,offset:n+8})}else G(e,n)?(t.hasAppMarkers=1,t.tiffHeaderOffset=n+8):B(e,n)&&(t.hasAppMarkers=1,t.pngChunkOffsets||(t.pngChunkOffsets=[]),t.pngChunkOffsets.push(n+0));n+=e.getUint32(n+0)+4+4+4}return t}(e);if(function(e){if(!e)return 0;var t=r(e,8,4);return"ftyp"===r(e,4,4)&&-1!==["heic","heix","hevc","hevx","heim","heis","hevm","hevs","mif1"].indexOf(t)}(e))return function(e){var t=function(e){for(var t=0;t+4+4<=e.byteLength;){var n=z(e,t);if(n>=8&&"meta"===r(e,t+4,4))return{offset:t,length:n};t+=n}return{offset:void 0,length:0}}(e),n=t.offset,i=t.length;if(void 0===n)return{hasAppMarkers:0};var o=Math.min(n+i,e.byteLength),a=function(e,t,n){for(var i={ilocOffset:void 0,exifItemOffset:void 0,colrOffset:void 0};t+4<=n&&(!i.ilocOffset||!i.exifItemOffset||!i.colrOffset);){var o=r(e,t,4);"iloc"===o?i.ilocOffset=t:"Exif"===o?i.exifItemOffset=t+-4:"colr"===o&&(i.colrOffset=t+-4),t++}return i}(e,n,o),u=a.exifItemOffset,c=a.ilocOffset,f=a.colrOffset,s=function(e,t,n,r){if(n&&t&&!(t+2>r)){var i=e.getUint16(t);for(n+=12;n+16<=r;){if(e.getUint16(n)===i){var o=e.getUint32(n+8);if(o+4<=e.byteLength)return o+(e.getUint32(o)+4)}n+=16}}}(e,u,c,o),l=function(e,t,n){if(t&&!(t+12>n)){var i=r(e,t+8,4);if("prof"===i||"rICC"===i)return[{offset:t+12,length:z(e,t)-12,chunkNumber:1,chunksTotal:1}]}}(e,f,o);return{hasAppMarkers:void 0!==s||void 0!==l,tiffHeaderOffset:s,iccChunks:l}}(e);if(function(e){return!!e&&"RIFF"===r(e,0,4)&&"WEBP"===r(e,8,4)}(e))return function(e){for(var t,n,i,o=12,a=0;o+8=e[1]?"".concat(Math.round(e[0]/e[1])):0!==e[0]?"1/".concat(Math.round(e[1]/e[0])):"0/".concat(e[1])},FNumber:function(e){return"f/".concat(e[0]/e[1])},FocalLength:function(e){return e[0]/e[1]+" mm"},FocalPlaneResolutionUnit:function(e){return 2===e?"inches":3===e?"centimeters":"Unknown"},LightSource:function(e){return 1===e?"Daylight":2===e?"Fluorescent":3===e?"Tungsten (incandescent light)":4===e?"Flash":9===e?"Fine weather":10===e?"Cloudy weather":11===e?"Shade":12===e?"Daylight fluorescent (D 5700 – 7100K)":13===e?"Day white fluorescent (N 4600 – 5400K)":14===e?"Cool white fluorescent (W 3900 – 4500K)":15===e?"White fluorescent (WW 3200 – 3700K)":17===e?"Standard light A":18===e?"Standard light B":19===e?"Standard light C":20===e?"D55":21===e?"D65":22===e?"D75":23===e?"D50":24===e?"ISO studio tungsten":255===e?"Other light source":"Unknown"},MeteringMode:function(e){return 1===e?"Average":2===e?"CenterWeightedAverage":3===e?"Spot":4===e?"MultiSpot":5===e?"Pattern":6===e?"Partial":255===e?"Other":"Unknown"},ResolutionUnit:function(e){return 2===e?"inches":3===e?"centimeters":"Unknown"},Saturation:function(e){return 0===e?"Normal":1===e?"Low saturation":2===e?"High saturation":"Unknown"},SceneCaptureType:function(e){return 0===e?"Standard":1===e?"Landscape":2===e?"Portrait":3===e?"Night scene":"Unknown"},Sharpness:function(e){return 0===e?"Normal":1===e?"Soft":2===e?"Hard":"Unknown"},ShutterSpeedValue:function(e){var t=Math.pow(2,e[0]/e[1]);return t<=1?"".concat(Math.round(1/t)):"1/".concat(Math.round(t))},WhiteBalance:function(e){return 0===e?"Auto white balance":1===e?"Manual white balance":"Unknown"},XResolution:function(e){return""+Math.round(e[0]/e[1])},YResolution:function(e){return""+Math.round(e[0]/e[1])}};function J(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n>31&1,e>>30&1,e>>29&1],n=[];return t[0]&&n.push("Dependent Parent Image"),t[1]&&n.push("Dependent Child Image"),t[2]&&n.push("Representative Image"),{value:t,description:n.join(", ")||"None"}}function fe(e){var t=e>>24&7;return{value:t,description:0===t?"JPEG":"Unknown"}}function se(e){var t=16777215&e;return{value:t,description:{196608:"Baseline MP Primary Image",65537:"Large Thumbnail (VGA equivalent)",65538:"Large Thumbnail (Full HD equivalent)",131073:"Multi-Frame Image (Panorama)",131074:"Multi-Frame Image (Disparity)",131075:"Multi-Frame Image (Multi-Angle)",0:"Undefined"}[t]||"Unknown"}}function le(e){return 0===e}function de(e,t,n,r,i,o){var a=X.getTypeSize("SHORT"),u={},c=function(e,t,n){return t+X.getTypeSize("SHORT")<=e.byteLength?X.getShortAt(e,t,n):0}(e,r,i);r+=a;for(var f=0;fe.byteLength);f++){var s=pe(e,t,n,r,i,o);void 0!==s&&(u[s.name]={id:s.id,value:s.value,description:s.description}),r+=12}if(r"}l===X.tagTypes.ASCII&&(a=function(e){try{return e.map((function(e){return decodeURIComponent(escape(e))}))}catch(t){return e}}(a=function(e){for(var t=[],n=0,r=0;r5&&void 0!==arguments[5]?arguments[5]:0,a=[];o&&(r*=X.typeSizes[n],n=X.tagTypes.BYTE);for(var u=0;un)){var r=X.getByteAt(e,t+7);return{value:r,description:""+r}}}(e,t,n);return{"Bits Per Sample":he(e,t,n),"Image Height":ye(e,t,n),"Image Width":Se(e,t,n),"Color Components":r,Subsampling:r&&be(e,t,r.value,n)}};function he(e,t,n){if(!(3>n)){var r=X.getByteAt(e,t+2);return{value:r,description:""+r}}}function ye(e,t,n){if(!(5>n)){var r=X.getShortAt(e,t+3);return{value:r,description:"".concat(r,"px")}}}function Se(e,t,n){if(!(7>n)){var r=X.getShortAt(e,t+5);return{value:r,description:"".concat(r,"px")}}}function be(e,t,n,r){if(!(8+3*n>r)){for(var i=[],o=0;o1?Ce(i)+Ae(i):""}}}function Ce(e){var t={1:"Y",2:"Cb",3:"Cr",4:"I",5:"Q"};return e.map((function(e){return t[e[0]]})).join("")}function Ae(e){var t={17:"4:4:4 (1 1)",18:"4:4:0 (1 2)",20:"4:4:1 (1 4)",33:"4:2:2 (2 1)",34:"4:2:0 (2 2)",36:"4:2:1 (2 4)",65:"4:1:1 (4 1)",66:"4:1:0 (4 2)"};return 0===e.length||void 0===e[0][1]||void 0===t[e[0][1]]?"":t[e[0][1]]}var Ie=function(e,t){var n=function(e,t){return X.getShortAt(e,t)}(e,t),r=function(e,t,n){if(!(15>n)){var r=X.getByteAt(e,t+14);return{value:r,description:"".concat(r,"px")}}}(e,t,n),i=function(e,t,n){if(!(16>n)){var r=X.getByteAt(e,t+15);return{value:r,description:"".concat(r,"px")}}}(e,t,n),o={"JFIF Version":Pe(e,t,n),"Resolution Unit":Ue(e,t,n),XResolution:Te(e,t,n),YResolution:De(e,t,n),"JFIF Thumbnail Width":r,"JFIF Thumbnail Height":i};if(void 0!==r&&void 0!==i){var a=function(e,t,n,r){if(!(0===n||16+n>r))return{value:e.buffer.slice(t+16,t+16+n),description:"<24-bit RGB pixel data>"}}(e,t,3*r.value*i.value,n);a&&(o["JFIF Thumbnail"]=a)}for(var u in o)void 0===o[u]&&delete o[u];return o};function Pe(e,t,n){if(!(9>n)){var r=X.getByteAt(e,t+7),i=X.getByteAt(e,t+7+1);return{value:256*r+i,description:r+"."+i}}}function Ue(e,t,n){if(!(10>n)){var r=X.getByteAt(e,t+9);return{value:r,description:we(r)}}}function we(e){return 0===e?"None":1===e?"inches":2===e?"cm":"Unknown"}function Te(e,t,n){if(!(12>n)){var r=X.getShortAt(e,t+10);return{value:r,description:""+r}}}function De(e,t,n){if(!(14>n)){var r=X.getShortAt(e,t+12);return{value:r,description:""+r}}}var xe={iptc:{256:{name:"Model Version",description:function(e){return""+((e[0]<<8)+e[1])}},261:{name:"Destination",repeatable:1},276:{name:"File Format",description:function(e){return""+((e[0]<<8)+e[1])}},278:{name:"File Format Version",description:function(e){return""+((e[0]<<8)+e[1])}},286:"Service Identifier",296:"Envelope Number",306:"Product ID",316:"Envelope Priority",326:{name:"Date Sent",description:Me},336:{name:"Time Sent",description:Oe},346:{name:"Coded Character Set",description:Fe,encoding_name:Fe},356:"UNO",376:{name:"ARM Identifier",description:function(e){return""+((e[0]<<8)+e[1])}},378:{name:"ARM Version",description:function(e){return""+((e[0]<<8)+e[1])}},512:{name:"Record Version",description:function(e){return""+((e[0]<<8)+e[1])}},515:"Object Type Reference",516:"Object Attribute Reference",517:"Object Name",519:"Edit Status",520:{name:"Editorial Update",description:function(e){return"01"===l(e)?"Additional Language":"Unknown"}},522:"Urgency",524:{name:"Subject Reference",repeatable:1,description:function(e){var t=l(e).split(":");return t[2]+(t[3]?"/"+t[3]:"")+(t[4]?"/"+t[4]:"")}},527:"Category",532:{name:"Supplemental Category",repeatable:1},534:"Fixture Identifier",537:{name:"Keywords",repeatable:1},538:{name:"Content Location Code",repeatable:1},539:{name:"Content Location Name",repeatable:1},542:"Release Date",547:"Release Time",549:"Expiration Date",550:"Expiration Time",552:"Special Instructions",554:{name:"Action Advised",description:function(e){var t=l(e);return"01"===t?"Object Kill":"02"===t?"Object Replace":"03"===t?"Object Append":"04"===t?"Object Reference":"Unknown"}},557:{name:"Reference Service",repeatable:1},559:{name:"Reference Date",repeatable:1},562:{name:"Reference Number",repeatable:1},567:{name:"Date Created",description:Me},572:{name:"Time Created",description:Oe},574:{name:"Digital Creation Date",description:Me},575:{name:"Digital Creation Time",description:Oe},577:"Originating Program",582:"Program Version",587:{name:"Object Cycle",description:function(e){var t=l(e);return"a"===t?"morning":"p"===t?"evening":"b"===t?"both":"Unknown"}},592:{name:"By-line",repeatable:1},597:{name:"By-line Title",repeatable:1},602:"City",604:"Sub-location",607:"Province/State",612:"Country/Primary Location Code",613:"Country/Primary Location Name",615:"Original Transmission Reference",617:"Headline",622:"Credit",627:"Source",628:"Copyright Notice",630:{name:"Contact",repeatable:1},632:"Caption/Abstract",634:{name:"Writer/Editor",repeatable:1},637:{name:"Rasterized Caption",description:function(e){return e}},642:"Image Type",643:{name:"Image Orientation",description:function(e){var t=l(e);return"P"===t?"Portrait":"L"===t?"Landscape":"S"===t?"Square":"Unknown"}},647:"Language Identifier",662:{name:"Audio Type",description:function(e){var t=l(e),n=t.charAt(0),r=t.charAt(1),i="";return"1"===n?i+="Mono":"2"===n&&(i+="Stereo"),"A"===r?i+=", actuality":"C"===r?i+=", question and answer session":"M"===r?i+=", music, transmitted by itself":"Q"===r?i+=", response to a question":"R"===r?i+=", raw sound":"S"===r?i+=", scener":"V"===r?i+=", voicer":"W"===r&&(i+=", wrap"),""!==i?i:t}},663:{name:"Audio Sampling Rate",description:function(e){return parseInt(l(e),10)+" Hz"}},664:{name:"Audio Sampling Resolution",description:function(e){var t=parseInt(l(e),10);return t+(1===t?" bit":" bits")}},665:{name:"Audio Duration",description:function(e){var t=l(e);return t.length>=6?t.substr(0,2)+":"+t.substr(2,2)+":"+t.substr(4,2):t}},666:"Audio Outcue",698:"Short Document ID",699:"Unique Document ID",700:"Owner ID",712:{name:function(e){return 2===e.length?"ObjectData Preview File Format":"Record 2 destination"},description:function(e){if(2===e.length){var t=(e[0]<<8)+e[1];return 0===t?"No ObjectData":1===t?"IPTC-NAA Digital Newsphoto Parameter Record":2===t?"IPTC7901 Recommended Message Format":3===t?"Tagged Image File Format (Adobe/Aldus Image data)":4===t?"Illustrator (Adobe Graphics data)":5===t?"AppleSingle (Apple Computer Inc)":6===t?"NAA 89-3 (ANPA 1312)":7===t?"MacBinary II":8===t?"IPTC Unstructured Character Oriented File Format (UCOFF)":9===t?"United Press International ANPA 1312 variant":10===t?"United Press International Down-Load Message":11===t?"JPEG File Interchange (JFIF)":12===t?"Photo-CD Image-Pac (Eastman Kodak)":13===t?"Microsoft Bit Mapped Graphics File [*.BMP]":14===t?"Digital Audio File [*.WAV] (Microsoft & Creative Labs)":15===t?"Audio plus Moving Video [*.AVI] (Microsoft)":16===t?"PC DOS/Windows Executable Files [*.COM][*.EXE]":17===t?"Compressed Binary File [*.ZIP] (PKWare Inc)":18===t?"Audio Interchange File Format AIFF (Apple Computer Inc)":19===t?"RIFF Wave (Microsoft Corporation)":20===t?"Freehand (Macromedia/Aldus)":21===t?'Hypertext Markup Language "HTML" (The Internet Society)':22===t?"MPEG 2 Audio Layer 2 (Musicom), ISO/IEC":23===t?"MPEG 2 Audio Layer 3, ISO/IEC":24===t?"Portable Document File (*.PDF) Adobe":25===t?"News Industry Text Format (NITF)":26===t?"Tape Archive (*.TAR)":27===t?"Tidningarnas Telegrambyrå NITF version (TTNITF DTD)":28===t?"Ritzaus Bureau NITF version (RBNITF DTD)":29===t?"Corel Draw [*.CDR]":"Unknown format ".concat(t)}return l(e)}},713:{name:"ObjectData Preview File Format Version",description:function(e,t){var n={"00":{"00":"1"},"01":{"01":"1","02":"2","03":"3","04":"4"},"02":{"04":"4"},"03":{"01":"5.0","02":"6.0"},"04":{"01":"1.40"},"05":{"01":"2"},"06":{"01":"1"},11:{"01":"1.02"},20:{"01":"3.1","02":"4.0","03":"5.0","04":"5.5"},21:{"02":"2.0"}},r=l(e);if(t["ObjectData Preview File Format"]){var i=l(t["ObjectData Preview File Format"].value);if(n[i]&&n[i][r])return n[i][r]}return r}},714:"ObjectData Preview Data",1802:{name:"Size Mode",description:function(e){return e[0].toString()}},1812:{name:"Max Subfile Size",description:function(e){for(var t=0,n=0;n=8?t.substr(0,4)+"-"+t.substr(4,2)+"-"+t.substr(6,2):t}function Oe(e){var t=l(e),n=t;return t.length>=6&&(n=t.substr(0,2)+":"+t.substr(2,2)+":"+t.substr(4,2),11===t.length&&(n+=t.substr(6,1)+t.substr(7,2)+":"+t.substr(9,2))),n}function Fe(e){var t=l(e);return"%G"===t?"UTF-8":"%5"===t?"Windows-1252":"%/G"===t?"UTF-8 Level 1":"%/H"===t?"UTF-8 Level 2":"%/I"===t?"UTF-8 Level 3":"/A"===t?"ISO-8859-1":"/B"===t?"ISO-8859-2":"/C"===t?"ISO-8859-3":"/D"===t?"ISO-8859-4":"/@"===t?"ISO-8859-5":"/G"===t?"ISO-8859-6":"/F"===t?"ISO-8859-7":"/H"===t?"ISO-8859-8":"Unknown"}var Re=function(e,t){var n=function(){if("undefined"!=typeof TextDecoder)return TextDecoder}();if("undefined"!=typeof n&&void 0!==e)try{return new n(e).decode(Uint8Array.from(t))}catch(e){}return function(e){try{return decodeURIComponent(escape(e))}catch(t){return e}}(t.map((function(e){return String.fromCharCode(e)})).join(""))},Le=function(e,t,n){try{if(Array.isArray(e))return Ge(new DataView(Uint8Array.from(e).buffer),{size:e.length},0,n);var r=function(e,t){for(;t+12<=e.byteLength;){var n=ke(e,t);if(Ee(n))return{naaBlock:n,dataOffset:t+12};t+=12+n.size+Ne(n)}throw Error("No IPTC NAA resource block.")}(e,t);return Ge(e,r.naaBlock,r.dataOffset,n)}catch(e){return{}}};function ke(e,t){if(943868237!==e.getUint32(t,0))throw Error("Not an IPTC resource block.");return{type:e.getUint16(t+4),size:e.getUint16(t+10)}}function Ee(e){return 1028===e.type}function Ne(e){return e.size%2!=0?1:0}function Ge(e,t,n,r){for(var i={},o=void 0,a=n+t.size;ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n1&&n.push(Je(e,t.slice(1))),n}(e,t),2,function(e){if(Array.isArray(e))return e}(r)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,i,o=[],a=1,u=0;try{for(n=n.call(e);!(a=(r=n.next()).done)&&(o.push(r.value),2!==o.length);a=1);}catch(e){u=1,i=e}finally{try{a||null==n.return||n.return()}finally{if(u)throw i}}return o}}(r)||function(e,t){if(e){if("string"==typeof e)return qe(e,2);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?qe(e,2):void 0}}(r)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),o=i[0],a=i[1],u=$e(n,o);if(a){var c=$e(n,a);u||c||(delete n._raw,$e(n,Je(e,t)))}return n};function Je(e,t){for(var n=t.reduce((function(e,t){return e+t.length}),0),r=new Uint8Array(n),i=0,o=0;o).+$/,"$1"),"application/xml");if("parsererror"===i.documentElement.nodeName)throw Error(i.documentElement.textContent);return{doc:i,raw:n}}(t),i=n.doc,o=n.raw;return e._raw=(e._raw||"")+o,a(e,ot(Ze(Qe(i),1))),1}catch(e){return 0}}function Qe(e){for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:0,n=et(e);return tt(n)?t?{}:nt(n[0]):rt(n)}function et(e){for(var t=[],n=0;n1&&void 0!==arguments[1]?arguments[1]:void 0;if(Array.isArray(e)){var n=lt(e);return t&&"function"==typeof We[t]?We[t](e,n):n}if("object"===_e(e))return dt(e);try{return t&&"function"==typeof We[t]?We[t](e):decodeURIComponent(escape(e))}catch(t){return e}}function lt(e){return e.map((function(e){return void 0!==e.value?st(e.value):st(e)})).join(", ")}function dt(e){var t=[];for(var n in e)t.push("".concat(pt(n),": ").concat(st(e[n].value)));return t.join("; ")}function pt(e){return"CiAdrCity"===e?"CreatorCity":"CiAdrCtry"===e?"CreatorCountry":"CiAdrExtadr"===e?"CreatorAddress":"CiAdrPcode"===e?"CreatorPostalCode":"CiAdrRegion"===e?"CreatorRegion":"CiEmailWork"===e?"CreatorWorkEmail":"CiTelWork"===e?"CreatorWorkPhone":"CiUrlWork"===e?"CreatorWorkUrl":e}function mt(e){var t={};for(var n in e)ct(n)||(t[ft(n)]=gt(e[n],n));return t}function gt(e,t){return vt(e)?ht(e,t):St(e)?bt(e,t):Ct(e)?At(e,t):function(e){return void 0!==It(e.value)}(e)?function(e,t){var n=It(e.value).value["rdf:li"],r=yt(e),i=[];return void 0===n?n=[]:Array.isArray(n)||(n=[n]),n.forEach((function(e){i.push(function(e){return vt(e)?ht(e):St(e)?bt(e).value:Ct(e)?At(e).value:Pt(e)}(e))})),{value:i,attributes:r,description:st(i,t)}}(e,t):Pt(e,t)}function vt(e){return"Resource"===e.attributes["rdf:parseType"]&&void 0!==e.value["rdf:value"]||void 0!==e.value["rdf:Description"]&&void 0!==e.value["rdf:Description"].value["rdf:value"]}function ht(e,t){var n=yt(e);void 0!==e.value["rdf:Description"]&&(e=e.value["rdf:Description"]),a(n,yt(e),function(e){var t={};for(var n in e.value)"rdf:value"===n||ct(n)||(t[ft(n)]=e.value[n].value);return t}(e));var r=function(e){return Ut(e.value["rdf:value"])||e.value["rdf:value"].value}(e);return{value:r,attributes:n,description:st(r,t)}}function yt(e){var t={};for(var n in e.attributes)"rdf:parseType"===n||"rdf:resource"===n||ct(n)||(t[ft(n)]=e.attributes[n]);return t}function St(e){return"Resource"===e.attributes["rdf:parseType"]||void 0!==e.value["rdf:Description"]&&void 0===e.value["rdf:Description"].value["rdf:value"]}function bt(e,t){var n={value:{},attributes:{}};return void 0!==e.value["rdf:Description"]&&(a(n.value,at(e.value["rdf:Description"].attributes)),a(n.attributes,yt(e)),e=e.value["rdf:Description"]),a(n.value,mt(e.value)),n.description=st(n.value,t),n}function Ct(e){return 0===Object.keys(e.value).length&&void 0===e.attributes["xml:lang"]&&void 0===e.attributes["rdf:resource"]}function At(e,t){var n=at(e.attributes);return{value:n,attributes:{},description:st(n,t)}}function It(e){return e["rdf:Bag"]||e["rdf:Seq"]||e["rdf:Alt"]}function Pt(e,t){var n=Ut(e)||ot(e.value);return{value:n,attributes:yt(e),description:st(n,t)}}function Ut(e){return e.attributes&&e.attributes["rdf:resource"]}var wt={desc:{name:"ICC Description"},cprt:{name:"ICC Copyright"},dmdd:{name:"ICC Device Model Description"},vued:{name:"ICC Viewing Conditions Description"},dmnd:{name:"ICC Device Manufacturer for Display"},tech:{name:"Technology"}},Tt={4:{name:"Preferred CMM type",value:function(e,t){return r(e,t,4)},description:function(e){return null!==e?Dt(e):""}},8:{name:"Profile Version",value:function(e,t){return e.getUint8(t).toString(10)+"."+(e.getUint8(t+1)>>4).toString(10)+"."+(e.getUint8(t+1)%16).toString(10)}},12:{name:"Profile/Device class",value:function(e,t){return r(e,t,4)},description:function(e){switch(e.toLowerCase()){case"scnr":return"Input Device profile";case"mntr":return"Display Device profile";case"prtr":return"Output Device profile";case"link":return"DeviceLink profile";case"abst":return"Abstract profile";case"spac":return"ColorSpace profile";case"nmcl":return"NamedColor profile";case"cenc":return"ColorEncodingSpace profile";case"mid ":return"MultiplexIdentification profile";case"mlnk":return"MultiplexLink profile";case"mvis":return"MultiplexVisualization profile";default:return e}}},16:{name:"Color Space",value:function(e,t){return r(e,t,4)}},20:{name:"Connection Space",value:function(e,t){return r(e,t,4)}},24:{name:"ICC Profile Date",value:function(e,t){return function(e,t){var n=e.getUint16(t),r=e.getUint16(t+2)-1,i=e.getUint16(t+4),o=e.getUint16(t+6),a=e.getUint16(t+8),u=e.getUint16(t+10);return new Date(Date.UTC(n,r,i,o,a,u))}(e,t).toISOString()}},36:{name:"ICC Signature",value:function(e,t){return n=e.buffer.slice(t,t+4),String.fromCharCode.apply(null,new Uint8Array(n));var n}},40:{name:"Primary Platform",value:function(e,t){return r(e,t,4)},description:function(e){return Dt(e)}},48:{name:"Device Manufacturer",value:function(e,t){return r(e,t,4)},description:function(e){return Dt(e)}},52:{name:"Device Model Number",value:function(e,t){return r(e,t,4)}},64:{name:"Rendering Intent",value:function(e,t){return e.getUint32(t)},description:function(e){switch(e){case 0:return"Perceptual";case 1:return"Relative Colorimetric";case 2:return"Saturation";case 3:return"Absolute Colorimetric";default:return e}}},80:{name:"Profile Creator",value:function(e,t){return r(e,t,4)}}};function Dt(e){switch(e.toLowerCase()){case"appl":return"Apple";case"adbe":return"Adobe";case"msft":return"Microsoft";case"sunw":return"Sun Microsystems";case"sgi":return"Silicon Graphics";case"tgnt":return"Taligent";default:return e}}var xt=function(e,t){try{for(var n=t.reduce((function(e,t){return e+t.length}),0),o=new Uint8Array(n),a=0,u=function(e){return Array.isArray(e)?new DataView(Uint8Array.from(e).buffer).buffer:e.buffer}(e),c=function(e){var n=t.find((function(t){return t.chunkNumber===e}));if(!n)throw Error("ICC chunk ".concat(e," not found"));var r=u.slice(n.offset,n.offset+n.length),i=new Uint8Array(r);o.set(i,a),a+=i.length},f=1;f<=t.length;f++)c(f);return function(e){var t=e.buffer,n=e.getUint32();if(e.byteLength!==n)throw Error("ICC profile length not matching");if(e.length<84)throw Error("ICC profile too short");for(var o={},a=Object.keys(Tt),u=0;ut.length)return o;var y=r(e,v,4);if(y===Ot){var S=e.getUint32(v+8);if(S>h)return o;Nt(o,g,Et(t.slice(v+12,v+S+11)))}else if(y===Ft){for(var b=e.getUint32(v+8),C=e.getUint32(v+12),A=v+16,I=[],P=0;Pe.byteLength)){var n=X.getLongAt(e,t);return{value:n,description:"".concat(n,"px")}}}function jt(e,t){if(!(t+4+4>e.byteLength)){var n=X.getLongAt(e,t+4);return{value:n,description:"".concat(n,"px")}}}function zt(e,t){if(!(t+8+1>e.byteLength)){var n=X.getByteAt(e,t+8);return{value:n,description:"".concat(n)}}}function Vt(e,t){if(!(t+9+1>e.byteLength)){var n=X.getByteAt(e,t+9);return{value:n,description:{0:"Grayscale",2:"RGB",3:"Palette",4:"Grayscale with Alpha",6:"RGB with Alpha"}[n]||"Unknown"}}}function Wt(e,t){if(!(t+10+1>e.byteLength)){var n=X.getByteAt(e,t+10);return{value:n,description:0===n?"Deflate/Inflate":"Unknown"}}}function Ht(e,t){if(!(t+11+1>e.byteLength)){var n=X.getByteAt(e,t+11);return{value:n,description:0===n?"Adaptive":"Unknown"}}}function Xt(e,t){if(!(t+12+1>e.byteLength)){var n=X.getByteAt(e,t+12);return{value:n,description:{0:"Noninterlaced",1:"Adam7 Interlace"}[n]||"Unknown"}}}var Yt=function(e,t){return t.reduce((function(t,n){var r=n.offset,i=n.length,a=n.type,u=function(e,t,n,r){for(var i=[],a=[],u=[],c=[],f=_t,s=0;s1&&void 0!==arguments[1]?arguments[1]:{}).length,n={method:"GET"};return Number.isInteger(t)&&t>=0&&(n.headers={range:"bytes=0-".concat(t-1)}),fetch(e,n).then((function(e){return e.arrayBuffer()}))}(e,t):function(e){var t=(arguments.length>1&&void 0!==arguments[1]?arguments[1]:{}).length;return new Promise((function(n,r){var i={};Number.isInteger(t)&&t>=0&&(i.headers={range:"bytes=0-".concat(t-1)}),mn(e)(e,i,(function(e){if(e.statusCode>=200&&e.statusCode<=299){var t=[];e.on("data",(function(e){return t.push(Buffer.from(e))})),e.on("error",(function(e){return r(e)})),e.on("end",(function(){return n(Buffer.concat(t))}))}else r("Could not fetch file: ".concat(e.statusCode," ").concat(e.statusMessage)),e.resume()})).on("error",(function(e){return r(e)}))}))}(e,t):function(e){return/^data:[^;,]*(;base64)?,/.test(e)}(e)?Promise.resolve(function(e){var t=e.substring(e.indexOf(",")+1);if(-1!==e.indexOf(";base64")){if("undefined"!=typeof atob)return Uint8Array.from(atob(t),(function(e){return e.charCodeAt(0)})).buffer;if("undefined"==typeof Buffer)return;return void 0!==n(Buffer.from)?Buffer.from(t,"base64"):new Buffer(t,"base64")}var r=decodeURIComponent(t);return"undefined"!=typeof Buffer?void 0!==n(Buffer.from)?Buffer.from(r):new Buffer(r):Uint8Array.from(r,(function(e){return e.charCodeAt(0)})).buffer}(e)):function(e){var t=(arguments.length>1&&void 0!==arguments[1]?arguments[1]:{}).length;return new Promise((function(n,r){var i=gn();i.open(e,(function(o,a){o?r(o):i.stat(e,(function(o,u){if(o)r(o);else{var c=Math.min(u.size,void 0!==t?t:u.size),f=Buffer.alloc(c),s={buffer:f,length:c};i.read(a,s,(function(t){t?r(t):i.close(a,(function(t){t&&console.warn("Could not close file ".concat(e,":"),t),n(f)}))}))}}))}))}))}(e,t)}(e,t).then((function(e){return vn(e,t)})):function(e){return"undefined"!=typeof window&&"undefined"!=typeof File&&e instanceof File}(e)?(r=e,new Promise((function(e,t){var n=new FileReader;n.onload=function(t){return e(t.target.result)},n.onerror=function(){return t(n.error)},n.readAsArrayBuffer(r)}))).then((function(e){return vn(e,t)})):vn(e,t);var r}function mn(e){return/^https:\/\//.test(e)?require("https").get:require("http").get}function gn(){try{return require("fs")}catch(e){return}}function vn(e,t){return function(e){try{return Buffer.isBuffer(e)}catch(e){return 0}}(e)&&(e=new Uint8Array(e).buffer),hn(function(e){try{return new DataView(e)}catch(t){return new s(e)}}(e),t)}function hn(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{expanded:0,includeUnknown:0},n=t.expanded,r=void 0===n?0:n,i=t.includeUnknown,u=void 0===i?0:i,c=0,f={},s=V(e),l=s.fileDataOffset,d=s.jfifDataOffset,p=s.tiffHeaderOffset,m=s.iptcDataOffset,g=s.xmpChunks,v=s.iccChunks,h=s.mpfDataOffset,y=s.pngHeaderOffset,S=s.pngTextChunks,b=s.pngChunkOffsets;if(yn(l)){c=1;var C=ve(e,l);r?f.file=C:f=a({},f,C)}if(Sn(d)){c=1;var A=Ie(e,d);r?f.jfif=A:f=a({},f,A)}if(bn(p)){c=1;var I=ie(e,p,u);if(I.Thumbnail&&(f.Thumbnail=I.Thumbnail,delete I.Thumbnail),r?(f.exif=I,Cn(f)):f=a({},f,I),I["IPTC-NAA"]&&!An(m)){var P=Le(I["IPTC-NAA"].value,0,u);r?f.iptc=P:f=a({},f,P)}if(I.ApplicationNotes&&!In(g)){var U=Ke(o(I.ApplicationNotes.value));r?f.xmp=U:(delete U._raw,f=a({},f,U))}if(I.ICC_Profile&&!Pn(v)){var w=xt(I.ICC_Profile.value,[{offset:0,length:I.ICC_Profile.value.length,chunkNumber:1,chunksTotal:1}]);r?f.icc=w:f=a({},f,w)}}if(An(m)){c=1;var T=Le(e,m,u);r?f.iptc=T:f=a({},f,T)}if(In(g)){c=1;var D=Ke(e,g);r?f.xmp=D:(delete D._raw,f=a({},f,D))}if(Pn(v)){c=1;var x=xt(e,v);r?f.icc=x:f=a({},f,x)}if(Un(h)){c=1;var M=oe(e,h,u);r?f.mpf=M:f=a({},f,M)}if(wn(y)){c=1;var O=Gt(e,y);r?(f.png=f.png?a({},f.png,O):O,f.pngFile=O):f=a({},f,O)}if(Tn(S)){c=1;var F=Yt(e,S);r?(f.png=f.png?a({},f.png,F):F,f.pngText=F):f=a({},f,F)}if(Dn(b)){c=1;var R=Zt(e,b);r?f.png=f.png?a({},f.png,R):R:f=a({},f,R)}var L=cn(e,f.Thumbnail,p);if(L?(c=1,f.Thumbnail=L):delete f.Thumbnail,!c)throw new sn.MetadataMissingError;return f}function yn(e){return void 0!==e}function Sn(e){return void 0!==e}function bn(e){return void 0!==e}function Cn(e){if(e.exif){if(e.exif.GPSLatitude&&e.exif.GPSLatitudeRef)try{e.gps=e.gps||{},e.gps.Latitude=p(e.exif.GPSLatitude.value),"S"===e.exif.GPSLatitudeRef.value.join("")&&(e.gps.Latitude=-e.gps.Latitude)}catch(e){}if(e.exif.GPSLongitude&&e.exif.GPSLongitudeRef)try{e.gps=e.gps||{},e.gps.Longitude=p(e.exif.GPSLongitude.value),"W"===e.exif.GPSLongitudeRef.value.join("")&&(e.gps.Longitude=-e.gps.Longitude)}catch(e){}if(e.exif.GPSAltitude&&e.exif.GPSAltitudeRef)try{e.gps=e.gps||{},e.gps.Altitude=e.exif.GPSAltitude.value[0]/e.exif.GPSAltitude.value[1],1===e.exif.GPSAltitudeRef.value&&(e.gps.Altitude=-e.gps.Altitude)}catch(e){}}}function An(e){return void 0!==e}function In(e){return Array.isArray(e)&&e.length>0}function Pn(e){return Array.isArray(e)&&e.length>0}function Un(e){return void 0!==e}function wn(e){return void 0!==e}function Tn(e){return void 0!==e}function Dn(e){return void 0!==e}return t}()})); +//# sourceMappingURL=exif-reader.js.map \ No newline at end of file diff --git a/ui/plugins/ui/image-editor-improvements.plugin.js b/ui/plugins/ui/image-editor-improvements.plugin.js index 672ed77b..fffa556b 100644 --- a/ui/plugins/ui/image-editor-improvements.plugin.js +++ b/ui/plugins/ui/image-editor-improvements.plugin.js @@ -14,32 +14,6 @@ (function() { "use strict" - var styleSheet = document.createElement("style"); - styleSheet.textContent = ` - .editor-canvas-overlay { - cursor: none; - } - - .image-brush-preview { - position: fixed; - background: black; - opacity: 0.3; - borderRadius: 50%; - cursor: none; - pointer-events: none; - transform: translate(-50%, -50%); - } - - .editor-options-container > * > *:not(.active):not(.button) { - border: 1px dotted slategray; - } - - .image_editor_opacity .editor-options-container > * > *:not(.active):not(.button) { - border: 1px dotted slategray; - } - `; - document.head.appendChild(styleSheet); - let imageBrushPreview let imageCanvas let canvasType @@ -169,25 +143,8 @@ /* ADD SUPPORT FOR DRAG-AND-DROPPING SOURCE IMAGE (from file or straight from UI) */ - document.querySelector('#editor-inputs-init-image label').insertAdjacentHTML('beforeEnd', ` Add img2img source image using the Browse button, via drag & drop from external file or browser image (incl. rendered image) or by pasting an image from the clipboard using Ctrl+V.

You may also reload the metadata embedded in a PNG or JPEG image (enable embedding from the Settings).
`) /* DROP AREAS */ - var styleSheet = document.createElement("style"); - styleSheet.textContent = ` - .drop-area { - width: 45%; - height: 50px; - border: 2px dashed #ccc; - text-align: center; - line-height: 50px; - font-size: small; - color: #ccc; - border-radius: 10px; - display: none; - margin: 12px 10px; - } - `; - document.head.appendChild(styleSheet); function createDropAreas(container) { // Create two drop areas @@ -304,18 +261,13 @@ } else if (event?.dataTransfer?.files) { // Use DataTransfer interface items = Array.from(event.dataTransfer.files) } - if (items[0].type === "image/png" || items[0].type === "image/jpeg") { - // check if image has embedded metadata, load task if it does - if (items[0].type === "image/png") { - readPNGMetadata(items[0]) - } else if (items[0].type === "image/jpeg") { - readJPEGMetadata(items[0]); - } else { - console.log("File must be a PNG or JPEG image."); - } - //dropAreaMD.innerHTML = "Image added to drop area MD" + // check if image has embedded metadata, load task if it does + if (items[0].type === "image/png") { + readPNGMetadata(items[0]) + } else if (items[0].type === "image/jpeg" || items[0].type === "image/webp") { + readJPEGMetadata(items[0]); } else { - //dropAreaMD.innerHTML = "Wrong file type. Please select a PNG or JPEG image." + console.log("File must be a PNG, WEBP or JPEG image."); } event.preventDefault() }) @@ -400,7 +352,6 @@ } /* PNG METADATA EXTRACTION */ - document.querySelector('#editor-inputs-prompt b').insertAdjacentHTML('afterEnd', ` You can type your prompts in the below textbox or load them from a file. You can also reload tasks from metadata embedded in PNG and JPEG images (enable embedding from the Settings).`) function readPNGMetadata(image) { const fileReader = new FileReader() @@ -469,29 +420,30 @@ }); }; - /* JPEG METADATA EXTRACTION */ + /* JPEG or WEBP METADATA EXTRACTION */ function readJPEGMetadata(image) { const fileReader = new FileReader() fileReader.onload = function (e) { - const exifObj = piexif.load(e.target.result) - - const exifData = exifObj['Exif'][piexif.ExifIFD.UserComment] - if (exifData !== undefined) { - try { - const isUnicode = (exifData.toLowerCase().startsWith('unicode')) - let keys = JSON.parse(isUnicode ? decodeUnicode(exifData.slice(8)) : exifData.slice(8)) - let reqBody = {} - for (let key in keys) { - reqBody[key] = keys[key] + ExifReader.load(e.target.result).then(tags => { + const exifData = String.fromCharCode(...tags['UserComment'].value) + if (exifData !== undefined) { + try { + const isUnicode = (exifData.toLowerCase().startsWith('unicode')) + let keys = JSON.parse(isUnicode ? decodeUnicode(exifData.slice(8)) : exifData.slice(8)) + let reqBody = {} + for (let key in keys) { + reqBody[key] = keys[key] + } + let task = { numOutputsTotal: reqBody["num_outputs"], seed: reqBody["seed"] } + task['reqBody'] = reqBody + clearAllImageTagCards() + restoreTaskToUI(task, TASK_REQ_NO_EXPORT) + } catch (e) { + console.error('No valid JSON in EXIF data') } - let task = { numOutputsTotal: reqBody["num_outputs"], seed: reqBody["seed"] } - task['reqBody'] = reqBody - clearAllImageTagCards() - restoreTaskToUI(task, TASK_REQ_NO_EXPORT) - } catch (e) { - console.error('No valid JSON in EXIF data') } - } + }) + } fileReader.readAsDataURL(image); } @@ -507,2483 +459,4 @@ return decodedString } - - /* 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. - */ - - let 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; - } })()