From 551c366e6c06265591c1ee3e654a7587271f3beb Mon Sep 17 00:00:00 2001 From: Zankaria Date: Tue, 18 Mar 2025 00:41:04 +0100 Subject: [PATCH] GdThumbGenerator.php: add GdThumbGenerator --- inc/Service/Media/GdThumbGenerator.php | 132 +++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 inc/Service/Media/GdThumbGenerator.php diff --git a/inc/Service/Media/GdThumbGenerator.php b/inc/Service/Media/GdThumbGenerator.php new file mode 100644 index 00000000..51278a34 --- /dev/null +++ b/inc/Service/Media/GdThumbGenerator.php @@ -0,0 +1,132 @@ += 8 && PHP_MINOR_VERSION >= 1; + + private const MIME_TO_EXT = [ + 'image/jpeg' => 'jpg', + 'image/png' => 'png', + 'image/gif' => 'gif', + 'image/webp' => 'webp', + 'image/bmp' => 'bmp', + 'image/avif' => 'avif' + ]; + + + private static function imageCreateFrom(string $file, string $mime): mixed { + switch ($mime) { + case 'image/jpeg': + return imagecreatefromjpeg($file); + case 'image/png': + return imagecreatefrompng($file); + case 'image/gif': + return imagecreatefromgif($file); + case 'image/webp': + return imagecreatefromwbmp($file); + case 'image/bmp': + return imagecreatefrombmp($file); + case 'image/avif': + return self::PHP81 ? imagecreatefromavif($file) : false; + } + return false; + } + + public static function imageSaveTo(mixed $gd, string $file, string $mime) { + // Somebody should tune the quality and speed values... + switch ($mime) { + case 'image/jpeg': + return imagejpeg($gd, $file, 50); + case 'image/png': + return imagepng($gd, $file, 7); + case 'image/gif': + return imagegif($gd, $file); + case 'image/webp': + return imagewbmp($gd, $file, 50); + case 'image/bmp': + return imagebmp($gd, $file, true); + case 'image/avif': + return self::PHP81 ? imageavif($gd, $file, 30, 6) : false; + } + return false; + } + + private static function createCanvas(string $mime, int $width, int $height) { + $gd = \imagecreatetruecolor($width, $height); + switch ($mime) { + case 'image/png': + imagecolortransparent($gd, imagecolorallocatealpha($gd, 0, 0, 0, 0)); + imagesavealpha($gd, true); + imagealphablending($gd, false); + break; + case 'image/gif': + \imagecolortransparent($gd, \imagecolorallocatealpha($gd, 0, 0, 0, 0)); + \imagesavealpha($gd, true); + break; + } + return $gd; + } + + public function supportsMime(string $mime): bool { + $info = \gd_info(); + return ($mime === 'image/jpeg' && $info['JPEG Support']) + || ($mime === 'image/png' && $info['PNG Support']) + || ($mime === 'image/gif' && $info['GIF Read Support'] && $info['GIF Create Support']) + || ($mime === 'image/webp' && $info['WebP Support']) + || $mime === 'image/bmp' + || ($mime === 'image/avif' && self::PHP81 && $info['AVIF Support']); + } + + public function generateThumb( + string $source_file_path, + string $source_file_mime, + string $preferred_out_file_path, + string $preferred_out_mime, + int $max_width, + int $max_height + ): ThumbGenerationResult { + $gd = self::imageCreateFrom($source_file_path, $source_file_mime); + if ($gd === false) { + throw new \RuntimeException("Could not open '$source_file_path'"); + } + + $width = \imagesx($gd); + $height = \imagesy($gd); + + if ($width <= $max_width && $height <= $max_height) { + $out_path = $preferred_out_file_path . '.' . self::MIME_TO_EXT[$source_file_mime]; + + if (!link_or_copy($source_file_path, $out_path)) { + throw new \RuntimeException("Could not link or copy '$source_file_path' to '$out_path'"); + } + $res = new ThumbGenerationResult(); + $res->thumb_file_path = $out_path; + $res->thumb_mime = $source_file_mime; + $res->is_thumb_file_temporary = false; + $res->width = $width; + $res->height = $height; + return $res; + } else { + $out_path = $preferred_out_file_path . '.' . self::MIME_TO_EXT[$preferred_out_mime]; + + $gd_other = self::createCanvas($preferred_out_mime, $max_width, $max_height); + \imagecopyresampled($gd_other, $gd, 0, 0, 0, 0, $max_width, $max_height, $width, $height); + + if (!self::imageSaveTo($gd_other, $out_path, $preferred_out_mime)) { + throw new \RuntimeException("Could not create thumbnail file at '$out_path'"); + } + + $res = new ThumbGenerationResult(); + $res->thumb_file_path = $out_path; + $res->thumb_mime = $preferred_out_mime; + $res->is_thumb_file_temporary = false; + $res->width = $max_width; + $res->height = $max_height; + return $res; + } + } +}