card game
This commit is contained in:
65
card-game/svg_to_png.js
Normal file
65
card-game/svg_to_png.js
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/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).`);
|
||||
})();
|
||||
Reference in New Issue
Block a user