1
0
mirror of https://github.com/kremalicious/blog.git synced 2024-11-14 09:05:17 +01:00

exif try with fast-exif

This commit is contained in:
Matthias Kretschmann 2018-09-07 13:08:01 +02:00
parent 970b18995c
commit 4acd2f227b
Signed by: m
GPG Key ID: 606EEEF3C479A91F
8 changed files with 142 additions and 85 deletions

View File

@ -110,8 +110,8 @@ module.exports = {
}, },
'gatsby-plugin-react-helmet', 'gatsby-plugin-react-helmet',
'gatsby-transformer-yaml', 'gatsby-transformer-yaml',
'gatsby-transformer-sharp',
'gatsby-plugin-sharp', 'gatsby-plugin-sharp',
'gatsby-transformer-sharp',
'gatsby-plugin-sitemap', 'gatsby-plugin-sitemap',
'gatsby-plugin-catch-links', 'gatsby-plugin-catch-links',
'gatsby-redirect-from', 'gatsby-redirect-from',

View File

@ -3,6 +3,7 @@ const fs = require('fs')
const yaml = require('js-yaml') const yaml = require('js-yaml')
const { createFilePath } = require('gatsby-source-filesystem') const { createFilePath } = require('gatsby-source-filesystem')
const { paginate } = require('gatsby-awesome-pagination') const { paginate } = require('gatsby-awesome-pagination')
const fastExif = require('fast-exif')
const meta = yaml.load(fs.readFileSync('./content/meta.yml', 'utf8')) const meta = yaml.load(fs.readFileSync('./content/meta.yml', 'utf8'))
const { itemsPerPage } = meta const { itemsPerPage } = meta
@ -46,6 +47,35 @@ exports.onCreateNode = ({ node, actions, getNode }) => {
value: date value: date
}) })
} }
// exif
if (node.internal.mediaType === 'image/jpeg') {
fastExif
.read(node.absolutePath)
.then(exifData => {
const iso = exifData.exif.ISO || null
const model = exifData.image.Model || null
const fstop = exifData.exif.FNumber || null
const shutterspeed = exifData.exif.ExposureTime || null
const focalLength = exifData.exif.FocalLength || null
const exposure = exifData.exif.ExposureBiasValue || null
// add exif fields to type File
createNodeField({
node,
name: 'exif',
value: {
iso,
model,
fstop,
shutterspeed,
focalLength,
exposure
}
})
})
.catch(() => null) // just silently fail when exif can't be extracted
}
} }
exports.createPages = ({ graphql, actions }) => { exports.createPages = ({ graphql, actions }) => {

View File

@ -22,12 +22,10 @@
"last 3 versions" "last 3 versions"
], ],
"dependencies": { "dependencies": {
"exif-js": "^2.3.0", "fast-exif": "^1.0.1",
"gatsby": "^2.0.0-rc.13", "gatsby": "^2.0.0-rc.15",
"gatsby-awesome-pagination": "^0.1.1", "gatsby-awesome-pagination": "^0.1.1",
"gatsby-image": "^2.0.0-rc.1", "gatsby-image": "^2.0.0-rc.1",
"gatsby-paginate": "^1.0.16",
"gatsby-pagination": "^1.2.0",
"gatsby-plugin-catch-links": "^2.0.2-rc.1", "gatsby-plugin-catch-links": "^2.0.2-rc.1",
"gatsby-plugin-lunr": "^1.1.0", "gatsby-plugin-lunr": "^1.1.0",
"gatsby-plugin-matomo": "^0.5.0", "gatsby-plugin-matomo": "^0.5.0",
@ -42,9 +40,9 @@
"gatsby-remark-images": "^2.0.1-rc.1", "gatsby-remark-images": "^2.0.1-rc.1",
"gatsby-remark-prismjs": "^3.0.0-rc.2", "gatsby-remark-prismjs": "^3.0.0-rc.2",
"gatsby-remark-smartypants": "^2.0.0-rc.1", "gatsby-remark-smartypants": "^2.0.0-rc.1",
"gatsby-source-filesystem": "^2.0.1-rc.1", "gatsby-source-filesystem": "^2.0.1-rc.2",
"gatsby-transformer-remark": "^2.1.1-rc.1", "gatsby-transformer-remark": "^2.1.1-rc.1",
"gatsby-transformer-sharp": "^2.1.1-rc.2", "gatsby-transformer-sharp": "^2.1.1-rc.3",
"gatsby-transformer-yaml": "^2.1.1-rc.2", "gatsby-transformer-yaml": "^2.1.1-rc.2",
"graphql": "^0.13.2", "graphql": "^0.13.2",
"intersection-observer": "^0.5.0", "intersection-observer": "^0.5.0",

View File

@ -1,65 +1,72 @@
import React, { PureComponent } from 'react' import React from 'react'
import EXIF from 'exif-js' import PropTypes from 'prop-types'
import styles from './Exif.module.scss' import styles from './Exif.module.scss'
export default class Exif extends PureComponent { const getFraction = decimal => {
state = { for (var denominator = 1; (decimal * denominator) % 1 !== 0; denominator++);
modelvalue: null, return { numerator: decimal * denominator, denominator: denominator }
shutterspeedvalue: null, }
aperturevalue: null,
exposurevalue: null,
isovalue: null,
focallengthvalue: null
}
componentDidMount() { const ExposureFormatted = ({ exposure }) => {
this.getExif(this.props.image) const exposureShortened = exposure.toFixed(0)
}
getExif = image => { if (exposureShortened === 0) {
EXIF.getData(image, function() { return `+/- ${exposureShortened}`
// Get individual data } else if (exposureShortened > 0) {
const modelvalue = EXIF.getTag(this, 'Model') return `+ ${exposureShortened}`
const shutterspeedvalue = EXIF.getTag(this, 'ExposureTime') } else {
const aperturevalue = EXIF.getTag(this, 'FNumber') return exposureShortened
const exposurevalue = EXIF.getTag(this, 'ExposureBias')
const isovalue = EXIF.getTag(this, 'ISOSpeedRatings')
const focallengthvalue = EXIF.getTag(this, 'FocalLength')
console.log(modelvalue)
this.setState({
modelvalue,
shutterspeedvalue,
aperturevalue,
exposurevalue,
isovalue,
focallengthvalue
})
})
}
render() {
const {
modelvalue,
shutterspeedvalue,
aperturevalue,
exposurevalue,
isovalue,
focallengthvalue
} = this.state
return (
<aside className="exif">
<span className="exif__model" title="Camera model">
{modelvalue}
</span>
<span className="exif__aperture" title="Aperture" />
<span className="exif__shutterspeed" title="Shutter speed" />
<span className="exif__exposure" title="Exposure" />
<span className="exif__iso" title="ISO" />
<span className="exif__focallength" title="Focal length" />
</aside>
)
} }
} }
const Exif = ({ exif }) => {
const { iso, model, fstop, shutterspeed, focalLength, exposure } = exif
return (
<aside className={styles.exif}>
{model && (
<span className="exif__model" title="Camera model">
{model}
</span>
)}
{fstop && (
<span className="exif__fstop" title="Aperture">
{`ƒ ${fstop}`}
</span>
)}
{shutterspeed && (
<span className="exif__shutterspeed" title="Shutter speed">
{`${getFraction(shutterspeed).numerator}/${
getFraction(shutterspeed).denominator
}s`}
</span>
)}
{exposure && (
<span className="exif__exposure" title="Exposure">
<ExposureFormatted exposure={exposure} />
</span>
)}
{iso && (
<span className="exif__iso" title="ISO">
{`ISO ${iso}`}
</span>
)}
{focalLength && (
<span className="exif__focallength" title="Focal length">
{`${focalLength}mm`}
</span>
)}
</aside>
)
}
Exif.propTypes = {
exif: PropTypes.object
}
export default Exif

View File

@ -0,0 +1,17 @@
@import 'variables';
.exif {
font-size: $font-size-small;
color: $brand-grey-light;
margin-top: -($spacer);
margin-bottom: $spacer * 2;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
text-align: center;
span {
flex: 1;
white-space: nowrap;
}
}

View File

@ -7,8 +7,8 @@ import Image from '../components/atoms/Image'
import PostTitle from '../components/atoms/PostTitle' import PostTitle from '../components/atoms/PostTitle'
import PostLead from '../components/atoms/PostLead' import PostLead from '../components/atoms/PostLead'
import PostContent from '../components/atoms/PostContent' import PostContent from '../components/atoms/PostContent'
import PostMeta from '../components/molecules/PostMeta'
import PostActions from '../components/atoms/PostActions' import PostActions from '../components/atoms/PostActions'
import PostMeta from '../components/molecules/PostMeta'
import Exif from '../components/atoms/Exif' import Exif from '../components/atoms/Exif'
import styles from './Post.module.scss' import styles from './Post.module.scss'
@ -32,9 +32,7 @@ const Post = ({ data, location }) => {
</figure> </figure>
)} )}
{type === 'photo' && ( {image && image.fields && <Exif exif={image.fields.exif} />}
<Exif image={image.childImageSharp.original.src} />
)}
<PostContent post={post} /> <PostContent post={post} />
@ -62,7 +60,7 @@ Post.propTypes = {
export default Post export default Post
export const pageQuery = graphql` export const pageQuery = graphql`
query BlogPostByPath($slug: String!) { query BlogPostBySlug($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) { markdownRemark(fields: { slug: { eq: $slug } }) {
html html
excerpt excerpt
@ -72,8 +70,15 @@ export const pageQuery = graphql`
image { image {
childImageSharp { childImageSharp {
...ImageFluid ...ImageFluid
original { }
src fields {
exif {
iso
model
fstop
shutterspeed
focalLength
exposure
} }
} }
} }

View File

@ -15,11 +15,6 @@
padding-top: $spacer * 3; padding-top: $spacer * 3;
padding-bottom: $spacer * 3; padding-bottom: $spacer * 3;
} }
a {
position: relative;
display: block;
}
} }
.hentryImageTitle { .hentryImageTitle {
@ -44,14 +39,19 @@
.hentryImage { .hentryImage {
composes: hentryImage from './Post.module.scss'; composes: hentryImage from './Post.module.scss';
a:hover { a {
> div { position: relative;
border-color: $link-color !important; display: block;
}
.hentryImageTitle { &:hover {
opacity: 1; > div {
transform: translate3d(0, 0, 0); border-color: $link-color !important;
}
.hentryImageTitle {
opacity: 1;
transform: translate3d(0, 0, 0);
}
} }
} }
} }