[wp-trac] [WordPress Trac] #63448: Image quality significantly degrades for resized PNGs with transparency in WordPress 6.8.1

WordPress Trac noreply at wordpress.org
Fri May 23 16:43:32 UTC 2025


#63448: Image quality significantly degrades for resized PNGs with transparency in
WordPress 6.8.1
-------------------------------------------------+-------------------------
 Reporter:  elvismdev                            |       Owner:
                                                 |  adamsilverstein
     Type:  defect (bug)                         |      Status:  reopened
 Priority:  normal                               |   Milestone:  6.8.2
Component:  Media                                |     Version:  6.8
 Severity:  critical                             |  Resolution:
 Keywords:  has-patch has-test-info dev-         |     Focuses:
  feedback has-unit-tests commit fixed-major     |
-------------------------------------------------+-------------------------

Comment (by nosilver4u):

 @SirLouen With `quantizeImage`, I'm getting 8-bit alpha after quantizing
 thumbs for oval-or8.png, so that's one win. For the grayscale issue, I
 think there are a few potential issues when doing as you said:

 {{{
 $this->image->quantizeImage( 257, Imagick::COLORSPACE_RGB, 0, false, false
 );
 }}}

 First, 257 is too high, as an indexed image can only have 256 palette
 entries. The SO thread is quite old, and I suspect the commenters were
 fighting old bugs in IM. Using 257 colors was their attempt to prevent IM
 from using indexed mode, but still keeping the number of colors down,
 which improves the PNG compression dramatically--just not as much as a
 properly indexed PNG.

 Now, often the quantization doesn't use as many colors as you allow, so
 257 will still work on some images, and not on others. Also, some folks
 claim that you might need to use 255 to allow 1 entry for alpha. I could
 never confirm or deny that, given `quantizeImage` frequently uses less
 colors than specified, so I stuck with 255 as the max. We'd then have
 this:

 {{{
 $this->image->quantizeImage( 255, Imagick::COLORSPACE_RGB, 0, false, false
 );
 }}}

 Second, I think you might get better results with `getColorspace()`. At
 least that's what we came up with last year, though I honestly couldn't
 tell you whether I tested that for sure, or if I picked it up from some
 other place online. We can supply the colorspace like this then:

 {{{
 $this->image->quantizeImage( 255, $this->image->getColorspace(), 0, false,
 false );
 }}}

 Third, the number of colors in the original PNG can be far less than 255.
 So for test8.png, using 255 when the original has only 9, you could get a
 20x larger image than you want. Here the original core fix isn't great
 since it relied on the (flaky) getImageDepth to set the maximum colors.
 But it could have been sufficient, as it uses `getImageColors` and uses
 that number if it is less than the maximum.

 But then again, this all happens after the image has been scaled, at which
 point the number of colors is far too high (50,000 or more on certain
 sizes), so then $max_colors isn't constrained properly at all.

 In EWWW IO, we run `getImageColors` to get the current color count prior
 to scaling, and then constrain that similarly by the number of colors
 allowed for the bit depth: 8-bit=255 colors, 4-bit=16 colors, 2-bit=4
 colors, 1-bit=2 colors. *255 instead of 256 due to the aforementioned
 possibility that alpha takes up 1 entry. I checked again back to Ubuntu
 16, and `getImageColors` appears to work properly even on ancient versions
 of IM. So we can do something like this:

 {{{
 $max_colors = $max_colors = pow( 2, $indexed_pixel_depth ); // or use a
 switch/case statement...
 if ( is_callable( array( $this->image, 'getImageColors' ) ) ) {
     $current_colors = $this->image->getImageColors();
     $max_colors     = min( $max_colors, $current_colors );
 }
 // do the scaling/resizing, and afterward...
 $this->image->quantizeImage( $max_colors, $this->image->getColorspace(),
 0, false, false );
 }}}

 As for the grayscale issue, once the above is done, this seems to work for
 me:


 {{{
 if ( Imagick::COLORSPACE_GRAY === $this->image->getImageColorspace() ) {
     $this->image->setOption( 'png:format', 'png8' );
 }
 }}}

 I added some debugging into our code in EWWW IO, and it's definitely
 detecting `Imagick::COLORSPACE_GRAY`. If you're still not getting that,
 I'd be curious what version of IM you've got. My dev server with Ubuntu
 24.04 is running IM 6.9.12-98 and seems to work. For reference, this is
 what I'm working with in EWWW IO after updating our code to use
 `getImageProperty()`: https://github.com/nosilver4u/ewww-image-
 optimizer/blob/ed85dd1de2c49bdfc690e1924737e626e4fc0c17/classes/class-
 ewwwio-imagick-editor.php#L350

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/63448#comment:63>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list