diff --git a/packages/gatsby-image/src/__tests__/__snapshots__/index.js.snap b/packages/gatsby-image/src/__tests__/__snapshots__/index.js.snap index c8f07e691e644..c13a35df2cbfc 100644 --- a/packages/gatsby-image/src/__tests__/__snapshots__/index.js.snap +++ b/packages/gatsby-image/src/__tests__/__snapshots__/index.js.snap @@ -6,6 +6,10 @@ exports[` should render fixed size images 1`] = ` class="fixedImage gatsby-image-wrapper" style="position: relative; overflow: hidden; display: inline; width: 100px; height: 100px;" > +
should render fixed size images 1`] = ` style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; opacity: 1; color: red;" title="Title for the image" /> -
should render fluid images 1`] = `
+
should render fluid images 1`] = ` style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; opacity: 1; color: red;" title="Title for the image" /> -
- {/* Show the blurry base64 image. */} - {image.base64 && ( - - )} - - {/* Show the traced SVG image. */} - {image.tracedSVG && ( - - )} - {/* Show a solid background color. */} {bgColor && ( )} + {/* Show the blurry base64 image. */} + {image.base64 && ( + + )} + + {/* Show the traced SVG image. */} + {image.tracedSVG && ( + + )} + {/* Once the image is visible (or the browser doesn't support IntersectionObserver), start downloading the image */} {this.state.isVisible && ( @@ -365,16 +366,6 @@ class Image extends React.Component { ref={this.handleRef} key={`fixed-${JSON.stringify(image.srcSet)}`} > - {/* Show the blurry base64 image. */} - {image.base64 && ( - - )} - - {/* Show the traced SVG image. */} - {image.tracedSVG && ( - - )} - {/* Show a solid background color. */} {bgColor && ( )} + {/* Show the blurry base64 image. */} + {image.base64 && ( + + )} + + {/* Show the traced SVG image. */} + {image.tracedSVG && ( + + )} + {/* Once the image is visible, start downloading the image */} {this.state.isVisible && ( diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js index fc31465c4c8e6..3805260eb7df3 100644 --- a/packages/gatsby-plugin-sharp/src/index.js +++ b/packages/gatsby-plugin-sharp/src/index.js @@ -41,6 +41,7 @@ exports.queue = queue /// Plugin options are loaded onPreInit in gatsby-node const pluginDefaults = { + forceBase64Format: false, useMozJpeg: process.env.GATSBY_JPEG_ENCODER === `MOZJPEG`, stripMetadata: true, lazyImageGeneration: true, @@ -58,6 +59,7 @@ const generalArgs = { duotone: false, pathPrefix: ``, toFormat: ``, + toFormatBase64: ``, sizeByPixelDensity: false, } @@ -93,6 +95,7 @@ const healOptions = ( options.pngCompressionLevel = parseInt(options.pngCompressionLevel, 10) options.pngCompressionSpeed = parseInt(options.pngCompressionSpeed, 10) options.toFormat = options.toFormat.toLowerCase() + options.toFormatBase64 = options.toFormatBase64.toLowerCase() // when toFormat is not set we set it based on fileExtension if (options.toFormat === ``) { @@ -235,9 +238,11 @@ function queueImageResizing({ file, args = {}, reporter }) { } } +// A value in pixels(Int) +const defaultBase64Width = () => pluginOptions.base64Width || 20 async function generateBase64({ file, args, reporter }) { const options = healOptions(pluginOptions, args, file.extension, { - width: 20, + width: defaultBase64Width(), }) let pipeline try { @@ -247,6 +252,12 @@ async function generateBase64({ file, args, reporter }) { return null } + const forceBase64Format = + args.toFormatBase64 || pluginOptions.forceBase64Format + if (forceBase64Format) { + args.toFormat = forceBase64Format + } + pipeline .resize(options.width, options.height, { position: options.cropFocus, @@ -261,6 +272,10 @@ async function generateBase64({ file, args, reporter }) { progressive: options.jpegProgressive, force: args.toFormat === `jpg`, }) + .webp({ + quality: options.quality, + force: args.toFormat === `webp`, + }) // grayscale if (options.grayscale) { @@ -342,9 +357,10 @@ async function fluid({ file, args = {}, reporter, cache }) { } const { width, height, density, format } = metadata + const defaultImagePPI = 72 // Standard digital image pixel density const pixelRatio = options.sizeByPixelDensity && typeof density === `number` && density > 0 - ? density / 72 + ? density / defaultImagePPI : 1 // if no maxWidth is passed, we need to resize the image based on the passed maxHeight @@ -446,13 +462,14 @@ async function fluid({ file, args = {}, reporter, cache }) { let base64Image if (options.base64) { - const base64Width = 20 + const base64Width = options.base64Width || defaultBase64Width() const base64Height = Math.max(1, Math.round((base64Width * height) / width)) const base64Args = { duotone: options.duotone, grayscale: options.grayscale, rotate: options.rotate, toFormat: options.toFormat, + toFormatBase64: options.toFormatBase64, width: base64Width, height: base64Height, } @@ -566,10 +583,13 @@ async function fixed({ file, args = {}, reporter, cache }) { let base64Image if (options.base64) { const base64Args = { + // height is adjusted accordingly with respect to the aspect ratio + width: options.base64Width, duotone: options.duotone, grayscale: options.grayscale, rotate: options.rotate, toFormat: options.toFormat, + toFormatBase64: options.toFormatBase64, } // Get base64 version diff --git a/packages/gatsby-transformer-sharp/src/extend-node-type.js b/packages/gatsby-transformer-sharp/src/extend-node-type.js index 935bb52e31b46..519c23a00d1c6 100644 --- a/packages/gatsby-transformer-sharp/src/extend-node-type.js +++ b/packages/gatsby-transformer-sharp/src/extend-node-type.js @@ -115,6 +115,9 @@ const fixedNodeType = ({ height: { type: GraphQLInt, }, + base64Width: { + type: GraphQLInt, + }, jpegProgressive: { type: GraphQLBoolean, defaultValue: true, @@ -142,6 +145,10 @@ const fixedNodeType = ({ type: ImageFormatType, defaultValue: ``, }, + toFormatBase64: { + type: ImageFormatType, + defaultValue: ``, + }, cropFocus: { type: ImageCropFocusType, defaultValue: sharp.strategy.attention, @@ -240,6 +247,9 @@ const fluidNodeType = ({ maxHeight: { type: GraphQLInt, }, + base64Width: { + type: GraphQLInt, + }, grayscale: { type: GraphQLBoolean, defaultValue: false, @@ -267,6 +277,10 @@ const fluidNodeType = ({ type: ImageFormatType, defaultValue: ``, }, + toFormatBase64: { + type: ImageFormatType, + defaultValue: ``, + }, cropFocus: { type: ImageCropFocusType, defaultValue: sharp.strategy.attention,