wip
This commit is contained in:
@@ -305,7 +305,7 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor {
|
||||
* image operations within the time of the HTTP request.
|
||||
*
|
||||
* @since 6.2.0
|
||||
* @since 6.3.0 This method was deprecated.
|
||||
* @deprecated 6.3.0 No longer used in core.
|
||||
*
|
||||
* @return int|null The new limit on success, null on failure.
|
||||
*/
|
||||
@@ -444,6 +444,51 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor {
|
||||
}
|
||||
|
||||
try {
|
||||
/**
|
||||
* Special handling for certain types of PNG images:
|
||||
* 1. For PNG images, we need to specify compression settings and remove unneeded chunks.
|
||||
* 2. For indexed PNG images, the number of colors must not exceed 256.
|
||||
* 3. For indexed PNG images with an alpha channel, the tRNS chunk must be preserved.
|
||||
* 4. For indexed PNG images with true alpha transparency (an alpha channel > 1 bit), we need to avoid saving
|
||||
* the image using ImageMagick's 'png8' format, because that supports only binary (1 bit) transparency.
|
||||
*
|
||||
* For #4 we want to check whether the image has a 1-bit alpha channel before resizing, because resizing
|
||||
* may cause the number of alpha values to multiply due to antialiasing. If the original image had only a
|
||||
* 1-bit alpha channel, then a 1-bit alpha channel should be good enough for the resized images.
|
||||
*
|
||||
* Perform all the necessary checks before resizing the image and store the results in variables for later use.
|
||||
*/
|
||||
$is_png = false;
|
||||
$is_indexed_png = false;
|
||||
$is_indexed_png_with_alpha_channel = false;
|
||||
$is_indexed_png_with_true_alpha_transparency = false;
|
||||
|
||||
if ( 'image/png' === $this->mime_type ) {
|
||||
$is_png = true;
|
||||
|
||||
if (
|
||||
is_callable( array( $this->image, 'getImageProperty' ) )
|
||||
&& '3' === $this->image->getImageProperty( 'png:IHDR.color-type-orig' )
|
||||
) {
|
||||
$is_indexed_png = true;
|
||||
|
||||
if (
|
||||
is_callable( array( $this->image, 'getImageAlphaChannel' ) )
|
||||
&& $this->image->getImageAlphaChannel()
|
||||
) {
|
||||
$is_indexed_png_with_alpha_channel = true;
|
||||
|
||||
if (
|
||||
is_callable( array( $this->image, 'getImageChannelDepth' ) )
|
||||
&& defined( 'Imagick::CHANNEL_ALPHA' )
|
||||
&& 1 < $this->image->getImageChannelDepth( Imagick::CHANNEL_ALPHA )
|
||||
) {
|
||||
$is_indexed_png_with_true_alpha_transparency = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* To be more efficient, resample large images to 5x the destination size before resizing
|
||||
* whenever the output size is less that 1/3 of the original image size (1/3^2 ~= .111),
|
||||
@@ -480,41 +525,44 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor {
|
||||
$this->image->setOption( 'jpeg:fancy-upsampling', 'off' );
|
||||
}
|
||||
|
||||
if ( 'image/png' === $this->mime_type ) {
|
||||
if ( $is_png ) {
|
||||
$this->image->setOption( 'png:compression-filter', '5' );
|
||||
$this->image->setOption( 'png:compression-level', '9' );
|
||||
$this->image->setOption( 'png:compression-strategy', '1' );
|
||||
// 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' );
|
||||
}
|
||||
// Indexed PNG files get some additional handling.
|
||||
// See #63448 for details.
|
||||
if ( $is_indexed_png ) {
|
||||
|
||||
// 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' );
|
||||
}
|
||||
// Check for an alpha channel.
|
||||
if ( $is_indexed_png_with_alpha_channel ) {
|
||||
$this->image->setOption( 'png:include-chunk', 'tRNS' );
|
||||
} else {
|
||||
$this->image->setOption( 'png:exclude-chunk', 'all' );
|
||||
}
|
||||
|
||||
$this->image->quantizeImage( 256, $this->image->getColorspace(), 0, false, false );
|
||||
|
||||
/*
|
||||
* If the colorspace is 'gray', use the png8 format to ensure it stays indexed.
|
||||
* ImageMagick tends to save grayscale images as grayscale PNGs rather than indexed PNGs,
|
||||
* even though grayscale PNGs usually have considerably larger file sizes.
|
||||
* But we can force ImageMagick to save the image as an indexed PNG instead,
|
||||
* by telling it to use png8 format.
|
||||
*
|
||||
* Note that we need to first call quantizeImage() before checking getImageColorspace(),
|
||||
* because only after calling quantizeImage() will the colorspace be COLORSPACE_GRAY for grayscale images
|
||||
* (and we have not found any other way to identify grayscale images).
|
||||
*
|
||||
* We need to avoid forcing indexed format for images with true alpha transparency,
|
||||
* because ImageMagick does not support saving an image with true alpha transparency as an indexed PNG.
|
||||
*/
|
||||
if ( Imagick::COLORSPACE_GRAY === $this->image->getImageColorspace() && ! $is_indexed_png_with_true_alpha_transparency ) {
|
||||
// Set the image format to Indexed PNG.
|
||||
$this->image->setOption( 'png:format', 'png8' );
|
||||
}
|
||||
} else {
|
||||
$this->image->setOption( 'png:exclude-chunk', 'all' );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user