/* * Bereitet die Bilder der Seite „Kantarci Markt – Neueröffnung“ für die Mediathek vor. * * Die Mediathek nimmt kein SVG. Das Seitensymbol und der runde Stempel „Frische • Qualität • * Vertrauen“ der Vorlage sind aber SVG (der Stempel mit Text auf einem Kreisbogen, das kann kein * Baustein). Chromium rastert beide zu PNG. Das Logo der Vorlage (1536 × 1024, 1,3 MB) wird auf * seinen sichtbaren Teil zugeschnitten und auf 600 px Breite verkleinert (doppelte Anzeigebreite), * angezeigt wird es mit höchstens 300 px. * * node scripts/build-kantarci-markt-assets.mjs [ordner] * → logo.png, symbol.png, stempel.png im Ordner (Standard var/kantarci-markt-assets) */ import { chromium } from 'playwright'; import { readFile, writeFile } from 'node:fs/promises'; const ordner = process.argv[2] || 'var/kantarci-markt-assets'; const FORST = '#123b26', GOLD = '#a88332', GOLD_HELL = '#d2b978'; const browser = await chromium.launch(); const seite = await browser.newPage(); // Logo: sichtbaren Bereich über den Alphakanal bestimmen, zuschneiden, verkleinern. const logo = (await readFile(`${ordner}/kantarci-markt-logo.png`)).toString('base64'); const logoPng = await seite.evaluate(async (daten) => { const bild = new Image(); bild.src = `data:image/png;base64,${daten}`; await bild.decode(); const quelle = new OffscreenCanvas(bild.width, bild.height); const q = quelle.getContext('2d'); q.drawImage(bild, 0, 0); const { data } = q.getImageData(0, 0, bild.width, bild.height); let [x0, y0, x1, y1] = [bild.width, bild.height, 0, 0]; for (let y = 0; y < bild.height; y++) { for (let x = 0; x < bild.width; x++) { // Der Schein um die Waage läuft sehr flach aus; erst ab etwa 8 % Deckkraft zählt er. if (data[(y * bild.width + x) * 4 + 3] > 20) { x0 = Math.min(x0, x); y0 = Math.min(y0, y); x1 = Math.max(x1, x); y1 = Math.max(y1, y); } } } const rand = 8; x0 = Math.max(0, x0 - rand); y0 = Math.max(0, y0 - rand); x1 = Math.min(bild.width - 1, x1 + rand); y1 = Math.min(bild.height - 1, y1 + rand); const breite = x1 - x0 + 1, hoehe = y1 - y0 + 1; const ziel = Math.min(600, breite); const leinwand = new OffscreenCanvas(ziel, Math.round(hoehe * ziel / breite)); const z = leinwand.getContext('2d'); z.imageSmoothingQuality = 'high'; z.drawImage(bild, x0, y0, breite, hoehe, 0, 0, leinwand.width, leinwand.height); const blob = await leinwand.convertToBlob({ type: 'image/png' }); const bytes = new Uint8Array(await blob.arrayBuffer()); let binaer = ''; for (const b of bytes) binaer += String.fromCharCode(b); return { png: btoa(binaer), breite: leinwand.width, hoehe: leinwand.height, ausschnitt: [x0, y0, breite, hoehe] }; }, logo); await writeFile(`${ordner}/logo.png`, Buffer.from(logoPng.png, 'base64')); console.log(`logo.png ${logoPng.breite} × ${logoPng.hoehe} (Ausschnitt ${logoPng.ausschnitt.join(', ')})`); const rastern = async (svg, groesse, datei) => { await seite.setViewportSize({ width: groesse, height: groesse }); await seite.setContent(`${svg}`); await seite.screenshot({ path: `${ordner}/${datei}`, omitBackground: true }); console.log(`${datei} ${groesse} × ${groesse}`); }; // Seitensymbol: das K mit Blatt aus dem Favicon der Vorlage. await rastern(` `, 256, 'symbol.png'); // Stempel: goldene Scheibe, Umschrift auf dem Kreis, Blatt in der Mitte. Doppelte Größe für // scharfe Kanten auf hochauflösenden Bildschirmen (angezeigt mit 122 px). await rastern(` FRISCHE • QUALITÄT • VERTRAUEN • `, 244, 'stempel.png'); await browser.close();