tischlerei-staffenberger/scripts/optimize-images.js

89 lines
2.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Image optimization script for Tischlerei Staffenberger.
* Generates WebP + JPEG variants at thumbnail (800px) and lightbox (1920px) sizes.
* Output: images/optimized/{category}/{name}-{size}w.{ext}
*
* Run: node scripts/optimize-images.js
*/
'use strict';
const sharp = require('sharp');
const fs = require('fs');
const path = require('path');
const PROJECT_ROOT = path.join(__dirname, '..');
const INPUT_ROOT = path.join(PROJECT_ROOT, 'images', 'fotowebsite');
const OUTPUT_ROOT = path.join(PROJECT_ROOT, 'images', 'optimized');
// Gallery categories: [input subdir, output subdir]
const GALLERY_DIRS = [
['küche', 'küche'],
['aussenbereich', 'aussenbereich'],
['sonderanfertigungen', 'sonderanfertigungen'],
];
const GALLERY_SIZES = [800, 1920];
const BANNER_SIZES = [800, 1920];
function safeName(filename) {
return path.basename(filename, path.extname(filename)).replace(/\s+/g, '-');
}
async function processImage(inputPath, outputDir, baseName, sizes) {
fs.mkdirSync(outputDir, { recursive: true });
for (const width of sizes) {
const jpegOut = path.join(outputDir, `${baseName}-${width}w.jpg`);
const webpOut = path.join(outputDir, `${baseName}-${width}w.webp`);
await sharp(inputPath)
.resize({ width, withoutEnlargement: true })
.jpeg({ quality: 85, mozjpeg: true })
.toFile(jpegOut);
await sharp(inputPath)
.resize({ width, withoutEnlargement: true })
.webp({ quality: 82 })
.toFile(webpOut);
const jpegSize = (fs.statSync(jpegOut).size / 1024).toFixed(0);
const webpSize = (fs.statSync(webpOut).size / 1024).toFixed(0);
console.log(` ${path.basename(jpegOut)}: JPEG ${jpegSize}KB WebP ${webpSize}KB`);
}
}
async function main() {
console.log('=== Tischlerei Staffenberger Image Optimization ===\n');
// --- Gallery images ---
for (const [inputSubdir, outputSubdir] of GALLERY_DIRS) {
const inputDir = path.join(INPUT_ROOT, inputSubdir);
const outputDir = path.join(OUTPUT_ROOT, outputSubdir);
const files = fs.readdirSync(inputDir)
.filter(f => /\.(jpe?g)$/i.test(f))
.sort();
console.log(`[${inputSubdir}] ${files.length} images`);
for (const file of files) {
const inputPath = path.join(inputDir, file);
const baseName = safeName(file);
await processImage(inputPath, outputDir, baseName, GALLERY_SIZES);
}
}
// --- Banner ---
const bannerInput = path.join(INPUT_ROOT, 'banner.jpg');
const bannerOutput = OUTPUT_ROOT;
console.log('\n[banner]');
await processImage(bannerInput, bannerOutput, 'banner', BANNER_SIZES);
console.log('\nDone.');
}
main().catch(err => {
console.error(err);
process.exit(1);
});