From f0c762741dd86d3f64a4fb719b44f9317e646836 Mon Sep 17 00:00:00 2001 From: Zankaria Date: Tue, 25 Mar 2025 21:22:05 +0100 Subject: [PATCH] LibMagickMediaHandler.php: implement installMediaAndGenerateThumb --- inc/Service/Media/LibMagickMediaHandler.php | 93 ++++++++++++++++++++- 1 file changed, 89 insertions(+), 4 deletions(-) diff --git a/inc/Service/Media/LibMagickMediaHandler.php b/inc/Service/Media/LibMagickMediaHandler.php index ba9d6886..03d2e5b5 100644 --- a/inc/Service/Media/LibMagickMediaHandler.php +++ b/inc/Service/Media/LibMagickMediaHandler.php @@ -91,6 +91,7 @@ class LibMagickMediaHandler implements MediaHandler { int $max_width, int $max_height ) { + // Special handling for gifs with multiple frames. if ( $source_file_mime === 'image/gif' && $this->frames_for_gif_thumbs !== self::THUMB_KEEP_FRAMES_NO @@ -106,13 +107,16 @@ class LibMagickMediaHandler implements MediaHandler { $thumb_height = $height; } - if ($this->frames_for_gif_thumbs !== self::THUMB_KEEP_FRAMES_ALL) { + // By now $this->frames_for_gif_thumbs !== 0. + $step = \floor($imagick->getNumberImages() / $this->frames_for_gif_thumbs); + + if ($this->frames_for_gif_thumbs !== self::THUMB_KEEP_FRAMES_ALL && $step > 1) { + // Reduce the number of frames. + $other = new \Imagick(); try { $other->setFormat('gif'); - $step = \floor($imagick->getNumberImages() / $this->frames_for_gif_thumbs); - for ($i = 0, $j = 0; $i < $imagick->getNumberImages(); $i += $step, $j++) { $imagick->setIteratorIndex($i); $delay = $imagick->getImageDelay(); @@ -132,6 +136,7 @@ class LibMagickMediaHandler implements MediaHandler { $other->clear(); } } else { + // Just try to optimize it a little. $imagick->stripImage(); $imagick->optimizeImageLayers(); @@ -151,6 +156,7 @@ class LibMagickMediaHandler implements MediaHandler { $thumb_width = $max_width; $thumb_height = $max_height; + // Unreliable behavior on some versions if the target width/height are under the limit? $imagick->thumbnailImage($max_width, $max_height, true); } else { $thumb_width = $width; @@ -174,6 +180,10 @@ class LibMagickMediaHandler implements MediaHandler { } } + /** + * Checks if the Imagick and ImageMagick are recent enough to support the required features. + * @return bool + */ public static function checkImagickVersion(): bool { $imagick_ver = \phpversion('imagick'); if ($imagick_ver !== false && \version_compare($imagick_ver, self::MIN_IMAGICK_VERSION, '>=')) { @@ -278,6 +288,81 @@ class LibMagickMediaHandler implements MediaHandler { int $thumb_max_width, int $thumb_max_height ): ThumbGenerationResult { - list($imagick, $file_path, $file_mime, $file_kind) = $handle; + list($imagick, $media_file_path, $media_file_mime, $media_file_kind) = $handle; + + $width = $imagick->getImageWidth(); + $height = $imagick->getImageHeight(); + + if (!$this->strip_metadata) { + $media_out_path = $media_preferred_out_file_dir . \DIRECTORY_SEPARATOR . $media_preferred_out_file_name . '.' . Mime\mime_to_ext($media_file_mime); + + if ($media_file_kind === self::FILE_KIND_UPLOADED) { + if (!Fs\move_or_copy_uploaded($media_file_path, $media_out_path)) { + throw new \RuntimeException("Could not move or copy uploaded file '$media_file_path' to '$media_out_path'"); + } + } else { + if (!Fs\link_or_copy($media_file_path, $media_out_path)) { + throw new \RuntimeException("Could not link or copy '$media_file_path' to '$media_out_path'"); + } + } + + if ($width <= $thumb_max_width && $height >= $thumb_max_height) { + $thumb_out_path = $thumb_preferred_out_file_dir . \DIRECTORY_SEPARATOR . '.' . Mime\mime_to_ext($media_file_mime); + if (!Fs\link_or_copy($media_out_path, $thumb_out_path)) { + throw new \RuntimeException("Could not link or copy '$media_out_path' to '$thumb_out_path'"); + } + + return new ThumbGenerationResult($thumb_out_path, $media_file_mime, false, $width, $height); + } else { + $swap = self::adjustOrientation($imagick); + if ($swap) { + $tmp = $width; + $width = $height; + $height = $tmp; + } + + return self::generateThumbImpl( + $imagick, + $media_file_mime, + $thumb_preferred_out_file_dir, + $thumb_preferred_out_file_name, + $thumb_preferred_out_mime, + $width, + $height, + $thumb_max_width, + $thumb_max_height + ); + } + } else { + $swap = self::adjustOrientation($imagick); + if ($swap) { + $tmp = $width; + $width = $height; + $height = $tmp; + } + + // Backup the color profile, then re-apply it. + $profiles = $imagick->getImageProfiles('icc', true); + $imagick->stripImage(); + if (!empty($profiles)) { + $imagick->profileImage('icc', $profiles['icc']); + } + + $out_ext = Mime\mime_to_ext($media_file_mime); + $out_path = $media_preferred_out_file_dir . \DIRECTORY_SEPARATOR . $media_preferred_out_file_name . '.' . $out_ext; + $imagick->writeImage("$out_ext:$out_path"); + + return self::generateThumbImpl( + $imagick, + $media_file_mime, + $thumb_preferred_out_file_dir, + $thumb_preferred_out_file_name, + $thumb_preferred_out_mime, + $width, + $height, + $thumb_max_width, + $thumb_max_height + ); + } } }