From a7cfbf13122d5f1c6898cf98b82f4fd88cf697ce Mon Sep 17 00:00:00 2001 From: StudioMaX Date: Mon, 20 Apr 2020 12:36:13 +0600 Subject: [PATCH 001/159] Compatibility with jQuery 3.5.0 --- js/demo/demo.js | 6 +++--- js/vendor/jquery.Jcrop.js | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/js/demo/demo.js b/js/demo/demo.js index 6dc9fa3..b42cdcd 100644 --- a/js/demo/demo.js +++ b/js/demo/demo.js @@ -29,7 +29,7 @@ $(function () { * @param {object} tags Tags object */ function displayTagData(node, tags) { - var table = $('') + var table = $('
') var row = $('') var cell = $('') var prop @@ -59,7 +59,7 @@ $(function () { */ function displayThumbnailImage(node, thumbnail, options) { if (thumbnail) { - var link = $('') + var link = $('') .attr('href', loadImage.createObjectURL(thumbnail)) .attr('download', 'thumbnail.jpg') .appendTo(node) @@ -105,7 +105,7 @@ $(function () { result.children().replaceWith($('Loading image file failed')) return } - var content = $('').append(img) + var content = $('').append(img) result.children().replaceWith(content) if (data) { if (img.getContext) { diff --git a/js/vendor/jquery.Jcrop.js b/js/vendor/jquery.Jcrop.js index 41f80e6..a879391 100755 --- a/js/vendor/jquery.Jcrop.js +++ b/js/vendor/jquery.Jcrop.js @@ -329,7 +329,7 @@ boundy = $img.height(), - $div = $('
').width(boundx).height(boundy).addClass(cssClass('holder')).css({ + $div = $('
').width(boundx).height(boundy).addClass(cssClass('holder')).css({ position: 'relative', backgroundColor: options.bgColor }).insertAfter($origimg).append($img); @@ -338,19 +338,19 @@ $div.addClass(options.addClass); } - var $img2 = $('
'), + var $img2 = $('
'), - $img_holder = $('
') + $img_holder = $('
') .width('100%').height('100%').css({ zIndex: 310, position: 'absolute', overflow: 'hidden' }), - $hdl_holder = $('
') + $hdl_holder = $('
') .width('100%').height('100%').css('zIndex', 320), - $sel = $('
') + $sel = $('
') .css({ position: 'absolute', zIndex: 600 @@ -737,7 +737,7 @@ // Shade Module {{{ var Shade = (function() { var enabled = false, - holder = $('
').css({ + holder = $('
').css({ position: 'absolute', zIndex: 240, opacity: 0 @@ -779,7 +779,7 @@ }); } function createShade() { - return $('
').css({ + return $('
').css({ position: 'absolute', backgroundColor: options.shadeColor||options.bgColor }).appendTo(holder); @@ -863,7 +863,7 @@ // Private Methods function insertBorder(type) //{{{ { - var jq = $('
').css({ + var jq = $('
').css({ position: 'absolute', opacity: options.borderOpacity }).addClass(cssClass(type)); @@ -873,7 +873,7 @@ //}}} function dragDiv(ord, zi) //{{{ { - var jq = $('
').mousedown(createDragger(ord)).css({ + var jq = $('
').mousedown(createDragger(ord)).css({ cursor: ord + '-resize', position: 'absolute', zIndex: zi @@ -1226,7 +1226,7 @@ width: '12px' }).addClass('jcrop-keymgr'), - $keywrap = $('
').css({ + $keywrap = $('
').css({ position: 'absolute', overflow: 'hidden' }).append($keymgr); From 804fd90a10177d7a9ccdbdfde2a663046cb02a8e Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Mon, 20 Apr 2020 22:31:56 +0900 Subject: [PATCH 002/159] Remove unnecessary whitespace. --- README.md | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index cc067d4..3c7a154 100644 --- a/README.md +++ b/README.md @@ -240,100 +240,103 @@ Defines the minimum height of the img/canvas element. The width of the sub-rectangle of the source image to draw into the destination canvas. - Defaults to the source image width and requires `canvas: true`. +Defaults to the source image width and requires `canvas: true`. ### sourceHeight The height of the sub-rectangle of the source image to draw into the destination canvas. - Defaults to the source image height and requires `canvas: true`. +Defaults to the source image height and requires `canvas: true`. ### top The top margin of the sub-rectangle of the source image. - Defaults to `0` and requires `canvas: true`. +Defaults to `0` and requires `canvas: true`. ### right The right margin of the sub-rectangle of the source image. - Defaults to `0` and requires `canvas: true`. +Defaults to `0` and requires `canvas: true`. ### bottom The bottom margin of the sub-rectangle of the source image. - Defaults to `0` and requires `canvas: true`. +Defaults to `0` and requires `canvas: true`. ### left The left margin of the sub-rectangle of the source image. - Defaults to `0` and requires `canvas: true`. +Defaults to `0` and requires `canvas: true`. ### contain Scales the image up/down to contain it in the max dimensions if set to `true`. - This emulates the CSS feature [background-image: contain](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Scaling_background_images#contain). +This emulates the CSS feature +[background-image: contain](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Scaling_background_images#contain). ### cover Scales the image up/down to cover the max dimensions with the image dimensions if set to `true`. - This emulates the CSS feature [background-image: cover](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Scaling_background_images#cover). +This emulates the CSS feature +[background-image: cover](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Scaling_background_images#cover). ### aspectRatio Crops the image to the given aspect ratio (e.g. `16/9`). - Setting the `aspectRatio` also enables the `crop` option. +Setting the `aspectRatio` also enables the `crop` option. ### pixelRatio Defines the ratio of the canvas pixels to the physical image pixels on the screen. - Should be set to `window.devicePixelRatio` unless the scaled image is not rendered -on screen. - Defaults to `1` and requires `canvas: true`. +Should be set to `window.devicePixelRatio` unless the scaled image is not +rendered on screen. +Defaults to `1` and requires `canvas: true`. ### downsamplingRatio Defines the ratio in which the image is downsampled. - By default, images are downsampled in one step. With a ratio of `0.5`, each step +By default, images are downsampled in one step. With a ratio of `0.5`, each step scales the image to half the size, before reaching the target dimensions. - Requires `canvas: true`. +Requires `canvas: true`. ### imageSmoothingEnabled If set to `false`, [disables image smoothing](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingEnabled). - Defaults to `true` and requires `canvas: true`. +Defaults to `true` and requires `canvas: true`. ### imageSmoothingQuality Sets the [quality of image smoothing](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingQuality). - Possible values: `'low'`, `'medium'`, `'high'` - Defaults to `'low'` and requires `canvas: true`. +Possible values: `'low'`, `'medium'`, `'high'` +Defaults to `'low'` and requires `canvas: true`. ### crop Crops the image to the maxWidth/maxHeight constraints if set to `true`. - Enabling the `crop` option also enables the `canvas` option. +Enabling the `crop` option also enables the `canvas` option. ### orientation Transform the canvas according to the specified Exif orientation, which can be an `integer` in the range of `1` to `8` or the boolean value `true`. - When set to `true`, it will set the orientation value based on the EXIF data of +When set to `true`, it will set the orientation value based on the EXIF data of the image, which will be parsed automatically if the exif library is available. Setting `orientation` to an integer in the range of `2` to `8` enables the `canvas` option. - Setting `orientation` to `true` enables the `canvas` and `meta` options, unless -the browser supports automatic image orientation (see [browser support for image-orientation](https://caniuse.com/#feat=css-image-orientation)). +Setting `orientation` to `true` enables the `canvas` and `meta` options, unless +the browser supports automatic image orientation (see +[browser support for image-orientation](https://caniuse.com/#feat=css-image-orientation)). ### meta Automatically parses the image meta data if set to `true`. - The meta data is passed to the callback as part of the second argument. - If the file is given as URL and the browser supports the +The meta data is passed to the callback as part of the second argument. +If the file is given as URL and the browser supports the [fetch API](https://developer.mozilla.org/en/docs/Web/API/Fetch_API), fetches the file as Blob to be able to parse the meta data. From 3f7b50eab933a339b1dac49b284581957b245c85 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Mon, 20 Apr 2020 22:43:51 +0900 Subject: [PATCH 003/159] Clarify meta option. --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3c7a154..8a1e09a 100644 --- a/README.md +++ b/README.md @@ -335,10 +335,13 @@ the browser supports automatic image orientation (see ### meta Automatically parses the image meta data if set to `true`. -The meta data is passed to the callback as part of the second argument. +If meta data has been found, the data object passed as second argument to the +callback function has additional properties (see +[meta data parsing](#meta-data-parsing)). If the file is given as URL and the browser supports the -[fetch API](https://developer.mozilla.org/en/docs/Web/API/Fetch_API), fetches -the file as Blob to be able to parse the meta data. +[fetch API](https://developer.mozilla.org/en/docs/Web/API/Fetch_API) or the XHR +[responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType) +`blob`, fetches the file as Blob to be able to parse the meta data. ### canvas From addca35c4769526606d303f44a5064557a1f420b Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Mon, 20 Apr 2020 22:51:22 +0900 Subject: [PATCH 004/159] Flash tag is not in the base exif map anymore. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8a1e09a..0e334be 100644 --- a/README.md +++ b/README.md @@ -473,7 +473,7 @@ become available, as well as three additional methods: - `exif.getAll()` ```js -var flashText = data.exif.getText('Flash') // e.g.: 'Flash fired, auto mode', +var flashText = data.exif.getText('Orientation') // e.g. right-top for value 6 var name = data.exif.getName(0x0112) // Orientation From 2715acb296be9dbbd122fbf4131bb2958becb635 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Mon, 20 Apr 2020 22:56:47 +0900 Subject: [PATCH 005/159] Add headlines for the Exif/IPTC parser options. --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0e334be..48c2d33 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,10 @@ - [Meta data parsing](#meta-data-parsing) - [Image head](#image-head) - [Exif parser](#exif-parser) + - [Exif parser options](#exif-parser-options) - [Exif writer](#exif-writer) - [IPTC parser](#iptc-parser) + - [IPTC parser options](#iptc-parser-options) - [License](#license) - [Credits](#credits) @@ -481,8 +483,9 @@ var name = data.exif.getName(0x0112) // Orientation var allTags = data.exif.getAll() ``` -The Exif parser also adds additional options for the parseMetaData method, to -disable certain aspects of the parser: +#### Exif parser options + +The Exif parser adds additional options: - `disableExif`: Disables Exif parsing when `true`. - `disableExifThumbnail`: Disables parsing of Thumbnail data when `true`. @@ -599,8 +602,9 @@ var name = data.iptc.getName(5) // ObjectName var allTags = data.iptc.getAll() ``` -The IPTC parser also adds additional options for the parseMetaData method, to -disable certain aspects of the parser: +#### IPTC parser options + +The IPTC parser adds additional options: - `disableIptc`: Disables IPTC parsing when true. - `disableIptcOffsets`: Disables storing IPTC tag offsets when `true`. From b96a82149f6fb13befc1764caec141647b1324e7 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Mon, 20 Apr 2020 23:35:53 +0900 Subject: [PATCH 006/159] Add examples for parsing Exif Thumbnail and IFDs. --- README.md | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 48c2d33..865156c 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,10 @@ - [Meta data parsing](#meta-data-parsing) - [Image head](#image-head) - [Exif parser](#exif-parser) + - [Exif Thumbnail](#exif-thumbnail) + - [Exif IFD](#exif-ifd) + - [GPSInfo IFD](#gpsinfo-ifd) + - [Interoperability IFD](#interoperability-ifd) - [Exif parser options](#exif-parser-options) - [Exif writer](#exif-writer) - [IPTC parser](#iptc-parser) @@ -463,9 +467,9 @@ By default, only the following names are mapped: - `Orientation` - `Thumbnail` -- `Exif` -- `GPSInfo` -- `Interoperability` +- `Exif` (see [Exif IFD](#exif-ifd)) +- `GPSInfo` (see [GPSInfo IFD](#gpsinfo-ifd)) +- `Interoperability` (see [Interoperability IFD](#interoperability-ifd)) If you also include the Load Image Exif Map library, additional tag mappings become available, as well as three additional methods: @@ -483,6 +487,86 @@ var name = data.exif.getName(0x0112) // Orientation var allTags = data.exif.getAll() ``` +#### Exif Thumbnail + +Example code displaying a thumbnail image embedded into the Exif meta data: + +```js +loadImage( + fileOrBlobOrUrl, + function (img, data) { + var thumbBlob = data.exif && data.exif.get('Thumbnail') + if (thumbBlob) { + loadImage(thumbBlob, function (thumbImage) { + document.body.appendChild(thumbImage) + }) + } + }, + { meta: true } +) +``` + +#### Exif IFD + +Example code displaying data from the Exif IFD (Image File Directory) that +contains Exif specified TIFF tags: + +```js +loadImage( + fileOrBlobOrUrl, + function (img, data) { + var exifIFD = data.exif && data.exif.get('Exif') + if (exifIFD) { + // Map of all Exif IFD tags with their mapped names/text as keys/values: + console.log(exifIFD.getAll()) + // A specific Exif IFD tag value: + console.log(exifIFD.get('UserComment')) + } + }, + { meta: true } +) +``` + +#### GPSInfo IFD + +Example code displaying data from the Exif IFD (Image File Directory) that +contains [GPS](https://en.wikipedia.org/wiki/Global_Positioning_System) info: + +```js +loadImage( + fileOrBlobOrUrl, + function (img, data) { + var gpsInfo = data.exif && data.exif.get('GPSInfo') + if (gpsInfo) { + // Map of all GPSInfo tags with their mapped names/text as keys/values: + console.log(gpsInfo.getAll()) + // A specific GPSInfo tag value: + console.log(gpsInfo.get('GPSLatitude')) + } + }, + { meta: true } +) +``` + +#### Interoperability IFD + +Example code displaying data from the Exif IFD (Image File Directory) that +contains Interoperability data: + +```js +loadImage( + fileOrBlobOrUrl, + function (img, data) { + var interoperabilityData = data.exif && data.exif.get('Interoperability') + if (interoperabilityData) { + // The InteroperabilityIndex tag value: + console.log(interoperabilityData.get('InteroperabilityIndex')) + } + }, + { meta: true } +) +``` + #### Exif parser options The Exif parser adds additional options: From 6869b3b537e0e88f7e9cad04932aaca922708e05 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Tue, 21 Apr 2020 17:34:37 +0900 Subject: [PATCH 007/159] Remove unnecessary "Should" as test prefix. --- test/test.js | 66 ++++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/test/test.js b/test/test.js index 35f9eab..cb1cd8d 100644 --- a/test/test.js +++ b/test/test.js @@ -682,7 +682,7 @@ }) describe('Orientation', function () { - it('Should keep the orientation', function (done) { + it('Keep the orientation', function (done) { expect( loadImage( blobGIF, @@ -696,7 +696,7 @@ ).to.be.ok }) - it('Should rotate left', function (done) { + it('Rotate left', function (done) { expect( loadImage( blobGIF, @@ -710,7 +710,7 @@ ).to.be.ok }) - it('Should rotate right', function (done) { + it('Rotate right', function (done) { expect( loadImage( blobGIF, @@ -724,7 +724,7 @@ ).to.be.ok }) - it('Should adjust constraints to new coordinates', function (done) { + it('Adjust constraints to new coordinates', function (done) { expect( loadImage( blobGIF, @@ -738,7 +738,7 @@ ).to.be.ok }) - it('Should adjust left and top to new coordinates', function (done) { + it('Adjust left and top to new coordinates', function (done) { expect( loadImage( blobGIF, @@ -752,7 +752,7 @@ ).to.be.ok }) - it('Should adjust right and bottom to new coordinates', function (done) { + it('Adjust right and bottom to new coordinates', function (done) { expect( loadImage( blobGIF, @@ -766,7 +766,7 @@ ).to.be.ok }) - it('Should adjust left and bottom to new coordinates', function (done) { + it('Adjust left and bottom to new coordinates', function (done) { expect( loadImage( blobGIF, @@ -780,7 +780,7 @@ ).to.be.ok }) - it('Should adjust right and top to new coordinates', function (done) { + it('Adjust right and top to new coordinates', function (done) { expect( loadImage( blobGIF, @@ -794,7 +794,7 @@ ).to.be.ok }) - it('Should rotate left with the given pixelRatio', function (done) { + it('Rotate left with the given pixelRatio', function (done) { expect( loadImage( blobGIF, @@ -810,7 +810,7 @@ ).to.be.ok }) - it('Should rotate right with the given pixelRatio', function (done) { + it('Rotate right with the given pixelRatio', function (done) { expect( loadImage( blobGIF, @@ -826,7 +826,7 @@ ).to.be.ok }) - it('Should ignore too small orientation value', function (done) { + it('Ignore too small orientation value', function (done) { expect( loadImage( blobGIF, @@ -840,7 +840,7 @@ ).to.be.ok }) - it('Should ignore too large orientation value', function (done) { + it('Ignore too large orientation value', function (done) { expect( loadImage( blobGIF, @@ -854,7 +854,7 @@ ).to.be.ok }) - it('Should rotate right based on the exif orientation value', function (done) { + it('Rotate right based on the exif orientation value', function (done) { expect( loadImage( blobJPEG, @@ -906,7 +906,7 @@ ).to.be.ok }) - it('Should scale image after exif based orientation', function (done) { + it('Scale image after exif based orientation', function (done) { expect( loadImage( blobJPEG, @@ -923,7 +923,7 @@ describe('from-image', function () { if (!loadImage.orientation) return - it('Should use automatic browser image orientation', function (done) { + it('Use automatic browser image orientation', function (done) { expect( loadImage( blobJPEG, @@ -1005,7 +1005,7 @@ }) describe('Metadata', function () { - it('Should parse Exif tags', function (done) { + it('Parse Exif tags', function (done) { loadImage.parseMetaData(blobJPEG, function (data) { expect(data.exif).to.be.ok expect(data.exif.get('Orientation')).to.equal(6) @@ -1013,7 +1013,7 @@ }) }) - it('Should not parse Exif tags if disabled', function (done) { + it('Do not parse Exif tags if disabled', function (done) { loadImage.parseMetaData( blobJPEG, function (data) { @@ -1024,7 +1024,7 @@ ) }) - it('Should parse Exif tag offsets', function (done) { + it('Parse Exif tag offsets', function (done) { loadImage.parseMetaData(blobJPEG, function (data) { expect(data.exifOffsets).to.be.ok expect(data.exifOffsets.get('Orientation')).to.equal(0x16) @@ -1034,7 +1034,7 @@ }) }) - it('Should not parse Exif tag offsets if disabled', function (done) { + it('Do not parse Exif tag offsets if disabled', function (done) { loadImage.parseMetaData( blobJPEG, function (data) { @@ -1045,7 +1045,7 @@ ) }) - it('Should only parse included Exif tags', function (done) { + it('Only parse included Exif tags', function (done) { loadImage.parseMetaData( blobJPEG, function (data) { @@ -1065,7 +1065,7 @@ ) }) - it('Should not parse excluded Exif tags', function (done) { + it('Do not parse excluded Exif tags', function (done) { loadImage.parseMetaData( blobJPEG, function (data) { @@ -1085,7 +1085,7 @@ ) }) - it('Should parse IPTC tags', function (done) { + it('Parse IPTC tags', function (done) { loadImage.parseMetaData(blobJPEG, function (data) { expect(data.iptc).to.be.ok expect(data.iptc.get('ObjectName')).to.equal('blueimp.net') @@ -1093,7 +1093,7 @@ }) }) - it('Should not parse IPTC tags if disabled', function (done) { + it('Do not parse IPTC tags if disabled', function (done) { loadImage.parseMetaData( blobJPEG, function (data) { @@ -1104,7 +1104,7 @@ ) }) - it('Should parse IPTC tag offsets', function (done) { + it('Parse IPTC tag offsets', function (done) { loadImage.parseMetaData(blobJPEG, function (data) { expect(data.iptcOffsets).to.be.ok expect(data.iptcOffsets.get('ObjectName')).to.equal(0x44) @@ -1112,7 +1112,7 @@ }) }) - it('Should not parse IPTC tag offsets if disabled', function (done) { + it('Do not parse IPTC tag offsets if disabled', function (done) { loadImage.parseMetaData( blobJPEG, function (data) { @@ -1123,7 +1123,7 @@ ) }) - it('Should only parse included IPTC tags', function (done) { + it('Only parse included IPTC tags', function (done) { loadImage.parseMetaData( blobJPEG, function (data) { @@ -1145,7 +1145,7 @@ ) }) - it('Should not parse excluded IPTC tags', function (done) { + it('Do not parse excluded IPTC tags', function (done) { loadImage.parseMetaData( blobJPEG, function (data) { @@ -1167,7 +1167,7 @@ ) }) - it('Should parse the complete image head', function (done) { + it('Parse the complete image head', function (done) { loadImage.parseMetaData(blobJPEG, function (data) { expect(data.imageHead).to.be.ok loadImage.parseMetaData( @@ -1181,7 +1181,7 @@ }) }) - it('Should not parse the complete image head if disabled', function (done) { + it('Do not parse the complete image head if disabled', function (done) { loadImage.parseMetaData( blobJPEG, function (data) { @@ -1192,7 +1192,7 @@ ) }) - it('Should parse meta data automatically', function (done) { + it('Parse meta data automatically', function (done) { expect( loadImage( blobJPEG, @@ -1210,7 +1210,7 @@ ).to.be.ok }) - it('Should write Exif Orientation tag and replace image head', function (done) { + it('Write Exif Orientation tag and replace image head', function (done) { loadImage( blobJPEG, function (img, data) { @@ -1253,7 +1253,7 @@ return } - it('Should fetch image URL as blob if meta option is true', function (done) { + it('Fetch image URL as blob if meta option is true', function (done) { expect( loadImage( // IE does not allow XMLHttpRequest access to data URLs, @@ -1273,7 +1273,7 @@ ).to.be.ok }) - it('Should load image URL as img if meta option is false', function (done) { + it('Load image URL as img if meta option is false', function (done) { expect( loadImage(imageUrlJPEG, function (img, data) { expect(data.imageHead).to.be.undefined From 4931b411b0d1df37850e0c480ee521a10e2e20a6 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Tue, 21 Apr 2020 23:16:45 +0900 Subject: [PATCH 008/159] Always pass a data arg to getTransformedOptions. --- js/load-image-scale.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/load-image-scale.js b/js/load-image-scale.js index 57ac273..dbebf50 100644 --- a/js/load-image-scale.js +++ b/js/load-image-scale.js @@ -45,7 +45,7 @@ // Returns transformed options, allows to override e.g. // maxWidth, maxHeight and crop options based on the aspectRatio. - // gets img, options passed as arguments: + // gets img, options, data passed as arguments: loadImage.getTransformedOptions = function (img, options) { var aspectRatio = options.aspectRatio var newOptions @@ -168,7 +168,7 @@ } if (useCanvas) { // eslint-disable-next-line no-param-reassign - options = loadImage.getTransformedOptions(img, options, data) + options = loadImage.getTransformedOptions(img, options, data || {}) sourceX = options.left || 0 sourceY = options.top || 0 if (options.sourceWidth) { From 379922b53b38a601738dfa8e79d3a396d494e82d Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Tue, 21 Apr 2020 23:23:47 +0900 Subject: [PATCH 009/159] Ensure pixelRatio scaling is idempotent. --- js/load-image-scale.js | 16 +++++++++++----- test/test.js | 12 ++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/js/load-image-scale.js b/js/load-image-scale.js index dbebf50..a662dde 100644 --- a/js/load-image-scale.js +++ b/js/load-image-scale.js @@ -225,11 +225,17 @@ if (useCanvas) { pixelRatio = options.pixelRatio if (pixelRatio > 1) { - canvas.style.width = destWidth + 'px' - canvas.style.height = destHeight + 'px' - destWidth *= pixelRatio - destHeight *= pixelRatio - canvas.getContext('2d').scale(pixelRatio, pixelRatio) + if (parseInt(img.style.width, 10) === width / pixelRatio) { + // Source image is already scaled according to device pixel ratio + canvas.style.width = destWidth / pixelRatio + 'px' + canvas.style.height = destHeight / pixelRatio + 'px' + } else { + canvas.style.width = destWidth + 'px' + canvas.style.height = destHeight + 'px' + destWidth *= pixelRatio + destHeight *= pixelRatio + canvas.getContext('2d').scale(pixelRatio, pixelRatio) + } } downsamplingRatio = options.downsamplingRatio if ( diff --git a/test/test.js b/test/test.js index cb1cd8d..1e688ae 100644 --- a/test/test.js +++ b/test/test.js @@ -300,6 +300,12 @@ expect(img.height).to.equal(160) expect(img.style.width).to.equal('120px') expect(img.style.height).to.equal('80px') + // Check if pixelRatio scaling is idempotent: + var img2 = loadImage.scale(img, { minWidth: 120, pixelRatio: 2 }) + expect(img2.width).to.equal(240) + expect(img2.height).to.equal(160) + expect(img2.style.width).to.equal('120px') + expect(img2.style.height).to.equal('80px') done() }, { minWidth: 120, canvas: true, pixelRatio: 2 } @@ -316,6 +322,12 @@ expect(img.height).to.equal(40) expect(img.style.width).to.equal('30px') expect(img.style.height).to.equal('20px') + // Check if pixelRatio scaling is idempotent: + var img2 = loadImage.scale(img, { minWidth: 30, pixelRatio: 2 }) + expect(img2.width).to.equal(60) + expect(img2.height).to.equal(40) + expect(img2.style.width).to.equal('30px') + expect(img2.style.height).to.equal('20px') done() }, { maxWidth: 30, canvas: true, pixelRatio: 2 } From 029ac424c3a9bb4c40951a1e12c73424c0808f00 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Tue, 21 Apr 2020 23:39:31 +0900 Subject: [PATCH 010/159] Document orientation values visually in source. --- js/load-image-orientation.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/js/load-image-orientation.js b/js/load-image-orientation.js index 74a5be1..7527527 100644 --- a/js/load-image-orientation.js +++ b/js/load-image-orientation.js @@ -9,6 +9,20 @@ * https://opensource.org/licenses/MIT */ +/* + +Exif orientation values to correctly display the letter F: + + 1 2 3 4 5 6 7 8 + +██████ ██████ ██ ██ ██████████ ██ ██ ██████████ +██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +████ ████ ████ ████ ██ ██████████ ██████████ ██ +██ ██ ██ ██ +██ ██ ██████ ██████ + +*/ + /* global define, module, require */ ;(function (factory) { From cda87fc468211987d808be08dc7ab06c059fa3e7 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Tue, 21 Apr 2020 23:41:32 +0900 Subject: [PATCH 011/159] Add missing degree character in source comments. --- js/load-image-orientation.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/load-image-orientation.js b/js/load-image-orientation.js index 7527527..e48ebcd 100644 --- a/js/load-image-orientation.js +++ b/js/load-image-orientation.js @@ -119,7 +119,7 @@ Exif orientation values to correctly display the letter F: ctx.scale(1, -1) break case 5: - // vertical flip + 90 rotate right + // vertical flip + 90° rotate right ctx.rotate(0.5 * Math.PI) ctx.scale(1, -1) break @@ -129,7 +129,7 @@ Exif orientation values to correctly display the letter F: ctx.translate(0, -height) break case 7: - // horizontal flip + 90 rotate right + // horizontal flip + 90° rotate right ctx.rotate(0.5 * Math.PI) ctx.translate(width, -height) ctx.scale(-1, 1) @@ -185,7 +185,7 @@ Exif orientation values to correctly display the letter F: newOptions.bottom = options.top break case 5: - // vertical flip + 90 rotate right + // vertical flip + 90° rotate right newOptions.left = options.top newOptions.top = options.left newOptions.right = options.bottom @@ -199,7 +199,7 @@ Exif orientation values to correctly display the letter F: newOptions.bottom = options.left break case 7: - // horizontal flip + 90 rotate right + // horizontal flip + 90° rotate right newOptions.left = options.bottom newOptions.top = options.right newOptions.right = options.top From 61761388e0b9fff19acef3c4d5c1413c11b8c843 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Tue, 21 Apr 2020 23:45:39 +0900 Subject: [PATCH 012/159] Normalize original width+height dimensions. Switch reported original dimensions for browsers with automatic image orientation. --- js/load-image-orientation.js | 28 ++++++++++++++++++++++++++++ test/test.js | 14 ++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/js/load-image-orientation.js b/js/load-image-orientation.js index e48ebcd..41ac1ee 100644 --- a/js/load-image-orientation.js +++ b/js/load-image-orientation.js @@ -43,6 +43,7 @@ Exif orientation values to correctly display the letter F: })(function (loadImage) { 'use strict' + var originalTransform = loadImage.transform var originalHasCanvasOption = loadImage.hasCanvasOption var originalHasMetaOption = loadImage.hasMetaOption var originalTransformCoordinates = loadImage.transformCoordinates @@ -66,6 +67,33 @@ Exif orientation values to correctly display the letter F: img.src = testImageURL })() + loadImage.transform = function (img, options, callback, file, data) { + originalTransform.call( + loadImage, + img, + options, + function (img, data) { + if (data) { + var exifOrientation = data.exif && data.exif.get('Orientation') + if ( + loadImage.orientation && + exifOrientation > 4 && + exifOrientation < 9 + ) { + // Automatic image orientation switched image dimensions + var originalWidth = data.originalWidth + var originalHeight = data.originalHeight + data.originalWidth = originalHeight + data.originalHeight = originalWidth + } + } + callback(img, data) + }, + file, + data + ) + } + // Determines if the target image should be a canvas element: loadImage.hasCanvasOption = function (options) { return ( diff --git a/test/test.js b/test/test.js index 1e688ae..84b4a4b 100644 --- a/test/test.js +++ b/test/test.js @@ -932,6 +932,20 @@ ).to.be.ok }) + it('Provide original image width+height from before orientation', function (done) { + expect( + loadImage( + blobJPEG, + function (img, data) { + expect(data.originalWidth).to.equal(3) + expect(data.originalHeight).to.equal(2) + done() + }, + { meta: true, minWidth: 20, minHeight: 30 } + ) + ).to.be.ok + }) + describe('from-image', function () { if (!loadImage.orientation) return From 2e72d13f9f4de50623d9b7e057d969e2121aa0ea Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Tue, 21 Apr 2020 23:46:48 +0900 Subject: [PATCH 013/159] Return early for invalid orientation values. --- js/load-image-orientation.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/js/load-image-orientation.js b/js/load-image-orientation.js index 41ac1ee..71faf2f 100644 --- a/js/load-image-orientation.js +++ b/js/load-image-orientation.js @@ -111,19 +111,18 @@ Exif orientation values to correctly display the letter F: ) } - // Transform image orientation based on - // the given EXIF orientation option: + // Transform image orientation based on the given EXIF orientation option: loadImage.transformCoordinates = function (canvas, options) { originalTransformCoordinates.call(loadImage, canvas, options) + var orientation = options.orientation + if (!(orientation > 1 && orientation < 9)) { + return + } var ctx = canvas.getContext('2d') var width = canvas.width var height = canvas.height var styleWidth = canvas.style.width var styleHeight = canvas.style.height - var orientation = options.orientation - if (!(orientation > 1 && orientation < 9)) { - return - } if (orientation > 4) { canvas.width = height canvas.height = width From ae7013d4084a1b82a283be23c0543e92bd8ff2c2 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Tue, 21 Apr 2020 23:49:37 +0900 Subject: [PATCH 014/159] Move transformCoordinates declaration to the end. --- js/load-image-orientation.js | 116 +++++++++++++++++------------------ 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/js/load-image-orientation.js b/js/load-image-orientation.js index 71faf2f..2f28171 100644 --- a/js/load-image-orientation.js +++ b/js/load-image-orientation.js @@ -111,64 +111,6 @@ Exif orientation values to correctly display the letter F: ) } - // Transform image orientation based on the given EXIF orientation option: - loadImage.transformCoordinates = function (canvas, options) { - originalTransformCoordinates.call(loadImage, canvas, options) - var orientation = options.orientation - if (!(orientation > 1 && orientation < 9)) { - return - } - var ctx = canvas.getContext('2d') - var width = canvas.width - var height = canvas.height - var styleWidth = canvas.style.width - var styleHeight = canvas.style.height - if (orientation > 4) { - canvas.width = height - canvas.height = width - canvas.style.width = styleHeight - canvas.style.height = styleWidth - } - switch (orientation) { - case 2: - // horizontal flip - ctx.translate(width, 0) - ctx.scale(-1, 1) - break - case 3: - // 180° rotate left - ctx.translate(width, height) - ctx.rotate(Math.PI) - break - case 4: - // vertical flip - ctx.translate(0, height) - ctx.scale(1, -1) - break - case 5: - // vertical flip + 90° rotate right - ctx.rotate(0.5 * Math.PI) - ctx.scale(1, -1) - break - case 6: - // 90° rotate right - ctx.rotate(0.5 * Math.PI) - ctx.translate(0, -height) - break - case 7: - // horizontal flip + 90° rotate right - ctx.rotate(0.5 * Math.PI) - ctx.translate(width, -height) - ctx.scale(-1, 1) - break - case 8: - // 90° rotate left - ctx.rotate(-0.5 * Math.PI) - ctx.translate(-width, 0) - break - } - } - // Transforms coordinate and dimension options // based on the given orientation option: loadImage.getTransformedOptions = function (img, opts, data) { @@ -250,4 +192,62 @@ Exif orientation values to correctly display the letter F: } return newOptions } + + // Transform image orientation based on the given EXIF orientation option: + loadImage.transformCoordinates = function (canvas, options) { + originalTransformCoordinates.call(loadImage, canvas, options) + var orientation = options.orientation + if (!(orientation > 1 && orientation < 9)) { + return + } + var ctx = canvas.getContext('2d') + var width = canvas.width + var height = canvas.height + var styleWidth = canvas.style.width + var styleHeight = canvas.style.height + if (orientation > 4) { + canvas.width = height + canvas.height = width + canvas.style.width = styleHeight + canvas.style.height = styleWidth + } + switch (orientation) { + case 2: + // horizontal flip + ctx.translate(width, 0) + ctx.scale(-1, 1) + break + case 3: + // 180° rotate left + ctx.translate(width, height) + ctx.rotate(Math.PI) + break + case 4: + // vertical flip + ctx.translate(0, height) + ctx.scale(1, -1) + break + case 5: + // vertical flip + 90° rotate right + ctx.rotate(0.5 * Math.PI) + ctx.scale(1, -1) + break + case 6: + // 90° rotate right + ctx.rotate(0.5 * Math.PI) + ctx.translate(0, -height) + break + case 7: + // horizontal flip + 90° rotate right + ctx.rotate(0.5 * Math.PI) + ctx.translate(width, -height) + ctx.scale(-1, 1) + break + case 8: + // 90° rotate left + ctx.rotate(-0.5 * Math.PI) + ctx.translate(-width, 0) + break + } + } }) From 83ace3efe41ffbf8221431f546365918311656aa Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Wed, 22 Apr 2020 00:07:26 +0900 Subject: [PATCH 015/159] Remove unnecessary double negation. --- js/load-image-orientation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/load-image-orientation.js b/js/load-image-orientation.js index 2f28171..312f6ac 100644 --- a/js/load-image-orientation.js +++ b/js/load-image-orientation.js @@ -97,7 +97,7 @@ Exif orientation values to correctly display the letter F: // Determines if the target image should be a canvas element: loadImage.hasCanvasOption = function (options) { return ( - (!!options.orientation === true && !loadImage.orientation) || + (options.orientation === true && !loadImage.orientation) || (options.orientation > 1 && options.orientation < 9) || originalHasCanvasOption.call(loadImage, options) ) From 2abe1704e69886711b4b3b8bafe946822a57f7cc Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Wed, 22 Apr 2020 18:31:51 +0900 Subject: [PATCH 016/159] Pass data object to transformCoordinates function. --- js/load-image-scale.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/js/load-image-scale.js b/js/load-image-scale.js index a662dde..2f1fcc7 100644 --- a/js/load-image-scale.js +++ b/js/load-image-scale.js @@ -40,7 +40,7 @@ // Transform image coordinates, allows to override e.g. // the canvas orientation based on the orientation option, - // gets canvas, options passed as arguments: + // gets canvas, options and data passed as arguments: loadImage.transformCoordinates = function () {} // Returns transformed options, allows to override e.g. @@ -121,6 +121,8 @@ loadImage.scale = function (img, options, data) { // eslint-disable-next-line no-param-reassign options = options || {} + // eslint-disable-next-line no-param-reassign + data = data || {} var canvas = document.createElement('canvas') var useCanvas = img.getContext || @@ -168,7 +170,7 @@ } if (useCanvas) { // eslint-disable-next-line no-param-reassign - options = loadImage.getTransformedOptions(img, options, data || {}) + options = loadImage.getTransformedOptions(img, options, data) sourceX = options.left || 0 sourceY = options.top || 0 if (options.sourceWidth) { @@ -285,7 +287,7 @@ } canvas.width = destWidth canvas.height = destHeight - loadImage.transformCoordinates(canvas, options) + loadImage.transformCoordinates(canvas, options, data) return loadImage.renderImageToCanvas( canvas, img, From e52c67b9f77c18a9a7a6f0f22b04ea0a80ce63ae Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Wed, 22 Apr 2020 21:22:09 +0900 Subject: [PATCH 017/159] Rename functions for canvas and meta requirements. --- js/load-image-meta.js | 2 +- js/load-image-orientation.js | 12 ++++++------ js/load-image-scale.js | 10 +++------- js/load-image.js | 4 ++-- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/js/load-image-meta.js b/js/load-image-meta.js index ecdb077..63177d3 100644 --- a/js/load-image-meta.js +++ b/js/load-image-meta.js @@ -181,7 +181,7 @@ var originalTransform = loadImage.transform loadImage.transform = function (img, options, callback, file, data) { - if (loadImage.hasMetaOption(options)) { + if (loadImage.requiresMetaData(options)) { loadImage.parseMetaData( file, function (data) { diff --git a/js/load-image-orientation.js b/js/load-image-orientation.js index 312f6ac..ce0557f 100644 --- a/js/load-image-orientation.js +++ b/js/load-image-orientation.js @@ -44,8 +44,8 @@ Exif orientation values to correctly display the letter F: 'use strict' var originalTransform = loadImage.transform - var originalHasCanvasOption = loadImage.hasCanvasOption - var originalHasMetaOption = loadImage.hasMetaOption + var originalRequiresCanvas = loadImage.requiresCanvas + var originalRequiresMetaData = loadImage.requiresMetaData var originalTransformCoordinates = loadImage.transformCoordinates var originalGetTransformedOptions = loadImage.getTransformedOptions @@ -95,19 +95,19 @@ Exif orientation values to correctly display the letter F: } // Determines if the target image should be a canvas element: - loadImage.hasCanvasOption = function (options) { + loadImage.requiresCanvas = function (options) { return ( (options.orientation === true && !loadImage.orientation) || (options.orientation > 1 && options.orientation < 9) || - originalHasCanvasOption.call(loadImage, options) + originalRequiresCanvas.call(loadImage, options) ) } // Determines if meta data should be loaded automatically: - loadImage.hasMetaOption = function (options) { + loadImage.requiresMetaData = function (options) { return ( (options && options.orientation === true && !loadImage.orientation) || - originalHasMetaOption.call(loadImage, options) + originalRequiresMetaData.call(loadImage, options) ) } diff --git a/js/load-image-scale.js b/js/load-image-scale.js index 2f1fcc7..53fe5e6 100644 --- a/js/load-image-scale.js +++ b/js/load-image-scale.js @@ -109,15 +109,12 @@ } // Determines if the target image should be a canvas element: - loadImage.hasCanvasOption = function (options) { + loadImage.requiresCanvas = function (options) { return options.canvas || options.crop || !!options.aspectRatio } // Scales and/or crops the given image (img or canvas HTML element) - // using the given options. - // Returns a canvas object if the browser supports canvas - // and the hasCanvasOption method returns true or a canvas - // object is passed as image, else the scaled image: + // using the given options: loadImage.scale = function (img, options, data) { // eslint-disable-next-line no-param-reassign options = options || {} @@ -125,8 +122,7 @@ data = data || {} var canvas = document.createElement('canvas') var useCanvas = - img.getContext || - (loadImage.hasCanvasOption(options) && canvas.getContext) + img.getContext || (loadImage.requiresCanvas(options) && canvas.getContext) var width = img.naturalWidth || img.width var height = img.naturalHeight || img.height var destWidth = width diff --git a/js/load-image.js b/js/load-image.js index 50a36cd..865586d 100644 --- a/js/load-image.js +++ b/js/load-image.js @@ -54,7 +54,7 @@ return loadImage.onload(img, event, file, url, callback, options) } if (typeof file === 'string') { - if (loadImage.hasMetaOption(options)) { + if (loadImage.requiresMetaData(options)) { loadImage.fetchBlob(file, fetchBlobCallback, options) } else { fetchBlobCallback() @@ -102,7 +102,7 @@ // Determines if meta data should be loaded automatically. // Requires the load image meta extension to load meta data. - loadImage.hasMetaOption = function (options) { + loadImage.requiresMetaData = function (options) { return options && options.meta } From 0a0dc98c0103463de2e8911306c8726321c842e8 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Wed, 22 Apr 2020 21:43:28 +0900 Subject: [PATCH 018/159] Refactor canvas+meta requirement checks for reuse. --- js/load-image-orientation.js | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/js/load-image-orientation.js b/js/load-image-orientation.js index ce0557f..6920d73 100644 --- a/js/load-image-orientation.js +++ b/js/load-image-orientation.js @@ -94,11 +94,31 @@ Exif orientation values to correctly display the letter F: ) } + /** + * Determines if the image requires orientation. + * + * @param {object} [options] Options object + * @param {boolean} [withMetaData] Is meta data required for orientation + * @returns {boolean} Returns true if the image requires orientation + */ + function requiresOrientation(options, withMetaData) { + var orientation = options && options.orientation + return ( + // Exif orientation for browsers without automatic image orientation: + (orientation === true && !loadImage.orientation) || + // Orientation reset for browsers with automatic image orientation: + (orientation === 1 && loadImage.orientation) || + // Orientation to defined value, requires meta data for orientation reset: + ((!withMetaData || loadImage.orientation) && + orientation > 1 && + orientation < 9) + ) + } + // Determines if the target image should be a canvas element: loadImage.requiresCanvas = function (options) { return ( - (options.orientation === true && !loadImage.orientation) || - (options.orientation > 1 && options.orientation < 9) || + requiresOrientation(options) || originalRequiresCanvas.call(loadImage, options) ) } @@ -106,7 +126,7 @@ Exif orientation values to correctly display the letter F: // Determines if meta data should be loaded automatically: loadImage.requiresMetaData = function (options) { return ( - (options && options.orientation === true && !loadImage.orientation) || + requiresOrientation(options, true) || originalRequiresMetaData.call(loadImage, options) ) } From a3eb4cda44a6b7d3327af93fe970151dea697f0c Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Wed, 22 Apr 2020 21:45:16 +0900 Subject: [PATCH 019/159] Move transform function below requirements checks. --- js/load-image-orientation.js | 54 ++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/js/load-image-orientation.js b/js/load-image-orientation.js index 6920d73..edddb7c 100644 --- a/js/load-image-orientation.js +++ b/js/load-image-orientation.js @@ -67,33 +67,6 @@ Exif orientation values to correctly display the letter F: img.src = testImageURL })() - loadImage.transform = function (img, options, callback, file, data) { - originalTransform.call( - loadImage, - img, - options, - function (img, data) { - if (data) { - var exifOrientation = data.exif && data.exif.get('Orientation') - if ( - loadImage.orientation && - exifOrientation > 4 && - exifOrientation < 9 - ) { - // Automatic image orientation switched image dimensions - var originalWidth = data.originalWidth - var originalHeight = data.originalHeight - data.originalWidth = originalHeight - data.originalHeight = originalWidth - } - } - callback(img, data) - }, - file, - data - ) - } - /** * Determines if the image requires orientation. * @@ -131,6 +104,33 @@ Exif orientation values to correctly display the letter F: ) } + loadImage.transform = function (img, options, callback, file, data) { + originalTransform.call( + loadImage, + img, + options, + function (img, data) { + if (data) { + var exifOrientation = data.exif && data.exif.get('Orientation') + if ( + loadImage.orientation && + exifOrientation > 4 && + exifOrientation < 9 + ) { + // Automatic image orientation switched image dimensions + var originalWidth = data.originalWidth + var originalHeight = data.originalHeight + data.originalWidth = originalHeight + data.originalHeight = originalWidth + } + } + callback(img, data) + }, + file, + data + ) + } + // Transforms coordinate and dimension options // based on the given orientation option: loadImage.getTransformedOptions = function (img, opts, data) { From 212a3a3dcc138da248163795e2fa9221b3d4c614 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Wed, 22 Apr 2020 23:35:29 +0900 Subject: [PATCH 020/159] Arrange Exif orientation visualization vertically. --- js/load-image-orientation.js | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/js/load-image-orientation.js b/js/load-image-orientation.js index edddb7c..f700df1 100644 --- a/js/load-image-orientation.js +++ b/js/load-image-orientation.js @@ -10,16 +10,31 @@ */ /* - Exif orientation values to correctly display the letter F: - 1 2 3 4 5 6 7 8 + 1 2 + ██████ ██████ + ██ ██ + ████ ████ + ██ ██ + ██ ██ + + 3 4 + ██ ██ + ██ ██ + ████ ████ + ██ ██ + ██████ ██████ + + 5 6 +██████████ ██ +██ ██ ██ ██ +██ ██████████ -██████ ██████ ██ ██ ██████████ ██ ██ ██████████ -██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ -████ ████ ████ ████ ██ ██████████ ██████████ ██ -██ ██ ██ ██ -██ ██ ██████ ██████ + 7 8 + ██ ██████████ + ██ ██ ██ ██ +██████████ ██ */ From 7e5f90b8c623bcdb2088715af89686f2ccb877b2 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Wed, 22 Apr 2020 23:36:38 +0900 Subject: [PATCH 021/159] Update orientation requirements for canvas/meta. --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 865156c..75d87c7 100644 --- a/README.md +++ b/README.md @@ -332,11 +332,15 @@ an `integer` in the range of `1` to `8` or the boolean value `true`. When set to `true`, it will set the orientation value based on the EXIF data of the image, which will be parsed automatically if the exif library is available. -Setting `orientation` to an integer in the range of `2` to `8` enables the -`canvas` option. Setting `orientation` to `true` enables the `canvas` and `meta` options, unless the browser supports automatic image orientation (see -[browser support for image-orientation](https://caniuse.com/#feat=css-image-orientation)). +[browser support for image-orientation](https://caniuse.com/#feat=css-image-orientation)). +Setting `orientation` to `1` enables the `canvas` and `meta` options if the +browser does support automatic image orientation (to allow reset of the +orientation). +Setting `orientation` to an integer in the range of `2` to `8` always enables +the `canvas` option and also enables the `meta` option if the browser supports +automatic image orientation (again to allow reset). ### meta From 0f65d7d1241dc0f0463a531e612a5b56c9e856da Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Wed, 22 Apr 2020 23:38:06 +0900 Subject: [PATCH 022/159] Add Exif orientation visualization to the README. --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index 75d87c7..a13ac05 100644 --- a/README.md +++ b/README.md @@ -332,6 +332,34 @@ an `integer` in the range of `1` to `8` or the boolean value `true`. When set to `true`, it will set the orientation value based on the EXIF data of the image, which will be parsed automatically if the exif library is available. +Exif orientation values to correctly display the letter F: + +``` + 1 2 + ██████ ██████ + ██ ██ + ████ ████ + ██ ██ + ██ ██ + + 3 4 + ██ ██ + ██ ██ + ████ ████ + ██ ██ + ██████ ██████ + + 5 6 +██████████ ██ +██ ██ ██ ██ +██ ██████████ + + 7 8 + ██ ██████████ + ██ ██ ██ ██ +██████████ ██ +``` + Setting `orientation` to `true` enables the `canvas` and `meta` options, unless the browser supports automatic image orientation (see [browser support for image-orientation](https://caniuse.com/#feat=css-image-orientation)). From 14b599e924979e43f8f5d75e3afde4752aea5ac9 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Thu, 23 Apr 2020 00:32:05 +0900 Subject: [PATCH 023/159] Simplify original dimensions normalization. --- js/load-image-orientation.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/js/load-image-orientation.js b/js/load-image-orientation.js index f700df1..30833de 100644 --- a/js/load-image-orientation.js +++ b/js/load-image-orientation.js @@ -126,12 +126,9 @@ Exif orientation values to correctly display the letter F: options, function (img, data) { if (data) { - var exifOrientation = data.exif && data.exif.get('Orientation') - if ( - loadImage.orientation && - exifOrientation > 4 && - exifOrientation < 9 - ) { + var autoOrientation = + loadImage.orientation && data.exif && data.exif.get('Orientation') + if (autoOrientation > 4 && autoOrientation < 9) { // Automatic image orientation switched image dimensions var originalWidth = data.originalWidth var originalHeight = data.originalHeight From f088760e7b29c88f75e622e97b2a937491a2fc60 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Sun, 26 Apr 2020 18:13:32 +0900 Subject: [PATCH 024/159] Normalize EXIF test names spelling. --- test/test.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/test.js b/test/test.js index 84b4a4b..33ed5f8 100644 --- a/test/test.js +++ b/test/test.js @@ -1031,7 +1031,7 @@ }) describe('Metadata', function () { - it('Parse Exif tags', function (done) { + it('Parse EXIF tags', function (done) { loadImage.parseMetaData(blobJPEG, function (data) { expect(data.exif).to.be.ok expect(data.exif.get('Orientation')).to.equal(6) @@ -1039,7 +1039,7 @@ }) }) - it('Do not parse Exif tags if disabled', function (done) { + it('Do not parse EXIF tags if disabled', function (done) { loadImage.parseMetaData( blobJPEG, function (data) { @@ -1050,7 +1050,7 @@ ) }) - it('Parse Exif tag offsets', function (done) { + it('Parse EXIF tag offsets', function (done) { loadImage.parseMetaData(blobJPEG, function (data) { expect(data.exifOffsets).to.be.ok expect(data.exifOffsets.get('Orientation')).to.equal(0x16) @@ -1060,7 +1060,7 @@ }) }) - it('Do not parse Exif tag offsets if disabled', function (done) { + it('Do not parse EXIF tag offsets if disabled', function (done) { loadImage.parseMetaData( blobJPEG, function (data) { @@ -1071,7 +1071,7 @@ ) }) - it('Only parse included Exif tags', function (done) { + it('Only parse included EXIF tags', function (done) { loadImage.parseMetaData( blobJPEG, function (data) { @@ -1091,7 +1091,7 @@ ) }) - it('Do not parse excluded Exif tags', function (done) { + it('Do not parse excluded EXIF tags', function (done) { loadImage.parseMetaData( blobJPEG, function (data) { @@ -1236,7 +1236,7 @@ ).to.be.ok }) - it('Write Exif Orientation tag and replace image head', function (done) { + it('Write EXIF Orientation tag and replace image head', function (done) { loadImage( blobJPEG, function (img, data) { @@ -1245,7 +1245,7 @@ expect(data.exif.get('Orientation')).to.equal(6) expect(data.iptc).to.be.ok expect(data.iptc.get('ObjectName')).to.equal('blueimp.net') - // Reset Exif Orientation data: + // Reset EXIF Orientation data: loadImage.writeExifData(data.imageHead, data, 'Orientation', 1) img.toBlob(function (blob) { loadImage.replaceHead(blob, data.imageHead, function (newBlob) { From 001fe7fcf345d1fb7e5a8faa9545a7eb09da5c94 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Sun, 26 Apr 2020 18:15:07 +0900 Subject: [PATCH 025/159] Test functions via instanceOf method. --- test/test.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/test.js b/test/test.js index 33ed5f8..64899a2 100644 --- a/test/test.js +++ b/test/test.js @@ -91,8 +91,8 @@ it('Return an object with onload and onerror methods', function () { var img = loadImage(blobGIF, function () {}) expect(img).to.be.an.instanceOf(Object) - expect(img.onload).to.be.a('function') - expect(img.onerror).to.be.a('function') + expect(img.onload).to.be.an.instanceOf(Function) + expect(img.onerror).to.be.an.instanceOf(Function) }) it('Load image url', function (done) { @@ -984,7 +984,7 @@ loadImage( blobGIF, function (img) { - expect(img.getContext).to.be.ok + expect(img.getContext).to.be.an.instanceOf(Function) expect(img.nodeName.toLowerCase()).to.equal('canvas') done() }, @@ -998,7 +998,7 @@ loadImage( blobGIF, function (img) { - expect(img.getContext).to.be.ok + expect(img.getContext).to.be.an.instanceOf(Function) expect(img.nodeName.toLowerCase()).to.equal('canvas') expect(img.width).to.equal(30) expect(img.height).to.equal(20) @@ -1018,7 +1018,7 @@ img = loadImage.scale(img, { maxWidth: 30 }) - expect(img.getContext).to.be.ok + expect(img.getContext).to.be.an.instanceOf(Function) expect(img.nodeName.toLowerCase()).to.equal('canvas') expect(img.width).to.equal(30) expect(img.height).to.equal(20) From 996dbb1bcfc60238961619be7a1889d8d409e383 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Sun, 26 Apr 2020 18:18:04 +0900 Subject: [PATCH 026/159] Remove unnecessary destX/destY arguments. --- js/load-image-scale.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/js/load-image-scale.js b/js/load-image-scale.js index 53fe5e6..4f6ab50 100644 --- a/js/load-image-scale.js +++ b/js/load-image-scale.js @@ -82,8 +82,6 @@ sourceY, sourceWidth, sourceHeight, - destX, - destY, destWidth, destHeight, options @@ -100,8 +98,8 @@ sourceY, sourceWidth, sourceHeight, - destX, - destY, + 0, + 0, destWidth, destHeight ) @@ -252,8 +250,6 @@ sourceY, sourceWidth, sourceHeight, - 0, - 0, canvas.width, canvas.height, options @@ -273,8 +269,6 @@ 0, sourceWidth, sourceHeight, - 0, - 0, sourceWidth, sourceHeight, options @@ -291,8 +285,6 @@ sourceY, sourceWidth, sourceHeight, - 0, - 0, destWidth, destHeight, options From 8776ebe52bbe9509ba4407a0ce873bda51639680 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Sun, 26 Apr 2020 18:22:33 +0900 Subject: [PATCH 027/159] Limit pixel ratio handling to scaling library. --- js/load-image-orientation.js | 4 ---- js/load-image-scale.js | 24 ++++++++++++------------ 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/js/load-image-orientation.js b/js/load-image-orientation.js index 30833de..d5e215e 100644 --- a/js/load-image-orientation.js +++ b/js/load-image-orientation.js @@ -235,13 +235,9 @@ Exif orientation values to correctly display the letter F: var ctx = canvas.getContext('2d') var width = canvas.width var height = canvas.height - var styleWidth = canvas.style.width - var styleHeight = canvas.style.height if (orientation > 4) { canvas.width = height canvas.height = width - canvas.style.width = styleHeight - canvas.style.height = styleWidth } switch (orientation) { case 2: diff --git a/js/load-image-scale.js b/js/load-image-scale.js index 4f6ab50..e398b13 100644 --- a/js/load-image-scale.js +++ b/js/load-image-scale.js @@ -220,18 +220,14 @@ } if (useCanvas) { pixelRatio = options.pixelRatio - if (pixelRatio > 1) { - if (parseInt(img.style.width, 10) === width / pixelRatio) { - // Source image is already scaled according to device pixel ratio - canvas.style.width = destWidth / pixelRatio + 'px' - canvas.style.height = destHeight / pixelRatio + 'px' - } else { - canvas.style.width = destWidth + 'px' - canvas.style.height = destHeight + 'px' - destWidth *= pixelRatio - destHeight *= pixelRatio - canvas.getContext('2d').scale(pixelRatio, pixelRatio) - } + if ( + pixelRatio > 1 && + // Check if image has not yet device pixel ratio applied: + parseInt(img.style.width, 10) !== width / pixelRatio + ) { + destWidth *= pixelRatio + destHeight *= pixelRatio + canvas.getContext('2d').scale(pixelRatio, pixelRatio) } downsamplingRatio = options.downsamplingRatio if ( @@ -278,6 +274,10 @@ canvas.width = destWidth canvas.height = destHeight loadImage.transformCoordinates(canvas, options, data) + if (pixelRatio > 1) { + canvas.style.width = canvas.width / pixelRatio + 'px' + canvas.style.height = canvas.height / pixelRatio + 'px' + } return loadImage.renderImageToCanvas( canvas, img, From 4c79652b5357fdf7fd5ce0b3f45c386e4e732719 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Sun, 26 Apr 2020 22:24:44 +0900 Subject: [PATCH 028/159] Fix IE10 ArrayBuffer.slice workaround. To use imageHead as DataView argument (e.g. for writing EXIF data), it needs to be a buffer. --- js/load-image-meta.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/js/load-image-meta.js b/js/load-image-meta.js index 63177d3..21c9961 100644 --- a/js/load-image-meta.js +++ b/js/load-image-meta.js @@ -96,6 +96,8 @@ var markerLength var parsers var i + var arr1 + var arr2 // Check for the JPEG marker (0xffd8): if (dataView.getUint16(0) === 0xffd8) { while (offset < maxOffset) { @@ -144,9 +146,12 @@ if (buffer.slice) { data.imageHead = buffer.slice(0, headLength) } else { - // Workaround for IE10, which does not yet - // support ArrayBuffer.slice: - data.imageHead = new Uint8Array(buffer).subarray(0, headLength) + // Workaround for IE10, which does not support + // ArrayBuffer.slice: + arr1 = new Uint8Array(buffer, 0, headLength) + arr2 = new Uint8Array(headLength) + arr2.set(arr1) + data.imageHead = arr2.buffer } } } else { From 681143cfb196bfeade745252fcc67fa04bb87d80 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Tue, 28 Apr 2020 19:40:14 +0900 Subject: [PATCH 029/159] Demo: take pixelRatio into account when cropping. Use contain:true instead of specifying both minWidth and maxWidth. Remove unnecessary downsamplingRatio option for cropping. --- js/demo/demo.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/js/demo/demo.js b/js/demo/demo.js index b42cdcd..fe1984c 100644 --- a/js/demo/demo.js +++ b/js/demo/demo.js @@ -250,10 +250,9 @@ $(function () { top: coordinates.y * pixelRatio, sourceWidth: coordinates.w * pixelRatio, sourceHeight: coordinates.h * pixelRatio, - minWidth: result.width(), - maxWidth: result.width(), + maxWidth: result.width() * pixelRatio, + contain: true, pixelRatio: pixelRatio, - downsamplingRatio: 0.5 }) ) coordinates = null From b86c22f62000513963980180454bb62901fba592 Mon Sep 17 00:00:00 2001 From: Sebastian Tschan Date: Tue, 28 Apr 2020 19:41:03 +0900 Subject: [PATCH 030/159] Demo: add orientation selector. --- index.html | 18 ++++++++++++++++++ js/demo/demo.js | 14 +++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index bc619ec..7192a00 100644 --- a/index.html +++ b/index.html @@ -80,6 +80,24 @@

Select an image file

Or drag & drop an image file onto this webpage.

+

+ + +

Result

Select an image file

+

+ + +

Result

Result

API.

-