├── .gitattributes ├── arrow.png ├── index.html ├── index.js ├── node_modules └── blueimp-load-image │ ├── LICENSE.txt │ ├── README.md │ ├── js │ ├── index.js │ ├── load-image-exif-map.js │ ├── load-image-exif.js │ ├── load-image-fetch.js │ ├── load-image-iptc-map.js │ ├── load-image-iptc.js │ ├── load-image-meta.js │ ├── load-image-orientation.js │ ├── load-image-scale.js │ ├── load-image.all.min.js │ ├── load-image.all.min.js.map │ └── load-image.js │ └── package.json ├── package-lock.json ├── package.json └── spinner3.gif /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racky7/image-background-remover/f9f6c8c70609c1249b1af671144afff6b8b601fc/arrow.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Remove Background 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 |

Remove Image Background

13 | 14 |
15 | 16 |
17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 |
32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | document 2 | .querySelector("input[type=file]") 3 | .addEventListener("change", async function () { 4 | const resizedImage = await loadImage(this.files[0], { 5 | 6 | //resizing image using blue-load-image module 7 | 8 | maxWidth: 1500, 9 | maxHeight: 1500, 10 | canvas: true 11 | }); 12 | 13 | resizedImage.image.toBlob(async function (inputBlob) { 14 | const formData = new FormData(); 15 | 16 | //display table 17 | 18 | document.getElementById("myTable").removeAttribute("Hidden"); 19 | 20 | //display input image 21 | const inputImage = document.createElement("img"); 22 | document.querySelector("#result1").appendChild(inputImage); 23 | inputImage.style.width = "250px"; 24 | inputImage.style.height = "250px"; 25 | inputImage.src = URL.createObjectURL(inputBlob); 26 | 27 | //display loader 28 | 29 | const conImage = document.createElement("img"); 30 | document.querySelector("#convert").appendChild(conImage); 31 | conImage.style.width = "25%"; 32 | conImage.src = "spinner3.gif"; 33 | 34 | //api call 35 | formData.append("image_file", inputBlob); 36 | 37 | const response = await fetch("https://sdk.photoroom.com/v1/segment", { 38 | method: "POST", 39 | headers: { 40 | "x-api-key": process.env.APIKEY 41 | }, 42 | body: formData 43 | }); 44 | 45 | 46 | //output image 47 | 48 | const outputBlob = await response.blob(); 49 | conImage.src = "arrow.png"; 50 | conImage.style.marginTop = "20%"; 51 | 52 | const outputImage = document.createElement("img"); 53 | document.querySelector("#result").appendChild(outputImage); 54 | outputImage.style.width = "250px"; 55 | outputImage.style.height = "250px"; 56 | outputImage.src = URL.createObjectURL(outputBlob); 57 | 58 | //download button 59 | 60 | const getImg = document.createElement("a"); 61 | const downBtn = document.querySelector("#downBtn"); 62 | downBtn.appendChild(getImg); 63 | downBtn.removeAttribute("Hidden"); 64 | getImg.href = URL.createObjectURL(outputBlob); 65 | getImg.style.textDecoration = "none"; 66 | getImg.style.color = "inherit"; 67 | getImg.download = "removed-bg-image"; 68 | getImg.innerText = "Download (PNG)"; 69 | 70 | //display clear button 71 | 72 | const clearBtn = document.querySelector("#clearBtn"); 73 | clearBtn.removeAttribute("Hidden"); 74 | 75 | 76 | 77 | 78 | }); 79 | }) -------------------------------------------------------------------------------- /node_modules/blueimp-load-image/LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright © 2011 Sebastian Tschan, https://blueimp.net 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /node_modules/blueimp-load-image/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript Load Image 2 | 3 | > A JavaScript library to load and transform image files. 4 | 5 | ## Contents 6 | 7 | - [Demo](https://blueimp.github.io/JavaScript-Load-Image/) 8 | - [Description](#description) 9 | - [Setup](#setup) 10 | - [Usage](#usage) 11 | - [Image loading](#image-loading) 12 | - [Image scaling](#image-scaling) 13 | - [Requirements](#requirements) 14 | - [Browser support](#browser-support) 15 | - [API](#api) 16 | - [Callback](#callback) 17 | - [Function signature](#function-signature) 18 | - [Cancel image loading](#cancel-image-loading) 19 | - [Callback arguments](#callback-arguments) 20 | - [Error handling](#error-handling) 21 | - [Promise](#promise) 22 | - [Options](#options) 23 | - [maxWidth](#maxwidth) 24 | - [maxHeight](#maxheight) 25 | - [minWidth](#minwidth) 26 | - [minHeight](#minheight) 27 | - [sourceWidth](#sourcewidth) 28 | - [sourceHeight](#sourceheight) 29 | - [top](#top) 30 | - [right](#right) 31 | - [bottom](#bottom) 32 | - [left](#left) 33 | - [contain](#contain) 34 | - [cover](#cover) 35 | - [aspectRatio](#aspectratio) 36 | - [pixelRatio](#pixelratio) 37 | - [downsamplingRatio](#downsamplingratio) 38 | - [imageSmoothingEnabled](#imagesmoothingenabled) 39 | - [imageSmoothingQuality](#imagesmoothingquality) 40 | - [crop](#crop) 41 | - [orientation](#orientation) 42 | - [meta](#meta) 43 | - [canvas](#canvas) 44 | - [crossOrigin](#crossorigin) 45 | - [noRevoke](#norevoke) 46 | - [Metadata parsing](#metadata-parsing) 47 | - [Image head](#image-head) 48 | - [Exif parser](#exif-parser) 49 | - [Exif Thumbnail](#exif-thumbnail) 50 | - [Exif IFD](#exif-ifd) 51 | - [GPSInfo IFD](#gpsinfo-ifd) 52 | - [Interoperability IFD](#interoperability-ifd) 53 | - [Exif parser options](#exif-parser-options) 54 | - [Exif writer](#exif-writer) 55 | - [IPTC parser](#iptc-parser) 56 | - [IPTC parser options](#iptc-parser-options) 57 | - [License](#license) 58 | - [Credits](#credits) 59 | 60 | ## Description 61 | 62 | JavaScript Load Image is a library to load images provided as `File` or `Blob` 63 | objects or via `URL`. It returns an optionally **scaled**, **cropped** or 64 | **rotated** HTML `img` or `canvas` element. 65 | 66 | It also provides methods to parse image metadata to extract 67 | [IPTC](https://iptc.org/standards/photo-metadata/) and 68 | [Exif](https://en.wikipedia.org/wiki/Exif) tags as well as embedded thumbnail 69 | images, to overwrite the Exif Orientation value and to restore the complete 70 | image header after resizing. 71 | 72 | ## Setup 73 | 74 | Install via [NPM](https://www.npmjs.com/package/blueimp-load-image): 75 | 76 | ```sh 77 | npm install blueimp-load-image 78 | ``` 79 | 80 | This will install the JavaScript files inside 81 | `./node_modules/blueimp-load-image/js/` relative to your current directory, from 82 | where you can copy them into a folder that is served by your web server. 83 | 84 | Next include the combined and minified JavaScript Load Image script in your HTML 85 | markup: 86 | 87 | ```html 88 | 89 | ``` 90 | 91 | Or alternatively, choose which components you want to include: 92 | 93 | ```html 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | ``` 121 | 122 | ## Usage 123 | 124 | ### Image loading 125 | 126 | In your application code, use the `loadImage()` function with 127 | [callback](#callback) style: 128 | 129 | ```js 130 | document.getElementById('file-input').onchange = function () { 131 | loadImage( 132 | this.files[0], 133 | function (img) { 134 | document.body.appendChild(img) 135 | }, 136 | { maxWidth: 600 } // Options 137 | ) 138 | } 139 | ``` 140 | 141 | Or use the [Promise](#promise) based API like this ([requires](#requirements) a 142 | polyfill for older browsers): 143 | 144 | ```js 145 | document.getElementById('file-input').onchange = function () { 146 | loadImage(this.files[0], { maxWidth: 600 }).then(function (data) { 147 | document.body.appendChild(data.image) 148 | }) 149 | } 150 | ``` 151 | 152 | With 153 | [async/await](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await) 154 | (requires a modern browser or a code transpiler like 155 | [Babel](https://babeljs.io/) or [TypeScript](https://www.typescriptlang.org/)): 156 | 157 | ```js 158 | document.getElementById('file-input').onchange = async function () { 159 | let data = await loadImage(this.files[0], { maxWidth: 600 }) 160 | document.body.appendChild(data.image) 161 | } 162 | ``` 163 | 164 | ### Image scaling 165 | 166 | It is also possible to use the image scaling functionality directly with an 167 | existing image: 168 | 169 | ```js 170 | var scaledImage = loadImage.scale( 171 | img, // img or canvas element 172 | { maxWidth: 600 } 173 | ) 174 | ``` 175 | 176 | ## Requirements 177 | 178 | The JavaScript Load Image library has zero dependencies, but benefits from the 179 | following two 180 | [polyfills](https://developer.mozilla.org/en-US/docs/Glossary/Polyfill): 181 | 182 | - [blueimp-canvas-to-blob](https://github.com/blueimp/JavaScript-Canvas-to-Blob) 183 | for browsers without native 184 | [HTMLCanvasElement.toBlob](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob) 185 | support, to create `Blob` objects out of `canvas` elements. 186 | - [promise-polyfill](https://github.com/taylorhakes/promise-polyfill) to be able 187 | to use the 188 | [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) 189 | based `loadImage` API in Browsers without native `Promise` support. 190 | 191 | ## Browser support 192 | 193 | Browsers which implement the following APIs support all options: 194 | 195 | - Loading images from File and Blob objects: 196 | - [URL.createObjectURL](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL) 197 | or 198 | [FileReader.readAsDataURL](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL) 199 | - Parsing meta data: 200 | - [FileReader.readAsArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsArrayBuffer) 201 | - [Blob.slice](https://developer.mozilla.org/en-US/docs/Web/API/Blob/slice) 202 | - [DataView](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView) 203 | (no [BigInt](https://developer.mozilla.org/en-US/docs/Glossary/BigInt) 204 | support required) 205 | - Parsing meta data from images loaded via URL: 206 | - [fetch Response.blob](https://developer.mozilla.org/en-US/docs/Web/API/Body/blob) 207 | or 208 | [XMLHttpRequest.responseType blob](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType#blob) 209 | - Promise based API: 210 | - [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) 211 | 212 | This includes (but is not limited to) the following browsers: 213 | 214 | - Chrome 32+ 215 | - Firefox 29+ 216 | - Safari 8+ 217 | - Mobile Chrome 42+ (Android) 218 | - Mobile Firefox 50+ (Android) 219 | - Mobile Safari 8+ (iOS) 220 | - Edge 74+ 221 | - Edge Legacy 12+ 222 | - Internet Explorer 10+ `*` 223 | 224 | `*` Internet Explorer [requires](#requirements) a polyfill for the `Promise` 225 | based API. 226 | 227 | Loading an image from a URL and applying transformations (scaling, cropping and 228 | rotating - except `orientation:true`, which requires reading meta data) is 229 | supported by all browsers which implement the 230 | [HTMLCanvasElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement) 231 | interface. 232 | 233 | Loading an image from a URL and scaling it in size is supported by all browsers 234 | which implement the 235 | [img](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img) element and 236 | has been tested successfully with browser engines as old as Internet Explorer 5 237 | (via 238 | [IE11's emulation mode]()). 239 | 240 | The `loadImage()` function applies options using 241 | [progressive enhancement](https://en.wikipedia.org/wiki/Progressive_enhancement) 242 | and falls back to a configuration that is supported by the browser, e.g. if the 243 | `canvas` element is not supported, an equivalent `img` element is returned. 244 | 245 | ## API 246 | 247 | ### Callback 248 | 249 | #### Function signature 250 | 251 | The `loadImage()` function accepts a 252 | [File](https://developer.mozilla.org/en-US/docs/Web/API/File) or 253 | [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) object or an image 254 | URL as first argument. 255 | 256 | If a [File](https://developer.mozilla.org/en-US/docs/Web/API/File) or 257 | [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) is passed as 258 | parameter, it returns an HTML `img` element if the browser supports the 259 | [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL) API, alternatively a 260 | [FileReader](https://developer.mozilla.org/en-US/docs/Web/API/FileReader) object 261 | if the `FileReader` API is supported, or `false`. 262 | 263 | It always returns an HTML 264 | [img](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Img) element 265 | when passing an image URL: 266 | 267 | ```js 268 | var loadingImage = loadImage( 269 | 'https://example.org/image.png', 270 | function (img) { 271 | document.body.appendChild(img) 272 | }, 273 | { maxWidth: 600 } 274 | ) 275 | ``` 276 | 277 | #### Cancel image loading 278 | 279 | Some browsers (e.g. Chrome) will cancel the image loading process if the `src` 280 | property of an `img` element is changed. 281 | To avoid unnecessary requests, we can use the 282 | [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs) 283 | of a 1x1 pixel transparent GIF image as `src` target to cancel the original 284 | image download. 285 | 286 | To disable callback handling, we can also unset the image event handlers and for 287 | maximum browser compatibility, cancel the file reading process if the returned 288 | object is a 289 | [FileReader](https://developer.mozilla.org/en-US/docs/Web/API/FileReader) 290 | instance: 291 | 292 | ```js 293 | var loadingImage = loadImage( 294 | 'https://example.org/image.png', 295 | function (img) { 296 | document.body.appendChild(img) 297 | }, 298 | { maxWidth: 600 } 299 | ) 300 | 301 | if (loadingImage) { 302 | // Unset event handling for the loading image: 303 | loadingImage.onload = loadingImage.onerror = null 304 | 305 | // Cancel image loading process: 306 | if (loadingImage.abort) { 307 | // FileReader instance, stop the file reading process: 308 | loadingImage.abort() 309 | } else { 310 | // HTMLImageElement element, cancel the original image request by changing 311 | // the target source to the data URL of a 1x1 pixel transparent image GIF: 312 | loadingImage.src = 313 | 'data:image/gif;base64,' + 314 | 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' 315 | } 316 | } 317 | ``` 318 | 319 | **Please note:** 320 | The `img` element (or `FileReader` instance) for the loading image is only 321 | returned when using the callback style API and not available with the 322 | [Promise](#promise) based API. 323 | 324 | #### Callback arguments 325 | 326 | For the callback style API, the second argument to `loadImage()` must be a 327 | `callback` function, which is called when the image has been loaded or an error 328 | occurred while loading the image. 329 | 330 | The callback function is passed two arguments: 331 | 332 | 1. An HTML [img](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img) 333 | element or 334 | [canvas](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) 335 | element, or an 336 | [Event](https://developer.mozilla.org/en-US/docs/Web/API/Event) object of 337 | type `error`. 338 | 2. An object with the original image dimensions as properties and potentially 339 | additional [metadata](#metadata-parsing). 340 | 341 | ```js 342 | loadImage( 343 | fileOrBlobOrUrl, 344 | function (img, data) { 345 | document.body.appendChild(img) 346 | console.log('Original image width: ', data.originalWidth) 347 | console.log('Original image height: ', data.originalHeight) 348 | }, 349 | { maxWidth: 600, meta: true } 350 | ) 351 | ``` 352 | 353 | **Please note:** 354 | The original image dimensions reflect the natural width and height of the loaded 355 | image before applying any transformation. 356 | For consistent values across browsers, [metadata](#metadata-parsing) parsing has 357 | to be enabled via `meta:true`, so `loadImage` can detect automatic image 358 | orientation and normalize the dimensions. 359 | 360 | #### Error handling 361 | 362 | Example code implementing error handling: 363 | 364 | ```js 365 | loadImage( 366 | fileOrBlobOrUrl, 367 | function (img, data) { 368 | if (img.type === 'error') { 369 | console.error('Error loading image file') 370 | } else { 371 | document.body.appendChild(img) 372 | } 373 | }, 374 | { maxWidth: 600 } 375 | ) 376 | ``` 377 | 378 | ### Promise 379 | 380 | If the `loadImage()` function is called without a `callback` function as second 381 | argument and the 382 | [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) 383 | API is available, it returns a `Promise` object: 384 | 385 | ```js 386 | loadImage(fileOrBlobOrUrl, { maxWidth: 600, meta: true }) 387 | .then(function (data) { 388 | document.body.appendChild(data.image) 389 | console.log('Original image width: ', data.originalWidth) 390 | console.log('Original image height: ', data.originalHeight) 391 | }) 392 | .catch(function (err) { 393 | // Handling image loading errors 394 | console.log(err) 395 | }) 396 | ``` 397 | 398 | The `Promise` resolves with an object with the following properties: 399 | 400 | - `image`: An HTML 401 | [img](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img) or 402 | [canvas](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) element. 403 | - `originalWidth`: The original width of the image. 404 | - `originalHeight`: The original height of the image. 405 | 406 | Please also read the note about original image dimensions normalization in the 407 | [callback arguments](#callback-arguments) section. 408 | 409 | If [metadata](#metadata-parsing) has been parsed, additional properties might be 410 | present on the object. 411 | 412 | If image loading fails, the `Promise` rejects with an 413 | [Event](https://developer.mozilla.org/en-US/docs/Web/API/Event) object of type 414 | `error`. 415 | 416 | ## Options 417 | 418 | The optional options argument to `loadImage()` allows to configure the image 419 | loading. 420 | 421 | It can be used the following way with the callback style: 422 | 423 | ```js 424 | loadImage( 425 | fileOrBlobOrUrl, 426 | function (img) { 427 | document.body.appendChild(img) 428 | }, 429 | { 430 | maxWidth: 600, 431 | maxHeight: 300, 432 | minWidth: 100, 433 | minHeight: 50, 434 | canvas: true 435 | } 436 | ) 437 | ``` 438 | 439 | Or the following way with the `Promise` based API: 440 | 441 | ```js 442 | loadImage(fileOrBlobOrUrl, { 443 | maxWidth: 600, 444 | maxHeight: 300, 445 | minWidth: 100, 446 | minHeight: 50, 447 | canvas: true 448 | }).then(function (data) { 449 | document.body.appendChild(data.image) 450 | }) 451 | ``` 452 | 453 | All settings are optional. By default, the image is returned as HTML `img` 454 | element without any image size restrictions. 455 | 456 | ### maxWidth 457 | 458 | Defines the maximum width of the `img`/`canvas` element. 459 | 460 | ### maxHeight 461 | 462 | Defines the maximum height of the `img`/`canvas` element. 463 | 464 | ### minWidth 465 | 466 | Defines the minimum width of the `img`/`canvas` element. 467 | 468 | ### minHeight 469 | 470 | Defines the minimum height of the `img`/`canvas` element. 471 | 472 | ### sourceWidth 473 | 474 | The width of the sub-rectangle of the source image to draw into the destination 475 | canvas. 476 | Defaults to the source image width and requires `canvas: true`. 477 | 478 | ### sourceHeight 479 | 480 | The height of the sub-rectangle of the source image to draw into the destination 481 | canvas. 482 | Defaults to the source image height and requires `canvas: true`. 483 | 484 | ### top 485 | 486 | The top margin of the sub-rectangle of the source image. 487 | Defaults to `0` and requires `canvas: true`. 488 | 489 | ### right 490 | 491 | The right margin of the sub-rectangle of the source image. 492 | Defaults to `0` and requires `canvas: true`. 493 | 494 | ### bottom 495 | 496 | The bottom margin of the sub-rectangle of the source image. 497 | Defaults to `0` and requires `canvas: true`. 498 | 499 | ### left 500 | 501 | The left margin of the sub-rectangle of the source image. 502 | Defaults to `0` and requires `canvas: true`. 503 | 504 | ### contain 505 | 506 | Scales the image up/down to contain it in the max dimensions if set to `true`. 507 | This emulates the CSS feature 508 | [background-image: contain](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Backgrounds_and_Borders/Resizing_background_images#contain). 509 | 510 | ### cover 511 | 512 | Scales the image up/down to cover the max dimensions with the image dimensions 513 | if set to `true`. 514 | This emulates the CSS feature 515 | [background-image: cover](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Backgrounds_and_Borders/Resizing_background_images#cover). 516 | 517 | ### aspectRatio 518 | 519 | Crops the image to the given aspect ratio (e.g. `16/9`). 520 | Setting the `aspectRatio` also enables the `crop` option. 521 | 522 | ### pixelRatio 523 | 524 | Defines the ratio of the canvas pixels to the physical image pixels on the 525 | screen. 526 | Should be set to 527 | [window.devicePixelRatio](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio) 528 | unless the scaled image is not rendered on screen. 529 | Defaults to `1` and requires `canvas: true`. 530 | 531 | ### downsamplingRatio 532 | 533 | Defines the ratio in which the image is downsampled (scaled down in steps). 534 | By default, images are downsampled in one step. 535 | With a ratio of `0.5`, each step scales the image to half the size, before 536 | reaching the target dimensions. 537 | Requires `canvas: true`. 538 | 539 | ### imageSmoothingEnabled 540 | 541 | If set to `false`, 542 | [disables image smoothing](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingEnabled). 543 | Defaults to `true` and requires `canvas: true`. 544 | 545 | ### imageSmoothingQuality 546 | 547 | Sets the 548 | [quality of image smoothing](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingQuality). 549 | Possible values: `'low'`, `'medium'`, `'high'` 550 | Defaults to `'low'` and requires `canvas: true`. 551 | 552 | ### crop 553 | 554 | Crops the image to the `maxWidth`/`maxHeight` constraints if set to `true`. 555 | Enabling the `crop` option also enables the `canvas` option. 556 | 557 | ### orientation 558 | 559 | Transform the canvas according to the specified Exif orientation, which can be 560 | an `integer` in the range of `1` to `8` or the boolean value `true`. 561 | 562 | When set to `true`, it will set the orientation value based on the Exif data of 563 | the image, which will be parsed automatically if the Exif extension is 564 | available. 565 | 566 | Exif orientation values to correctly display the letter F: 567 | 568 | ``` 569 | 1 2 570 | ██████ ██████ 571 | ██ ██ 572 | ████ ████ 573 | ██ ██ 574 | ██ ██ 575 | 576 | 3 4 577 | ██ ██ 578 | ██ ██ 579 | ████ ████ 580 | ██ ██ 581 | ██████ ██████ 582 | 583 | 5 6 584 | ██████████ ██ 585 | ██ ██ ██ ██ 586 | ██ ██████████ 587 | 588 | 7 8 589 | ██ ██████████ 590 | ██ ██ ██ ██ 591 | ██████████ ██ 592 | ``` 593 | 594 | Setting `orientation` to `true` enables the `canvas` and `meta` options, unless 595 | the browser supports automatic image orientation (see 596 | [browser support for image-orientation](https://caniuse.com/#feat=css-image-orientation)). 597 | 598 | Setting `orientation` to `1` enables the `canvas` and `meta` options if the 599 | browser does support automatic image orientation (to allow reset of the 600 | orientation). 601 | 602 | Setting `orientation` to an integer in the range of `2` to `8` always enables 603 | the `canvas` option and also enables the `meta` option if the browser supports 604 | automatic image orientation (again to allow reset). 605 | 606 | ### meta 607 | 608 | Automatically parses the image metadata if set to `true`. 609 | 610 | If metadata has been found, the data object passed as second argument to the 611 | callback function has additional properties (see 612 | [metadata parsing](#metadata-parsing)). 613 | 614 | If the file is given as URL and the browser supports the 615 | [fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) or the 616 | XHR 617 | [responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType) 618 | `blob`, fetches the file as `Blob` to be able to parse the metadata. 619 | 620 | ### canvas 621 | 622 | Returns the image as 623 | [canvas](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) element if 624 | set to `true`. 625 | 626 | ### crossOrigin 627 | 628 | Sets the `crossOrigin` property on the `img` element for loading 629 | [CORS enabled images](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image). 630 | 631 | ### noRevoke 632 | 633 | By default, the 634 | [created object URL](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL) 635 | is revoked after the image has been loaded, except when this option is set to 636 | `true`. 637 | 638 | ## Metadata parsing 639 | 640 | If the Load Image Meta extension is included, it is possible to parse image meta 641 | data automatically with the `meta` option: 642 | 643 | ```js 644 | loadImage( 645 | fileOrBlobOrUrl, 646 | function (img, data) { 647 | console.log('Original image head: ', data.imageHead) 648 | console.log('Exif data: ', data.exif) // requires exif extension 649 | console.log('IPTC data: ', data.iptc) // requires iptc extension 650 | }, 651 | { meta: true } 652 | ) 653 | ``` 654 | 655 | Or alternatively via `loadImage.parseMetaData`, which can be used with an 656 | available `File` or `Blob` object as first argument: 657 | 658 | ```js 659 | loadImage.parseMetaData( 660 | fileOrBlob, 661 | function (data) { 662 | console.log('Original image head: ', data.imageHead) 663 | console.log('Exif data: ', data.exif) // requires exif extension 664 | console.log('IPTC data: ', data.iptc) // requires iptc extension 665 | }, 666 | { 667 | maxMetaDataSize: 262144 668 | } 669 | ) 670 | ``` 671 | 672 | Or using the 673 | [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) 674 | based API: 675 | 676 | ```js 677 | loadImage 678 | .parseMetaData(fileOrBlob, { 679 | maxMetaDataSize: 262144 680 | }) 681 | .then(function (data) { 682 | console.log('Original image head: ', data.imageHead) 683 | console.log('Exif data: ', data.exif) // requires exif extension 684 | console.log('IPTC data: ', data.iptc) // requires iptc extension 685 | }) 686 | ``` 687 | 688 | The Metadata extension adds additional options used for the `parseMetaData` 689 | method: 690 | 691 | - `maxMetaDataSize`: Maximum number of bytes of metadata to parse. 692 | - `disableImageHead`: Disable parsing the original image head. 693 | - `disableMetaDataParsers`: Disable parsing metadata (image head only) 694 | 695 | ### Image head 696 | 697 | Resized JPEG images can be combined with their original image head via 698 | `loadImage.replaceHead`, which requires the resized image as `Blob` object as 699 | first argument and an `ArrayBuffer` image head as second argument. 700 | 701 | With callback style, the third argument must be a `callback` function, which is 702 | called with the new `Blob` object: 703 | 704 | ```js 705 | loadImage( 706 | fileOrBlobOrUrl, 707 | function (img, data) { 708 | if (data.imageHead) { 709 | img.toBlob(function (blob) { 710 | loadImage.replaceHead(blob, data.imageHead, function (newBlob) { 711 | // do something with the new Blob object 712 | }) 713 | }, 'image/jpeg') 714 | } 715 | }, 716 | { meta: true, canvas: true, maxWidth: 800 } 717 | ) 718 | ``` 719 | 720 | Or using the 721 | [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) 722 | based API like this: 723 | 724 | ```js 725 | loadImage(fileOrBlobOrUrl, { meta: true, canvas: true, maxWidth: 800 }) 726 | .then(function (data) { 727 | if (!data.imageHead) throw new Error('Could not parse image metadata') 728 | return new Promise(function (resolve) { 729 | data.image.toBlob(function (blob) { 730 | data.blob = blob 731 | resolve(data) 732 | }, 'image/jpeg') 733 | }) 734 | }) 735 | .then(function (data) { 736 | return loadImage.replaceHead(data.blob, data.imageHead) 737 | }) 738 | .then(function (blob) { 739 | // do something with the new Blob object 740 | }) 741 | .catch(function (err) { 742 | console.error(err) 743 | }) 744 | ``` 745 | 746 | **Please note:** 747 | `Blob` objects of resized images can be created via 748 | [HTMLCanvasElement.toBlob](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob). 749 | [blueimp-canvas-to-blob](https://github.com/blueimp/JavaScript-Canvas-to-Blob) 750 | provides a polyfill for browsers without native `canvas.toBlob()` support. 751 | 752 | ### Exif parser 753 | 754 | If you include the Load Image Exif Parser extension, the argument passed to the 755 | callback for `parseMetaData` will contain the following additional properties if 756 | Exif data could be found in the given image: 757 | 758 | - `exif`: The parsed Exif tags 759 | - `exifOffsets`: The parsed Exif tag offsets 760 | - `exifTiffOffset`: TIFF header offset (used for offset pointers) 761 | - `exifLittleEndian`: little endian order if true, big endian if false 762 | 763 | The `exif` object stores the parsed Exif tags: 764 | 765 | ```js 766 | var orientation = data.exif[0x0112] // Orientation 767 | ``` 768 | 769 | The `exif` and `exifOffsets` objects also provide a `get()` method to retrieve 770 | the tag value/offset via the tag's mapped name: 771 | 772 | ```js 773 | var orientation = data.exif.get('Orientation') 774 | var orientationOffset = data.exifOffsets.get('Orientation') 775 | ``` 776 | 777 | By default, only the following names are mapped: 778 | 779 | - `Orientation` 780 | - `Thumbnail` (see [Exif Thumbnail](#exif-thumbnail)) 781 | - `Exif` (see [Exif IFD](#exif-ifd)) 782 | - `GPSInfo` (see [GPSInfo IFD](#gpsinfo-ifd)) 783 | - `Interoperability` (see [Interoperability IFD](#interoperability-ifd)) 784 | 785 | If you also include the Load Image Exif Map library, additional tag mappings 786 | become available, as well as three additional methods: 787 | 788 | - `exif.getText()` 789 | - `exif.getName()` 790 | - `exif.getAll()` 791 | 792 | ```js 793 | var orientationText = data.exif.getText('Orientation') // e.g. "Rotate 90° CW" 794 | 795 | var name = data.exif.getName(0x0112) // "Orientation" 796 | 797 | // A map of all parsed tags with their mapped names/text as keys/values: 798 | var allTags = data.exif.getAll() 799 | ``` 800 | 801 | #### Exif Thumbnail 802 | 803 | Example code displaying a thumbnail image embedded into the Exif metadata: 804 | 805 | ```js 806 | loadImage( 807 | fileOrBlobOrUrl, 808 | function (img, data) { 809 | var exif = data.exif 810 | var thumbnail = exif && exif.get('Thumbnail') 811 | var blob = thumbnail && thumbnail.get('Blob') 812 | if (blob) { 813 | loadImage( 814 | blob, 815 | function (thumbImage) { 816 | document.body.appendChild(thumbImage) 817 | }, 818 | { orientation: exif.get('Orientation') } 819 | ) 820 | } 821 | }, 822 | { meta: true } 823 | ) 824 | ``` 825 | 826 | #### Exif IFD 827 | 828 | Example code displaying data from the Exif IFD (Image File Directory) that 829 | contains Exif specified TIFF tags: 830 | 831 | ```js 832 | loadImage( 833 | fileOrBlobOrUrl, 834 | function (img, data) { 835 | var exifIFD = data.exif && data.exif.get('Exif') 836 | if (exifIFD) { 837 | // Map of all Exif IFD tags with their mapped names/text as keys/values: 838 | console.log(exifIFD.getAll()) 839 | // A specific Exif IFD tag value: 840 | console.log(exifIFD.get('UserComment')) 841 | } 842 | }, 843 | { meta: true } 844 | ) 845 | ``` 846 | 847 | #### GPSInfo IFD 848 | 849 | Example code displaying data from the Exif IFD (Image File Directory) that 850 | contains [GPS](https://en.wikipedia.org/wiki/Global_Positioning_System) info: 851 | 852 | ```js 853 | loadImage( 854 | fileOrBlobOrUrl, 855 | function (img, data) { 856 | var gpsInfo = data.exif && data.exif.get('GPSInfo') 857 | if (gpsInfo) { 858 | // Map of all GPSInfo tags with their mapped names/text as keys/values: 859 | console.log(gpsInfo.getAll()) 860 | // A specific GPSInfo tag value: 861 | console.log(gpsInfo.get('GPSLatitude')) 862 | } 863 | }, 864 | { meta: true } 865 | ) 866 | ``` 867 | 868 | #### Interoperability IFD 869 | 870 | Example code displaying data from the Exif IFD (Image File Directory) that 871 | contains Interoperability data: 872 | 873 | ```js 874 | loadImage( 875 | fileOrBlobOrUrl, 876 | function (img, data) { 877 | var interoperabilityData = data.exif && data.exif.get('Interoperability') 878 | if (interoperabilityData) { 879 | // The InteroperabilityIndex tag value: 880 | console.log(interoperabilityData.get('InteroperabilityIndex')) 881 | } 882 | }, 883 | { meta: true } 884 | ) 885 | ``` 886 | 887 | #### Exif parser options 888 | 889 | The Exif parser adds additional options: 890 | 891 | - `disableExif`: Disables Exif parsing when `true`. 892 | - `disableExifOffsets`: Disables storing Exif tag offsets when `true`. 893 | - `includeExifTags`: A map of Exif tags to include for parsing (includes all but 894 | the excluded tags by default). 895 | - `excludeExifTags`: A map of Exif tags to exclude from parsing (defaults to 896 | exclude `Exif` `MakerNote`). 897 | 898 | An example parsing only Orientation, Thumbnail and ExifVersion tags: 899 | 900 | ```js 901 | loadImage.parseMetaData( 902 | fileOrBlob, 903 | function (data) { 904 | console.log('Exif data: ', data.exif) 905 | }, 906 | { 907 | includeExifTags: { 908 | 0x0112: true, // Orientation 909 | ifd1: { 910 | 0x0201: true, // JPEGInterchangeFormat (Thumbnail data offset) 911 | 0x0202: true // JPEGInterchangeFormatLength (Thumbnail data length) 912 | }, 913 | 0x8769: { 914 | // ExifIFDPointer 915 | 0x9000: true // ExifVersion 916 | } 917 | } 918 | } 919 | ) 920 | ``` 921 | 922 | An example excluding `Exif` `MakerNote` and `GPSInfo`: 923 | 924 | ```js 925 | loadImage.parseMetaData( 926 | fileOrBlob, 927 | function (data) { 928 | console.log('Exif data: ', data.exif) 929 | }, 930 | { 931 | excludeExifTags: { 932 | 0x8769: { 933 | // ExifIFDPointer 934 | 0x927c: true // MakerNote 935 | }, 936 | 0x8825: true // GPSInfoIFDPointer 937 | } 938 | } 939 | ) 940 | ``` 941 | 942 | ### Exif writer 943 | 944 | The Exif parser extension also includes a minimal writer that allows to override 945 | the Exif `Orientation` value in the parsed `imageHead` `ArrayBuffer`: 946 | 947 | ```js 948 | loadImage( 949 | fileOrBlobOrUrl, 950 | function (img, data) { 951 | if (data.imageHead && data.exif) { 952 | // Reset Exif Orientation data: 953 | loadImage.writeExifData(data.imageHead, data, 'Orientation', 1) 954 | img.toBlob(function (blob) { 955 | loadImage.replaceHead(blob, data.imageHead, function (newBlob) { 956 | // do something with newBlob 957 | }) 958 | }, 'image/jpeg') 959 | } 960 | }, 961 | { meta: true, orientation: true, canvas: true, maxWidth: 800 } 962 | ) 963 | ``` 964 | 965 | **Please note:** 966 | The Exif writer relies on the Exif tag offsets being available as 967 | `data.exifOffsets` property, which requires that Exif data has been parsed from 968 | the image. 969 | The Exif writer can only change existing values, not add new tags, e.g. it 970 | cannot add an Exif `Orientation` tag for an image that does not have one. 971 | 972 | ### IPTC parser 973 | 974 | If you include the Load Image IPTC Parser extension, the argument passed to the 975 | callback for `parseMetaData` will contain the following additional properties if 976 | IPTC data could be found in the given image: 977 | 978 | - `iptc`: The parsed IPTC tags 979 | - `iptcOffsets`: The parsed IPTC tag offsets 980 | 981 | The `iptc` object stores the parsed IPTC tags: 982 | 983 | ```js 984 | var objectname = data.iptc[5] 985 | ``` 986 | 987 | The `iptc` and `iptcOffsets` objects also provide a `get()` method to retrieve 988 | the tag value/offset via the tag's mapped name: 989 | 990 | ```js 991 | var objectname = data.iptc.get('ObjectName') 992 | ``` 993 | 994 | By default, only the following names are mapped: 995 | 996 | - `ObjectName` 997 | 998 | If you also include the Load Image IPTC Map library, additional tag mappings 999 | become available, as well as three additional methods: 1000 | 1001 | - `iptc.getText()` 1002 | - `iptc.getName()` 1003 | - `iptc.getAll()` 1004 | 1005 | ```js 1006 | var keywords = data.iptc.getText('Keywords') // e.g.: ['Weather','Sky'] 1007 | 1008 | var name = data.iptc.getName(5) // ObjectName 1009 | 1010 | // A map of all parsed tags with their mapped names/text as keys/values: 1011 | var allTags = data.iptc.getAll() 1012 | ``` 1013 | 1014 | #### IPTC parser options 1015 | 1016 | The IPTC parser adds additional options: 1017 | 1018 | - `disableIptc`: Disables IPTC parsing when true. 1019 | - `disableIptcOffsets`: Disables storing IPTC tag offsets when `true`. 1020 | - `includeIptcTags`: A map of IPTC tags to include for parsing (includes all but 1021 | the excluded tags by default). 1022 | - `excludeIptcTags`: A map of IPTC tags to exclude from parsing (defaults to 1023 | exclude `ObjectPreviewData`). 1024 | 1025 | An example parsing only the `ObjectName` tag: 1026 | 1027 | ```js 1028 | loadImage.parseMetaData( 1029 | fileOrBlob, 1030 | function (data) { 1031 | console.log('IPTC data: ', data.iptc) 1032 | }, 1033 | { 1034 | includeIptcTags: { 1035 | 5: true // ObjectName 1036 | } 1037 | } 1038 | ) 1039 | ``` 1040 | 1041 | An example excluding `ApplicationRecordVersion` and `ObjectPreviewData`: 1042 | 1043 | ```js 1044 | loadImage.parseMetaData( 1045 | fileOrBlob, 1046 | function (data) { 1047 | console.log('IPTC data: ', data.iptc) 1048 | }, 1049 | { 1050 | excludeIptcTags: { 1051 | 0: true, // ApplicationRecordVersion 1052 | 202: true // ObjectPreviewData 1053 | } 1054 | } 1055 | ) 1056 | ``` 1057 | 1058 | ## License 1059 | 1060 | The JavaScript Load Image library is released under the 1061 | [MIT license](https://opensource.org/licenses/MIT). 1062 | 1063 | ## Credits 1064 | 1065 | - Original image metadata handling implemented with the help and contribution of 1066 | Achim Stöhr. 1067 | - Original Exif tags mapping based on Jacob Seidelin's 1068 | [exif-js](https://github.com/exif-js/exif-js) library. 1069 | - Original IPTC parser implementation by 1070 | [Dave Bevan](https://github.com/bevand10). 1071 | -------------------------------------------------------------------------------- /node_modules/blueimp-load-image/js/index.js: -------------------------------------------------------------------------------- 1 | /* global module, require */ 2 | 3 | module.exports = require('./load-image') 4 | 5 | require('./load-image-scale') 6 | require('./load-image-meta') 7 | require('./load-image-fetch') 8 | require('./load-image-exif') 9 | require('./load-image-exif-map') 10 | require('./load-image-iptc') 11 | require('./load-image-iptc-map') 12 | require('./load-image-orientation') 13 | -------------------------------------------------------------------------------- /node_modules/blueimp-load-image/js/load-image-exif-map.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JavaScript Load Image Exif Map 3 | * https://github.com/blueimp/JavaScript-Load-Image 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Exif tags mapping based on 9 | * https://github.com/jseidelin/exif-js 10 | * 11 | * Licensed under the MIT license: 12 | * https://opensource.org/licenses/MIT 13 | */ 14 | 15 | /* global define, module, require */ 16 | 17 | ;(function (factory) { 18 | 'use strict' 19 | if (typeof define === 'function' && define.amd) { 20 | // Register as an anonymous AMD module: 21 | define(['./load-image', './load-image-exif'], factory) 22 | } else if (typeof module === 'object' && module.exports) { 23 | factory(require('./load-image'), require('./load-image-exif')) 24 | } else { 25 | // Browser globals: 26 | factory(window.loadImage) 27 | } 28 | })(function (loadImage) { 29 | 'use strict' 30 | 31 | var ExifMapProto = loadImage.ExifMap.prototype 32 | 33 | ExifMapProto.tags = { 34 | // ================= 35 | // TIFF tags (IFD0): 36 | // ================= 37 | 0x0100: 'ImageWidth', 38 | 0x0101: 'ImageHeight', 39 | 0x0102: 'BitsPerSample', 40 | 0x0103: 'Compression', 41 | 0x0106: 'PhotometricInterpretation', 42 | 0x0112: 'Orientation', 43 | 0x0115: 'SamplesPerPixel', 44 | 0x011c: 'PlanarConfiguration', 45 | 0x0212: 'YCbCrSubSampling', 46 | 0x0213: 'YCbCrPositioning', 47 | 0x011a: 'XResolution', 48 | 0x011b: 'YResolution', 49 | 0x0128: 'ResolutionUnit', 50 | 0x0111: 'StripOffsets', 51 | 0x0116: 'RowsPerStrip', 52 | 0x0117: 'StripByteCounts', 53 | 0x0201: 'JPEGInterchangeFormat', 54 | 0x0202: 'JPEGInterchangeFormatLength', 55 | 0x012d: 'TransferFunction', 56 | 0x013e: 'WhitePoint', 57 | 0x013f: 'PrimaryChromaticities', 58 | 0x0211: 'YCbCrCoefficients', 59 | 0x0214: 'ReferenceBlackWhite', 60 | 0x0132: 'DateTime', 61 | 0x010e: 'ImageDescription', 62 | 0x010f: 'Make', 63 | 0x0110: 'Model', 64 | 0x0131: 'Software', 65 | 0x013b: 'Artist', 66 | 0x8298: 'Copyright', 67 | 0x8769: { 68 | // ExifIFDPointer 69 | 0x9000: 'ExifVersion', // EXIF version 70 | 0xa000: 'FlashpixVersion', // Flashpix format version 71 | 0xa001: 'ColorSpace', // Color space information tag 72 | 0xa002: 'PixelXDimension', // Valid width of meaningful image 73 | 0xa003: 'PixelYDimension', // Valid height of meaningful image 74 | 0xa500: 'Gamma', 75 | 0x9101: 'ComponentsConfiguration', // Information about channels 76 | 0x9102: 'CompressedBitsPerPixel', // Compressed bits per pixel 77 | 0x927c: 'MakerNote', // Any desired information written by the manufacturer 78 | 0x9286: 'UserComment', // Comments by user 79 | 0xa004: 'RelatedSoundFile', // Name of related sound file 80 | 0x9003: 'DateTimeOriginal', // Date and time when the original image was generated 81 | 0x9004: 'DateTimeDigitized', // Date and time when the image was stored digitally 82 | 0x9010: 'OffsetTime', // Time zone when the image file was last changed 83 | 0x9011: 'OffsetTimeOriginal', // Time zone when the image was stored digitally 84 | 0x9012: 'OffsetTimeDigitized', // Time zone when the image was stored digitally 85 | 0x9290: 'SubSecTime', // Fractions of seconds for DateTime 86 | 0x9291: 'SubSecTimeOriginal', // Fractions of seconds for DateTimeOriginal 87 | 0x9292: 'SubSecTimeDigitized', // Fractions of seconds for DateTimeDigitized 88 | 0x829a: 'ExposureTime', // Exposure time (in seconds) 89 | 0x829d: 'FNumber', 90 | 0x8822: 'ExposureProgram', // Exposure program 91 | 0x8824: 'SpectralSensitivity', // Spectral sensitivity 92 | 0x8827: 'PhotographicSensitivity', // EXIF 2.3, ISOSpeedRatings in EXIF 2.2 93 | 0x8828: 'OECF', // Optoelectric conversion factor 94 | 0x8830: 'SensitivityType', 95 | 0x8831: 'StandardOutputSensitivity', 96 | 0x8832: 'RecommendedExposureIndex', 97 | 0x8833: 'ISOSpeed', 98 | 0x8834: 'ISOSpeedLatitudeyyy', 99 | 0x8835: 'ISOSpeedLatitudezzz', 100 | 0x9201: 'ShutterSpeedValue', // Shutter speed 101 | 0x9202: 'ApertureValue', // Lens aperture 102 | 0x9203: 'BrightnessValue', // Value of brightness 103 | 0x9204: 'ExposureBias', // Exposure bias 104 | 0x9205: 'MaxApertureValue', // Smallest F number of lens 105 | 0x9206: 'SubjectDistance', // Distance to subject in meters 106 | 0x9207: 'MeteringMode', // Metering mode 107 | 0x9208: 'LightSource', // Kind of light source 108 | 0x9209: 'Flash', // Flash status 109 | 0x9214: 'SubjectArea', // Location and area of main subject 110 | 0x920a: 'FocalLength', // Focal length of the lens in mm 111 | 0xa20b: 'FlashEnergy', // Strobe energy in BCPS 112 | 0xa20c: 'SpatialFrequencyResponse', 113 | 0xa20e: 'FocalPlaneXResolution', // Number of pixels in width direction per FPRUnit 114 | 0xa20f: 'FocalPlaneYResolution', // Number of pixels in height direction per FPRUnit 115 | 0xa210: 'FocalPlaneResolutionUnit', // Unit for measuring the focal plane resolution 116 | 0xa214: 'SubjectLocation', // Location of subject in image 117 | 0xa215: 'ExposureIndex', // Exposure index selected on camera 118 | 0xa217: 'SensingMethod', // Image sensor type 119 | 0xa300: 'FileSource', // Image source (3 == DSC) 120 | 0xa301: 'SceneType', // Scene type (1 == directly photographed) 121 | 0xa302: 'CFAPattern', // Color filter array geometric pattern 122 | 0xa401: 'CustomRendered', // Special processing 123 | 0xa402: 'ExposureMode', // Exposure mode 124 | 0xa403: 'WhiteBalance', // 1 = auto white balance, 2 = manual 125 | 0xa404: 'DigitalZoomRatio', // Digital zoom ratio 126 | 0xa405: 'FocalLengthIn35mmFilm', 127 | 0xa406: 'SceneCaptureType', // Type of scene 128 | 0xa407: 'GainControl', // Degree of overall image gain adjustment 129 | 0xa408: 'Contrast', // Direction of contrast processing applied by camera 130 | 0xa409: 'Saturation', // Direction of saturation processing applied by camera 131 | 0xa40a: 'Sharpness', // Direction of sharpness processing applied by camera 132 | 0xa40b: 'DeviceSettingDescription', 133 | 0xa40c: 'SubjectDistanceRange', // Distance to subject 134 | 0xa420: 'ImageUniqueID', // Identifier assigned uniquely to each image 135 | 0xa430: 'CameraOwnerName', 136 | 0xa431: 'BodySerialNumber', 137 | 0xa432: 'LensSpecification', 138 | 0xa433: 'LensMake', 139 | 0xa434: 'LensModel', 140 | 0xa435: 'LensSerialNumber' 141 | }, 142 | 0x8825: { 143 | // GPSInfoIFDPointer 144 | 0x0000: 'GPSVersionID', 145 | 0x0001: 'GPSLatitudeRef', 146 | 0x0002: 'GPSLatitude', 147 | 0x0003: 'GPSLongitudeRef', 148 | 0x0004: 'GPSLongitude', 149 | 0x0005: 'GPSAltitudeRef', 150 | 0x0006: 'GPSAltitude', 151 | 0x0007: 'GPSTimeStamp', 152 | 0x0008: 'GPSSatellites', 153 | 0x0009: 'GPSStatus', 154 | 0x000a: 'GPSMeasureMode', 155 | 0x000b: 'GPSDOP', 156 | 0x000c: 'GPSSpeedRef', 157 | 0x000d: 'GPSSpeed', 158 | 0x000e: 'GPSTrackRef', 159 | 0x000f: 'GPSTrack', 160 | 0x0010: 'GPSImgDirectionRef', 161 | 0x0011: 'GPSImgDirection', 162 | 0x0012: 'GPSMapDatum', 163 | 0x0013: 'GPSDestLatitudeRef', 164 | 0x0014: 'GPSDestLatitude', 165 | 0x0015: 'GPSDestLongitudeRef', 166 | 0x0016: 'GPSDestLongitude', 167 | 0x0017: 'GPSDestBearingRef', 168 | 0x0018: 'GPSDestBearing', 169 | 0x0019: 'GPSDestDistanceRef', 170 | 0x001a: 'GPSDestDistance', 171 | 0x001b: 'GPSProcessingMethod', 172 | 0x001c: 'GPSAreaInformation', 173 | 0x001d: 'GPSDateStamp', 174 | 0x001e: 'GPSDifferential', 175 | 0x001f: 'GPSHPositioningError' 176 | }, 177 | 0xa005: { 178 | // InteroperabilityIFDPointer 179 | 0x0001: 'InteroperabilityIndex' 180 | } 181 | } 182 | 183 | // IFD1 directory can contain any IFD0 tags: 184 | ExifMapProto.tags.ifd1 = ExifMapProto.tags 185 | 186 | ExifMapProto.stringValues = { 187 | ExposureProgram: { 188 | 0: 'Undefined', 189 | 1: 'Manual', 190 | 2: 'Normal program', 191 | 3: 'Aperture priority', 192 | 4: 'Shutter priority', 193 | 5: 'Creative program', 194 | 6: 'Action program', 195 | 7: 'Portrait mode', 196 | 8: 'Landscape mode' 197 | }, 198 | MeteringMode: { 199 | 0: 'Unknown', 200 | 1: 'Average', 201 | 2: 'CenterWeightedAverage', 202 | 3: 'Spot', 203 | 4: 'MultiSpot', 204 | 5: 'Pattern', 205 | 6: 'Partial', 206 | 255: 'Other' 207 | }, 208 | LightSource: { 209 | 0: 'Unknown', 210 | 1: 'Daylight', 211 | 2: 'Fluorescent', 212 | 3: 'Tungsten (incandescent light)', 213 | 4: 'Flash', 214 | 9: 'Fine weather', 215 | 10: 'Cloudy weather', 216 | 11: 'Shade', 217 | 12: 'Daylight fluorescent (D 5700 - 7100K)', 218 | 13: 'Day white fluorescent (N 4600 - 5400K)', 219 | 14: 'Cool white fluorescent (W 3900 - 4500K)', 220 | 15: 'White fluorescent (WW 3200 - 3700K)', 221 | 17: 'Standard light A', 222 | 18: 'Standard light B', 223 | 19: 'Standard light C', 224 | 20: 'D55', 225 | 21: 'D65', 226 | 22: 'D75', 227 | 23: 'D50', 228 | 24: 'ISO studio tungsten', 229 | 255: 'Other' 230 | }, 231 | Flash: { 232 | 0x0000: 'Flash did not fire', 233 | 0x0001: 'Flash fired', 234 | 0x0005: 'Strobe return light not detected', 235 | 0x0007: 'Strobe return light detected', 236 | 0x0009: 'Flash fired, compulsory flash mode', 237 | 0x000d: 'Flash fired, compulsory flash mode, return light not detected', 238 | 0x000f: 'Flash fired, compulsory flash mode, return light detected', 239 | 0x0010: 'Flash did not fire, compulsory flash mode', 240 | 0x0018: 'Flash did not fire, auto mode', 241 | 0x0019: 'Flash fired, auto mode', 242 | 0x001d: 'Flash fired, auto mode, return light not detected', 243 | 0x001f: 'Flash fired, auto mode, return light detected', 244 | 0x0020: 'No flash function', 245 | 0x0041: 'Flash fired, red-eye reduction mode', 246 | 0x0045: 'Flash fired, red-eye reduction mode, return light not detected', 247 | 0x0047: 'Flash fired, red-eye reduction mode, return light detected', 248 | 0x0049: 'Flash fired, compulsory flash mode, red-eye reduction mode', 249 | 0x004d: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected', 250 | 0x004f: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected', 251 | 0x0059: 'Flash fired, auto mode, red-eye reduction mode', 252 | 0x005d: 'Flash fired, auto mode, return light not detected, red-eye reduction mode', 253 | 0x005f: 'Flash fired, auto mode, return light detected, red-eye reduction mode' 254 | }, 255 | SensingMethod: { 256 | 1: 'Undefined', 257 | 2: 'One-chip color area sensor', 258 | 3: 'Two-chip color area sensor', 259 | 4: 'Three-chip color area sensor', 260 | 5: 'Color sequential area sensor', 261 | 7: 'Trilinear sensor', 262 | 8: 'Color sequential linear sensor' 263 | }, 264 | SceneCaptureType: { 265 | 0: 'Standard', 266 | 1: 'Landscape', 267 | 2: 'Portrait', 268 | 3: 'Night scene' 269 | }, 270 | SceneType: { 271 | 1: 'Directly photographed' 272 | }, 273 | CustomRendered: { 274 | 0: 'Normal process', 275 | 1: 'Custom process' 276 | }, 277 | WhiteBalance: { 278 | 0: 'Auto white balance', 279 | 1: 'Manual white balance' 280 | }, 281 | GainControl: { 282 | 0: 'None', 283 | 1: 'Low gain up', 284 | 2: 'High gain up', 285 | 3: 'Low gain down', 286 | 4: 'High gain down' 287 | }, 288 | Contrast: { 289 | 0: 'Normal', 290 | 1: 'Soft', 291 | 2: 'Hard' 292 | }, 293 | Saturation: { 294 | 0: 'Normal', 295 | 1: 'Low saturation', 296 | 2: 'High saturation' 297 | }, 298 | Sharpness: { 299 | 0: 'Normal', 300 | 1: 'Soft', 301 | 2: 'Hard' 302 | }, 303 | SubjectDistanceRange: { 304 | 0: 'Unknown', 305 | 1: 'Macro', 306 | 2: 'Close view', 307 | 3: 'Distant view' 308 | }, 309 | FileSource: { 310 | 3: 'DSC' 311 | }, 312 | ComponentsConfiguration: { 313 | 0: '', 314 | 1: 'Y', 315 | 2: 'Cb', 316 | 3: 'Cr', 317 | 4: 'R', 318 | 5: 'G', 319 | 6: 'B' 320 | }, 321 | Orientation: { 322 | 1: 'Original', 323 | 2: 'Horizontal flip', 324 | 3: 'Rotate 180° CCW', 325 | 4: 'Vertical flip', 326 | 5: 'Vertical flip + Rotate 90° CW', 327 | 6: 'Rotate 90° CW', 328 | 7: 'Horizontal flip + Rotate 90° CW', 329 | 8: 'Rotate 90° CCW' 330 | } 331 | } 332 | 333 | ExifMapProto.getText = function (name) { 334 | var value = this.get(name) 335 | switch (name) { 336 | case 'LightSource': 337 | case 'Flash': 338 | case 'MeteringMode': 339 | case 'ExposureProgram': 340 | case 'SensingMethod': 341 | case 'SceneCaptureType': 342 | case 'SceneType': 343 | case 'CustomRendered': 344 | case 'WhiteBalance': 345 | case 'GainControl': 346 | case 'Contrast': 347 | case 'Saturation': 348 | case 'Sharpness': 349 | case 'SubjectDistanceRange': 350 | case 'FileSource': 351 | case 'Orientation': 352 | return this.stringValues[name][value] 353 | case 'ExifVersion': 354 | case 'FlashpixVersion': 355 | if (!value) return 356 | return String.fromCharCode(value[0], value[1], value[2], value[3]) 357 | case 'ComponentsConfiguration': 358 | if (!value) return 359 | return ( 360 | this.stringValues[name][value[0]] + 361 | this.stringValues[name][value[1]] + 362 | this.stringValues[name][value[2]] + 363 | this.stringValues[name][value[3]] 364 | ) 365 | case 'GPSVersionID': 366 | if (!value) return 367 | return value[0] + '.' + value[1] + '.' + value[2] + '.' + value[3] 368 | } 369 | return String(value) 370 | } 371 | 372 | ExifMapProto.getAll = function () { 373 | var map = {} 374 | var prop 375 | var obj 376 | var name 377 | for (prop in this) { 378 | if (Object.prototype.hasOwnProperty.call(this, prop)) { 379 | obj = this[prop] 380 | if (obj && obj.getAll) { 381 | map[this.ifds[prop].name] = obj.getAll() 382 | } else { 383 | name = this.tags[prop] 384 | if (name) map[name] = this.getText(name) 385 | } 386 | } 387 | } 388 | return map 389 | } 390 | 391 | ExifMapProto.getName = function (tagCode) { 392 | var name = this.tags[tagCode] 393 | if (typeof name === 'object') return this.ifds[tagCode].name 394 | return name 395 | } 396 | 397 | // Extend the map of tag names to tag codes: 398 | ;(function () { 399 | var tags = ExifMapProto.tags 400 | var prop 401 | var ifd 402 | var subTags 403 | // Map the tag names to tags: 404 | for (prop in tags) { 405 | if (Object.prototype.hasOwnProperty.call(tags, prop)) { 406 | ifd = ExifMapProto.ifds[prop] 407 | if (ifd) { 408 | subTags = tags[prop] 409 | for (prop in subTags) { 410 | if (Object.prototype.hasOwnProperty.call(subTags, prop)) { 411 | ifd.map[subTags[prop]] = Number(prop) 412 | } 413 | } 414 | } else { 415 | ExifMapProto.map[tags[prop]] = Number(prop) 416 | } 417 | } 418 | } 419 | })() 420 | }) 421 | -------------------------------------------------------------------------------- /node_modules/blueimp-load-image/js/load-image-exif.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JavaScript Load Image Exif Parser 3 | * https://github.com/blueimp/JavaScript-Load-Image 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* global define, module, require, DataView */ 13 | 14 | /* eslint-disable no-console */ 15 | 16 | ;(function (factory) { 17 | 'use strict' 18 | if (typeof define === 'function' && define.amd) { 19 | // Register as an anonymous AMD module: 20 | define(['./load-image', './load-image-meta'], factory) 21 | } else if (typeof module === 'object' && module.exports) { 22 | factory(require('./load-image'), require('./load-image-meta')) 23 | } else { 24 | // Browser globals: 25 | factory(window.loadImage) 26 | } 27 | })(function (loadImage) { 28 | 'use strict' 29 | 30 | /** 31 | * Exif tag map 32 | * 33 | * @name ExifMap 34 | * @class 35 | * @param {number|string} tagCode IFD tag code 36 | */ 37 | function ExifMap(tagCode) { 38 | if (tagCode) { 39 | Object.defineProperty(this, 'map', { 40 | value: this.ifds[tagCode].map 41 | }) 42 | Object.defineProperty(this, 'tags', { 43 | value: (this.tags && this.tags[tagCode]) || {} 44 | }) 45 | } 46 | } 47 | 48 | ExifMap.prototype.map = { 49 | Orientation: 0x0112, 50 | Thumbnail: 'ifd1', 51 | Blob: 0x0201, // Alias for JPEGInterchangeFormat 52 | Exif: 0x8769, 53 | GPSInfo: 0x8825, 54 | Interoperability: 0xa005 55 | } 56 | 57 | ExifMap.prototype.ifds = { 58 | ifd1: { name: 'Thumbnail', map: ExifMap.prototype.map }, 59 | 0x8769: { name: 'Exif', map: {} }, 60 | 0x8825: { name: 'GPSInfo', map: {} }, 61 | 0xa005: { name: 'Interoperability', map: {} } 62 | } 63 | 64 | /** 65 | * Retrieves exif tag value 66 | * 67 | * @param {number|string} id Exif tag code or name 68 | * @returns {object} Exif tag value 69 | */ 70 | ExifMap.prototype.get = function (id) { 71 | return this[id] || this[this.map[id]] 72 | } 73 | 74 | /** 75 | * Returns the Exif Thumbnail data as Blob. 76 | * 77 | * @param {DataView} dataView Data view interface 78 | * @param {number} offset Thumbnail data offset 79 | * @param {number} length Thumbnail data length 80 | * @returns {undefined|Blob} Returns the Thumbnail Blob or undefined 81 | */ 82 | function getExifThumbnail(dataView, offset, length) { 83 | if (!length) return 84 | if (offset + length > dataView.byteLength) { 85 | console.log('Invalid Exif data: Invalid thumbnail data.') 86 | return 87 | } 88 | return new Blob( 89 | [loadImage.bufferSlice.call(dataView.buffer, offset, offset + length)], 90 | { 91 | type: 'image/jpeg' 92 | } 93 | ) 94 | } 95 | 96 | var ExifTagTypes = { 97 | // byte, 8-bit unsigned int: 98 | 1: { 99 | getValue: function (dataView, dataOffset) { 100 | return dataView.getUint8(dataOffset) 101 | }, 102 | size: 1 103 | }, 104 | // ascii, 8-bit byte: 105 | 2: { 106 | getValue: function (dataView, dataOffset) { 107 | return String.fromCharCode(dataView.getUint8(dataOffset)) 108 | }, 109 | size: 1, 110 | ascii: true 111 | }, 112 | // short, 16 bit int: 113 | 3: { 114 | getValue: function (dataView, dataOffset, littleEndian) { 115 | return dataView.getUint16(dataOffset, littleEndian) 116 | }, 117 | size: 2 118 | }, 119 | // long, 32 bit int: 120 | 4: { 121 | getValue: function (dataView, dataOffset, littleEndian) { 122 | return dataView.getUint32(dataOffset, littleEndian) 123 | }, 124 | size: 4 125 | }, 126 | // rational = two long values, first is numerator, second is denominator: 127 | 5: { 128 | getValue: function (dataView, dataOffset, littleEndian) { 129 | return ( 130 | dataView.getUint32(dataOffset, littleEndian) / 131 | dataView.getUint32(dataOffset + 4, littleEndian) 132 | ) 133 | }, 134 | size: 8 135 | }, 136 | // slong, 32 bit signed int: 137 | 9: { 138 | getValue: function (dataView, dataOffset, littleEndian) { 139 | return dataView.getInt32(dataOffset, littleEndian) 140 | }, 141 | size: 4 142 | }, 143 | // srational, two slongs, first is numerator, second is denominator: 144 | 10: { 145 | getValue: function (dataView, dataOffset, littleEndian) { 146 | return ( 147 | dataView.getInt32(dataOffset, littleEndian) / 148 | dataView.getInt32(dataOffset + 4, littleEndian) 149 | ) 150 | }, 151 | size: 8 152 | } 153 | } 154 | // undefined, 8-bit byte, value depending on field: 155 | ExifTagTypes[7] = ExifTagTypes[1] 156 | 157 | /** 158 | * Returns Exif tag value. 159 | * 160 | * @param {DataView} dataView Data view interface 161 | * @param {number} tiffOffset TIFF offset 162 | * @param {number} offset Tag offset 163 | * @param {number} type Tag type 164 | * @param {number} length Tag length 165 | * @param {boolean} littleEndian Little endian encoding 166 | * @returns {object} Tag value 167 | */ 168 | function getExifValue( 169 | dataView, 170 | tiffOffset, 171 | offset, 172 | type, 173 | length, 174 | littleEndian 175 | ) { 176 | var tagType = ExifTagTypes[type] 177 | var tagSize 178 | var dataOffset 179 | var values 180 | var i 181 | var str 182 | var c 183 | if (!tagType) { 184 | console.log('Invalid Exif data: Invalid tag type.') 185 | return 186 | } 187 | tagSize = tagType.size * length 188 | // Determine if the value is contained in the dataOffset bytes, 189 | // or if the value at the dataOffset is a pointer to the actual data: 190 | dataOffset = 191 | tagSize > 4 192 | ? tiffOffset + dataView.getUint32(offset + 8, littleEndian) 193 | : offset + 8 194 | if (dataOffset + tagSize > dataView.byteLength) { 195 | console.log('Invalid Exif data: Invalid data offset.') 196 | return 197 | } 198 | if (length === 1) { 199 | return tagType.getValue(dataView, dataOffset, littleEndian) 200 | } 201 | values = [] 202 | for (i = 0; i < length; i += 1) { 203 | values[i] = tagType.getValue( 204 | dataView, 205 | dataOffset + i * tagType.size, 206 | littleEndian 207 | ) 208 | } 209 | if (tagType.ascii) { 210 | str = '' 211 | // Concatenate the chars: 212 | for (i = 0; i < values.length; i += 1) { 213 | c = values[i] 214 | // Ignore the terminating NULL byte(s): 215 | if (c === '\u0000') { 216 | break 217 | } 218 | str += c 219 | } 220 | return str 221 | } 222 | return values 223 | } 224 | 225 | /** 226 | * Determines if the given tag should be included. 227 | * 228 | * @param {object} includeTags Map of tags to include 229 | * @param {object} excludeTags Map of tags to exclude 230 | * @param {number|string} tagCode Tag code to check 231 | * @returns {boolean} True if the tag should be included 232 | */ 233 | function shouldIncludeTag(includeTags, excludeTags, tagCode) { 234 | return ( 235 | (!includeTags || includeTags[tagCode]) && 236 | (!excludeTags || excludeTags[tagCode] !== true) 237 | ) 238 | } 239 | 240 | /** 241 | * Parses Exif tags. 242 | * 243 | * @param {DataView} dataView Data view interface 244 | * @param {number} tiffOffset TIFF offset 245 | * @param {number} dirOffset Directory offset 246 | * @param {boolean} littleEndian Little endian encoding 247 | * @param {ExifMap} tags Map to store parsed exif tags 248 | * @param {ExifMap} tagOffsets Map to store parsed exif tag offsets 249 | * @param {object} includeTags Map of tags to include 250 | * @param {object} excludeTags Map of tags to exclude 251 | * @returns {number} Next directory offset 252 | */ 253 | function parseExifTags( 254 | dataView, 255 | tiffOffset, 256 | dirOffset, 257 | littleEndian, 258 | tags, 259 | tagOffsets, 260 | includeTags, 261 | excludeTags 262 | ) { 263 | var tagsNumber, dirEndOffset, i, tagOffset, tagNumber, tagValue 264 | if (dirOffset + 6 > dataView.byteLength) { 265 | console.log('Invalid Exif data: Invalid directory offset.') 266 | return 267 | } 268 | tagsNumber = dataView.getUint16(dirOffset, littleEndian) 269 | dirEndOffset = dirOffset + 2 + 12 * tagsNumber 270 | if (dirEndOffset + 4 > dataView.byteLength) { 271 | console.log('Invalid Exif data: Invalid directory size.') 272 | return 273 | } 274 | for (i = 0; i < tagsNumber; i += 1) { 275 | tagOffset = dirOffset + 2 + 12 * i 276 | tagNumber = dataView.getUint16(tagOffset, littleEndian) 277 | if (!shouldIncludeTag(includeTags, excludeTags, tagNumber)) continue 278 | tagValue = getExifValue( 279 | dataView, 280 | tiffOffset, 281 | tagOffset, 282 | dataView.getUint16(tagOffset + 2, littleEndian), // tag type 283 | dataView.getUint32(tagOffset + 4, littleEndian), // tag length 284 | littleEndian 285 | ) 286 | tags[tagNumber] = tagValue 287 | if (tagOffsets) { 288 | tagOffsets[tagNumber] = tagOffset 289 | } 290 | } 291 | // Return the offset to the next directory: 292 | return dataView.getUint32(dirEndOffset, littleEndian) 293 | } 294 | 295 | /** 296 | * Parses tags in a given IFD (Image File Directory). 297 | * 298 | * @param {object} data Data object to store exif tags and offsets 299 | * @param {number|string} tagCode IFD tag code 300 | * @param {DataView} dataView Data view interface 301 | * @param {number} tiffOffset TIFF offset 302 | * @param {boolean} littleEndian Little endian encoding 303 | * @param {object} includeTags Map of tags to include 304 | * @param {object} excludeTags Map of tags to exclude 305 | */ 306 | function parseExifIFD( 307 | data, 308 | tagCode, 309 | dataView, 310 | tiffOffset, 311 | littleEndian, 312 | includeTags, 313 | excludeTags 314 | ) { 315 | var dirOffset = data.exif[tagCode] 316 | if (dirOffset) { 317 | data.exif[tagCode] = new ExifMap(tagCode) 318 | if (data.exifOffsets) { 319 | data.exifOffsets[tagCode] = new ExifMap(tagCode) 320 | } 321 | parseExifTags( 322 | dataView, 323 | tiffOffset, 324 | tiffOffset + dirOffset, 325 | littleEndian, 326 | data.exif[tagCode], 327 | data.exifOffsets && data.exifOffsets[tagCode], 328 | includeTags && includeTags[tagCode], 329 | excludeTags && excludeTags[tagCode] 330 | ) 331 | } 332 | } 333 | 334 | loadImage.parseExifData = function (dataView, offset, length, data, options) { 335 | if (options.disableExif) { 336 | return 337 | } 338 | var includeTags = options.includeExifTags 339 | var excludeTags = options.excludeExifTags || { 340 | 0x8769: { 341 | // ExifIFDPointer 342 | 0x927c: true // MakerNote 343 | } 344 | } 345 | var tiffOffset = offset + 10 346 | var littleEndian 347 | var dirOffset 348 | var thumbnailIFD 349 | // Check for the ASCII code for "Exif" (0x45786966): 350 | if (dataView.getUint32(offset + 4) !== 0x45786966) { 351 | // No Exif data, might be XMP data instead 352 | return 353 | } 354 | if (tiffOffset + 8 > dataView.byteLength) { 355 | console.log('Invalid Exif data: Invalid segment size.') 356 | return 357 | } 358 | // Check for the two null bytes: 359 | if (dataView.getUint16(offset + 8) !== 0x0000) { 360 | console.log('Invalid Exif data: Missing byte alignment offset.') 361 | return 362 | } 363 | // Check the byte alignment: 364 | switch (dataView.getUint16(tiffOffset)) { 365 | case 0x4949: 366 | littleEndian = true 367 | break 368 | case 0x4d4d: 369 | littleEndian = false 370 | break 371 | default: 372 | console.log('Invalid Exif data: Invalid byte alignment marker.') 373 | return 374 | } 375 | // Check for the TIFF tag marker (0x002A): 376 | if (dataView.getUint16(tiffOffset + 2, littleEndian) !== 0x002a) { 377 | console.log('Invalid Exif data: Missing TIFF marker.') 378 | return 379 | } 380 | // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal: 381 | dirOffset = dataView.getUint32(tiffOffset + 4, littleEndian) 382 | // Create the exif object to store the tags: 383 | data.exif = new ExifMap() 384 | if (!options.disableExifOffsets) { 385 | data.exifOffsets = new ExifMap() 386 | data.exifTiffOffset = tiffOffset 387 | data.exifLittleEndian = littleEndian 388 | } 389 | // Parse the tags of the main image directory (IFD0) and retrieve the 390 | // offset to the next directory (IFD1), usually the thumbnail directory: 391 | dirOffset = parseExifTags( 392 | dataView, 393 | tiffOffset, 394 | tiffOffset + dirOffset, 395 | littleEndian, 396 | data.exif, 397 | data.exifOffsets, 398 | includeTags, 399 | excludeTags 400 | ) 401 | if (dirOffset && shouldIncludeTag(includeTags, excludeTags, 'ifd1')) { 402 | data.exif.ifd1 = dirOffset 403 | if (data.exifOffsets) { 404 | data.exifOffsets.ifd1 = tiffOffset + dirOffset 405 | } 406 | } 407 | Object.keys(data.exif.ifds).forEach(function (tagCode) { 408 | parseExifIFD( 409 | data, 410 | tagCode, 411 | dataView, 412 | tiffOffset, 413 | littleEndian, 414 | includeTags, 415 | excludeTags 416 | ) 417 | }) 418 | thumbnailIFD = data.exif.ifd1 419 | // Check for JPEG Thumbnail offset and data length: 420 | if (thumbnailIFD && thumbnailIFD[0x0201]) { 421 | thumbnailIFD[0x0201] = getExifThumbnail( 422 | dataView, 423 | tiffOffset + thumbnailIFD[0x0201], 424 | thumbnailIFD[0x0202] // Thumbnail data length 425 | ) 426 | } 427 | } 428 | 429 | // Registers the Exif parser for the APP1 JPEG metadata segment: 430 | loadImage.metaDataParsers.jpeg[0xffe1].push(loadImage.parseExifData) 431 | 432 | loadImage.exifWriters = { 433 | // Orientation writer: 434 | 0x0112: function (buffer, data, value) { 435 | var orientationOffset = data.exifOffsets[0x0112] 436 | if (!orientationOffset) return buffer 437 | var view = new DataView(buffer, orientationOffset + 8, 2) 438 | view.setUint16(0, value, data.exifLittleEndian) 439 | return buffer 440 | } 441 | } 442 | 443 | loadImage.writeExifData = function (buffer, data, id, value) { 444 | return loadImage.exifWriters[data.exif.map[id]](buffer, data, value) 445 | } 446 | 447 | loadImage.ExifMap = ExifMap 448 | 449 | // Adds the following properties to the parseMetaData callback data: 450 | // - exif: The parsed Exif tags 451 | // - exifOffsets: The parsed Exif tag offsets 452 | // - exifTiffOffset: TIFF header offset (used for offset pointers) 453 | // - exifLittleEndian: little endian order if true, big endian if false 454 | 455 | // Adds the following options to the parseMetaData method: 456 | // - disableExif: Disables Exif parsing when true. 457 | // - disableExifOffsets: Disables storing Exif tag offsets when true. 458 | // - includeExifTags: A map of Exif tags to include for parsing. 459 | // - excludeExifTags: A map of Exif tags to exclude from parsing. 460 | }) 461 | -------------------------------------------------------------------------------- /node_modules/blueimp-load-image/js/load-image-fetch.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JavaScript Load Image Fetch 3 | * https://github.com/blueimp/JavaScript-Load-Image 4 | * 5 | * Copyright 2017, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* global define, module, require, Promise */ 13 | 14 | ;(function (factory) { 15 | 'use strict' 16 | if (typeof define === 'function' && define.amd) { 17 | // Register as an anonymous AMD module: 18 | define(['./load-image'], factory) 19 | } else if (typeof module === 'object' && module.exports) { 20 | factory(require('./load-image')) 21 | } else { 22 | // Browser globals: 23 | factory(window.loadImage) 24 | } 25 | })(function (loadImage) { 26 | 'use strict' 27 | 28 | var global = loadImage.global 29 | 30 | if ( 31 | global.fetch && 32 | global.Request && 33 | global.Response && 34 | global.Response.prototype.blob 35 | ) { 36 | loadImage.fetchBlob = function (url, callback, options) { 37 | /** 38 | * Fetch response handler. 39 | * 40 | * @param {Response} response Fetch response 41 | * @returns {Blob} Fetched Blob. 42 | */ 43 | function responseHandler(response) { 44 | return response.blob() 45 | } 46 | if (global.Promise && typeof callback !== 'function') { 47 | return fetch(new Request(url, callback)).then(responseHandler) 48 | } 49 | fetch(new Request(url, options)) 50 | .then(responseHandler) 51 | .then(callback) 52 | [ 53 | // Avoid parsing error in IE<9, where catch is a reserved word. 54 | // eslint-disable-next-line dot-notation 55 | 'catch' 56 | ](function (err) { 57 | callback(null, err) 58 | }) 59 | } 60 | } else if ( 61 | global.XMLHttpRequest && 62 | // https://xhr.spec.whatwg.org/#the-responsetype-attribute 63 | new XMLHttpRequest().responseType === '' 64 | ) { 65 | loadImage.fetchBlob = function (url, callback, options) { 66 | /** 67 | * Promise executor 68 | * 69 | * @param {Function} resolve Resolution function 70 | * @param {Function} reject Rejection function 71 | */ 72 | function executor(resolve, reject) { 73 | options = options || {} // eslint-disable-line no-param-reassign 74 | var req = new XMLHttpRequest() 75 | req.open(options.method || 'GET', url) 76 | if (options.headers) { 77 | Object.keys(options.headers).forEach(function (key) { 78 | req.setRequestHeader(key, options.headers[key]) 79 | }) 80 | } 81 | req.withCredentials = options.credentials === 'include' 82 | req.responseType = 'blob' 83 | req.onload = function () { 84 | resolve(req.response) 85 | } 86 | req.onerror = req.onabort = req.ontimeout = function (err) { 87 | if (resolve === reject) { 88 | // Not using Promises 89 | reject(null, err) 90 | } else { 91 | reject(err) 92 | } 93 | } 94 | req.send(options.body) 95 | } 96 | if (global.Promise && typeof callback !== 'function') { 97 | options = callback // eslint-disable-line no-param-reassign 98 | return new Promise(executor) 99 | } 100 | return executor(callback, callback) 101 | } 102 | } 103 | }) 104 | -------------------------------------------------------------------------------- /node_modules/blueimp-load-image/js/load-image-iptc-map.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JavaScript Load Image IPTC Map 3 | * https://github.com/blueimp/JavaScript-Load-Image 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * Copyright 2018, Dave Bevan 7 | * 8 | * IPTC tags mapping based on 9 | * https://iptc.org/standards/photo-metadata 10 | * https://exiftool.org/TagNames/IPTC.html 11 | * 12 | * Licensed under the MIT license: 13 | * https://opensource.org/licenses/MIT 14 | */ 15 | 16 | /* global define, module, require */ 17 | 18 | ;(function (factory) { 19 | 'use strict' 20 | if (typeof define === 'function' && define.amd) { 21 | // Register as an anonymous AMD module: 22 | define(['./load-image', './load-image-iptc'], factory) 23 | } else if (typeof module === 'object' && module.exports) { 24 | factory(require('./load-image'), require('./load-image-iptc')) 25 | } else { 26 | // Browser globals: 27 | factory(window.loadImage) 28 | } 29 | })(function (loadImage) { 30 | 'use strict' 31 | 32 | var IptcMapProto = loadImage.IptcMap.prototype 33 | 34 | IptcMapProto.tags = { 35 | 0: 'ApplicationRecordVersion', 36 | 3: 'ObjectTypeReference', 37 | 4: 'ObjectAttributeReference', 38 | 5: 'ObjectName', 39 | 7: 'EditStatus', 40 | 8: 'EditorialUpdate', 41 | 10: 'Urgency', 42 | 12: 'SubjectReference', 43 | 15: 'Category', 44 | 20: 'SupplementalCategories', 45 | 22: 'FixtureIdentifier', 46 | 25: 'Keywords', 47 | 26: 'ContentLocationCode', 48 | 27: 'ContentLocationName', 49 | 30: 'ReleaseDate', 50 | 35: 'ReleaseTime', 51 | 37: 'ExpirationDate', 52 | 38: 'ExpirationTime', 53 | 40: 'SpecialInstructions', 54 | 42: 'ActionAdvised', 55 | 45: 'ReferenceService', 56 | 47: 'ReferenceDate', 57 | 50: 'ReferenceNumber', 58 | 55: 'DateCreated', 59 | 60: 'TimeCreated', 60 | 62: 'DigitalCreationDate', 61 | 63: 'DigitalCreationTime', 62 | 65: 'OriginatingProgram', 63 | 70: 'ProgramVersion', 64 | 75: 'ObjectCycle', 65 | 80: 'Byline', 66 | 85: 'BylineTitle', 67 | 90: 'City', 68 | 92: 'Sublocation', 69 | 95: 'State', 70 | 100: 'CountryCode', 71 | 101: 'Country', 72 | 103: 'OriginalTransmissionReference', 73 | 105: 'Headline', 74 | 110: 'Credit', 75 | 115: 'Source', 76 | 116: 'CopyrightNotice', 77 | 118: 'Contact', 78 | 120: 'Caption', 79 | 121: 'LocalCaption', 80 | 122: 'Writer', 81 | 125: 'RasterizedCaption', 82 | 130: 'ImageType', 83 | 131: 'ImageOrientation', 84 | 135: 'LanguageIdentifier', 85 | 150: 'AudioType', 86 | 151: 'AudioSamplingRate', 87 | 152: 'AudioSamplingResolution', 88 | 153: 'AudioDuration', 89 | 154: 'AudioOutcue', 90 | 184: 'JobID', 91 | 185: 'MasterDocumentID', 92 | 186: 'ShortDocumentID', 93 | 187: 'UniqueDocumentID', 94 | 188: 'OwnerID', 95 | 200: 'ObjectPreviewFileFormat', 96 | 201: 'ObjectPreviewFileVersion', 97 | 202: 'ObjectPreviewData', 98 | 221: 'Prefs', 99 | 225: 'ClassifyState', 100 | 228: 'SimilarityIndex', 101 | 230: 'DocumentNotes', 102 | 231: 'DocumentHistory', 103 | 232: 'ExifCameraInfo', 104 | 255: 'CatalogSets' 105 | } 106 | 107 | IptcMapProto.stringValues = { 108 | 10: { 109 | 0: '0 (reserved)', 110 | 1: '1 (most urgent)', 111 | 2: '2', 112 | 3: '3', 113 | 4: '4', 114 | 5: '5 (normal urgency)', 115 | 6: '6', 116 | 7: '7', 117 | 8: '8 (least urgent)', 118 | 9: '9 (user-defined priority)' 119 | }, 120 | 75: { 121 | a: 'Morning', 122 | b: 'Both Morning and Evening', 123 | p: 'Evening' 124 | }, 125 | 131: { 126 | L: 'Landscape', 127 | P: 'Portrait', 128 | S: 'Square' 129 | } 130 | } 131 | 132 | IptcMapProto.getText = function (id) { 133 | var value = this.get(id) 134 | var tagCode = this.map[id] 135 | var stringValue = this.stringValues[tagCode] 136 | if (stringValue) return stringValue[value] 137 | return String(value) 138 | } 139 | 140 | IptcMapProto.getAll = function () { 141 | var map = {} 142 | var prop 143 | var name 144 | for (prop in this) { 145 | if (Object.prototype.hasOwnProperty.call(this, prop)) { 146 | name = this.tags[prop] 147 | if (name) map[name] = this.getText(name) 148 | } 149 | } 150 | return map 151 | } 152 | 153 | IptcMapProto.getName = function (tagCode) { 154 | return this.tags[tagCode] 155 | } 156 | 157 | // Extend the map of tag names to tag codes: 158 | ;(function () { 159 | var tags = IptcMapProto.tags 160 | var map = IptcMapProto.map || {} 161 | var prop 162 | // Map the tag names to tags: 163 | for (prop in tags) { 164 | if (Object.prototype.hasOwnProperty.call(tags, prop)) { 165 | map[tags[prop]] = Number(prop) 166 | } 167 | } 168 | })() 169 | }) 170 | -------------------------------------------------------------------------------- /node_modules/blueimp-load-image/js/load-image-iptc.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JavaScript Load Image IPTC Parser 3 | * https://github.com/blueimp/JavaScript-Load-Image 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * Copyright 2018, Dave Bevan 7 | * https://blueimp.net 8 | * 9 | * Licensed under the MIT license: 10 | * https://opensource.org/licenses/MIT 11 | */ 12 | 13 | /* global define, module, require, DataView */ 14 | 15 | ;(function (factory) { 16 | 'use strict' 17 | if (typeof define === 'function' && define.amd) { 18 | // Register as an anonymous AMD module: 19 | define(['./load-image', './load-image-meta'], factory) 20 | } else if (typeof module === 'object' && module.exports) { 21 | factory(require('./load-image'), require('./load-image-meta')) 22 | } else { 23 | // Browser globals: 24 | factory(window.loadImage) 25 | } 26 | })(function (loadImage) { 27 | 'use strict' 28 | 29 | /** 30 | * IPTC tag map 31 | * 32 | * @name IptcMap 33 | * @class 34 | */ 35 | function IptcMap() {} 36 | 37 | IptcMap.prototype.map = { 38 | ObjectName: 5 39 | } 40 | 41 | IptcMap.prototype.types = { 42 | 0: 'Uint16', // ApplicationRecordVersion 43 | 200: 'Uint16', // ObjectPreviewFileFormat 44 | 201: 'Uint16', // ObjectPreviewFileVersion 45 | 202: 'binary' // ObjectPreviewData 46 | } 47 | 48 | /** 49 | * Retrieves IPTC tag value 50 | * 51 | * @param {number|string} id IPTC tag code or name 52 | * @returns {object} IPTC tag value 53 | */ 54 | IptcMap.prototype.get = function (id) { 55 | return this[id] || this[this.map[id]] 56 | } 57 | 58 | /** 59 | * Retrieves string for the given DataView and range 60 | * 61 | * @param {DataView} dataView Data view interface 62 | * @param {number} offset Offset start 63 | * @param {number} length Offset length 64 | * @returns {string} String value 65 | */ 66 | function getStringValue(dataView, offset, length) { 67 | var outstr = '' 68 | var end = offset + length 69 | for (var n = offset; n < end; n += 1) { 70 | outstr += String.fromCharCode(dataView.getUint8(n)) 71 | } 72 | return outstr 73 | } 74 | 75 | /** 76 | * Retrieves tag value for the given DataView and range 77 | * 78 | * @param {number} tagCode tag code 79 | * @param {IptcMap} map IPTC tag map 80 | * @param {DataView} dataView Data view interface 81 | * @param {number} offset Range start 82 | * @param {number} length Range length 83 | * @returns {object} Tag value 84 | */ 85 | function getTagValue(tagCode, map, dataView, offset, length) { 86 | if (map.types[tagCode] === 'binary') { 87 | return new Blob([dataView.buffer.slice(offset, offset + length)]) 88 | } 89 | if (map.types[tagCode] === 'Uint16') { 90 | return dataView.getUint16(offset) 91 | } 92 | return getStringValue(dataView, offset, length) 93 | } 94 | 95 | /** 96 | * Combines IPTC value with existing ones. 97 | * 98 | * @param {object} value Existing IPTC field value 99 | * @param {object} newValue New IPTC field value 100 | * @returns {object} Resulting IPTC field value 101 | */ 102 | function combineTagValues(value, newValue) { 103 | if (value === undefined) return newValue 104 | if (value instanceof Array) { 105 | value.push(newValue) 106 | return value 107 | } 108 | return [value, newValue] 109 | } 110 | 111 | /** 112 | * Parses IPTC tags. 113 | * 114 | * @param {DataView} dataView Data view interface 115 | * @param {number} segmentOffset Segment offset 116 | * @param {number} segmentLength Segment length 117 | * @param {object} data Data export object 118 | * @param {object} includeTags Map of tags to include 119 | * @param {object} excludeTags Map of tags to exclude 120 | */ 121 | function parseIptcTags( 122 | dataView, 123 | segmentOffset, 124 | segmentLength, 125 | data, 126 | includeTags, 127 | excludeTags 128 | ) { 129 | var value, tagSize, tagCode 130 | var segmentEnd = segmentOffset + segmentLength 131 | var offset = segmentOffset 132 | while (offset < segmentEnd) { 133 | if ( 134 | dataView.getUint8(offset) === 0x1c && // tag marker 135 | dataView.getUint8(offset + 1) === 0x02 // record number, only handles v2 136 | ) { 137 | tagCode = dataView.getUint8(offset + 2) 138 | if ( 139 | (!includeTags || includeTags[tagCode]) && 140 | (!excludeTags || !excludeTags[tagCode]) 141 | ) { 142 | tagSize = dataView.getInt16(offset + 3) 143 | value = getTagValue(tagCode, data.iptc, dataView, offset + 5, tagSize) 144 | data.iptc[tagCode] = combineTagValues(data.iptc[tagCode], value) 145 | if (data.iptcOffsets) { 146 | data.iptcOffsets[tagCode] = offset 147 | } 148 | } 149 | } 150 | offset += 1 151 | } 152 | } 153 | 154 | /** 155 | * Tests if field segment starts at offset. 156 | * 157 | * @param {DataView} dataView Data view interface 158 | * @param {number} offset Segment offset 159 | * @returns {boolean} True if '8BIM' exists at offset 160 | */ 161 | function isSegmentStart(dataView, offset) { 162 | return ( 163 | dataView.getUint32(offset) === 0x3842494d && // Photoshop segment start 164 | dataView.getUint16(offset + 4) === 0x0404 // IPTC segment start 165 | ) 166 | } 167 | 168 | /** 169 | * Returns header length. 170 | * 171 | * @param {DataView} dataView Data view interface 172 | * @param {number} offset Segment offset 173 | * @returns {number} Header length 174 | */ 175 | function getHeaderLength(dataView, offset) { 176 | var length = dataView.getUint8(offset + 7) 177 | if (length % 2 !== 0) length += 1 178 | // Check for pre photoshop 6 format 179 | if (length === 0) { 180 | // Always 4 181 | length = 4 182 | } 183 | return length 184 | } 185 | 186 | loadImage.parseIptcData = function (dataView, offset, length, data, options) { 187 | if (options.disableIptc) { 188 | return 189 | } 190 | var markerLength = offset + length 191 | while (offset + 8 < markerLength) { 192 | if (isSegmentStart(dataView, offset)) { 193 | var headerLength = getHeaderLength(dataView, offset) 194 | var segmentOffset = offset + 8 + headerLength 195 | if (segmentOffset > markerLength) { 196 | // eslint-disable-next-line no-console 197 | console.log('Invalid IPTC data: Invalid segment offset.') 198 | break 199 | } 200 | var segmentLength = dataView.getUint16(offset + 6 + headerLength) 201 | if (offset + segmentLength > markerLength) { 202 | // eslint-disable-next-line no-console 203 | console.log('Invalid IPTC data: Invalid segment size.') 204 | break 205 | } 206 | // Create the iptc object to store the tags: 207 | data.iptc = new IptcMap() 208 | if (!options.disableIptcOffsets) { 209 | data.iptcOffsets = new IptcMap() 210 | } 211 | parseIptcTags( 212 | dataView, 213 | segmentOffset, 214 | segmentLength, 215 | data, 216 | options.includeIptcTags, 217 | options.excludeIptcTags || { 202: true } // ObjectPreviewData 218 | ) 219 | return 220 | } 221 | // eslint-disable-next-line no-param-reassign 222 | offset += 1 223 | } 224 | } 225 | 226 | // Registers this IPTC parser for the APP13 JPEG metadata segment: 227 | loadImage.metaDataParsers.jpeg[0xffed].push(loadImage.parseIptcData) 228 | 229 | loadImage.IptcMap = IptcMap 230 | 231 | // Adds the following properties to the parseMetaData callback data: 232 | // - iptc: The iptc tags, parsed by the parseIptcData method 233 | 234 | // Adds the following options to the parseMetaData method: 235 | // - disableIptc: Disables IPTC parsing when true. 236 | // - disableIptcOffsets: Disables storing IPTC tag offsets when true. 237 | // - includeIptcTags: A map of IPTC tags to include for parsing. 238 | // - excludeIptcTags: A map of IPTC tags to exclude from parsing. 239 | }) 240 | -------------------------------------------------------------------------------- /node_modules/blueimp-load-image/js/load-image-meta.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JavaScript Load Image Meta 3 | * https://github.com/blueimp/JavaScript-Load-Image 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Image metadata handling implementation 9 | * based on the help and contribution of 10 | * Achim Stöhr. 11 | * 12 | * Licensed under the MIT license: 13 | * https://opensource.org/licenses/MIT 14 | */ 15 | 16 | /* global define, module, require, Promise, DataView, Uint8Array, ArrayBuffer */ 17 | 18 | ;(function (factory) { 19 | 'use strict' 20 | if (typeof define === 'function' && define.amd) { 21 | // Register as an anonymous AMD module: 22 | define(['./load-image'], factory) 23 | } else if (typeof module === 'object' && module.exports) { 24 | factory(require('./load-image')) 25 | } else { 26 | // Browser globals: 27 | factory(window.loadImage) 28 | } 29 | })(function (loadImage) { 30 | 'use strict' 31 | 32 | var global = loadImage.global 33 | var originalTransform = loadImage.transform 34 | 35 | var blobSlice = 36 | global.Blob && 37 | (Blob.prototype.slice || 38 | Blob.prototype.webkitSlice || 39 | Blob.prototype.mozSlice) 40 | 41 | var bufferSlice = 42 | (global.ArrayBuffer && ArrayBuffer.prototype.slice) || 43 | function (begin, end) { 44 | // Polyfill for IE10, which does not support ArrayBuffer.slice 45 | // eslint-disable-next-line no-param-reassign 46 | end = end || this.byteLength - begin 47 | var arr1 = new Uint8Array(this, begin, end) 48 | var arr2 = new Uint8Array(end) 49 | arr2.set(arr1) 50 | return arr2.buffer 51 | } 52 | 53 | var metaDataParsers = { 54 | jpeg: { 55 | 0xffe1: [], // APP1 marker 56 | 0xffed: [] // APP13 marker 57 | } 58 | } 59 | 60 | /** 61 | * Parses image metadata and calls the callback with an object argument 62 | * with the following property: 63 | * - imageHead: The complete image head as ArrayBuffer 64 | * The options argument accepts an object and supports the following 65 | * properties: 66 | * - maxMetaDataSize: Defines the maximum number of bytes to parse. 67 | * - disableImageHead: Disables creating the imageHead property. 68 | * 69 | * @param {Blob} file Blob object 70 | * @param {Function} [callback] Callback function 71 | * @param {object} [options] Parsing options 72 | * @param {object} [data] Result data object 73 | * @returns {Promise|undefined} Returns Promise if no callback given. 74 | */ 75 | function parseMetaData(file, callback, options, data) { 76 | var that = this 77 | /** 78 | * Promise executor 79 | * 80 | * @param {Function} resolve Resolution function 81 | * @param {Function} reject Rejection function 82 | * @returns {undefined} Undefined 83 | */ 84 | function executor(resolve, reject) { 85 | if ( 86 | !( 87 | global.DataView && 88 | blobSlice && 89 | file && 90 | file.size >= 12 && 91 | file.type === 'image/jpeg' 92 | ) 93 | ) { 94 | // Nothing to parse 95 | return resolve(data) 96 | } 97 | // 256 KiB should contain all EXIF/ICC/IPTC segments: 98 | var maxMetaDataSize = options.maxMetaDataSize || 262144 99 | if ( 100 | !loadImage.readFile( 101 | blobSlice.call(file, 0, maxMetaDataSize), 102 | function (buffer) { 103 | // Note on endianness: 104 | // Since the marker and length bytes in JPEG files are always 105 | // stored in big endian order, we can leave the endian parameter 106 | // of the DataView methods undefined, defaulting to big endian. 107 | var dataView = new DataView(buffer) 108 | // Check for the JPEG marker (0xffd8): 109 | if (dataView.getUint16(0) !== 0xffd8) { 110 | return reject( 111 | new Error('Invalid JPEG file: Missing JPEG marker.') 112 | ) 113 | } 114 | var offset = 2 115 | var maxOffset = dataView.byteLength - 4 116 | var headLength = offset 117 | var markerBytes 118 | var markerLength 119 | var parsers 120 | var i 121 | while (offset < maxOffset) { 122 | markerBytes = dataView.getUint16(offset) 123 | // Search for APPn (0xffeN) and COM (0xfffe) markers, 124 | // which contain application-specific metadata like 125 | // Exif, ICC and IPTC data and text comments: 126 | if ( 127 | (markerBytes >= 0xffe0 && markerBytes <= 0xffef) || 128 | markerBytes === 0xfffe 129 | ) { 130 | // The marker bytes (2) are always followed by 131 | // the length bytes (2), indicating the length of the 132 | // marker segment, which includes the length bytes, 133 | // but not the marker bytes, so we add 2: 134 | markerLength = dataView.getUint16(offset + 2) + 2 135 | if (offset + markerLength > dataView.byteLength) { 136 | // eslint-disable-next-line no-console 137 | console.log('Invalid JPEG metadata: Invalid segment size.') 138 | break 139 | } 140 | parsers = metaDataParsers.jpeg[markerBytes] 141 | if (parsers && !options.disableMetaDataParsers) { 142 | for (i = 0; i < parsers.length; i += 1) { 143 | parsers[i].call( 144 | that, 145 | dataView, 146 | offset, 147 | markerLength, 148 | data, 149 | options 150 | ) 151 | } 152 | } 153 | offset += markerLength 154 | headLength = offset 155 | } else { 156 | // Not an APPn or COM marker, probably safe to 157 | // assume that this is the end of the metadata 158 | break 159 | } 160 | } 161 | // Meta length must be longer than JPEG marker (2) 162 | // plus APPn marker (2), followed by length bytes (2): 163 | if (!options.disableImageHead && headLength > 6) { 164 | data.imageHead = bufferSlice.call(buffer, 0, headLength) 165 | } 166 | resolve(data) 167 | }, 168 | reject, 169 | 'readAsArrayBuffer' 170 | ) 171 | ) { 172 | // No support for the FileReader interface, nothing to parse 173 | resolve(data) 174 | } 175 | } 176 | options = options || {} // eslint-disable-line no-param-reassign 177 | if (global.Promise && typeof callback !== 'function') { 178 | options = callback || {} // eslint-disable-line no-param-reassign 179 | data = options // eslint-disable-line no-param-reassign 180 | return new Promise(executor) 181 | } 182 | data = data || {} // eslint-disable-line no-param-reassign 183 | return executor(callback, callback) 184 | } 185 | 186 | /** 187 | * Replaces the head of a JPEG Blob 188 | * 189 | * @param {Blob} blob Blob object 190 | * @param {ArrayBuffer} oldHead Old JPEG head 191 | * @param {ArrayBuffer} newHead New JPEG head 192 | * @returns {Blob} Combined Blob 193 | */ 194 | function replaceJPEGHead(blob, oldHead, newHead) { 195 | if (!blob || !oldHead || !newHead) return null 196 | return new Blob([newHead, blobSlice.call(blob, oldHead.byteLength)], { 197 | type: 'image/jpeg' 198 | }) 199 | } 200 | 201 | /** 202 | * Replaces the image head of a JPEG blob with the given one. 203 | * Returns a Promise or calls the callback with the new Blob. 204 | * 205 | * @param {Blob} blob Blob object 206 | * @param {ArrayBuffer} head New JPEG head 207 | * @param {Function} [callback] Callback function 208 | * @returns {Promise|undefined} Combined Blob 209 | */ 210 | function replaceHead(blob, head, callback) { 211 | var options = { maxMetaDataSize: 256, disableMetaDataParsers: true } 212 | if (!callback && global.Promise) { 213 | return parseMetaData(blob, options).then(function (data) { 214 | return replaceJPEGHead(blob, data.imageHead, head) 215 | }) 216 | } 217 | parseMetaData( 218 | blob, 219 | function (data) { 220 | callback(replaceJPEGHead(blob, data.imageHead, head)) 221 | }, 222 | options 223 | ) 224 | } 225 | 226 | loadImage.transform = function (img, options, callback, file, data) { 227 | if (loadImage.requiresMetaData(options)) { 228 | data = data || {} // eslint-disable-line no-param-reassign 229 | parseMetaData( 230 | file, 231 | function (result) { 232 | if (result !== data) { 233 | // eslint-disable-next-line no-console 234 | if (global.console) console.log(result) 235 | result = data // eslint-disable-line no-param-reassign 236 | } 237 | originalTransform.call( 238 | loadImage, 239 | img, 240 | options, 241 | callback, 242 | file, 243 | result 244 | ) 245 | }, 246 | options, 247 | data 248 | ) 249 | } else { 250 | originalTransform.apply(loadImage, arguments) 251 | } 252 | } 253 | 254 | loadImage.blobSlice = blobSlice 255 | loadImage.bufferSlice = bufferSlice 256 | loadImage.replaceHead = replaceHead 257 | loadImage.parseMetaData = parseMetaData 258 | loadImage.metaDataParsers = metaDataParsers 259 | }) 260 | -------------------------------------------------------------------------------- /node_modules/blueimp-load-image/js/load-image-orientation.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JavaScript Load Image Orientation 3 | * https://github.com/blueimp/JavaScript-Load-Image 4 | * 5 | * Copyright 2013, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* 13 | Exif orientation values to correctly display the letter F: 14 | 15 | 1 2 16 | ██████ ██████ 17 | ██ ██ 18 | ████ ████ 19 | ██ ██ 20 | ██ ██ 21 | 22 | 3 4 23 | ██ ██ 24 | ██ ██ 25 | ████ ████ 26 | ██ ██ 27 | ██████ ██████ 28 | 29 | 5 6 30 | ██████████ ██ 31 | ██ ██ ██ ██ 32 | ██ ██████████ 33 | 34 | 7 8 35 | ██ ██████████ 36 | ██ ██ ██ ██ 37 | ██████████ ██ 38 | 39 | */ 40 | 41 | /* global define, module, require */ 42 | 43 | ;(function (factory) { 44 | 'use strict' 45 | if (typeof define === 'function' && define.amd) { 46 | // Register as an anonymous AMD module: 47 | define(['./load-image', './load-image-scale', './load-image-meta'], factory) 48 | } else if (typeof module === 'object' && module.exports) { 49 | factory( 50 | require('./load-image'), 51 | require('./load-image-scale'), 52 | require('./load-image-meta') 53 | ) 54 | } else { 55 | // Browser globals: 56 | factory(window.loadImage) 57 | } 58 | })(function (loadImage) { 59 | 'use strict' 60 | 61 | var originalTransform = loadImage.transform 62 | var originalRequiresCanvas = loadImage.requiresCanvas 63 | var originalRequiresMetaData = loadImage.requiresMetaData 64 | var originalTransformCoordinates = loadImage.transformCoordinates 65 | var originalGetTransformedOptions = loadImage.getTransformedOptions 66 | 67 | ;(function ($) { 68 | // Guard for non-browser environments (e.g. server-side rendering): 69 | if (!$.global.document) return 70 | // black+white 3x2 JPEG, with the following meta information set: 71 | // - EXIF Orientation: 6 (Rotated 90° CCW) 72 | // Image data layout (B=black, F=white): 73 | // BFF 74 | // BBB 75 | var testImageURL = 76 | 'data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAA' + 77 | 'AAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA' + 78 | 'QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE' + 79 | 'BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAIAAwMBEQACEQEDEQH/x' + 80 | 'ABRAAEAAAAAAAAAAAAAAAAAAAAKEAEBAQADAQEAAAAAAAAAAAAGBQQDCAkCBwEBAAAAAAA' + 81 | 'AAAAAAAAAAAAAABEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AG8T9NfSMEVMhQ' + 82 | 'voP3fFiRZ+MTHDifa/95OFSZU5OzRzxkyejv8ciEfhSceSXGjS8eSdLnZc2HDm4M3BxcXw' + 83 | 'H/9k=' 84 | var img = document.createElement('img') 85 | img.onload = function () { 86 | // Check if the browser supports automatic image orientation: 87 | $.orientation = img.width === 2 && img.height === 3 88 | if ($.orientation) { 89 | var canvas = $.createCanvas(1, 1, true) 90 | var ctx = canvas.getContext('2d') 91 | ctx.drawImage(img, 1, 1, 1, 1, 0, 0, 1, 1) 92 | // Check if the source image coordinates (sX, sY, sWidth, sHeight) are 93 | // correctly applied to the auto-orientated image, which should result 94 | // in a white opaque pixel (e.g. in Safari). 95 | // Browsers that show a transparent pixel (e.g. Chromium) fail to crop 96 | // auto-oriented images correctly and require a workaround, e.g. 97 | // drawing the complete source image to an intermediate canvas first. 98 | // See https://bugs.chromium.org/p/chromium/issues/detail?id=1074354 99 | $.orientationCropBug = 100 | ctx.getImageData(0, 0, 1, 1).data.toString() !== '255,255,255,255' 101 | } 102 | } 103 | img.src = testImageURL 104 | })(loadImage) 105 | 106 | /** 107 | * Determines if the orientation requires a canvas element. 108 | * 109 | * @param {object} [options] Options object 110 | * @param {boolean} [withMetaData] Is metadata required for orientation 111 | * @returns {boolean} Returns true if orientation requires canvas/meta 112 | */ 113 | function requiresCanvasOrientation(options, withMetaData) { 114 | var orientation = options && options.orientation 115 | return ( 116 | // Exif orientation for browsers without automatic image orientation: 117 | (orientation === true && !loadImage.orientation) || 118 | // Orientation reset for browsers with automatic image orientation: 119 | (orientation === 1 && loadImage.orientation) || 120 | // Orientation to defined value, requires meta for orientation reset only: 121 | ((!withMetaData || loadImage.orientation) && 122 | orientation > 1 && 123 | orientation < 9) 124 | ) 125 | } 126 | 127 | /** 128 | * Determines if the image requires an orientation change. 129 | * 130 | * @param {number} [orientation] Defined orientation value 131 | * @param {number} [autoOrientation] Auto-orientation based on Exif data 132 | * @returns {boolean} Returns true if an orientation change is required 133 | */ 134 | function requiresOrientationChange(orientation, autoOrientation) { 135 | return ( 136 | orientation !== autoOrientation && 137 | ((orientation === 1 && autoOrientation > 1 && autoOrientation < 9) || 138 | (orientation > 1 && orientation < 9)) 139 | ) 140 | } 141 | 142 | /** 143 | * Determines orientation combinations that require a rotation by 180°. 144 | * 145 | * The following is a list of combinations that return true: 146 | * 147 | * 2 (flip) => 5 (rot90,flip), 7 (rot90,flip), 6 (rot90), 8 (rot90) 148 | * 4 (flip) => 5 (rot90,flip), 7 (rot90,flip), 6 (rot90), 8 (rot90) 149 | * 150 | * 5 (rot90,flip) => 2 (flip), 4 (flip), 6 (rot90), 8 (rot90) 151 | * 7 (rot90,flip) => 2 (flip), 4 (flip), 6 (rot90), 8 (rot90) 152 | * 153 | * 6 (rot90) => 2 (flip), 4 (flip), 5 (rot90,flip), 7 (rot90,flip) 154 | * 8 (rot90) => 2 (flip), 4 (flip), 5 (rot90,flip), 7 (rot90,flip) 155 | * 156 | * @param {number} [orientation] Defined orientation value 157 | * @param {number} [autoOrientation] Auto-orientation based on Exif data 158 | * @returns {boolean} Returns true if rotation by 180° is required 159 | */ 160 | function requiresRot180(orientation, autoOrientation) { 161 | if (autoOrientation > 1 && autoOrientation < 9) { 162 | switch (orientation) { 163 | case 2: 164 | case 4: 165 | return autoOrientation > 4 166 | case 5: 167 | case 7: 168 | return autoOrientation % 2 === 0 169 | case 6: 170 | case 8: 171 | return ( 172 | autoOrientation === 2 || 173 | autoOrientation === 4 || 174 | autoOrientation === 5 || 175 | autoOrientation === 7 176 | ) 177 | } 178 | } 179 | return false 180 | } 181 | 182 | // Determines if the target image should be a canvas element: 183 | loadImage.requiresCanvas = function (options) { 184 | return ( 185 | requiresCanvasOrientation(options) || 186 | originalRequiresCanvas.call(loadImage, options) 187 | ) 188 | } 189 | 190 | // Determines if metadata should be loaded automatically: 191 | loadImage.requiresMetaData = function (options) { 192 | return ( 193 | requiresCanvasOrientation(options, true) || 194 | originalRequiresMetaData.call(loadImage, options) 195 | ) 196 | } 197 | 198 | loadImage.transform = function (img, options, callback, file, data) { 199 | originalTransform.call( 200 | loadImage, 201 | img, 202 | options, 203 | function (img, data) { 204 | if (data) { 205 | var autoOrientation = 206 | loadImage.orientation && data.exif && data.exif.get('Orientation') 207 | if (autoOrientation > 4 && autoOrientation < 9) { 208 | // Automatic image orientation switched image dimensions 209 | var originalWidth = data.originalWidth 210 | var originalHeight = data.originalHeight 211 | data.originalWidth = originalHeight 212 | data.originalHeight = originalWidth 213 | } 214 | } 215 | callback(img, data) 216 | }, 217 | file, 218 | data 219 | ) 220 | } 221 | 222 | // Transforms coordinate and dimension options 223 | // based on the given orientation option: 224 | loadImage.getTransformedOptions = function (img, opts, data) { 225 | var options = originalGetTransformedOptions.call(loadImage, img, opts) 226 | var exifOrientation = data.exif && data.exif.get('Orientation') 227 | var orientation = options.orientation 228 | var autoOrientation = loadImage.orientation && exifOrientation 229 | if (orientation === true) orientation = exifOrientation 230 | if (!requiresOrientationChange(orientation, autoOrientation)) { 231 | return options 232 | } 233 | var top = options.top 234 | var right = options.right 235 | var bottom = options.bottom 236 | var left = options.left 237 | var newOptions = {} 238 | for (var i in options) { 239 | if (Object.prototype.hasOwnProperty.call(options, i)) { 240 | newOptions[i] = options[i] 241 | } 242 | } 243 | newOptions.orientation = orientation 244 | if ( 245 | (orientation > 4 && !(autoOrientation > 4)) || 246 | (orientation < 5 && autoOrientation > 4) 247 | ) { 248 | // Image dimensions and target dimensions are switched 249 | newOptions.maxWidth = options.maxHeight 250 | newOptions.maxHeight = options.maxWidth 251 | newOptions.minWidth = options.minHeight 252 | newOptions.minHeight = options.minWidth 253 | newOptions.sourceWidth = options.sourceHeight 254 | newOptions.sourceHeight = options.sourceWidth 255 | } 256 | if (autoOrientation > 1) { 257 | // Browsers which correctly apply source image coordinates to 258 | // auto-oriented images 259 | switch (autoOrientation) { 260 | case 2: 261 | // Horizontal flip 262 | right = options.left 263 | left = options.right 264 | break 265 | case 3: 266 | // 180° Rotate CCW 267 | top = options.bottom 268 | right = options.left 269 | bottom = options.top 270 | left = options.right 271 | break 272 | case 4: 273 | // Vertical flip 274 | top = options.bottom 275 | bottom = options.top 276 | break 277 | case 5: 278 | // Horizontal flip + 90° Rotate CCW 279 | top = options.left 280 | right = options.bottom 281 | bottom = options.right 282 | left = options.top 283 | break 284 | case 6: 285 | // 90° Rotate CCW 286 | top = options.left 287 | right = options.top 288 | bottom = options.right 289 | left = options.bottom 290 | break 291 | case 7: 292 | // Vertical flip + 90° Rotate CCW 293 | top = options.right 294 | right = options.top 295 | bottom = options.left 296 | left = options.bottom 297 | break 298 | case 8: 299 | // 90° Rotate CW 300 | top = options.right 301 | right = options.bottom 302 | bottom = options.left 303 | left = options.top 304 | break 305 | } 306 | // Some orientation combinations require additional rotation by 180°: 307 | if (requiresRot180(orientation, autoOrientation)) { 308 | var tmpTop = top 309 | var tmpRight = right 310 | top = bottom 311 | right = left 312 | bottom = tmpTop 313 | left = tmpRight 314 | } 315 | } 316 | newOptions.top = top 317 | newOptions.right = right 318 | newOptions.bottom = bottom 319 | newOptions.left = left 320 | // Account for defined browser orientation: 321 | switch (orientation) { 322 | case 2: 323 | // Horizontal flip 324 | newOptions.right = left 325 | newOptions.left = right 326 | break 327 | case 3: 328 | // 180° Rotate CCW 329 | newOptions.top = bottom 330 | newOptions.right = left 331 | newOptions.bottom = top 332 | newOptions.left = right 333 | break 334 | case 4: 335 | // Vertical flip 336 | newOptions.top = bottom 337 | newOptions.bottom = top 338 | break 339 | case 5: 340 | // Vertical flip + 90° Rotate CW 341 | newOptions.top = left 342 | newOptions.right = bottom 343 | newOptions.bottom = right 344 | newOptions.left = top 345 | break 346 | case 6: 347 | // 90° Rotate CW 348 | newOptions.top = right 349 | newOptions.right = bottom 350 | newOptions.bottom = left 351 | newOptions.left = top 352 | break 353 | case 7: 354 | // Horizontal flip + 90° Rotate CW 355 | newOptions.top = right 356 | newOptions.right = top 357 | newOptions.bottom = left 358 | newOptions.left = bottom 359 | break 360 | case 8: 361 | // 90° Rotate CCW 362 | newOptions.top = left 363 | newOptions.right = top 364 | newOptions.bottom = right 365 | newOptions.left = bottom 366 | break 367 | } 368 | return newOptions 369 | } 370 | 371 | // Transform image orientation based on the given EXIF orientation option: 372 | loadImage.transformCoordinates = function (canvas, options, data) { 373 | originalTransformCoordinates.call(loadImage, canvas, options, data) 374 | var orientation = options.orientation 375 | var autoOrientation = 376 | loadImage.orientation && data.exif && data.exif.get('Orientation') 377 | if (!requiresOrientationChange(orientation, autoOrientation)) { 378 | return 379 | } 380 | var ctx = canvas.getContext('2d') 381 | var width = canvas.width 382 | var height = canvas.height 383 | var sourceWidth = width 384 | var sourceHeight = height 385 | if ( 386 | (orientation > 4 && !(autoOrientation > 4)) || 387 | (orientation < 5 && autoOrientation > 4) 388 | ) { 389 | // Image dimensions and target dimensions are switched 390 | canvas.width = height 391 | canvas.height = width 392 | } 393 | if (orientation > 4) { 394 | // Destination and source dimensions are switched 395 | sourceWidth = height 396 | sourceHeight = width 397 | } 398 | // Reset automatic browser orientation: 399 | switch (autoOrientation) { 400 | case 2: 401 | // Horizontal flip 402 | ctx.translate(sourceWidth, 0) 403 | ctx.scale(-1, 1) 404 | break 405 | case 3: 406 | // 180° Rotate CCW 407 | ctx.translate(sourceWidth, sourceHeight) 408 | ctx.rotate(Math.PI) 409 | break 410 | case 4: 411 | // Vertical flip 412 | ctx.translate(0, sourceHeight) 413 | ctx.scale(1, -1) 414 | break 415 | case 5: 416 | // Horizontal flip + 90° Rotate CCW 417 | ctx.rotate(-0.5 * Math.PI) 418 | ctx.scale(-1, 1) 419 | break 420 | case 6: 421 | // 90° Rotate CCW 422 | ctx.rotate(-0.5 * Math.PI) 423 | ctx.translate(-sourceWidth, 0) 424 | break 425 | case 7: 426 | // Vertical flip + 90° Rotate CCW 427 | ctx.rotate(-0.5 * Math.PI) 428 | ctx.translate(-sourceWidth, sourceHeight) 429 | ctx.scale(1, -1) 430 | break 431 | case 8: 432 | // 90° Rotate CW 433 | ctx.rotate(0.5 * Math.PI) 434 | ctx.translate(0, -sourceHeight) 435 | break 436 | } 437 | // Some orientation combinations require additional rotation by 180°: 438 | if (requiresRot180(orientation, autoOrientation)) { 439 | ctx.translate(sourceWidth, sourceHeight) 440 | ctx.rotate(Math.PI) 441 | } 442 | switch (orientation) { 443 | case 2: 444 | // Horizontal flip 445 | ctx.translate(width, 0) 446 | ctx.scale(-1, 1) 447 | break 448 | case 3: 449 | // 180° Rotate CCW 450 | ctx.translate(width, height) 451 | ctx.rotate(Math.PI) 452 | break 453 | case 4: 454 | // Vertical flip 455 | ctx.translate(0, height) 456 | ctx.scale(1, -1) 457 | break 458 | case 5: 459 | // Vertical flip + 90° Rotate CW 460 | ctx.rotate(0.5 * Math.PI) 461 | ctx.scale(1, -1) 462 | break 463 | case 6: 464 | // 90° Rotate CW 465 | ctx.rotate(0.5 * Math.PI) 466 | ctx.translate(0, -height) 467 | break 468 | case 7: 469 | // Horizontal flip + 90° Rotate CW 470 | ctx.rotate(0.5 * Math.PI) 471 | ctx.translate(width, -height) 472 | ctx.scale(-1, 1) 473 | break 474 | case 8: 475 | // 90° Rotate CCW 476 | ctx.rotate(-0.5 * Math.PI) 477 | ctx.translate(-width, 0) 478 | break 479 | } 480 | } 481 | }) 482 | -------------------------------------------------------------------------------- /node_modules/blueimp-load-image/js/load-image-scale.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JavaScript Load Image Scaling 3 | * https://github.com/blueimp/JavaScript-Load-Image 4 | * 5 | * Copyright 2011, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | */ 11 | 12 | /* global define, module, require */ 13 | 14 | ;(function (factory) { 15 | 'use strict' 16 | if (typeof define === 'function' && define.amd) { 17 | // Register as an anonymous AMD module: 18 | define(['./load-image'], factory) 19 | } else if (typeof module === 'object' && module.exports) { 20 | factory(require('./load-image')) 21 | } else { 22 | // Browser globals: 23 | factory(window.loadImage) 24 | } 25 | })(function (loadImage) { 26 | 'use strict' 27 | 28 | var originalTransform = loadImage.transform 29 | 30 | loadImage.createCanvas = function (width, height, offscreen) { 31 | if (offscreen && loadImage.global.OffscreenCanvas) { 32 | return new OffscreenCanvas(width, height) 33 | } 34 | var canvas = document.createElement('canvas') 35 | canvas.width = width 36 | canvas.height = height 37 | return canvas 38 | } 39 | 40 | loadImage.transform = function (img, options, callback, file, data) { 41 | originalTransform.call( 42 | loadImage, 43 | loadImage.scale(img, options, data), 44 | options, 45 | callback, 46 | file, 47 | data 48 | ) 49 | } 50 | 51 | // Transform image coordinates, allows to override e.g. 52 | // the canvas orientation based on the orientation option, 53 | // gets canvas, options and data passed as arguments: 54 | loadImage.transformCoordinates = function () {} 55 | 56 | // Returns transformed options, allows to override e.g. 57 | // maxWidth, maxHeight and crop options based on the aspectRatio. 58 | // gets img, options, data passed as arguments: 59 | loadImage.getTransformedOptions = function (img, options) { 60 | var aspectRatio = options.aspectRatio 61 | var newOptions 62 | var i 63 | var width 64 | var height 65 | if (!aspectRatio) { 66 | return options 67 | } 68 | newOptions = {} 69 | for (i in options) { 70 | if (Object.prototype.hasOwnProperty.call(options, i)) { 71 | newOptions[i] = options[i] 72 | } 73 | } 74 | newOptions.crop = true 75 | width = img.naturalWidth || img.width 76 | height = img.naturalHeight || img.height 77 | if (width / height > aspectRatio) { 78 | newOptions.maxWidth = height * aspectRatio 79 | newOptions.maxHeight = height 80 | } else { 81 | newOptions.maxWidth = width 82 | newOptions.maxHeight = width / aspectRatio 83 | } 84 | return newOptions 85 | } 86 | 87 | // Canvas render method, allows to implement a different rendering algorithm: 88 | loadImage.drawImage = function ( 89 | img, 90 | canvas, 91 | sourceX, 92 | sourceY, 93 | sourceWidth, 94 | sourceHeight, 95 | destWidth, 96 | destHeight, 97 | options 98 | ) { 99 | var ctx = canvas.getContext('2d') 100 | if (options.imageSmoothingEnabled === false) { 101 | ctx.msImageSmoothingEnabled = false 102 | ctx.imageSmoothingEnabled = false 103 | } else if (options.imageSmoothingQuality) { 104 | ctx.imageSmoothingQuality = options.imageSmoothingQuality 105 | } 106 | ctx.drawImage( 107 | img, 108 | sourceX, 109 | sourceY, 110 | sourceWidth, 111 | sourceHeight, 112 | 0, 113 | 0, 114 | destWidth, 115 | destHeight 116 | ) 117 | return ctx 118 | } 119 | 120 | // Determines if the target image should be a canvas element: 121 | loadImage.requiresCanvas = function (options) { 122 | return options.canvas || options.crop || !!options.aspectRatio 123 | } 124 | 125 | // Scales and/or crops the given image (img or canvas HTML element) 126 | // using the given options: 127 | loadImage.scale = function (img, options, data) { 128 | // eslint-disable-next-line no-param-reassign 129 | options = options || {} 130 | // eslint-disable-next-line no-param-reassign 131 | data = data || {} 132 | var useCanvas = 133 | img.getContext || 134 | (loadImage.requiresCanvas(options) && 135 | !!loadImage.global.HTMLCanvasElement) 136 | var width = img.naturalWidth || img.width 137 | var height = img.naturalHeight || img.height 138 | var destWidth = width 139 | var destHeight = height 140 | var maxWidth 141 | var maxHeight 142 | var minWidth 143 | var minHeight 144 | var sourceWidth 145 | var sourceHeight 146 | var sourceX 147 | var sourceY 148 | var pixelRatio 149 | var downsamplingRatio 150 | var tmp 151 | var canvas 152 | /** 153 | * Scales up image dimensions 154 | */ 155 | function scaleUp() { 156 | var scale = Math.max( 157 | (minWidth || destWidth) / destWidth, 158 | (minHeight || destHeight) / destHeight 159 | ) 160 | if (scale > 1) { 161 | destWidth *= scale 162 | destHeight *= scale 163 | } 164 | } 165 | /** 166 | * Scales down image dimensions 167 | */ 168 | function scaleDown() { 169 | var scale = Math.min( 170 | (maxWidth || destWidth) / destWidth, 171 | (maxHeight || destHeight) / destHeight 172 | ) 173 | if (scale < 1) { 174 | destWidth *= scale 175 | destHeight *= scale 176 | } 177 | } 178 | if (useCanvas) { 179 | // eslint-disable-next-line no-param-reassign 180 | options = loadImage.getTransformedOptions(img, options, data) 181 | sourceX = options.left || 0 182 | sourceY = options.top || 0 183 | if (options.sourceWidth) { 184 | sourceWidth = options.sourceWidth 185 | if (options.right !== undefined && options.left === undefined) { 186 | sourceX = width - sourceWidth - options.right 187 | } 188 | } else { 189 | sourceWidth = width - sourceX - (options.right || 0) 190 | } 191 | if (options.sourceHeight) { 192 | sourceHeight = options.sourceHeight 193 | if (options.bottom !== undefined && options.top === undefined) { 194 | sourceY = height - sourceHeight - options.bottom 195 | } 196 | } else { 197 | sourceHeight = height - sourceY - (options.bottom || 0) 198 | } 199 | destWidth = sourceWidth 200 | destHeight = sourceHeight 201 | } 202 | maxWidth = options.maxWidth 203 | maxHeight = options.maxHeight 204 | minWidth = options.minWidth 205 | minHeight = options.minHeight 206 | if (useCanvas && maxWidth && maxHeight && options.crop) { 207 | destWidth = maxWidth 208 | destHeight = maxHeight 209 | tmp = sourceWidth / sourceHeight - maxWidth / maxHeight 210 | if (tmp < 0) { 211 | sourceHeight = (maxHeight * sourceWidth) / maxWidth 212 | if (options.top === undefined && options.bottom === undefined) { 213 | sourceY = (height - sourceHeight) / 2 214 | } 215 | } else if (tmp > 0) { 216 | sourceWidth = (maxWidth * sourceHeight) / maxHeight 217 | if (options.left === undefined && options.right === undefined) { 218 | sourceX = (width - sourceWidth) / 2 219 | } 220 | } 221 | } else { 222 | if (options.contain || options.cover) { 223 | minWidth = maxWidth = maxWidth || minWidth 224 | minHeight = maxHeight = maxHeight || minHeight 225 | } 226 | if (options.cover) { 227 | scaleDown() 228 | scaleUp() 229 | } else { 230 | scaleUp() 231 | scaleDown() 232 | } 233 | } 234 | if (useCanvas) { 235 | pixelRatio = options.pixelRatio 236 | if ( 237 | pixelRatio > 1 && 238 | // Check if the image has not yet had the device pixel ratio applied: 239 | !( 240 | img.style.width && 241 | Math.floor(parseFloat(img.style.width, 10)) === 242 | Math.floor(width / pixelRatio) 243 | ) 244 | ) { 245 | destWidth *= pixelRatio 246 | destHeight *= pixelRatio 247 | } 248 | // Check if workaround for Chromium orientation crop bug is required: 249 | // https://bugs.chromium.org/p/chromium/issues/detail?id=1074354 250 | if ( 251 | loadImage.orientationCropBug && 252 | !img.getContext && 253 | (sourceX || sourceY || sourceWidth !== width || sourceHeight !== height) 254 | ) { 255 | // Write the complete source image to an intermediate canvas first: 256 | tmp = img 257 | // eslint-disable-next-line no-param-reassign 258 | img = loadImage.createCanvas(width, height, true) 259 | loadImage.drawImage( 260 | tmp, 261 | img, 262 | 0, 263 | 0, 264 | width, 265 | height, 266 | width, 267 | height, 268 | options 269 | ) 270 | } 271 | downsamplingRatio = options.downsamplingRatio 272 | if ( 273 | downsamplingRatio > 0 && 274 | downsamplingRatio < 1 && 275 | destWidth < sourceWidth && 276 | destHeight < sourceHeight 277 | ) { 278 | while (sourceWidth * downsamplingRatio > destWidth) { 279 | canvas = loadImage.createCanvas( 280 | sourceWidth * downsamplingRatio, 281 | sourceHeight * downsamplingRatio, 282 | true 283 | ) 284 | loadImage.drawImage( 285 | img, 286 | canvas, 287 | sourceX, 288 | sourceY, 289 | sourceWidth, 290 | sourceHeight, 291 | canvas.width, 292 | canvas.height, 293 | options 294 | ) 295 | sourceX = 0 296 | sourceY = 0 297 | sourceWidth = canvas.width 298 | sourceHeight = canvas.height 299 | // eslint-disable-next-line no-param-reassign 300 | img = canvas 301 | } 302 | } 303 | canvas = loadImage.createCanvas(destWidth, destHeight) 304 | loadImage.transformCoordinates(canvas, options, data) 305 | if (pixelRatio > 1) { 306 | canvas.style.width = canvas.width / pixelRatio + 'px' 307 | } 308 | loadImage 309 | .drawImage( 310 | img, 311 | canvas, 312 | sourceX, 313 | sourceY, 314 | sourceWidth, 315 | sourceHeight, 316 | destWidth, 317 | destHeight, 318 | options 319 | ) 320 | .setTransform(1, 0, 0, 1, 0, 0) // reset to the identity matrix 321 | return canvas 322 | } 323 | img.width = destWidth 324 | img.height = destHeight 325 | return img 326 | } 327 | }) 328 | -------------------------------------------------------------------------------- /node_modules/blueimp-load-image/js/load-image.all.min.js: -------------------------------------------------------------------------------- 1 | !function(c){"use strict";var t=c.URL||c.webkitURL;function f(e){return!!t&&t.createObjectURL(e)}function i(e){return!!t&&t.revokeObjectURL(e)}function u(e,t){!e||"blob:"!==e.slice(0,5)||t&&t.noRevoke||i(e)}function d(e,t,i,a){if(!c.FileReader)return!1;var n=new FileReader;n.onload=function(){t.call(n,this.result)},i&&(n.onabort=n.onerror=function(){i.call(n,this.error)});var r=n[a||"readAsDataURL"];return r?(r.call(n,e),n):void 0}function g(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"}function m(s,e,l){function t(i,a){var n,r=document.createElement("img");function o(e,t){i!==a?e instanceof Error?a(e):((t=t||{}).image=e,i(t)):i&&i(e,t)}function e(e,t){t&&c.console&&console.log(t),e&&g("Blob",e)?n=f(s=e):(n=s,l&&l.crossOrigin&&(r.crossOrigin=l.crossOrigin)),r.src=n}return r.onerror=function(e){u(n,l),a&&a.call(r,e)},r.onload=function(){u(n,l);var e={originalWidth:r.naturalWidth||r.width,originalHeight:r.naturalHeight||r.height};try{m.transform(r,l,o,s,e)}catch(t){a&&a(t)}},"string"==typeof s?(m.requiresMetaData(l)?m.fetchBlob(s,e,l):e(),r):g("Blob",s)||g("File",s)?(n=f(s))?(r.src=n,r):d(s,function(e){r.src=e},a):void 0}return c.Promise&&"function"!=typeof e?(l=e,new Promise(t)):t(e,e)}m.requiresMetaData=function(e){return e&&e.meta},m.fetchBlob=function(e,t){t()},m.transform=function(e,t,i,a,n){i(e,n)},m.global=c,m.readFile=d,m.isInstanceOf=g,m.createObjectURL=f,m.revokeObjectURL=i,"function"==typeof define&&define.amd?define(function(){return m}):"object"==typeof module&&module.exports?module.exports=m:c.loadImage=m}("undefined"!=typeof window&&window||this),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image"],e):"object"==typeof module&&module.exports?e(require("./load-image")):e(window.loadImage)}(function(E){"use strict";var r=E.transform;E.createCanvas=function(e,t,i){if(i&&E.global.OffscreenCanvas)return new OffscreenCanvas(e,t);var a=document.createElement("canvas");return a.width=e,a.height=t,a},E.transform=function(e,t,i,a,n){r.call(E,E.scale(e,t,n),t,i,a,n)},E.transformCoordinates=function(){},E.getTransformedOptions=function(e,t){var i,a,n,r,o=t.aspectRatio;if(!o)return t;for(a in i={},t)Object.prototype.hasOwnProperty.call(t,a)&&(i[a]=t[a]);return i.crop=!0,o<(n=e.naturalWidth||e.width)/(r=e.naturalHeight||e.height)?(i.maxWidth=r*o,i.maxHeight=r):(i.maxWidth=n,i.maxHeight=n/o),i},E.drawImage=function(e,t,i,a,n,r,o,s,l){var c=t.getContext("2d");return!1===l.imageSmoothingEnabled?(c.msImageSmoothingEnabled=!1,c.imageSmoothingEnabled=!1):l.imageSmoothingQuality&&(c.imageSmoothingQuality=l.imageSmoothingQuality),c.drawImage(e,i,a,n,r,0,0,o,s),c},E.requiresCanvas=function(e){return e.canvas||e.crop||!!e.aspectRatio},E.scale=function(e,t,i){t=t||{},i=i||{};var a,n,r,o,s,l,c,f,u,d,g,m,h=e.getContext||E.requiresCanvas(t)&&!!E.global.HTMLCanvasElement,p=e.naturalWidth||e.width,A=e.naturalHeight||e.height,b=p,y=A;function S(){var e=Math.max((r||b)/b,(o||y)/y);1t.byteLength){console.log("Invalid JPEG metadata: Invalid segment size.");break}if((n=h.jpeg[i])&&!u.disableMetaDataParsers)for(r=0;re.byteLength)console.log("Invalid Exif data: Invalid directory offset.");else{if(!((c=i+2+12*(l=e.getUint16(i,a)))+4>e.byteLength)){for(f=0;fe.byteLength)){if(1===n)return d.getValue(e,s,r);for(l=[],c=0;cc.byteLength)console.log("Invalid Exif data: Invalid segment size.");else if(0===c.getUint16(e+8)){switch(c.getUint16(m)){case 18761:u=!0;break;case 19789:u=!1;break;default:return void console.log("Invalid Exif data: Invalid byte alignment marker.")}42===c.getUint16(m+2,u)?(a=c.getUint32(m+4,u),f.exif=new h,i.disableExifOffsets||(f.exifOffsets=new h,f.exifTiffOffset=m,f.exifLittleEndian=u),(a=A(c,m,m+a,u,f.exif,f.exifOffsets,d,g))&&p(d,g,"ifd1")&&(f.exif.ifd1=a,f.exifOffsets&&(f.exifOffsets.ifd1=m+a)),Object.keys(f.exif.ifds).forEach(function(e){var t,i,a,n,r,o,s,l;i=e,a=c,n=m,r=u,o=d,s=g,(l=(t=f).exif[i])&&(t.exif[i]=new h(i),t.exifOffsets&&(t.exifOffsets[i]=new h(i)),A(a,n,n+l,r,t.exif[i],t.exifOffsets&&t.exifOffsets[i],o&&o[i],s&&s[i]))}),(n=f.exif.ifd1)&&n[513]&&(n[513]=function(e,t,i){if(i){if(!(t+i>e.byteLength))return new Blob([r.bufferSlice.call(e.buffer,t,t+i)],{type:"image/jpeg"});console.log("Invalid Exif data: Invalid thumbnail data.")}}(c,m+n[513],n[514]))):console.log("Invalid Exif data: Missing TIFF marker.")}else console.log("Invalid Exif data: Missing byte alignment offset.")}},r.metaDataParsers.jpeg[65505].push(r.parseExifData),r.exifWriters={274:function(e,t,i){var a=t.exifOffsets[274];return a&&new DataView(e,a+8,2).setUint16(0,i,t.exifLittleEndian),e}},r.writeExifData=function(e,t,i,a){return r.exifWriters[t.exif.map[i]](e,t,a)},r.ExifMap=h}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-exif"],e):"object"==typeof module&&module.exports?e(require("./load-image"),require("./load-image-exif")):e(window.loadImage)}(function(e){"use strict";var n=e.ExifMap.prototype;n.tags={256:"ImageWidth",257:"ImageHeight",258:"BitsPerSample",259:"Compression",262:"PhotometricInterpretation",274:"Orientation",277:"SamplesPerPixel",284:"PlanarConfiguration",530:"YCbCrSubSampling",531:"YCbCrPositioning",282:"XResolution",283:"YResolution",296:"ResolutionUnit",273:"StripOffsets",278:"RowsPerStrip",279:"StripByteCounts",513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength",301:"TransferFunction",318:"WhitePoint",319:"PrimaryChromaticities",529:"YCbCrCoefficients",532:"ReferenceBlackWhite",306:"DateTime",270:"ImageDescription",271:"Make",272:"Model",305:"Software",315:"Artist",33432:"Copyright",34665:{36864:"ExifVersion",40960:"FlashpixVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",42240:"Gamma",37121:"ComponentsConfiguration",37122:"CompressedBitsPerPixel",37500:"MakerNote",37510:"UserComment",40964:"RelatedSoundFile",36867:"DateTimeOriginal",36868:"DateTimeDigitized",36880:"OffsetTime",36881:"OffsetTimeOriginal",36882:"OffsetTimeDigitized",37520:"SubSecTime",37521:"SubSecTimeOriginal",37522:"SubSecTimeDigitized",33434:"ExposureTime",33437:"FNumber",34850:"ExposureProgram",34852:"SpectralSensitivity",34855:"PhotographicSensitivity",34856:"OECF",34864:"SensitivityType",34865:"StandardOutputSensitivity",34866:"RecommendedExposureIndex",34867:"ISOSpeed",34868:"ISOSpeedLatitudeyyy",34869:"ISOSpeedLatitudezzz",37377:"ShutterSpeedValue",37378:"ApertureValue",37379:"BrightnessValue",37380:"ExposureBias",37381:"MaxApertureValue",37382:"SubjectDistance",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37396:"SubjectArea",37386:"FocalLength",41483:"FlashEnergy",41484:"SpatialFrequencyResponse",41486:"FocalPlaneXResolution",41487:"FocalPlaneYResolution",41488:"FocalPlaneResolutionUnit",41492:"SubjectLocation",41493:"ExposureIndex",41495:"SensingMethod",41728:"FileSource",41729:"SceneType",41730:"CFAPattern",41985:"CustomRendered",41986:"ExposureMode",41987:"WhiteBalance",41988:"DigitalZoomRatio",41989:"FocalLengthIn35mmFilm",41990:"SceneCaptureType",41991:"GainControl",41992:"Contrast",41993:"Saturation",41994:"Sharpness",41995:"DeviceSettingDescription",41996:"SubjectDistanceRange",42016:"ImageUniqueID",42032:"CameraOwnerName",42033:"BodySerialNumber",42034:"LensSpecification",42035:"LensMake",42036:"LensModel",42037:"LensSerialNumber"},34853:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude",5:"GPSAltitudeRef",6:"GPSAltitude",7:"GPSTimeStamp",8:"GPSSatellites",9:"GPSStatus",10:"GPSMeasureMode",11:"GPSDOP",12:"GPSSpeedRef",13:"GPSSpeed",14:"GPSTrackRef",15:"GPSTrack",16:"GPSImgDirectionRef",17:"GPSImgDirection",18:"GPSMapDatum",19:"GPSDestLatitudeRef",20:"GPSDestLatitude",21:"GPSDestLongitudeRef",22:"GPSDestLongitude",23:"GPSDestBearingRef",24:"GPSDestBearing",25:"GPSDestDistanceRef",26:"GPSDestDistance",27:"GPSProcessingMethod",28:"GPSAreaInformation",29:"GPSDateStamp",30:"GPSDifferential",31:"GPSHPositioningError"},40965:{1:"InteroperabilityIndex"}},n.tags.ifd1=n.tags,n.stringValues={ExposureProgram:{0:"Undefined",1:"Manual",2:"Normal program",3:"Aperture priority",4:"Shutter priority",5:"Creative program",6:"Action program",7:"Portrait mode",8:"Landscape mode"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{0:"Unknown",1:"Daylight",2:"Fluorescent",3:"Tungsten (incandescent light)",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 - 5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},SensingMethod:{1:"Undefined",2:"One-chip color area sensor",3:"Two-chip color area sensor",4:"Three-chip color area sensor",5:"Color sequential area sensor",7:"Trilinear sensor",8:"Color sequential linear sensor"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},SceneType:{1:"Directly photographed"},CustomRendered:{0:"Normal process",1:"Custom process"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},GainControl:{0:"None",1:"Low gain up",2:"High gain up",3:"Low gain down",4:"High gain down"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},SubjectDistanceRange:{0:"Unknown",1:"Macro",2:"Close view",3:"Distant view"},FileSource:{3:"DSC"},ComponentsConfiguration:{0:"",1:"Y",2:"Cb",3:"Cr",4:"R",5:"G",6:"B"},Orientation:{1:"Original",2:"Horizontal flip",3:"Rotate 180° CCW",4:"Vertical flip",5:"Vertical flip + Rotate 90° CW",6:"Rotate 90° CW",7:"Horizontal flip + Rotate 90° CW",8:"Rotate 90° CCW"}},n.getText=function(e){var t=this.get(e);switch(e){case"LightSource":case"Flash":case"MeteringMode":case"ExposureProgram":case"SensingMethod":case"SceneCaptureType":case"SceneType":case"CustomRendered":case"WhiteBalance":case"GainControl":case"Contrast":case"Saturation":case"Sharpness":case"SubjectDistanceRange":case"FileSource":case"Orientation":return this.stringValues[e][t];case"ExifVersion":case"FlashpixVersion":if(!t)return;return String.fromCharCode(t[0],t[1],t[2],t[3]);case"ComponentsConfiguration":if(!t)return;return this.stringValues[e][t[0]]+this.stringValues[e][t[1]]+this.stringValues[e][t[2]]+this.stringValues[e][t[3]];case"GPSVersionID":if(!t)return;return t[0]+"."+t[1]+"."+t[2]+"."+t[3]}return String(t)},n.getAll=function(){var e,t,i,a={};for(e in this)Object.prototype.hasOwnProperty.call(this,e)&&((t=this[e])&&t.getAll?a[this.ifds[e].name]=t.getAll():(i=this.tags[e])&&(a[i]=this.getText(i)));return a},n.getName=function(e){var t=this.tags[e];return"object"==typeof t?this.ifds[e].name:t},function(){var e,t,i,a=n.tags;for(e in a)if(Object.prototype.hasOwnProperty.call(a,e))if(t=n.ifds[e])for(e in i=a[e])Object.prototype.hasOwnProperty.call(i,e)&&(t.map[i[e]]=Number(e));else n.map[a[e]]=Number(e)}()}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-meta"],e):"object"==typeof module&&module.exports?e(require("./load-image"),require("./load-image-meta")):e(window.loadImage)}(function(e){"use strict";function g(){}function m(e,t,i,a,n){return"binary"===t.types[e]?new Blob([i.buffer.slice(a,a+n)]):"Uint16"===t.types[e]?i.getUint16(a):function(e,t,i){for(var a="",n=t+i,r=t;r} Object 101 | */ 102 | function loadImage(file, callback, options) { 103 | /** 104 | * Promise executor 105 | * 106 | * @param {Function} resolve Resolution function 107 | * @param {Function} reject Rejection function 108 | * @returns {HTMLImageElement|FileReader} Object 109 | */ 110 | function executor(resolve, reject) { 111 | var img = document.createElement('img') 112 | var url 113 | /** 114 | * Callback for the fetchBlob call. 115 | * 116 | * @param {HTMLImageElement|HTMLCanvasElement} img Error object 117 | * @param {object} data Data object 118 | * @returns {undefined} Undefined 119 | */ 120 | function resolveWrapper(img, data) { 121 | if (resolve === reject) { 122 | // Not using Promises 123 | if (resolve) resolve(img, data) 124 | return 125 | } else if (img instanceof Error) { 126 | reject(img) 127 | return 128 | } 129 | data = data || {} // eslint-disable-line no-param-reassign 130 | data.image = img 131 | resolve(data) 132 | } 133 | /** 134 | * Callback for the fetchBlob call. 135 | * 136 | * @param {Blob} blob Blob object 137 | * @param {Error} err Error object 138 | */ 139 | function fetchBlobCallback(blob, err) { 140 | if (err && $.console) console.log(err) // eslint-disable-line no-console 141 | if (blob && isInstanceOf('Blob', blob)) { 142 | file = blob // eslint-disable-line no-param-reassign 143 | url = createObjectURL(file) 144 | } else { 145 | url = file 146 | if (options && options.crossOrigin) { 147 | img.crossOrigin = options.crossOrigin 148 | } 149 | } 150 | img.src = url 151 | } 152 | img.onerror = function (event) { 153 | revokeHelper(url, options) 154 | if (reject) reject.call(img, event) 155 | } 156 | img.onload = function () { 157 | revokeHelper(url, options) 158 | var data = { 159 | originalWidth: img.naturalWidth || img.width, 160 | originalHeight: img.naturalHeight || img.height 161 | } 162 | try { 163 | loadImage.transform(img, options, resolveWrapper, file, data) 164 | } catch (error) { 165 | if (reject) reject(error) 166 | } 167 | } 168 | if (typeof file === 'string') { 169 | if (loadImage.requiresMetaData(options)) { 170 | loadImage.fetchBlob(file, fetchBlobCallback, options) 171 | } else { 172 | fetchBlobCallback() 173 | } 174 | return img 175 | } else if (isInstanceOf('Blob', file) || isInstanceOf('File', file)) { 176 | url = createObjectURL(file) 177 | if (url) { 178 | img.src = url 179 | return img 180 | } 181 | return readFile( 182 | file, 183 | function (url) { 184 | img.src = url 185 | }, 186 | reject 187 | ) 188 | } 189 | } 190 | if ($.Promise && typeof callback !== 'function') { 191 | options = callback // eslint-disable-line no-param-reassign 192 | return new Promise(executor) 193 | } 194 | return executor(callback, callback) 195 | } 196 | 197 | // Determines if metadata should be loaded automatically. 198 | // Requires the load image meta extension to load metadata. 199 | loadImage.requiresMetaData = function (options) { 200 | return options && options.meta 201 | } 202 | 203 | // If the callback given to this function returns a blob, it is used as image 204 | // source instead of the original url and overrides the file argument used in 205 | // the onload and onerror event callbacks: 206 | loadImage.fetchBlob = function (url, callback) { 207 | callback() 208 | } 209 | 210 | loadImage.transform = function (img, options, callback, file, data) { 211 | callback(img, data) 212 | } 213 | 214 | loadImage.global = $ 215 | loadImage.readFile = readFile 216 | loadImage.isInstanceOf = isInstanceOf 217 | loadImage.createObjectURL = createObjectURL 218 | loadImage.revokeObjectURL = revokeObjectURL 219 | 220 | if (typeof define === 'function' && define.amd) { 221 | define(function () { 222 | return loadImage 223 | }) 224 | } else if (typeof module === 'object' && module.exports) { 225 | module.exports = loadImage 226 | } else { 227 | $.loadImage = loadImage 228 | } 229 | })((typeof window !== 'undefined' && window) || this) 230 | -------------------------------------------------------------------------------- /node_modules/blueimp-load-image/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_from": "blueimp-load-image@^5.14.0", 3 | "_id": "blueimp-load-image@5.14.0", 4 | "_inBundle": false, 5 | "_integrity": "sha512-g5l+4dCOESBG8HkPLdGnBx8dhEwpQHaOZ0en623sl54o3bGhGMLYGc54L5cWfGmPvfKUjbsY7LOAmcW/xlkBSA==", 6 | "_location": "/blueimp-load-image", 7 | "_phantomChildren": {}, 8 | "_requested": { 9 | "type": "range", 10 | "registry": true, 11 | "raw": "blueimp-load-image@^5.14.0", 12 | "name": "blueimp-load-image", 13 | "escapedName": "blueimp-load-image", 14 | "rawSpec": "^5.14.0", 15 | "saveSpec": null, 16 | "fetchSpec": "^5.14.0" 17 | }, 18 | "_requiredBy": [ 19 | "#USER", 20 | "/" 21 | ], 22 | "_resolved": "https://registry.npmjs.org/blueimp-load-image/-/blueimp-load-image-5.14.0.tgz", 23 | "_shasum": "e8086415e580df802c33ff0da6b37a8d20205cc6", 24 | "_spec": "blueimp-load-image@^5.14.0", 25 | "_where": "C:\\Users\\HARSH\\Desktop\\imgrem", 26 | "author": { 27 | "name": "Sebastian Tschan", 28 | "url": "https://blueimp.net" 29 | }, 30 | "bugs": { 31 | "url": "https://github.com/blueimp/JavaScript-Load-Image/issues" 32 | }, 33 | "bundleDependencies": false, 34 | "deprecated": false, 35 | "description": "JavaScript Load Image is a library to load images provided as File or Blob objects or via URL. It returns an optionally scaled, cropped or rotated HTML img or canvas element. It also provides methods to parse image metadata to extract IPTC and Exif tags as well as embedded thumbnail images, to overwrite the Exif Orientation value and to restore the complete image header after resizing.", 36 | "devDependencies": { 37 | "eslint": "7", 38 | "eslint-config-blueimp": "2", 39 | "eslint-config-prettier": "6", 40 | "eslint-plugin-jsdoc": "30", 41 | "eslint-plugin-prettier": "3", 42 | "prettier": "2", 43 | "uglify-js": "3" 44 | }, 45 | "eslintConfig": { 46 | "extends": [ 47 | "blueimp", 48 | "plugin:jsdoc/recommended", 49 | "plugin:prettier/recommended" 50 | ], 51 | "env": { 52 | "browser": true 53 | } 54 | }, 55 | "eslintIgnore": [ 56 | "js/*.min.js", 57 | "js/vendor", 58 | "test/vendor" 59 | ], 60 | "files": [ 61 | "js/*.js", 62 | "js/*.js.map" 63 | ], 64 | "homepage": "https://github.com/blueimp/JavaScript-Load-Image", 65 | "keywords": [ 66 | "javascript", 67 | "load", 68 | "loading", 69 | "image", 70 | "file", 71 | "blob", 72 | "url", 73 | "scale", 74 | "crop", 75 | "rotate", 76 | "img", 77 | "canvas", 78 | "meta", 79 | "exif", 80 | "orientation", 81 | "thumbnail", 82 | "iptc" 83 | ], 84 | "license": "MIT", 85 | "main": "js/index.js", 86 | "name": "blueimp-load-image", 87 | "prettier": { 88 | "arrowParens": "avoid", 89 | "proseWrap": "always", 90 | "semi": false, 91 | "singleQuote": true, 92 | "trailingComma": "none" 93 | }, 94 | "repository": { 95 | "type": "git", 96 | "url": "git://github.com/blueimp/JavaScript-Load-Image.git" 97 | }, 98 | "scripts": { 99 | "build": "cd js && uglifyjs load-image.js load-image-scale.js load-image-meta.js load-image-fetch.js load-image-orientation.js load-image-exif.js load-image-exif-map.js load-image-iptc.js load-image-iptc-map.js --ie8 -c -m -o load-image.all.min.js --source-map url=load-image.all.min.js.map", 100 | "lint": "eslint .", 101 | "posttest": "docker-compose down -v", 102 | "postversion": "git push --tags origin master master:gh-pages && npm publish", 103 | "preversion": "npm test", 104 | "test": "npm run lint && npm run unit", 105 | "unit": "docker-compose run --rm mocha", 106 | "version": "npm run build && git add -A js" 107 | }, 108 | "title": "JavaScript Load Image", 109 | "version": "5.14.0" 110 | } 111 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "photoroom-api-web-demo", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "blueimp-load-image": { 8 | "version": "5.14.0", 9 | "resolved": "https://registry.npmjs.org/blueimp-load-image/-/blueimp-load-image-5.14.0.tgz", 10 | "integrity": "sha512-g5l+4dCOESBG8HkPLdGnBx8dhEwpQHaOZ0en623sl54o3bGhGMLYGc54L5cWfGmPvfKUjbsY7LOAmcW/xlkBSA==" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "photoroom-api-web-demo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.html", 6 | "scripts": { 7 | "start": "parcel index.html --open", 8 | "build": "parcel build index.html" 9 | }, 10 | "dependencies": { 11 | "blueimp-load-image": "^5.14.0", 12 | "parcel-bundler": "^1.6.1" 13 | }, 14 | "devDependencies": { 15 | "@babel/core": "7.2.0" 16 | }, 17 | "resolutions": { 18 | "@babel/preset-env": "7.13.8" 19 | }, 20 | "keywords": [] 21 | } 22 | -------------------------------------------------------------------------------- /spinner3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/racky7/image-background-remover/f9f6c8c70609c1249b1af671144afff6b8b601fc/spinner3.gif --------------------------------------------------------------------------------