OG image creation improved

This commit is contained in:
hbrain 2026-06-04 10:39:04 +02:00
parent cb126a1ca1
commit 947b509f0b

91
new.php
View file

@ -49,7 +49,8 @@ function slugify($s){ $s = ascii_safe($s); $s = strtolower(trim($s)); $s = preg_
function rrmdir($dir){ if(!is_dir($dir)) return; foreach(scandir($dir) as $f){ if($f==='.'||$f==='..') continue; $p="$dir/$f"; is_dir($p)?rrmdir($p):unlink($p);} rmdir($dir); }
function apply_thumbnail_overlay($imagePath, $title, $teaser) {
$logFile = __DIR__ . '/logs/image_magick.log';
file_put_contents($logFile, "--- New Thumbnail Job ---\n", FILE_APPEND);
file_put_contents($logFile, "--- New Thumbnail Job ---
", FILE_APPEND);
$fontPath = __DIR__ . '/assets/fonts/IBMPlexSans-SemiBold.ttf';
$titleFontPath = is_file(__DIR__ . '/assets/fonts/BebasNeue-Regular.ttf')
@ -62,8 +63,13 @@ function apply_thumbnail_overlay($imagePath, $title, $teaser) {
throw new RuntimeException('Thumbnail font file is missing.');
}
$imgW = 1200;
$imgH = 630;
$scale = 3;
$baseW = 1200;
$baseH = 630;
$imgW = $baseW * $scale;
$imgH = $baseH * $scale;
$targetW = $baseW;
$targetH = $baseH;
$normalize = static function ($text): string {
$text = trim((string)$text);
@ -73,7 +79,8 @@ function apply_thumbnail_overlay($imagePath, $title, $teaser) {
};
$wrapText = static function ($text, int $width) use ($normalize): string {
$text = $normalize($text);
return $text === '' ? '' : wordwrap($text, $width, "\n", false);
return $text === '' ? '' : wordwrap($text, $width, "
", false);
};
$clampWrappedText = static function ($text, int $width, int $maxLines, bool $cutLongWords = false) use ($normalize): string {
$text = $normalize($text);
@ -82,8 +89,10 @@ function apply_thumbnail_overlay($imagePath, $title, $teaser) {
if (!$words) return '';
$candidate = implode(' ', $words);
while (true) {
$wrapped = wordwrap($candidate, $width, "\n", $cutLongWords);
$lineCount = substr_count($wrapped, "\n") + 1;
$wrapped = wordwrap($candidate, $width, "
", $cutLongWords);
$lineCount = substr_count($wrapped, "
") + 1;
if ($lineCount <= $maxLines || count($words) <= 1) return $wrapped;
array_pop($words);
$candidate = implode(' ', $words) . '…';
@ -97,7 +106,8 @@ function apply_thumbnail_overlay($imagePath, $title, $teaser) {
for ($size = 84; $size >= 54; $size -= 4) {
$width = max(16, min(46, (int)round(23 + (84 - $size) / 2.7)));
$candidate = $wrapText($text, $width);
$lines = substr_count($candidate, "\n") + 1;
$lines = substr_count($candidate, "
") + 1;
$bestText = $candidate;
$bestSize = $size;
$bestWidth = $width;
@ -107,15 +117,28 @@ function apply_thumbnail_overlay($imagePath, $title, $teaser) {
return [$bestText, $bestSize, $bestWidth, $bestLines];
};
[$titleText, $titleFontSize, $titleWrapWidth, $titleLines] = $fitTitleText($title);
[$titleText, $titleFontSizeBase, $titleWrapWidth, $titleLines] = $fitTitleText($title);
$teaserText = $clampWrappedText($teaser, 34, 6, true);
$teaserLines = max(1, substr_count($teaserText, "\n") + 1);
$teaserLines = max(1, substr_count($teaserText, "
") + 1);
// Move the whole block a bit left and higher while keeping left-aligned text.
$left = max(14, (int)round($imgW * 0.046));
$titleY = max(20, (int)round($imgH * 0.062));
$titleLineStep = max(68, (int)round($imgH * 0.043));
$teaserY = max((int)round($imgH * 0.235), $titleY + ($titleLines * $titleLineStep) + max(54, (int)round($imgH * 0.03)));
$baseLeft = max(14, (int)round($baseW * 0.046));
$baseTitleY = max(20, (int)round($baseH * 0.062));
$baseTitleLineStep = max(68, (int)round($baseH * 0.043));
$baseTeaserY = max((int)round($baseH * 0.235), $baseTitleY + ($titleLines * $baseTitleLineStep) + max(54, (int)round($baseH * 0.03)));
$left = $baseLeft * $scale;
$titleY = $baseTitleY * $scale;
$titleLineStep = $baseTitleLineStep * $scale;
$teaserY = $baseTeaserY * $scale;
$shadowOffset = 3 * $scale;
$titleLineSpacing = 2 * $scale;
$teaserLineSpacing = -18 * $scale;
$titlePointSize = $titleFontSizeBase * $scale;
$teaserPointSize = 58 * $scale;
$shadowFill = 'rgba(0,0,0,0.35)';
$titleFill = '#F3F4F6';
$teaserFill = '#EADFC9';
$overlayBase = tempnam(sys_get_temp_dir(), 'thumb_overlay_');
$outputPath = dirname($imagePath) . '/' . basename($imagePath) . '.tmp.' . uniqid('', true) . '.jpg';
@ -126,23 +149,38 @@ function apply_thumbnail_overlay($imagePath, $title, $teaser) {
@unlink($overlayBase);
$cmd1 = sprintf(
'/usr/bin/convert -size %dx%d xc:none -font %s -pointsize %d -fill "#F3F4F6" -stroke black -strokewidth 2 -interline-spacing 2 -gravity northwest -annotate +%d+%d %s -font %s -pointsize 58 -fill "#EADFC9" -stroke black -strokewidth 2 -interline-spacing -18 -gravity northwest -annotate +%d+%d %s %s 2>&1',
'/usr/bin/convert -size %dx%d xc:none -font %s -pointsize %d -fill %s -interline-spacing %d -gravity northwest -annotate +%d+%d %s -fill %s -annotate +%d+%d %s -font %s -pointsize %d -fill %s -interline-spacing %d -gravity northwest -annotate +%d+%d %s -fill %s -annotate +%d+%d %s %s 2>&1',
$imgW,
$imgH,
escapeshellarg($titleFontPath),
$titleFontSize,
$titlePointSize,
escapeshellarg($shadowFill),
$titleLineSpacing,
$left + $shadowOffset,
$titleY + $shadowOffset,
escapeshellarg($titleText),
escapeshellarg($titleFill),
$left,
$titleY,
escapeshellarg($titleText),
escapeshellarg($teaserFontPath),
$teaserPointSize,
escapeshellarg($shadowFill),
$teaserLineSpacing,
$left + $shadowOffset,
$teaserY + $shadowOffset,
escapeshellarg($teaserText),
escapeshellarg($teaserFill),
$left,
$teaserY,
escapeshellarg($teaserText),
escapeshellarg($overlayPath)
);
file_put_contents($logFile, "Overlay CMD: " . $cmd1 . "\n", FILE_APPEND);
file_put_contents($logFile, "Overlay CMD: " . $cmd1 . "
", FILE_APPEND);
$out1 = shell_exec($cmd1);
file_put_contents($logFile, "Overlay Output: " . $out1 . "\n", FILE_APPEND);
file_put_contents($logFile, "Overlay Output: " . $out1 . "
", FILE_APPEND);
if (!is_file($overlayPath) || filesize($overlayPath) < 100) {
@unlink($overlayPath);
@unlink($outputPath);
@ -150,7 +188,7 @@ function apply_thumbnail_overlay($imagePath, $title, $teaser) {
}
$maxBytes = 600 * 1024;
$qualities = [88, 84, 80, 76, 72, 68, 64, 60, 56, 52, 48];
$qualities = [96, 92, 88, 84, 80, 76, 72, 68, 64];
$finalPath = '';
$finalSize = 0;
$finalOut = '';
@ -158,19 +196,25 @@ function apply_thumbnail_overlay($imagePath, $title, $teaser) {
foreach ($qualities as $quality) {
$attemptPath = dirname($imagePath) . '/' . basename($imagePath) . '.tmp.' . uniqid('', true) . '.jpg';
$cmd2 = sprintf(
'/usr/bin/convert -filter Lanczos -define filter:blur=0.85 %s -resize %dx%d^ -gravity center -extent %dx%d -modulate 70,82 %s -composite -strip -interlace Plane -sampling-factor 4:2:0 -quality %d %s 2>&1',
'/usr/bin/convert -filter Lanczos -define filter:blur=0.85 %s -resize %dx%d^ -gravity center -extent %dx%d -modulate 70,82 %s -composite -resize %dx%d -gravity center -extent %dx%d -unsharp 0x0.75+0.75+0.008 -strip -interlace Plane -sampling-factor 4:2:0 -quality %d %s 2>&1',
escapeshellarg($imagePath),
$imgW,
$imgH,
$imgW,
$imgH,
escapeshellarg($overlayPath),
$targetW,
$targetH,
$targetW,
$targetH,
$quality,
escapeshellarg($attemptPath)
);
file_put_contents($logFile, "Composite CMD (q=$quality): " . $cmd2 . "\n", FILE_APPEND);
file_put_contents($logFile, "Composite CMD (q=$quality): " . $cmd2 . "
", FILE_APPEND);
$out2 = shell_exec($cmd2);
file_put_contents($logFile, "Composite Output (q=$quality): " . $out2 . "\n", FILE_APPEND);
file_put_contents($logFile, "Composite Output (q=$quality): " . $out2 . "
", FILE_APPEND);
if (!is_file($attemptPath) || filesize($attemptPath) < 100) {
@unlink($attemptPath);
@ -191,7 +235,8 @@ function apply_thumbnail_overlay($imagePath, $title, $teaser) {
}
if ($finalSize > $maxBytes) {
file_put_contents($logFile, "Thumbnail still above size limit: " . $finalSize . " bytes\n", FILE_APPEND);
file_put_contents($logFile, "Thumbnail still above size limit: " . $finalSize . " bytes
", FILE_APPEND);
}
if (!@rename($finalPath, $imagePath)) {