66 lines
2.4 KiB
JavaScript
66 lines
2.4 KiB
JavaScript
#!/usr/bin/env node
|
||
/* ============================================================
|
||
TROX – SVG -> PNG Konverter für The Game Crafter
|
||
------------------------------------------------------------
|
||
TGC akzeptiert nur PNG/JPG bei 300 DPI in RGB (kein SVG, kein CMYK).
|
||
Rendert jede SVG exakt auf ihre width/height-Pixelgröße (= 300 DPI)
|
||
und gibt flaches RGB aus.
|
||
|
||
Voraussetzung (einmalig): npm install sharp
|
||
|
||
Verwendung:
|
||
node svg_to_png.js karten_export_tgc
|
||
node svg_to_png.js box_export
|
||
node svg_to_png.js scorepad_export
|
||
============================================================ */
|
||
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
let sharp;
|
||
try { sharp = require('sharp'); }
|
||
catch (e) {
|
||
console.error('Fehlendes Modul "sharp". Bitte zuerst ausführen:\n npm install sharp\n');
|
||
process.exit(1);
|
||
}
|
||
|
||
const srcDir = process.argv[2];
|
||
if (!srcDir || !fs.existsSync(srcDir)) {
|
||
console.error('Bitte gültigen Quellordner angeben, z.B.:\n node svg_to_png.js karten_export_tgc');
|
||
process.exit(1);
|
||
}
|
||
|
||
const outDir = `${srcDir.replace(/\/$/, '')}_png`;
|
||
if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });
|
||
|
||
const files = fs.readdirSync(srcDir).filter(f => f.toLowerCase().endsWith('.svg'));
|
||
if (!files.length) { console.error('Keine SVG-Dateien gefunden in', srcDir); process.exit(1); }
|
||
|
||
function readSize(svg) {
|
||
const wm = svg.match(/<svg[^>]*\bwidth="(\d+(?:\.\d+)?)"/);
|
||
const hm = svg.match(/<svg[^>]*\bheight="(\d+(?:\.\d+)?)"/);
|
||
if (wm && hm) return { w: Math.round(+wm[1]), h: Math.round(+hm[1]) };
|
||
const vb = svg.match(/viewBox="0 0 (\d+(?:\.\d+)?) (\d+(?:\.\d+)?)"/);
|
||
if (vb) return { w: Math.round(+vb[1]), h: Math.round(+vb[2]) };
|
||
return null;
|
||
}
|
||
|
||
console.log(`Konvertiere ${files.length} SVG -> PNG (${srcDir} -> ${outDir}) ...`);
|
||
|
||
(async () => {
|
||
for (const f of files) {
|
||
const svg = fs.readFileSync(path.join(srcDir, f), 'utf8');
|
||
const size = readSize(svg);
|
||
const outPath = path.join(outDir, f.replace(/\.svg$/i, '.png'));
|
||
|
||
let img = sharp(Buffer.from(svg), { density: 300 });
|
||
if (size) img = img.resize(size.w, size.h, { fit: 'fill' });
|
||
|
||
await img
|
||
.flatten({ background: '#ffffff' })
|
||
.png({ compressionLevel: 9 })
|
||
.toFile(outPath);
|
||
}
|
||
console.log(`Fertig. PNGs liegen in ${outDir} (RGB, exakte 300-DPI-Pixelmaße).`);
|
||
})();
|