Make WordPress Core


Ignore:
Timestamp:
01/07/2025 10:33:37 PM (16 months ago)
Author:
adamsilverstein
Message:

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.

File:
1 edited

Legend:

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

    r59588 r59589  
    485485                $this->image->setOption( 'png:compression-level', '9' );
    486486                $this->image->setOption( 'png:compression-strategy', '1' );
    487                 $this->image->setOption( 'png:exclude-chunk', 'all' );
     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                        }
     517                    }
     518                }
    488519            }
    489520
Note: See TracChangeset for help on using the changeset viewer.