= 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'"); } return new ThumbGenerationResult( $out_path, $source_file_mime, false, $width, $height ); } 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'"); } return new ThumbGenerationResult( $out_path, $preferred_out_mime, false, $max_width, $max_height ); } } }