Replace entire repo content with correct code from /root/shahikitchen-website/
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
/**
|
||||
* Enhance all images under ftp-images/ and write to ~/Desktop/ftp-images-new
|
||||
* preserving directory structure. Non-image files are copied as-is.
|
||||
*/
|
||||
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import sharp from 'sharp';
|
||||
|
||||
const ROOT = path.resolve(__dirname, '..');
|
||||
const SRC_ROOT = path.join(ROOT, 'ftp-images');
|
||||
const OUT_ROOT = path.join(process.env.HOME ?? '', 'Desktop', 'ftp-images-new');
|
||||
|
||||
const IMAGE_RE = /\.(jpe?g|png|webp)$/i;
|
||||
const TARGET_W = 1600;
|
||||
const TARGET_H = 1200;
|
||||
const JPEG_QUALITY = 92;
|
||||
|
||||
function walk(dir: string): string[] {
|
||||
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
return entries.flatMap((entry) => {
|
||||
const full = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) return walk(full);
|
||||
return [full];
|
||||
});
|
||||
}
|
||||
|
||||
function isPosterPath(rel: string): boolean {
|
||||
return rel.includes('/others/') || /poster/i.test(rel);
|
||||
}
|
||||
|
||||
async function enhanceFoodPhoto(input: string, output: string) {
|
||||
const rotated = sharp(input, { failOn: 'none' }).rotate();
|
||||
const { data, info } = await rotated
|
||||
.toColorspace('srgb')
|
||||
.removeAlpha()
|
||||
.toBuffer({ resolveWithObject: true });
|
||||
|
||||
const width = info.width;
|
||||
const height = info.height;
|
||||
|
||||
const targetAspect = TARGET_W / TARGET_H;
|
||||
const sourceAspect = width / height;
|
||||
|
||||
let cropW = width;
|
||||
let cropH = height;
|
||||
let left = 0;
|
||||
let top = 0;
|
||||
|
||||
if (sourceAspect > targetAspect) {
|
||||
cropW = Math.round(height * targetAspect);
|
||||
left = Math.round((width - cropW) / 2);
|
||||
} else if (sourceAspect < targetAspect) {
|
||||
cropH = Math.round(width / targetAspect);
|
||||
top = Math.round((height - cropH) / 2);
|
||||
}
|
||||
|
||||
cropW = Math.min(cropW, width - left);
|
||||
cropH = Math.min(cropH, height - top);
|
||||
|
||||
let pipeline = sharp(data)
|
||||
.extract({ left, top, width: cropW, height: cropH })
|
||||
.normalize()
|
||||
.modulate({ brightness: 1.04, saturation: 1.18 })
|
||||
.gamma(1.05);
|
||||
|
||||
const minDim = Math.min(cropW, cropH);
|
||||
if (minDim < 900) {
|
||||
pipeline = pipeline.sharpen({ sigma: 1.2, m1: 0.8, m2: 0.4 });
|
||||
} else {
|
||||
pipeline = pipeline.sharpen({ sigma: 0.9, m1: 0.6, m2: 0.3 });
|
||||
}
|
||||
|
||||
await pipeline
|
||||
.resize(TARGET_W, TARGET_H, { fit: 'fill', kernel: sharp.kernel.lanczos3 })
|
||||
.jpeg({ quality: JPEG_QUALITY, mozjpeg: true, chromaSubsampling: '4:4:4' })
|
||||
.toFile(output);
|
||||
}
|
||||
|
||||
async function enhancePoster(input: string, output: string) {
|
||||
await sharp(input, { failOn: 'none' })
|
||||
.rotate()
|
||||
.toColorspace('srgb')
|
||||
.normalize()
|
||||
.modulate({ brightness: 1.02, saturation: 1.08 })
|
||||
.sharpen({ sigma: 0.6, m1: 0.5, m2: 0.25 })
|
||||
.resize({ width: 2400, withoutEnlargement: false, kernel: sharp.kernel.lanczos3 })
|
||||
.jpeg({ quality: 94, mozjpeg: true })
|
||||
.toFile(output);
|
||||
}
|
||||
|
||||
async function processImage(src: string, rel: string) {
|
||||
const outRel = rel.replace(IMAGE_RE, '.jpg');
|
||||
const dest = path.join(OUT_ROOT, outRel);
|
||||
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
||||
|
||||
if (isPosterPath(rel)) {
|
||||
await enhancePoster(src, dest);
|
||||
} else {
|
||||
await enhanceFoodPhoto(src, dest);
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
if (!fs.existsSync(SRC_ROOT)) {
|
||||
console.error(`Source not found: ${SRC_ROOT}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
fs.mkdirSync(OUT_ROOT, { recursive: true });
|
||||
|
||||
const files = walk(SRC_ROOT);
|
||||
let images = 0;
|
||||
let copied = 0;
|
||||
|
||||
for (const src of files) {
|
||||
const rel = path.relative(SRC_ROOT, src);
|
||||
|
||||
if (IMAGE_RE.test(src)) {
|
||||
try {
|
||||
const dest = await processImage(src, rel);
|
||||
images++;
|
||||
console.log(` ✓ ${rel} → ${path.basename(dest)}`);
|
||||
} catch (err) {
|
||||
console.error(` ✗ ${rel}: ${err instanceof Error ? err.message : err}`);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const dest = path.join(OUT_ROOT, rel);
|
||||
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
||||
fs.copyFileSync(src, dest);
|
||||
copied++;
|
||||
}
|
||||
|
||||
console.log(`\nDone: ${images} images enhanced → ${OUT_ROOT}`);
|
||||
console.log(` ${copied} non-image files copied`);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user