Skip to content

Instantly share code, notes, and snippets.

@simbo
Last active February 25, 2019 03:47
Show Gist options
  • Save simbo/0a45c556a479032d9cd64eae2e61c3a6 to your computer and use it in GitHub Desktop.
Save simbo/0a45c556a479032d9cd64eae2e61c3a6 to your computer and use it in GitHub Desktop.
const { mkdirp } = require('mkdirp');
const { readFile, writeFile } = require('fs');
const { dirname, join } = require('path');
const rimraf = require('rimraf');
const { green, red, yellow } = require('chalk');
const imagemin = require('imagemin');
const imageminJpegRecompress = require('imagemin-jpeg-recompress');
const jimp = require('jimp');
const denodeify = require('denodeify');
const globby = require('globby');
const Queue = require('p-queue');
const minimist = require('minimist');
const ora = require('ora');
const rootPath = dirname(__dirname);
const params = minimist(process.argv.slice(2));
const scaleSize = parseInt(params.size, 10);
const quality = ['low', 'medium', 'high', 'veryhigh']
.includes(params.quality) ? params.quality : 'medium';
const imgInputPath = join(rootPath, 'src/raw-images');
const imgOutputPath = join(rootPath, 'src/assets/images');
async function optimizeImages() {
const spinner = ora({
spinner: 'dots12',
color: 'cyan',
text: 'Processing images...'
}).start();
await denodeify(rimraf)(imgOutputPath);
await denodeify(mkdirp)(imgOutputPath);
const imgFilenames = await globby('*.jpg', { cwd: imgInputPath });
const queue = new Queue({ concurrency: 1 });
const succeeded = [];
const failed = [];
imgFilenames.forEach(imgFilename => {
queue.add(async () => {
const image = {
name: imgFilename,
inputPath: join(imgInputPath, imgFilename),
inputSize: null,
outputPath: join(imgOutputPath, imgFilename),
outputSize: null,
error: null,
}
try {
let buffer = await denodeify(readFile)(image.inputPath);
image.inputSize = buffer.byteLength;
const img = await jimp.create(buffer);
img.scaleToFit(scaleSize, scaleSize, jimp.RESIZE_BICUBIC);
buffer = await img.getBufferAsync(jimp.MIME_JPEG);
buffer = await imagemin.buffer(buffer, {
plugins: [
imageminJpegRecompress({ quality })
]
});
image.outputSize = buffer.byteLength;
await denodeify(writeFile)(image.outputPath, buffer);
succeeded.push(image);
} catch (err) {
image.error = err;
failed.push(image);
}
});
});
await queue.onEmpty();
const messages = [];
if (succeeded.length) {
messages.push(
green(`${succeeded.length} images successfully processed.`),
...succeeded.map(image => ` • ${image.name} ${yellow(`${
(100 - Math.round(image.outputSize / image.inputSize * 10000) / 100) * -1
}%`)}`)
);
}
if (failed.length) {
messages.push(
red(`${failed.length} images failed processing:`),
...failed.map(file => red(` • ${file.name}: ${file.error.message || file.error}`))
);
}
spinner.stop();
console.log(messages.join('\n'));
}
optimizeImages()
.catch(error => console.error(error));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment