From 60eace0734b55f6ccd80050e5f18c679a566981a Mon Sep 17 00:00:00 2001 From: Andrew Moore Date: Thu, 29 Nov 2018 15:50:25 -0500 Subject: [PATCH 1/5] Add option to keep metadata in files processed by `gatsby-plugin-sharp` --- packages/gatsby-plugin-sharp/README.md | 21 +++++++++++-- .../gatsby-plugin-sharp/src/gatsby-node.js | 5 +-- packages/gatsby-plugin-sharp/src/index.js | 31 ++++++++++++++++--- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/packages/gatsby-plugin-sharp/README.md b/packages/gatsby-plugin-sharp/README.md index 5edf65d1e67e1..f030c718f8abc 100644 --- a/packages/gatsby-plugin-sharp/README.md +++ b/packages/gatsby-plugin-sharp/README.md @@ -22,7 +22,15 @@ images. By default it uses a quality setting of [50-75]. ```javascript // In your gatsby-config.js -plugins: [`gatsby-plugin-sharp`] +plugins: [ + { + resolve: `gatsby-plugin-sharp`, + options: { + useMozJpeg: process.env.GATSBY_JPEG_ENCODER === `MOZJPEG`, + stripMetadata: true, + }, + }, +] ``` ## Methods @@ -242,12 +250,21 @@ You can opt-in to use [MozJPEG][16] for jpeg-encoding. MozJPEG provides even better image compression than the default encoder used in `gatsby-plugin-sharp`. However, when using MozJPEG the build time of your Gatsby project will increase significantly. -To enable MozJPEG set the [environment variable](/docs/environment-variables/#environment-variables): +To enable MozJPEG, you can set the `useMozJpeg` plugin option to `true` in +`gatsby-config.js` or set +the [environment variable](/docs/environment-variables/#environment-variables): ```shell GATSBY_JPEG_ENCODER=MOZJPEG ``` +### EXIF and ICC metadata + +By default, `gatsby-plugin-sharp` strips all EXIF, ICC and other metadata +present in your source file. If you wish to preserve this metadata, you can +set the `stripMetadata` plugin option to `false` in +`gatsby-config.js`. + [1]: https://alistapart.com/article/finessing-fecolormatrix [2]: http://blog.72lions.com/blog/2015/7/7/duotone-in-js [3]: https://ines.io/blog/dynamic-duotone-svg-jade diff --git a/packages/gatsby-plugin-sharp/src/gatsby-node.js b/packages/gatsby-plugin-sharp/src/gatsby-node.js index 98c258030c6e4..66c14a6f39f81 100644 --- a/packages/gatsby-plugin-sharp/src/gatsby-node.js +++ b/packages/gatsby-plugin-sharp/src/gatsby-node.js @@ -1,7 +1,8 @@ -const { setBoundActionCreators } = require(`./index`) +const { setBoundActionCreators, setPluginOptions } = require(`./index`) -exports.onPreInit = ({ actions }) => { +exports.onPreInit = ({ actions }, pluginOptions) => { setBoundActionCreators(actions) + setPluginOptions(pluginOptions) } // TODO diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js index baf2d06aed4d5..1b4cdecfa1945 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -41,6 +41,22 @@ exports.setBoundActionCreators = actions => { boundActionCreators = actions } +/// Plugin options are loaded onPreInit in gatsby-node +let pluginOptions = { + useMozJpeg: process.env.GATSBY_JPEG_ENCODER === `MOZJPEG`, + stripMetadata: true, +} +exports.setPluginOptions = options => { + // Typechecks + if (typeof options.useMozJpeg === `boolean`) { + pluginOptions.useMozJpeg = options.useMozJpeg + } + + if (typeof options.stripMetadata === `boolean`) { + pluginOptions.stripMetadata = options.stripMetadata + } +} + // Promisify the sharp prototype (methods) to promisify the alternative (for // raw) callback-accepting toBuffer(...) method Promise.promisifyAll(sharp.prototype, { multiArgs: true }) @@ -110,8 +126,6 @@ const healOptions = (args, defaultArgs) => { return options } -const useMozjpeg = process.env.GATSBY_JPEG_ENCODER === `MOZJPEG` - let totalJobs = 0 const processFile = (file, jobs, cb, reporter) => { // console.log("totalJobs", totalJobs) @@ -124,7 +138,14 @@ const processFile = (file, jobs, cb, reporter) => { let pipeline try { - pipeline = sharp(file).rotate() + pipeline = sharp(file) + + // Keep Metadata + if (pluginOptions.stripMetadata === false) { + pipeline = pipeline.withMetadata() + } + + pipeline = pipeline.rotate() } catch (err) { reportError(`Failed to process image ${file}`, err, reporter) jobs.forEach(job => job.outsideReject(err)) @@ -170,7 +191,7 @@ const processFile = (file, jobs, cb, reporter) => { }) // jpeg - if (!useMozjpeg) { + if (!pluginOptions.useMozJpeg) { clonedPipeline = clonedPipeline.jpeg({ quality: args.quality, progressive: args.jpegProgressive, @@ -242,7 +263,7 @@ const processFile = (file, jobs, cb, reporter) => { .catch(onFinish) // Compress jpeg } else if ( - useMozjpeg && + pluginOptions.useMozJpeg && ((job.file.extension === `jpg` && args.toFormat === ``) || (job.file.extension === `jpeg` && args.toFormat === ``) || args.toFormat === `jpg`) From 8cb85f4345d85b77cdd96eaaa24a970e1fd4f938 Mon Sep 17 00:00:00 2001 From: Dustin Schau Date: Thu, 29 Nov 2018 20:26:13 -0500 Subject: [PATCH 2/5] Since pluginOptions are strictly type-checked, no need for the strict check for false. Co-Authored-By: FineWolf --- packages/gatsby-plugin-sharp/src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js index 1b4cdecfa1945..b816178d153e3 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -141,7 +141,7 @@ const processFile = (file, jobs, cb, reporter) => { pipeline = sharp(file) // Keep Metadata - if (pluginOptions.stripMetadata === false) { + if (!pluginOptions.stripMetadata) { pipeline = pipeline.withMetadata() } From eec9dfc4b2c2368d3167e545c7c89ebf9012517e Mon Sep 17 00:00:00 2001 From: Andrew Moore Date: Thu, 29 Nov 2018 21:44:10 -0500 Subject: [PATCH 3/5] Changed README.md and index.js based on recommendations from @DSchau --- packages/gatsby-plugin-sharp/README.md | 27 ++++++++++++++++++----- packages/gatsby-plugin-sharp/src/index.js | 14 ++++-------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/packages/gatsby-plugin-sharp/README.md b/packages/gatsby-plugin-sharp/README.md index f030c718f8abc..2bdcd14ffeb45 100644 --- a/packages/gatsby-plugin-sharp/README.md +++ b/packages/gatsby-plugin-sharp/README.md @@ -26,7 +26,7 @@ plugins: [ { resolve: `gatsby-plugin-sharp`, options: { - useMozJpeg: process.env.GATSBY_JPEG_ENCODER === `MOZJPEG`, + useMozJpeg: false, stripMetadata: true, }, }, @@ -250,9 +250,13 @@ You can opt-in to use [MozJPEG][16] for jpeg-encoding. MozJPEG provides even better image compression than the default encoder used in `gatsby-plugin-sharp`. However, when using MozJPEG the build time of your Gatsby project will increase significantly. + To enable MozJPEG, you can set the `useMozJpeg` plugin option to `true` in -`gatsby-config.js` or set -the [environment variable](/docs/environment-variables/#environment-variables): +`gatsby-config.js`. + +For backwards compatible reasons, if `useMozJpeg` is not defined in the plugin +options, the [environment variable](/docs/environment-variables/#environment-variables) +`GATSBY_JPEG_ENCODER` acts as a fallback if set to `MOZJPEG`: ```shell GATSBY_JPEG_ENCODER=MOZJPEG @@ -261,10 +265,22 @@ GATSBY_JPEG_ENCODER=MOZJPEG ### EXIF and ICC metadata By default, `gatsby-plugin-sharp` strips all EXIF, ICC and other metadata -present in your source file. If you wish to preserve this metadata, you can -set the `stripMetadata` plugin option to `false` in +present in your source file. This is the recommended default for most +situations as it leads to smaller file sizes. + +However, in situations where you wish to preserve EXIF metadata or ICC profiles +(for example if you are building a photography portfolio and which to conserve +the color profile of the photos you've exported from Adobe Lightroom or Phase +One's Capture One), you can set the `stripMetadata` plugin option to `false` in `gatsby-config.js`. +It is important to note that if `stripMetadata` is set to `false`, **all** +metadata information will be preserved from the source image, including but not +limited to the latitude/longitude information of where the picture was taken +(if present). If you wish to strip this information from the source file, you +can either leave `stripMetadata` to its default of `true`, or manually +pre-process your images with a tool such as [ExifTool][17]. + [1]: https://alistapart.com/article/finessing-fecolormatrix [2]: http://blog.72lions.com/blog/2015/7/7/duotone-in-js [3]: https://ines.io/blog/dynamic-duotone-svg-jade @@ -281,3 +297,4 @@ set the `stripMetadata` plugin option to `false` in [14]: https://github.com/oliver-moran/jimp [15]: http://sharp.dimens.io/en/stable/api-operation/#flatten [16]: https://github.com/mozilla/mozjpeg +[17]: https://www.sno.phy.queensu.ca/~phil/exiftool/ diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js index b816178d153e3..328812ee9be10 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -42,19 +42,13 @@ exports.setBoundActionCreators = actions => { } /// Plugin options are loaded onPreInit in gatsby-node -let pluginOptions = { +const pluginDefaults = { useMozJpeg: process.env.GATSBY_JPEG_ENCODER === `MOZJPEG`, stripMetadata: true, } -exports.setPluginOptions = options => { - // Typechecks - if (typeof options.useMozJpeg === `boolean`) { - pluginOptions.useMozJpeg = options.useMozJpeg - } - - if (typeof options.stripMetadata === `boolean`) { - pluginOptions.stripMetadata = options.stripMetadata - } +let pluginOptions = Object.assign({}, pluginDefaults) +exports.setPluginOptions = opts => { + pluginOptions = Object.assign({}, pluginOptions, opts) } // Promisify the sharp prototype (methods) to promisify the alternative (for From 93359784753ce2d477c7528e4c5e83975bd42398 Mon Sep 17 00:00:00 2001 From: Andrew Moore Date: Thu, 29 Nov 2018 21:50:08 -0500 Subject: [PATCH 4/5] Spelling corrections in README.md --- packages/gatsby-plugin-sharp/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/gatsby-plugin-sharp/README.md b/packages/gatsby-plugin-sharp/README.md index 2bdcd14ffeb45..1a0f682826a44 100644 --- a/packages/gatsby-plugin-sharp/README.md +++ b/packages/gatsby-plugin-sharp/README.md @@ -265,14 +265,14 @@ GATSBY_JPEG_ENCODER=MOZJPEG ### EXIF and ICC metadata By default, `gatsby-plugin-sharp` strips all EXIF, ICC and other metadata -present in your source file. This is the recommended default for most -situations as it leads to smaller file sizes. +present in your source file. This is the recommended default as it leads to +smaller file sizes. However, in situations where you wish to preserve EXIF metadata or ICC profiles -(for example if you are building a photography portfolio and which to conserve -the color profile of the photos you've exported from Adobe Lightroom or Phase -One's Capture One), you can set the `stripMetadata` plugin option to `false` in -`gatsby-config.js`. +(example: you are building a photography portfolio and wish to conserve +the color profile or the copyright information of the photos you've exported +from Adobe Lightroom or Phase One's Capture One), you can set the `stripMetadata` +plugin option to `false` in `gatsby-config.js`. It is important to note that if `stripMetadata` is set to `false`, **all** metadata information will be preserved from the source image, including but not From 3529bbedfa379c1fa50686eacffa8bbac25bf1ae Mon Sep 17 00:00:00 2001 From: Andrew Moore Date: Mon, 3 Dec 2018 07:45:45 -0500 Subject: [PATCH 5/5] Fixed Pngquant not respecting the stripMetadata option --- packages/gatsby-plugin-sharp/src/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js index 328812ee9be10..dc17f04bcdc0b 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -246,6 +246,7 @@ const processFile = (file, jobs, cb, reporter) => { args.quality + 25, 100 )}`, // e.g. 40-65 + strip: !!pluginOptions.stripMetadata, // Must be a bool }), ], })