Created
January 12, 2022 01:08
-
-
Save kapowaz/d43f6f86501937ca14eb8e8dea14c84f to your computer and use it in GitHub Desktop.
Batch image resize/creation script using sharp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "resize-images", | |
"version": "0.1.0", | |
"engines": { | |
"node": "14.18.*", | |
"npm": "please-use-yarn", | |
"yarn": ">= 1.22.15" | |
}, | |
"scripts": { | |
"images:resize": "node resizeImages.js", | |
"images:resize:name": "sh -c 'node resizeImages.js ${0}'" | |
}, | |
"devDependencies": { | |
"colors": "^1.4.0", | |
"js-yaml": "^4.1.0", | |
"mustache": "^4.2.0", | |
"sharp": "^0.29.3" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
output: 'src/assets/{{name}}/{{name}}-{{width}}px@{{scale}}x.jpg' | |
templates: | |
- width: 320 | |
height: 180 | |
variants: | |
- scale: 1 | |
quality: 100 | |
- scale: 2 | |
quality: 100 | |
- scale: 3 | |
quality: 100 | |
- width: 480 | |
height: 270 | |
variants: | |
- scale: 1 | |
quality: 100 | |
- scale: 2 | |
quality: 100 | |
- scale: 3 | |
quality: 95 | |
- width: 800 | |
height: 450 | |
variants: | |
- scale: 1 | |
quality: 100 | |
- scale: 2 | |
quality: 100 | |
- scale: 3 | |
quality: 95 | |
- width: 1280 | |
height: 640 | |
variants: | |
- scale: 1 | |
quality: 100 | |
- scale: 2 | |
quality: 95 | |
- width: 1440 | |
height: 640 | |
variants: | |
- scale: 1 | |
quality: 95 | |
- scale: 2 | |
quality: 90 | |
- width: 1920 | |
height: 720 | |
variants: | |
- scale: 1 | |
quality: 95 | |
- scale: 2 | |
quality: 90 | |
- width: 2560 | |
height: 960 | |
variants: | |
- scale: 1 | |
quality: 90 | |
- scale: 2 | |
quality: 85 | |
inputs: | |
- name: dsa-gotham | |
source: ./assets/renders/dsa-gotham.png | |
fit: cover | |
position: top | |
- name: dsa-johnston | |
source: ./assets/renders/dsa-johnston.png | |
fit: cover | |
position: center | |
- name: dsa-saturn | |
source: ./assets/renders/dsa-saturn-dalco-959-v3.png | |
crop: | |
bottom: 275 | |
fit: cover | |
position: center | |
- name: epbt-creative-studio | |
source: ./assets/renders/epbt-creative-studio.png | |
crop: | |
top: 215 | |
fit: cover | |
position: center | |
- name: gmk-taschenrechner | |
source: ./assets/renders/gmk-taschenrechner.png | |
fit: cover | |
position: center |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable @typescript-eslint/no-var-requires */ | |
/* eslint-disable import/no-extraneous-dependencies */ | |
const sharp = require('sharp'); | |
const yaml = require('js-yaml'); | |
const fs = require('fs'); | |
const Mustache = require('mustache'); | |
const colors = require('colors'); | |
const RECIPES = './recipes.yml'; | |
const [onlyName] = process.argv.reverse(); | |
async function resizeImages() { | |
try { | |
const recipes = yaml.load(fs.readFileSync(RECIPES, 'utf8')); | |
const { output, templates } = recipes; | |
let { inputs } = recipes; | |
const namedInput = recipes.inputs.find(({ name }) => name === onlyName); | |
if (process.argv.length === 3 && namedInput) inputs = [namedInput]; | |
inputs.forEach(({ name, source: sourcePath, crop, fit, position }) => { | |
try { | |
templates.map(async (template) => { | |
const { width, height } = template; | |
template.variants.map(async ({ scale, quality }) => { | |
const outputPath = Mustache.render(output, { | |
name, | |
width, | |
scale, | |
}); | |
const outputDir = (() => { | |
const parts = outputPath.split('/'); | |
parts.pop(); | |
return parts.join('/'); | |
})(); | |
if (!fs.existsSync(outputDir)) { | |
fs.mkdirSync(outputDir, { recursive: true }); | |
} | |
if (crop) { | |
const source = sharp(sourcePath); | |
const { width: sourceWidth, height: sourceHeight } = await source.metadata(); | |
const offset = crop ? (crop.top ? crop.top : crop.bottom) : 0; | |
const top = crop.top ? crop.top : 0; | |
const extractOptions = { left: 0, top, width: sourceWidth, height: sourceHeight - offset }; | |
const resizeOptions = { | |
width: width * scale, | |
height: height * scale, | |
fit, | |
position, | |
}; | |
try { | |
await source | |
.extract(extractOptions) | |
.resize(resizeOptions) | |
.jpeg({ quality, chromaSubsampling: '4:4:4' }) | |
.toFile(outputPath); | |
console.log(`${colors.green('✓')} ${outputPath}`); | |
} catch (error) { | |
console.error(`${colors.red('✗')} ${outputPath}`); | |
console.error(`${error}`, { | |
extractOptions, | |
resizeOptions, | |
}); | |
} | |
} else { | |
const resizeOptions = { width: width * scale, height: height * scale, fit, position }; | |
await sharp(sourcePath).resize(resizeOptions).jpeg({ quality }).toFile(outputPath); | |
console.log(`${colors.green('✓')} ${outputPath}`); | |
} | |
}); | |
}); | |
} catch (error) { | |
console.error(`${colors.red('✗')} An error occurred processing '${sourcePath}': ${error}`); | |
} | |
}); | |
} catch (error) { | |
console.error(`${colors.red('✗')} Unable to process YAML file '${RECIPES}'`); | |
} | |
} | |
resizeImages(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment