diff --git a/packages/gatsby-plugin-sharp/README.md b/packages/gatsby-plugin-sharp/README.md index 5edf65d1e67e1..1a0f682826a44 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: false, + stripMetadata: true, + }, + }, +] ``` ## Methods @@ -242,12 +250,37 @@ 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`. + +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 ``` +### 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 as it leads to +smaller file sizes. + +However, in situations where you wish to preserve EXIF metadata or ICC profiles +(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 +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 @@ -264,3 +297,4 @@ GATSBY_JPEG_ENCODER=MOZJPEG [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/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..dc17f04bcdc0b 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -41,6 +41,16 @@ exports.setBoundActionCreators = actions => { boundActionCreators = actions } +/// Plugin options are loaded onPreInit in gatsby-node +const pluginDefaults = { + useMozJpeg: process.env.GATSBY_JPEG_ENCODER === `MOZJPEG`, + stripMetadata: true, +} +let pluginOptions = Object.assign({}, pluginDefaults) +exports.setPluginOptions = opts => { + pluginOptions = Object.assign({}, pluginOptions, opts) +} + // Promisify the sharp prototype (methods) to promisify the alternative (for // raw) callback-accepting toBuffer(...) method Promise.promisifyAll(sharp.prototype, { multiArgs: true }) @@ -110,8 +120,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 +132,14 @@ const processFile = (file, jobs, cb, reporter) => { let pipeline try { - pipeline = sharp(file).rotate() + pipeline = sharp(file) + + // Keep Metadata + if (!pluginOptions.stripMetadata) { + pipeline = pipeline.withMetadata() + } + + pipeline = pipeline.rotate() } catch (err) { reportError(`Failed to process image ${file}`, err, reporter) jobs.forEach(job => job.outsideReject(err)) @@ -170,7 +185,7 @@ const processFile = (file, jobs, cb, reporter) => { }) // jpeg - if (!useMozjpeg) { + if (!pluginOptions.useMozJpeg) { clonedPipeline = clonedPipeline.jpeg({ quality: args.quality, progressive: args.jpegProgressive, @@ -231,6 +246,7 @@ const processFile = (file, jobs, cb, reporter) => { args.quality + 25, 100 )}`, // e.g. 40-65 + strip: !!pluginOptions.stripMetadata, // Must be a bool }), ], }) @@ -242,7 +258,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`)