React iptc metadata from images

This commit is contained in:
Chuck Dries 2021-05-31 00:01:12 -07:00
parent 46419a1559
commit 8fcae96197
8 changed files with 167 additions and 50 deletions

13
gatsby/TODO.md Normal file
View File

@ -0,0 +1,13 @@
- Gallery
- [x] Custom image metadata
- [ ] add metadata to image files
- [ ] image details page (modal route?)
- [ ] gallery page
- [ ] homepage to gallery page transition
- [ ] homepage basic layout
- [ ] portfolio page
- [ ] tailwind
- [ ] typescript
- [ ] graphql codegen

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

View File

@ -16,6 +16,7 @@ module.exports = {
"gatsby-plugin-mdx", "gatsby-plugin-mdx",
"gatsby-plugin-sharp", "gatsby-plugin-sharp",
"gatsby-transformer-sharp", "gatsby-transformer-sharp",
// "gatsby-plugin-sharp-exif",
{ {
resolve: "gatsby-source-filesystem", resolve: "gatsby-source-filesystem",
options: { options: {

65
gatsby/gatsby-node.js Normal file
View File

@ -0,0 +1,65 @@
const fs = require('fs');
const util = require('util')
const { read } = require('fast-exif');
const iptc = require('node-iptc');
const readFile = util.promisify(fs.readFile)
function convertDMSToDD(dms, positiveDirection) {
const res = dms
.map((item, i) => {
return item / Math.pow(60, i);
})
.reduce((a, b) => a + b);
return positiveDirection ? res : -res;
}
function transformMetaToNodeData(exifData, iptcData) {
const gps = { longitude: null, latitude: null };
if (exifData) {
if (
exifData.gps &&
exifData.gps.GPSLongitude &&
exifData.gps.GPSLatitude
) {
gps.longitude = convertDMSToDD(
exifData.gps.GPSLongitude,
exifData.gps.GPSLongitudeRef === 'E'
);
gps.latitude = convertDMSToDD(
exifData.gps.GPSLatitude,
exifData.gps.GPSLatitudeRef === 'N'
);
}
}
return {
exif: exifData?.exif,
gps,
meta: {
dateTaken: exifData?.exif?.DateTimeOriginal
},
iptc: iptcData || undefined
};
}
exports.onCreateNode = async function ({ node, getNode, actions }) {
const { createNodeField } = actions;
if (node.internal.type === 'ImageSharp') {
console.log(node)
const parent = getNode(node.parent);
const file = await readFile(parent.absolutePath)
const iptcData = iptc(file)
const exifData = await read(parent.absolutePath)
createNodeField({
node,
name: 'imageMeta',
value: transformMetaToNodeData(exifData, iptcData)
});
}
}

View File

@ -11,6 +11,7 @@
"@mdx-js/mdx": "^1.6.22", "@mdx-js/mdx": "^1.6.22",
"@mdx-js/react": "^1.6.22", "@mdx-js/react": "^1.6.22",
"babel-plugin-styled-components": "^1.12.0", "babel-plugin-styled-components": "^1.12.0",
"fast-exif": "^1.0.1",
"gatsby": "^3.4.1", "gatsby": "^3.4.1",
"gatsby-plugin-image": "^1.6.0", "gatsby-plugin-image": "^1.6.0",
"gatsby-plugin-manifest": "^3.6.0", "gatsby-plugin-manifest": "^3.6.0",
@ -18,9 +19,11 @@
"gatsby-plugin-react-helmet": "^4.6.0", "gatsby-plugin-react-helmet": "^4.6.0",
"gatsby-plugin-sass": "^4.6.0", "gatsby-plugin-sass": "^4.6.0",
"gatsby-plugin-sharp": "^3.6.0", "gatsby-plugin-sharp": "^3.6.0",
"gatsby-plugin-sharp-exif": "^1.0.4",
"gatsby-plugin-styled-components": "^4.6.0", "gatsby-plugin-styled-components": "^4.6.0",
"gatsby-source-filesystem": "^3.6.0", "gatsby-source-filesystem": "^3.6.0",
"gatsby-transformer-sharp": "^3.6.0", "gatsby-transformer-sharp": "^3.6.0",
"node-iptc": "^1.0.5",
"react": "^17.0.1", "react": "^17.0.1",
"react-dom": "^17.0.1", "react-dom": "^17.0.1",
"react-helmet": "^6.1.0", "react-helmet": "^6.1.0",
@ -9370,6 +9373,11 @@
"resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz",
"integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=" "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI="
}, },
"node_modules/exif-reader": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/exif-reader/-/exif-reader-1.0.3.tgz",
"integrity": "sha512-tWMBj1+9jUSibgR/kv/GQ/fkR0biaN9GEZ5iPdf7jFeH//d2bSzgPoaWf1OfMv4MXFD4upwvpCCyeMvSyLWSfA=="
},
"node_modules/expand-brackets": { "node_modules/expand-brackets": {
"version": "2.1.4", "version": "2.1.4",
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
@ -9786,6 +9794,15 @@
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
}, },
"node_modules/fast-exif": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/fast-exif/-/fast-exif-1.0.1.tgz",
"integrity": "sha1-F9HQTWST5j1LbAs1xrC9v1Hjlv8=",
"dependencies": {
"bluebird": "^3.3.3",
"exif-reader": "^1.0.0"
}
},
"node_modules/fast-glob": { "node_modules/fast-glob": {
"version": "3.2.5", "version": "3.2.5",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
@ -11261,6 +11278,19 @@
"gatsby": "^3.0.0-next.0" "gatsby": "^3.0.0-next.0"
} }
}, },
"node_modules/gatsby-plugin-sharp-exif": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/gatsby-plugin-sharp-exif/-/gatsby-plugin-sharp-exif-1.0.4.tgz",
"integrity": "sha512-j2mQLcXOyBT9qODcr/fx4yFXpbtZyn6VT/4Z/6YvvgU/b53p3tkLCmxSeRdiF8rJB0jlDAY2lFJsfBJlyA1paA==",
"dependencies": {
"@babel/runtime": "^7.7.4",
"fast-exif": "^1.0.1"
},
"peerDependencies": {
"gatsby": "^2.0.0",
"gatsby-plugin-sharp": "^2.3.4"
}
},
"node_modules/gatsby-plugin-sharp/node_modules/@sindresorhus/is": { "node_modules/gatsby-plugin-sharp/node_modules/@sindresorhus/is": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-2.1.1.tgz", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-2.1.1.tgz",
@ -16150,6 +16180,11 @@
"node": ">= 6.0.0" "node": ">= 6.0.0"
} }
}, },
"node_modules/node-iptc": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/node-iptc/-/node-iptc-1.0.5.tgz",
"integrity": "sha1-Y37FwpaImzQQSo3nXWuU7jyFwsk="
},
"node_modules/node-object-hash": { "node_modules/node-object-hash": {
"version": "2.3.3", "version": "2.3.3",
"resolved": "https://registry.npmjs.org/node-object-hash/-/node-object-hash-2.3.3.tgz", "resolved": "https://registry.npmjs.org/node-object-hash/-/node-object-hash-2.3.3.tgz",
@ -31744,6 +31779,11 @@
"resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz",
"integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=" "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI="
}, },
"exif-reader": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/exif-reader/-/exif-reader-1.0.3.tgz",
"integrity": "sha512-tWMBj1+9jUSibgR/kv/GQ/fkR0biaN9GEZ5iPdf7jFeH//d2bSzgPoaWf1OfMv4MXFD4upwvpCCyeMvSyLWSfA=="
},
"expand-brackets": { "expand-brackets": {
"version": "2.1.4", "version": "2.1.4",
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
@ -32091,6 +32131,15 @@
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
}, },
"fast-exif": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/fast-exif/-/fast-exif-1.0.1.tgz",
"integrity": "sha1-F9HQTWST5j1LbAs1xrC9v1Hjlv8=",
"requires": {
"bluebird": "^3.3.3",
"exif-reader": "^1.0.0"
}
},
"fast-glob": { "fast-glob": {
"version": "3.2.5", "version": "3.2.5",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
@ -33519,6 +33568,15 @@
} }
} }
}, },
"gatsby-plugin-sharp-exif": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/gatsby-plugin-sharp-exif/-/gatsby-plugin-sharp-exif-1.0.4.tgz",
"integrity": "sha512-j2mQLcXOyBT9qODcr/fx4yFXpbtZyn6VT/4Z/6YvvgU/b53p3tkLCmxSeRdiF8rJB0jlDAY2lFJsfBJlyA1paA==",
"requires": {
"@babel/runtime": "^7.7.4",
"fast-exif": "^1.0.1"
}
},
"gatsby-plugin-styled-components": { "gatsby-plugin-styled-components": {
"version": "4.6.0", "version": "4.6.0",
"resolved": "https://registry.npmjs.org/gatsby-plugin-styled-components/-/gatsby-plugin-styled-components-4.6.0.tgz", "resolved": "https://registry.npmjs.org/gatsby-plugin-styled-components/-/gatsby-plugin-styled-components-4.6.0.tgz",
@ -37004,6 +37062,11 @@
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
"integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA=="
}, },
"node-iptc": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/node-iptc/-/node-iptc-1.0.5.tgz",
"integrity": "sha1-Y37FwpaImzQQSo3nXWuU7jyFwsk="
},
"node-object-hash": { "node-object-hash": {
"version": "2.3.3", "version": "2.3.3",
"resolved": "https://registry.npmjs.org/node-object-hash/-/node-object-hash-2.3.3.tgz", "resolved": "https://registry.npmjs.org/node-object-hash/-/node-object-hash-2.3.3.tgz",

View File

@ -18,6 +18,7 @@
"@mdx-js/mdx": "^1.6.22", "@mdx-js/mdx": "^1.6.22",
"@mdx-js/react": "^1.6.22", "@mdx-js/react": "^1.6.22",
"babel-plugin-styled-components": "^1.12.0", "babel-plugin-styled-components": "^1.12.0",
"fast-exif": "^1.0.1",
"gatsby": "^3.4.1", "gatsby": "^3.4.1",
"gatsby-plugin-image": "^1.6.0", "gatsby-plugin-image": "^1.6.0",
"gatsby-plugin-manifest": "^3.6.0", "gatsby-plugin-manifest": "^3.6.0",
@ -25,9 +26,11 @@
"gatsby-plugin-react-helmet": "^4.6.0", "gatsby-plugin-react-helmet": "^4.6.0",
"gatsby-plugin-sass": "^4.6.0", "gatsby-plugin-sass": "^4.6.0",
"gatsby-plugin-sharp": "^3.6.0", "gatsby-plugin-sharp": "^3.6.0",
"gatsby-plugin-sharp-exif": "^1.0.4",
"gatsby-plugin-styled-components": "^4.6.0", "gatsby-plugin-styled-components": "^4.6.0",
"gatsby-source-filesystem": "^3.6.0", "gatsby-source-filesystem": "^3.6.0",
"gatsby-transformer-sharp": "^3.6.0", "gatsby-transformer-sharp": "^3.6.0",
"node-iptc": "^1.0.5",
"react": "^17.0.1", "react": "^17.0.1",
"react-dom": "^17.0.1", "react-dom": "^17.0.1",
"react-helmet": "^6.1.0", "react-helmet": "^6.1.0",

View File

@ -5,53 +5,6 @@ import { GatsbyImage, getImage } from "gatsby-plugin-image"
import "../styles/gallery.scss" import "../styles/gallery.scss"
import "../styles/index.scss" import "../styles/index.scss"
// data
const links = [
{
text: "Tutorial",
url: "https://www.gatsbyjs.com/docs/tutorial/",
description:
"A great place to get started if you're new to web development. Designed to guide you through setting up your first Gatsby site.",
color: "#E95800",
},
{
text: "How to Guides",
url: "https://www.gatsbyjs.com/docs/how-to/",
description:
"Practical step-by-step guides to help you achieve a specific goal. Most useful when you're trying to get something done.",
color: "#1099A8",
},
{
text: "Reference Guides",
url: "https://www.gatsbyjs.com/docs/reference/",
description:
"Nitty-gritty technical descriptions of how Gatsby works. Most useful when you need detailed information about Gatsby's APIs.",
color: "#BC027F",
},
{
text: "Conceptual Guides",
url: "https://www.gatsbyjs.com/docs/conceptual/",
description:
"Big-picture explanations of higher-level Gatsby concepts. Most useful for building understanding of a particular topic.",
color: "#0D96F2",
},
{
text: "Plugin Library",
url: "https://www.gatsbyjs.com/plugins",
description:
"Add functionality and customize your Gatsby site or app with thousands of plugins built by our amazing developer community.",
color: "#8EB814",
},
{
text: "Build and Host",
url: "https://www.gatsbyjs.com/cloud",
badge: true,
description:
"Now youre ready to show the world! Give your Gatsby site superpowers: Build and host on Gatsby Cloud. Get started for free!",
color: "#663399",
},
]
// markup // markup
const IndexPage = ({ data }) => { const IndexPage = ({ data }) => {
const images = React.useMemo(() => data.allFile.edges.map(edge => edge.node, [data])) const images = React.useMemo(() => data.allFile.edges.map(edge => edge.node, [data]))
@ -70,11 +23,12 @@ const IndexPage = ({ data }) => {
</h1> </h1>
<div className="gallery"> <div className="gallery">
{images.map(image => { {images.map(image => {
console.log('imag', image) const name = image.childImageSharp.fields.imageMeta.iptc.object_name || image.base
console.log('name', name)
// const file = data.allFile // const file = data.allFile
// console.log(fileName) // console.log(fileName)
// return <></> // return <></>
return <GatsbyImage key={image.base} image={getImage(image)} alt={image.base} />; return <GatsbyImage key={image.base} image={getImage(image)} alt={name} />;
})} })}
</div> </div>
<img <img
@ -95,6 +49,23 @@ query HomePageGallery {
base, base,
childImageSharp{ childImageSharp{
gatsbyImageData(width: 400) gatsbyImageData(width: 400)
fields {
imageMeta {
meta {
dateTaken
}
iptc {
caption
object_name
}
exif {
FNumber
ExposureTime
ShutterSpeedValue
ISO
}
}
}
} }
} }
} }

View File

@ -1,6 +1,6 @@
.gallery { .gallery {
width: 100%; width: 100%;
aspect-ratio: 5/3; // aspect-ratio: 5/3;
background: black; background: black;
display: flex; display: flex;
overflow-x: scroll; overflow-x: scroll;
@ -20,6 +20,7 @@
.gatsby-image-wrapper { .gatsby-image-wrapper {
aspect-ratio: 3/2; aspect-ratio: 3/2;
width: 400px;
flex-shrink: 0; flex-shrink: 0;
// height: 280px; // height: 280px;
// width: 350px; // width: 350px;