Make WordPress Core

Opened 7 months ago

Last modified 4 weeks ago

#63773 assigned defect (bug)

Palette-based PNG cause failure attempting AVIF/WebP conversion under GD

Reported by: adamsilverstein's profile adamsilverstein Owned by: adamsilverstein's profile adamsilverstein
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 5.8
Component: Media Keywords: has-patch has-unit-tests dev-reviewed has-screenshots has-test-info
Focuses: Cc:

Description (last modified by adamsilverstein)

When uploading a palette based PNG image and attempting to use core's image_editor_output_format to output WebP or AVIF images, conversion fails with a PHP error when using GD. GD cannot convert palette-based PNG to WebP/AVIF formats so to fix the issue, a palette image is first converted to truecolor (imagepalettetotruecolor). Testing shows the PHP error is resolved and the resulting images are still significantly smaller than their PNG counterparts.

This issue was originally reported in the Performance Lab Modern Images plugin - https://github.com/WordPress/performance/issues/1561. The issue is fixed by this PR in the plugin: https://github.com/WordPress/performance/pull/2024. The purpose of this ticket is to bring that fix directly into core, into WP_Image_Editor_GD.

We can start by adding a unit test to demonstrate the issue.

Change History (7)

#1 @adamsilverstein
7 months ago

  • Description modified (diff)

#4 @adamsilverstein
7 months ago

  • Keywords dev-reviewed needs-testing added

Pushed the fix in https://github.com/WordPress/wordpress-develop/pull/9368/commits/73b5cb2a1a37e1d275668011fdd06a903d0f75c5, tests should now pass.

This is ready for review and testing.

Test instructions

  1. Add a filter to WordPress as an mu plugin:
// Convert PNG's uploads to WebP.
add_filter( 'image_editor_output_format', function( $format ) {
	return array(
		'image/png' => 'image/webp'
	);
} );
  1. Upload the sample dice image from the PR (or any palette based PNG image) to the media library.
  2. Check the generated files and PHP logs.

Expected

All files are generated as WebPs.
No errors in logs.

Actual (before fix)

Fill sized image is generated with zero file size and is not a valid image.
PHP error or warning in log.

#5 @adamsilverstein
7 months ago

  • Owner set to adamsilverstein
  • Status changed from new to assigned

#6 @b1ink0
7 months ago

I confirmed the fix by uploading a palette-based PNG and everything converted to WebP properly without any PHP errors. To double-check, I commented out the imagepalettetotruecolor logic and got the expected "Palette image not supported by webp" error, so the fix is working.

Also tested this patch with the Modern Image Formats 2.5.1 https://wordpress.org/plugins/webp-uploads/ plugin active as an additional test case and had no issues there either.

#7 @ozgursar
4 weeks ago

  • Keywords has-screenshots has-test-info added; needs-testing removed

Patch Testing Report

Patch Tested: https://github.com/WordPress/wordpress-develop/pull/9368

Environment

  • WordPress: 7.0-alpha-61215-src
  • PHP: 8.2.29
  • Server: nginx/1.29.4
  • Database: mysqli (Server: 8.4.7 / Client: mysqlnd 8.2.29)
  • Browser: Chrome 144.0.0.0
  • OS: macOS
  • Theme: Twenty Twenty-One 2.7
  • MU Plugins: None activated
  • Plugins:
    • Code Snippets 3.9.4
    • Test Reports 1.2.1

Steps taken

  1. Download the sample image from PR https://raw.githubusercontent.com/WordPress/wordpress-develop/6e5d64ef20c75f464632f1c7c4fb92bf60d55a36/tests/phpunit/data/images/png-tests/dice-palette.png
  2. In order to use GD and confirm it via admin notices add the following code via Code Snippets or functions.php
add_filter('wp_image_editors', function($editors) {
    return array('WP_Image_Editor_GD');
});

add_action('admin_notices', function() {
    $implementations = _wp_image_editor_choose(array('mime_type' => 'image/png'));
    echo '<div class="notice notice-info"><p>';
    echo 'Image Editor: ' . (!is_wp_error($implementations) && !empty($implementations) ? $implementations : 'Error or none found');
    echo '</p></div>';
});

add_filter('image_editor_output_format', function($formats) {
    $formats['image/png'] = 'image/webp';
    return $formats;
});
  1. You should now see Image Editor: WP_Image_Editor_GD at the admin notices section.
  2. Media > Add Media File > Upload the sample dice-palette.png
  3. ❌ Bug occurs. Generated webp image is zero file size.
  4. The following error is added to log.

[DATETIME] PHP Warning: imagewebp(): Palette image not supported by webp in /var/www/src/wp-includes/class-wp-image-editor.php on line 577

  1. Manually check the wp-content/uploads to confirm the filesize to be zero.
  2. Apply patch.
  3. Reupload the dice-palette.png sample image.
  4. Image properly gets uploaded, no error is logged.
  5. ✅ Patch is solving the problem.

Expected result

  • Patch works as expected. GD library can properly convert a palette based PNG image to webp.

Screenshots/Screencast with results

Media before applying patch:
https://i.imgur.com/G9QocLu.png

Filesize before applying patch:
https://i.imgur.com/iVuQajZ.png


Media after applying patch:
https://i.imgur.com/WJutBpc.png

Filesize after applying patch:
https://i.imgur.com/q0tbbEV.png

Last edited 4 weeks ago by ozgursar (previous) (diff)
Note: See TracTickets for help on using tickets.