This is just a general question - apologies if it's not the appropriate place to ask.
I'm looking at using Gatsby to build image galleries and would quite like to hook into the EXIF data for things like captions/copyright/potentially geodata/etc.
A quick skim of the Sharp docs suggests you can get access to that stuff and I was wondering if the gatsby plugin could be modified to retrieve that, or if I'm barking up the wrong tree...?
It's ok to ask here :)
This would be great candidate to create separate plugin - maybe gatsby-transformer-exif? It then could use sharp, node-exif or whatever other dependency (if this would be in separate package we are not tied to sharp then).
I can guide you if you want to create this plugin.
Someone on the Discord server did something similar. Maybe you can connect with him there.

Thanks, folks! I'll definitely look in to contributing to a plugin!
@foxxmd
Hello! Here's what I ended up doing...
I'm using exiftool to set fields for some of the non-standard fields like this
exiftool -DocumentName='Savannah, Ga' -ImageDescription='Bridge At Night' -ImageHistory='Places' 20180219-_MG_9929_HDR.jpg
Then extracting exif data using fast-exif on build:
// package.json
{
"dependencies": {
"fast-exif": "^1.0.1",
"lodash": "^4.17.5",
"gatsby-plugin-sharp": "^1.6.27",
}
}
```js
// gatsby-config.js
modules.exports = {
plugins: [
{
resolve: gatsby-source-filesystem,
options: {
name: pictures,
path: ${__dirname}/content/pictures/,
plugins: [
gatsby-plugin-sharp
]
}
},
gatsby-plugin-sharp,
gatsby-transformer-sharp,
]
}
```js
// gatsby-node.js
const fastExif = require('fast-exif');
const get = require('lodash/get');
exports.onCreateNode = ({ node, getNode, boundActionCreators }) => {
const { createNodeField } = boundActionCreators;
if(node.internal.type === 'ImageSharp' && node.id.includes('content/pictures/')) {
const absolutePath = node.id.split(' ')[0];
fastExif.read(absolutePath)
.then((exifData) => {
const title = get( exifData, [ 'image', 'ImageDescription' ], null );
const location = get( exifData, [ 'image', 'DocumentName' ], null );
const categoryData = get( exifData, [ 'exif', 'ImageHistory' ], null );
const categories = categoryData === null ? [ 'uncategorized' ] : categoryData.split( ',' );
const iso = get( exifData, [ 'exif', 'ISO' ], null );
const model = get( exifData, [ 'exif', 'LensModel' ], null );
const fstop = get( exifData, [ 'exif', 'FNumber' ], null );
const focalLength = get( exifData, [ 'exif', 'FocalLength' ], null );
createNodeField({
node,
name: 'exif',
value: {title, location, categories, technical: {iso, model, fstop, focalLength}}
});
})
.catch((err) => console.error(err));
}
}
On my photos page I pull the data using graphql and display using react-masonry-component for layout and react-image-lightbox for individual photos displaying which has handy props for displaying a caption box where I put the exif data.
export const guery = graphql`
query PhotosQuery {
photos: allImageSharp(filter: { id: { regex: "//pictures//" } }) {
edges {
node {
original {
width
height
src
},
sizes(maxWidth: 1600) {
src,
srcSet,
sizes
},
resolutions(width: 200) {
src,
srcSet,
width,
height,
aspectRatio,
base64
}
fields {
exif {
title
location
categories
technical {
iso
model
fstop
focalLength
}
}
}
}
}
}
}
`;
You can see the result here for some of the photos -- the BMW pic is a good example (screenshot)
Wow that's mega, thanks @FoxxMD! I'll dive into that a bit deeper soon.
Would love to see a plugin that wraps fast-exif!
Most helpful comment
Hello! Here's what I ended up doing...
I'm using exiftool to set fields for some of the non-standard fields like this
Then extracting exif data using fast-exif on build:
```js
// gatsby-config.js
modules.exports = {
plugins: [
{
resolve:
gatsby-source-filesystem,options: {
name:
pictures,path:
${__dirname}/content/pictures/,plugins: [
gatsby-plugin-sharp]
}
},
gatsby-plugin-sharp,gatsby-transformer-sharp,]
}
On my photos page I pull the data using graphql and display using react-masonry-component for layout and react-image-lightbox for individual photos displaying which has handy props for displaying a caption box where I put the exif data.
You can see the result here for some of the photos -- the BMW pic is a good example (screenshot)