From 69b48e2e80462bdcf5a6cfd48d38073c7738f442 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 7 Jan 2025 22:35:23 +0000 Subject: [PATCH] Media: improve Imagick handling of colors and alpha channel for PNG image uploads. Fix an issue where index color (8 bit) PNG uploads were output as true color (24 bit) PNGs, significantly increasing their size. When using Imagick, PNG output images will now match the colors of the uploaded image. Also, correct handling of PNG alpha channel information so it is preserved in output images. Props adamsilverstein, pbearne, nosilver4u, peterdavehello, joemcgill, azaozz, codex-m, kirasong, justlevine, jokanane, sallyruchman, wpfed, tgsrvrs, antpb, tb1909. Fixes #36477. Built from https://develop.svn.wordpress.org/trunk@59589 git-svn-id: http://core.svn.wordpress.org/trunk@58975 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/class-wp-image-editor-imagick.php | 33 ++++++++++++++++++- wp-includes/version.php | 2 +- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/wp-includes/class-wp-image-editor-imagick.php b/wp-includes/class-wp-image-editor-imagick.php index 9abb631847..edce8d2b7d 100644 --- a/wp-includes/class-wp-image-editor-imagick.php +++ b/wp-includes/class-wp-image-editor-imagick.php @@ -484,7 +484,38 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor { $this->image->setOption( 'png:compression-filter', '5' ); $this->image->setOption( 'png:compression-level', '9' ); $this->image->setOption( 'png:compression-strategy', '1' ); - $this->image->setOption( 'png:exclude-chunk', 'all' ); + // Check to see if a PNG is indexed, and find the pixel depth. + if ( is_callable( array( $this->image, 'getImageDepth' ) ) ) { + $indexed_pixel_depth = $this->image->getImageDepth(); + + // Indexed PNG files get some additional handling. + if ( 0 < $indexed_pixel_depth && 8 >= $indexed_pixel_depth ) { + // Check for an alpha channel. + if ( + is_callable( array( $this->image, 'getImageAlphaChannel' ) ) + && $this->image->getImageAlphaChannel() + ) { + $this->image->setOption( 'png:include-chunk', 'tRNS' ); + } else { + $this->image->setOption( 'png:exclude-chunk', 'all' ); + } + + // Reduce colors in the images to maximum needed, using the global colorspace. + $max_colors = pow( 2, $indexed_pixel_depth ); + if ( is_callable( array( $this->image, 'getImageColors' ) ) ) { + $current_colors = $this->image->getImageColors(); + $max_colors = min( $max_colors, $current_colors ); + } + $this->image->quantizeImage( $max_colors, $this->image->getColorspace(), 0, false, false ); + + /** + * If the colorspace is 'gray', use the png8 format to ensure it stays indexed. + */ + if ( Imagick::COLORSPACE_GRAY === $this->image->getImageColorspace() ) { + $this->image->setOption( 'png:format', 'png8' ); + } + } + } } /* diff --git a/wp-includes/version.php b/wp-includes/version.php index 53071345ad..d1dcbd66d3 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.8-alpha-59588'; +$wp_version = '6.8-alpha-59589'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.