Cover-Spielerfoto: Varianten statt 12-MB-Original (iOS Safari)
Das Cover blieb am iPhone leer, während Chrome am Desktop es zeigte. Ursache war kein fehlendes Bild: das freigestellte Spielerfoto hatte 2584x5093 Pixel und 12,3 MB. iOS Safari verwirft Bilder, deren dekodierte Größe sein Budget übersteigt — hier gut 53 MB, und auf einer Ausgabe liegen 86 Bilder. Dargestellt wird das Foto mit 98cqi Höhe, bei 480px Seitenbreite also etwa 238x470 CSS-Pixel. Es gibt jetzt 320/640/1000 als PNG mit erhaltener Transparenz (0,2 / 0,8 / 1,9 MB); sizes nennt die echte Breite, sonst zöge ein Handy mit DPR 3 die größte Variante. Das Original ist gelöscht. Dafür kann resize_image_variants() nun Alpha erhalten ($alpha = true schreibt PNG statt JPG) und die img-Komponente eine Endung ($image['ext']). Der Default bleibt JPG, weil bestehende Aufrufer PNG-Quellen absichtlich zu JPG verkleinern. bin/stadionzeitung-add.php erzeugt die Varianten künftig selbst. Dort stand "unverändert kopieren, Felix liefert bereits ein web-taugliches Foto" — genau diese Annahme ist gerissen. Außerdem: smtp.password stand in der Produktiv-Config noch auf dem Platzhalter POSTFACH_PASSWORT (von preflight auf dem Server gefunden, einziger harter Fehler). Übernommen wurde das Passwort aus der Dev-Config, mit dem der Versand am 27.07.2026 verifiziert wurde; Host, Postfach und Empfänger sind identisch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
This commit is contained in:
@@ -208,8 +208,15 @@ function img_intrinsic_attrs(string $rel): string
|
||||
* Kernlogik von bin/img-resize.php (CLI-Wrapper) und bin/stadionzeitung-add.php
|
||||
* (ruft das direkt im Loop auf, ohne 22× einen Subprozess zu starten).
|
||||
* Rückgabe: [['width' => int, 'height' => int, 'file' => string, 'bytes' => int], …].
|
||||
*
|
||||
* $alpha = true schreibt stattdessen <destBase>-<breite>.png und erhält die
|
||||
* Transparenz — nötig für freigestellte Motive (Spielerfoto auf dem
|
||||
* Stadionzeitungs-Cover), bei denen JPG die Freistellung gegen Schwarz wegrechnen
|
||||
* würde. $quality gilt dann nicht (PNG ist verlustfrei). Der Default bleibt JPG,
|
||||
* weil bestehende Aufrufer PNG-Quellen absichtlich zu JPG verkleinern und deren
|
||||
* Pfade in den data/*.json auf .jpg zeigen.
|
||||
*/
|
||||
function resize_image_variants(string $src, string $destBase, array $widths, int $quality = 78): array
|
||||
function resize_image_variants(string $src, string $destBase, array $widths, int $quality = 78, bool $alpha = false): array
|
||||
{
|
||||
$image = match (strtolower(pathinfo($src, PATHINFO_EXTENSION))) {
|
||||
'jpg', 'jpeg' => imagecreatefromjpeg($src),
|
||||
@@ -229,9 +236,25 @@ function resize_image_variants(string $src, string $destBase, array $widths, int
|
||||
$w = min((int) $width, $srcW); // nie hochskalieren
|
||||
$h = (int) round($srcH * $w / $srcW);
|
||||
$frame = imagecreatetruecolor($w, $h);
|
||||
|
||||
if ($alpha) {
|
||||
// Transparenz retten: ohne Blending kopieren (sonst rechnet GD den
|
||||
// Alphakanal gegen Schwarz weg) und die Fläche vorher transparent füllen.
|
||||
imagealphablending($frame, false);
|
||||
imagesavealpha($frame, true);
|
||||
$leer = (int) imagecolorallocatealpha($frame, 0, 0, 0, 127);
|
||||
imagefilledrectangle($frame, 0, 0, $w, $h, $leer);
|
||||
}
|
||||
|
||||
imagecopyresampled($frame, $image, 0, 0, 0, 0, $w, $h, $srcW, $srcH);
|
||||
$file = "{$destBase}-{$w}.jpg";
|
||||
imagejpeg($frame, $file, $quality);
|
||||
|
||||
if ($alpha) {
|
||||
$file = "{$destBase}-{$w}.png";
|
||||
imagepng($frame, $file, 9);
|
||||
} else {
|
||||
$file = "{$destBase}-{$w}.jpg";
|
||||
imagejpeg($frame, $file, $quality);
|
||||
}
|
||||
$out[] = ['width' => $w, 'height' => $h, 'file' => $file, 'bytes' => (int) filesize($file)];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user