Programmatically check and improve contrast ratios on dynamic color palettes

This commit is contained in:
Chuck Dries 2021-06-19 10:35:17 -07:00
parent cd6b279d01
commit 68a8c3ba90
3 changed files with 57 additions and 21 deletions

View File

@ -4,11 +4,61 @@ const path = require('path');
const { read } = require('fast-exif');
const iptc = require('node-iptc');
const Vibrant = require('node-vibrant');
const R = require('ramda');
const chroma = require('chroma-js');
const chalk = require('chalk');
const readFile = util.promisify(fs.readFile);
const badContrast = (color1, color2) => chroma.contrast(color1, color2) < 4.5;
function processColors(vibrantData, imagePath) {
let Vibrant = chroma(vibrantData.Vibrant.getRgb());
let DarkVibrant = chroma(vibrantData.DarkVibrant.getRgb());
let LightVibrant = chroma(vibrantData.LightVibrant.getRgb());
let Muted = chroma(vibrantData.Muted.getRgb());
let DarkMuted = chroma(vibrantData.DarkMuted.getRgb());
let LightMuted = chroma(vibrantData.LightMuted.getRgb());
// first pass - darken bg and lighten relevant fg colors
if (badContrast(DarkVibrant, Vibrant) || badContrast(DarkVibrant, LightMuted)) {
DarkVibrant = DarkVibrant.darken();
if (badContrast(DarkVibrant, Vibrant)) {
Vibrant = Vibrant.brighten();
}
if (badContrast(DarkVibrant, Vibrant)) {
Vibrant = Vibrant.brighten();
}
}
// second pass - first doesn't always get it right.
if (badContrast(DarkVibrant, Vibrant) || badContrast(DarkVibrant, LightMuted)) {
DarkVibrant = DarkVibrant.darken();
if (badContrast(DarkVibrant, Vibrant)) {
Vibrant = Vibrant.brighten(2);
}
if (badContrast(DarkVibrant, LightMuted)) {
LightMuted = LightMuted.brighten(2);
}
}
if (badContrast(DarkVibrant, Vibrant)){
console.log('contrast still too low', imagePath);
console.log(chalk.hex(Vibrant.hex()).bgHex(DarkVibrant.hex())(`DV-V: ${chroma.contrast(DarkVibrant, Vibrant)}`));
}
if (badContrast(DarkVibrant, LightMuted)){
console.log('contrast still too low', imagePath);
console.log(chalk.hex(LightMuted.hex()).bgHex(DarkVibrant.hex())(`DV-LM: ${chroma.contrast(DarkVibrant, LightMuted)}`));
}
return {
Vibrant: Vibrant.rgb(),
DarkVibrant: DarkVibrant.rgb(),
LightVibrant: LightVibrant.rgb(),
Muted: Muted.rgb(),
DarkMuted: DarkMuted.rgb(),
LightMuted: LightMuted.rgb(),
};
}
function convertDMSToDD(dms, positiveDirection) {
const res = dms
@ -19,7 +69,7 @@ function convertDMSToDD(dms, positiveDirection) {
return positiveDirection ? res : -res;
}
function transformMetaToNodeData(exifData, iptcData, vibrantData) {
function transformMetaToNodeData(exifData, iptcData, vibrantData, imagePath) {
const gps = { longitude: null, latitude: null };
if (exifData) {
@ -39,22 +89,7 @@ function transformMetaToNodeData(exifData, iptcData, vibrantData) {
}
}
const vbChroma = R.map((swatch) => (chroma(swatch.getRgb()))
, vibrantData);
if (chroma.contrast(vbChroma.DarkVibrant, vbChroma.Vibrant) < 4.5) {
// console.log('adjusting colors', chroma.contrast(vbChroma.DarkVibrant, vbChroma.Vibrant));
// console.log(vbChroma.DarkVibrant.hex());
// console.log(vbChroma.Vibrant.hex());
vbChroma.DarkVibrant = vbChroma.DarkVibrant.darken();
vbChroma.Vibrant = vbChroma.Vibrant.brighten();
// console.log('adjusted', chroma.contrast(vbChroma.DarkVibrant, vbChroma.Vibrant));
// console.log(vbChroma.DarkVibrant.hex());
// console.log(vbChroma.Vibrant.hex());
}
const vibrantRgb = R.map((color) => color.rgb(), vbChroma);
const vibrant = processColors(vibrantData, imagePath);
return {
@ -62,7 +97,7 @@ function transformMetaToNodeData(exifData, iptcData, vibrantData) {
gps,
dateTaken: exifData?.exif?.DateTimeOriginal,
iptc: iptcData || undefined,
vibrant: vibrantRgb,
vibrant,
};
}
@ -82,7 +117,7 @@ exports.onCreateNode = async function ({ node, getNode, actions }) {
createNodeField({
node,
name: 'imageMeta',
value: transformMetaToNodeData(exifData, iptcData, vibrantData),
value: transformMetaToNodeData(exifData, iptcData, vibrantData, parent.absolutePath),
});
}
};

View File

@ -26,6 +26,7 @@
"babel-eslint": "^10.1.0",
"babel-plugin-preval": "^5.0.0",
"babel-plugin-styled-components": "^1.12.0",
"chalk": "^4.1.1",
"chroma-js": "^2.1.2",
"classnames": "^2.3.1",
"eslint": "^7.28.0",

View File

@ -3581,7 +3581,7 @@ chalk@^3.0.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chalk@^4.0.0, chalk@^4.1.0:
chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad"
integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==