Files
MrTerm/scripts/make-icons.js
T

48 lines
2.5 KiB
JavaScript

// Erzeugt App-Icons aus assets/logo-full.png: npx electron scripts/make-icons.js
// Der dunkle Hintergrund um das Emblem wird freigestellt (transparent), das Gesicht innerhalb der Kontur bleibt.
const { app, nativeImage } = require('electron');
const fs = require('fs');
// Von den Bildrändern aus fluten: Pixel ähnlich der Hintergrundfarbe werden transparent, der Kantensaum (max. 3 px)
// bekommt Transparenz aus seiner Helligkeit und wird gegen den Hintergrund "entmischt", damit kein dunkler Rand bleibt.
function cutOut(img) {
const { width: w, height: h } = img.getSize();
const src = img.toBitmap(); // BGRA
const out = Buffer.from(src);
const at = (x, y) => (y * w + x) * 4;
const bgI = at(w >> 1, 1);
const bg = [src[bgI + 2], src[bgI + 1], src[bgI]];
const seen = new Uint8Array(w * h);
const q = [];
for (let x = 0; x < w; x++) q.push([x, 0, 0], [x, h - 1, 0]);
for (let y = 0; y < h; y++) q.push([0, y, 0], [w - 1, y, 0]);
while (q.length) {
const [x, y, depth] = q.pop();
if (x < 0 || y < 0 || x >= w || y >= h || seen[y * w + x]) continue;
const i = at(x, y), r = src[i + 2], g = src[i + 1], b = src[i];
const lum = 0.299 * r + 0.587 * g + 0.114 * b;
const bgLike = Math.hypot(r - bg[0], g - bg[1], b - bg[2]) < 34;
if (!bgLike && (lum >= 215 || depth >= 3)) continue;
seen[y * w + x] = 1;
const a = bgLike ? 0 : Math.max(0, Math.min(1, (lum - 40) / 195));
const un = (v, c) => Math.max(0, Math.min(255, Math.round((v - (1 - a) * c) / a)));
if (a <= 0) out.fill(0, i, i + 4);
else { out[i + 2] = un(r, bg[0]); out[i + 1] = un(g, bg[1]); out[i] = un(b, bg[2]); out[i + 3] = Math.round(a * 255); }
const nd = bgLike ? 0 : depth + 1;
q.push([x + 1, y, nd], [x - 1, y, nd], [x, y + 1, nd], [x, y - 1, nd]);
}
return nativeImage.createFromBitmap(out, { width: w, height: h });
}
app.whenReady().then(() => {
const src = nativeImage.createFromPath('assets/logo-full.png');
const { width } = src.getSize();
const k = width / 1254;
// Ausschnitt: Kopf mit Hut, ohne Schriftzug
const head = cutOut(src.crop({ x: Math.round(282 * k), y: Math.round(172 * k), width: Math.round(706 * k), height: Math.round(706 * k) }));
fs.writeFileSync('build/icon.png', head.resize({ width: 512, height: 512, quality: 'best' }).toPNG());
fs.writeFileSync('src/renderer/logo.png', head.resize({ width: 96, height: 96, quality: 'best' }).toPNG());
fs.writeFileSync('assets/icon.png', head.resize({ width: 256, height: 256, quality: 'best' }).toPNG());
app.quit();
});