Make WordPress Core


Ignore:
Timestamp:
05/22/2025 09:38:22 PM (15 months ago)
Author:
adamsilverstein
Message:

Media: fix degraded handling for 24 bit PNG uploads.

Add additional logic to correctly identify indexed PNG images so output PNGs correctly match the uploaded image depth.

Fix a regression introduced in WordPress 6.8 [59589] where uploaded Truecolor PNG images (meaning > 8 bit) were mis-identified as indexed (8 bit) images, causing output images to be indexed instead of Truecolor resulting in a noticeable visual degradation.

Props elvismdev, wildworks, SirLouen, siliconforks, joemcgill, iamshashank, nosilver4u.
Fixes #63448.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-image-editor-imagick.php

    r60047 r60246  
    485485                                $this->image->setOption( 'png:compression-level', '9' );
    486486                                $this->image->setOption( 'png:compression-strategy', '1' );
    487                                 // Check to see if a PNG is indexed, and find the pixel depth.
    488                                 if ( is_callable( array( $this->image, 'getImageDepth' ) ) ) {
    489                                         $indexed_pixel_depth = $this->image->getImageDepth();
    490 
    491                                         // Indexed PNG files get some additional handling.
    492                                         if ( 0 < $indexed_pixel_depth && 8 >= $indexed_pixel_depth ) {
    493                                                 // Check for an alpha channel.
    494                                                 if (
    495                                                         is_callable( array( $this->image, 'getImageAlphaChannel' ) )
    496                                                         && $this->image->getImageAlphaChannel()
    497                                                 ) {
    498                                                         $this->image->setOption( 'png:include-chunk', 'tRNS' );
    499                                                 } else {
    500                                                         $this->image->setOption( 'png:exclude-chunk', 'all' );
    501                                                 }
    502 
    503                                                 // Reduce colors in the images to maximum needed, using the global colorspace.
    504                                                 $max_colors = pow( 2, $indexed_pixel_depth );
    505                                                 if ( is_callable( array( $this->image, 'getImageColors' ) ) ) {
    506                                                         $current_colors = $this->image->getImageColors();
    507                                                         $max_colors     = min( $max_colors, $current_colors );
    508                                                 }
    509                                                 $this->image->quantizeImage( $max_colors, $this->image->getColorspace(), 0, false, false );
    510 
    511                                                 /**
    512                                                  * If the colorspace is 'gray', use the png8 format to ensure it stays indexed.
    513                                                  */
    514                                                 if ( Imagick::COLORSPACE_GRAY === $this->image->getImageColorspace() ) {
    515                                                         $this->image->setOption( 'png:format', 'png8' );
    516                                                 }
     487
     488                                // Indexed PNG files get some additional handling.
     489                                // See #63448 for details.
     490                                if (
     491                                        is_callable( array( $this->image, 'getImageProperty' ) )
     492                                        && '3' === $this->image->getImageProperty( 'png:IHDR.color-type-orig' )
     493                                ) {
     494
     495                                        // Check for an alpha channel.
     496                                        if (
     497                                                is_callable( array( $this->image, 'getImageAlphaChannel' ) )
     498                                                && $this->image->getImageAlphaChannel()
     499                                        ) {
     500                                                $this->image->setOption( 'png:include-chunk', 'tRNS' );
     501                                        } else {
     502                                                $this->image->setOption( 'png:exclude-chunk', 'all' );
    517503                                        }
     504                                        // Set the image format to Indexed PNG.
     505                                        $this->image->setOption( 'png:format', 'png8' );
     506
     507                                } else {
     508                                        $this->image->setOption( 'png:exclude-chunk', 'all' );
    518509                                }
    519510                        }
Note: See TracChangeset for help on using the changeset viewer.