Skip to content

Instantly share code, notes, and snippets.

@kapowaz
Created January 12, 2022 01:08
Show Gist options
  • Save kapowaz/d43f6f86501937ca14eb8e8dea14c84f to your computer and use it in GitHub Desktop.
Save kapowaz/d43f6f86501937ca14eb8e8dea14c84f to your computer and use it in GitHub Desktop.
Batch image resize/creation script using sharp
{
"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"
}
}
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
/* 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