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,