Seed, asset and reset scripts for Becker - Just In Time e. Kfm. (Wiernsheim): logo cut from the PDF raster, logo-free photos generated with ChatGPT, before/after slider, service pages, contact form, legal pages. Launch configs on ports 8116/8117, Manrope 800 and Montserrat 700/800 fetched locally. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
130 lines
6.0 KiB
PHP
130 lines
6.0 KiB
PHP
<?php
|
||
|
||
/**
|
||
* Bereitet Logo und Fotos von „Becker – Just In Time e. Kfm.“ für die Mediathek des Nachbaus vor.
|
||
*
|
||
* Quellordner (var/becker-quelle):
|
||
* - logo-original.png: das Rasterbild aus Logo_Becker_original.pdf (1536 × 1024, Navy-Grund #172234),
|
||
* - ki/*.png: die von ChatGPT ohne Logos neu erzeugten Fotos (10.11.2026, nach Umuts Vorlagen).
|
||
*
|
||
* Daraus entstehen im Zielordner:
|
||
* - logo.png: Bagger-Signet links, „BECKER / JUST IN TIME e. Kfm.“ rechts – für den Kopf,
|
||
* - logo-gross.png: das Logo gestapelt mit den drei Leistungssymbolen – für den Fuß,
|
||
* - favicon.png: das Bagger-Signet auf Navy, 192 × 192,
|
||
* - je Foto eine WebP-Datei (Startbild 1920 px, sonst 1600 px breit).
|
||
*
|
||
* Der Navy-Grund des Logos wird weich freigestellt: Deckkraft aus dem Farbabstand zum Grund,
|
||
* die Kantenfarbe zurückgerechnet. So passt das Logo auf jede dunkle Fläche.
|
||
*
|
||
* Aufruf: php scripts/build-becker-assets.php <Quellordner> <Zielordner>
|
||
*/
|
||
$quelle = rtrim($argv[1] ?? '', '/\\');
|
||
$ziel = rtrim($argv[2] ?? '', '/\\');
|
||
if ('' === $quelle || '' === $ziel || !is_file($quelle.'/logo-original.png')) {
|
||
fwrite(STDERR, "Aufruf: php scripts/build-becker-assets.php <Ordner mit logo-original.png und ki/> <Zielordner>\n");
|
||
exit(1);
|
||
}
|
||
if (!is_dir($ziel) && !mkdir($ziel, 0775, true)) {
|
||
fwrite(STDERR, "Zielordner lässt sich nicht anlegen: $ziel\n");
|
||
exit(1);
|
||
}
|
||
|
||
$logo = imagecreatefrompng($quelle.'/logo-original.png');
|
||
$grund = [23, 34, 52];
|
||
|
||
/** Ein Ausschnitt des Logos mit freigestelltem Navy-Grund. */
|
||
$freistellen = static function (int $x, int $y, int $b, int $h) use ($logo, $grund): GdImage {
|
||
$bild = imagecreatetruecolor($b, $h);
|
||
imagealphablending($bild, false);
|
||
imagesavealpha($bild, true);
|
||
for ($j = 0; $j < $h; ++$j) {
|
||
for ($i = 0; $i < $b; ++$i) {
|
||
$c = imagecolorat($logo, $x + $i, $y + $j);
|
||
$p = [$c >> 16 & 0xFF, $c >> 8 & 0xFF, $c & 0xFF];
|
||
$abstand = max(abs($p[0] - $grund[0]), abs($p[1] - $grund[1]), abs($p[2] - $grund[2]));
|
||
$a = min(1.0, max(0.0, ($abstand - 6) / 90));
|
||
if ($a <= 0.0) {
|
||
imagesetpixel($bild, $i, $j, imagecolorallocatealpha($bild, 0, 0, 0, 127));
|
||
continue;
|
||
}
|
||
$f = array_map(static fn (int $k): int => (int) max(0, min(255, round($grund[$k] + ($p[$k] - $grund[$k]) / $a))), [0, 1, 2]);
|
||
imagesetpixel($bild, $i, $j, imagecolorallocatealpha($bild, $f[0], $f[1], $f[2], (int) round(127 * (1 - $a))));
|
||
}
|
||
}
|
||
|
||
return $bild;
|
||
};
|
||
|
||
/** Verkleinert mit Durchsichtigkeit. */
|
||
$verkleinern = static function (GdImage $bild, int $breite): GdImage {
|
||
$hoehe = (int) round(imagesy($bild) * $breite / imagesx($bild));
|
||
$neu = imagecreatetruecolor($breite, $hoehe);
|
||
imagealphablending($neu, false);
|
||
imagesavealpha($neu, true);
|
||
imagefill($neu, 0, 0, imagecolorallocatealpha($neu, 0, 0, 0, 127));
|
||
imagecopyresampled($neu, $bild, 0, 0, 0, 0, $breite, $hoehe, imagesx($bild), imagesy($bild));
|
||
|
||
return $neu;
|
||
};
|
||
|
||
// Bänder im Original (gemessen): Signet y 15–455 / x 360–1196, „BECKER“ y 466–636,
|
||
// „JUST IN TIME e. Kfm.“ mit Linien y 647–701 / x 162–1382, Leistungssymbole y 722–897.
|
||
$signet = $freistellen(352, 8, 852, 456);
|
||
$schrift = $freistellen(154, 458, 1236, 252);
|
||
|
||
// Querformat für den Kopf: Signet links (so hoch wie die Schrift plus etwas), Schrift rechts.
|
||
$sh = 330;
|
||
$sb = (int) round(852 * $sh / 456);
|
||
$quer = imagecreatetruecolor($sb + 36 + 1236, $sh);
|
||
imagealphablending($quer, false);
|
||
imagesavealpha($quer, true);
|
||
imagefill($quer, 0, 0, imagecolorallocatealpha($quer, 0, 0, 0, 127));
|
||
imagealphablending($quer, true);
|
||
imagecopyresampled($quer, $signet, 0, 0, 0, 0, $sb, $sh, 852, 456);
|
||
imagecopy($quer, $schrift, $sb + 36, (int) round(($sh - 252) / 2) + 10, 0, 0, 1236, 252);
|
||
imagealphablending($quer, false);
|
||
imagepng($verkleinern($quer, 760), $ziel.'/logo.png', 9);
|
||
echo 'logo.png: 760 × '.(int) round($sh * 760 / imagesx($quer))."\n";
|
||
|
||
$gross = $freistellen(100, 8, 1336, 898);
|
||
imagepng($verkleinern($gross, 560), $ziel.'/logo-gross.png', 9);
|
||
echo "logo-gross.png: 560 px breit\n";
|
||
|
||
// Die drei Leistungssymbole des Logos (Blätter, Zaun, Dach) einzeln, quadratisch, 128 px.
|
||
foreach (['symbol-garten' => [250, 716, 186, 120], 'symbol-zaun' => [679, 716, 176, 124], 'symbol-asbest' => [1071, 716, 226, 120]] as $name => [$x, $y, $b, $h]) {
|
||
$teil = $freistellen($x, $y, $b, $h);
|
||
$q = max($b, $h);
|
||
$quadrat = imagecreatetruecolor(128, 128);
|
||
imagealphablending($quadrat, false);
|
||
imagesavealpha($quadrat, true);
|
||
imagefill($quadrat, 0, 0, imagecolorallocatealpha($quadrat, 0, 0, 0, 127));
|
||
$f = 128 / $q;
|
||
imagecopyresampled($quadrat, $teil, (int) round((128 - $b * $f) / 2), (int) round((128 - $h * $f) / 2), 0, 0, (int) round($b * $f), (int) round($h * $f), $b, $h);
|
||
imagepng($quadrat, $ziel.'/'.$name.'.png', 9);
|
||
echo "$name.png: 128 × 128\n";
|
||
}
|
||
|
||
// Seitensymbol: Signet mittig auf Navy.
|
||
$fav = imagecreatetruecolor(192, 192);
|
||
imagefill($fav, 0, 0, imagecolorallocate($fav, ...$grund));
|
||
imagecopyresampled($fav, $logo, 14, 22 + (int) round((148 - 164 * 440 / 836) / 2), 360, 15, 164, (int) round(164 * 440 / 836), 836, 440);
|
||
imagepng($fav, $ziel.'/favicon.png', 9);
|
||
echo "favicon.png: 192 × 192\n";
|
||
|
||
// Fotos: ChatGPT liefert PNG; als WebP auf Zielbreite.
|
||
foreach (['haus' => 1920, 'team' => 1600, 'zaun' => 1600, 'zauntor' => 1600, 'asbest' => 1600, 'dach' => 1600,
|
||
'bagger' => 1600, 'terrasse' => 1600, 'zisterne' => 1600, 'vorher' => 1600, 'nachher' => 1600] as $name => $breite) {
|
||
$pfad = $quelle.'/ki/'.$name.'.png';
|
||
if (!is_file($pfad)) {
|
||
fwrite(STDERR, "Foto fehlt: $pfad\n");
|
||
exit(1);
|
||
}
|
||
$bild = imagecreatefrompng($pfad);
|
||
$breite = min($breite, imagesx($bild));
|
||
$hoehe = (int) round(imagesy($bild) * $breite / imagesx($bild));
|
||
$neu = imagecreatetruecolor($breite, $hoehe);
|
||
imagecopyresampled($neu, $bild, 0, 0, 0, 0, $breite, $hoehe, imagesx($bild), imagesy($bild));
|
||
imagewebp($neu, $ziel.'/'.$name.'.webp', 80);
|
||
echo "$name.webp: $breite × $hoehe\n";
|
||
}
|