Skip to content

Prevent transparency loss in AVIF by falling back to WebP on older ImageMagick#2245

Closed
b1ink0 wants to merge 55 commits into
WordPress:trunkfrom
b1ink0:fix/imagemagick-old-version-avif-transparency-loss
Closed

Prevent transparency loss in AVIF by falling back to WebP on older ImageMagick#2245
b1ink0 wants to merge 55 commits into
WordPress:trunkfrom
b1ink0:fix/imagemagick-old-version-avif-transparency-loss

Conversation

@b1ink0

@b1ink0 b1ink0 commented Oct 30, 2025

Copy link
Copy Markdown
Contributor

Summary

Fixes #2237

Relevant technical choices

Prevents transparent backgrounds from being lost when converting PNG images to AVIF format on older ImageMagick

TODO:

  • Site health test
  • Add tests

@b1ink0 b1ink0 added this to the webp-uploads n.e.x.t milestone Oct 30, 2025
@b1ink0 b1ink0 added [Type] Bug An existing feature is broken [Plugin] Modern Image Formats Issues for the Modern Image Formats plugin (formerly WebP Uploads) labels Oct 30, 2025
@codecov

codecov Bot commented Oct 30, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.92105% with 29 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.20%. Comparing base (b1608b2) to head (207b3de).
⚠️ Report is 21 commits behind head on trunk.

Files with missing lines Patch % Lines
...ploads/class-webp-uploads-image-editor-imagick.php 64.00% 18 Missing ⚠️
plugins/webp-uploads/helper.php 91.30% 4 Missing ⚠️
plugins/webp-uploads/settings.php 33.33% 4 Missing ⚠️
plugins/webp-uploads/hooks.php 86.36% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            trunk    #2245      +/-   ##
==========================================
+ Coverage   69.14%   70.20%   +1.06%     
==========================================
  Files          90       93       +3     
  Lines        7723     7874     +151     
==========================================
+ Hits         5340     5528     +188     
+ Misses       2383     2346      -37     
Flag Coverage Δ
multisite 70.20% <80.92%> (+1.06%) ⬆️
single 35.06% <15.13%> (-0.44%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread plugins/webp-uploads/hooks.php Outdated
$imagick = $image_property->getValue( $editor );

if ( $imagick instanceof Imagick ) {
wp_cache_set( 'webp_uploads_image_has_transparency', (bool) $imagick->getImageAlphaChannel(), 'webp-uploads' );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this set here in the cache since this function runs first and then later webp_uploads_get_image_output_format() runs to then read the value from the cache? This seems perhaps brittle. Normally setting and getting a cache value would happen in the context of the same function, not across separate functions, right? It feels like there may not be guarantees that the cached value would be set when it is checked for.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it works but is definitely brittle. The other approach I can think of is using a global variable or a transient with a short expiration time to store the transparency status and hash of any uploaded file for the current request, and then using it in the webp_uploads_filter_image_editor_output_format to determine the output format. If you have any ideas for a temporary storage that can be used within the same request, I’d appreciate that.
@adamsilverstein if you also have a better idea to handle this case, I’d appreciate that as well.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these are both part of the same request, perhaps you could apply a filter inside the webp_uploads_filter_image_editor_output_format function, then add a filter here to set the value?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are multiple approaches. I came up with this to solve it:
The most elegant way is to replace the WP_Image_Editor_Imagick class with a custom class WebP_Uploads_Image_Editor_Imagick, which can be used to detect transparency and provide access to the protected variable.

But this will interfere with other plugins if they are trying to use their own custom class. I was thinking of just dynamically extending any custom classes extended from the WP_Image_Editor_Imagick class.

@b1ink0 b1ink0 Dec 17, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these are both part of the same request, perhaps you could apply a filter inside the webp_uploads_filter_image_editor_output_format function, then add a filter here to set the value?

The issue I faced was with the subsize-image generation. The webp_uploads_filter_image_editor_output_format filter is called with an empty filename, so with this approach the sub-size images were getting generated as AVIF.

Because of that, the only way to check the current processing image calling the output-format filter is to access the $image of the image-editor instance that is processing it. But since the core does not expose the image-editor instance through globals or filters, there seems to be no way to determine the currently processed image. To solve this, the only idea I could come up with was using our own custom Image Editor class.

I have implemented the mentioned approach in this commit 2247b61.

cc: @adamsilverstein

Comment thread plugins/webp-uploads/hooks.php Outdated
Comment on lines +1004 to +1009
$reflection = new ReflectionClass( $editor );
$image_property = $reflection->getProperty( 'image' );
if ( PHP_VERSION_ID < 80100 ) {
$image_property->setAccessible( true );
}
$imagick = $image_property->getValue( $editor );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's too bad that the image property is protected. Note how in the Image Placeholder plugin it actually extends WP_Image_Editor_Imagick with a Dominant_Color_Image_Editor_Imagick which it then uses. This is problematic though since multiple plugins can't each register their own editor classes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did try to create an anonymous class and added a method to expose the image property, but the Reflection API seemed better.

Comment thread plugins/webp-uploads/helper.php Outdated
function webp_uploads_imagick_avif_transparency_supported(): bool {
if ( extension_loaded( 'imagick' ) && class_exists( 'Imagick' ) ) {
$imagick_version = Imagick::getVersion();
if ( (bool) preg_match( '/((?:[0-9]+\\.?)+)/', $imagick_version['versionString'], $matches ) ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if ( (bool) preg_match( '/((?:[0-9]+\\.?)+)/', $imagick_version['versionString'], $matches ) ) {
if ( (bool) preg_match( '/^\d+(?:\.\d+)+$/', $imagick_version['versionString'], $matches ) ) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated regex to /\d+(?:\.\d+)+(?:-\d+)?/ for handling version string like this:

ImageMagick 7.1.1-15 Q16 aarch64 98eceff6a:20230729 https://imagemagick.org

@b1ink0 b1ink0 Nov 14, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make more sense to move this Site Health test to the Modern Image Formats plugin?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just seeing this comment. I think it makes sense to move all Site Health tests for images to the plugin. See #1781

@b1ink0 b1ink0 marked this pull request as ready for review December 26, 2025 13:05
@b1ink0 b1ink0 requested a review from felixarntz as a code owner December 26, 2025 13:05
@github-actions

github-actions Bot commented Dec 26, 2025

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @xtecneo, @wes-davis.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Unlinked contributors: xtecneo, wes-davis.

Co-authored-by: b1ink0 <b1ink0@git.wordpress.org>
Co-authored-by: adamsilverstein <adamsilverstein@git.wordpress.org>
Co-authored-by: westonruter <westonruter@git.wordpress.org>
Co-authored-by: mindctrl <mindctrl@git.wordpress.org>
Co-authored-by: paulgibbs <djpaul@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Comment thread plugins/webp-uploads/tests/test-helper.php Outdated
Comment thread plugins/webp-uploads/class-webp-uploads-image-editor-imagick.php Outdated
* has been compiled against ImageMagick version 6.4.0 or newer.
*/
if ( is_callable( array( $this->image, 'getImageAlphaChannel' ) ) ) {
if ( ! $this->image->getImageAlphaChannel() ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you checked that this works correctly with PNG, WebP and AVIF uploads with transparencies?

}

// Walk through the pixels and look transparent pixels.
$w = $this->image->getImageWidth();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this strikes me as very heavy and deserving of caching at the very least to avoid repeating.

I would also be fine saying Imagick 6.4 is required for transparency support :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in fece741.

Comment thread plugins/webp-uploads/helper.php Outdated
$avif_support = webp_uploads_mime_type_supported( 'image/avif' );

if ( $avif_support && webp_uploads_check_image_transparency( $filename ) ) {
$avif_support = false;

@adamsilverstein adamsilverstein Jan 12, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AVIF should still be supported in Imagick is new enough, right? this line sets it as false if the image has a transparency without regard to the Imagick version.

misread that call ^^

@adamsilverstein

Copy link
Copy Markdown
Member

@b1ink0 - overall this looks very good!

I wonder if this belongs in core directly: does this impact AVIF with transparency uploads in core (without the upload transform from PNG->AVIF)? If so this probably belongs in core directly since we aim to support AVIF as completely as possible. You probably noticed the existing PNG transparency handling in core, we could add similar handling for AVIFs.

@b1ink0

b1ink0 commented Jan 12, 2026

Copy link
Copy Markdown
Contributor Author

@adamsilverstein I was just thinking all this complex logic is just so that if an image does not have transparency and the site has an AVIF transparency unsupported version of ImageMagick, we allow the AVIF conversion. The simplest way could be to turn off AVIF conversion completely, even for non-transparent images.

Comment thread plugins/webp-uploads/helper.php Outdated
Comment thread plugins/webp-uploads/helper.php Outdated
Comment thread plugins/webp-uploads/tests/test-helper.php Outdated
Comment thread plugins/webp-uploads/tests/test-helper.php Outdated
Comment thread plugins/webp-uploads/tests/test-helper.php Outdated
Comment thread plugins/webp-uploads/tests/test-helper.php Outdated
Comment thread plugins/webp-uploads/tests/test-helper.php Outdated
@adamsilverstein

Copy link
Copy Markdown
Member

@adamsilverstein I was just thinking all this complex logic is just so that if an image does not have transparency and the site has an AVIF transparency unsupported version of ImageMagick, we allow the AVIF conversion. The simplest way could be to turn off AVIF conversion completely, even for non-transparent images.

Thats fine for the plugin! Happy to see this fix land here. I'm just thinking we may also be able to introduce a more general fix in core to handle this case. I will check to see if we have an existing ticket for this.

@b1ink0

b1ink0 commented Feb 17, 2026

Copy link
Copy Markdown
Contributor Author

Response to Gemini feedback @westonruter please forward this to Gemini:

However, inside webp_uploads_check_image_transparency, you do:
$editor = wp_get_image_editor( ... );
if ( ... $editor instanceof WebP_Uploads_Image_Editor_Imagick ) { ... }
If webp_uploads_set_image_editors logic changes or if another plugin intervenes, this could become fragile.

The webp_uploads_set_image_editors will not change, and I am not sure how another plugin can intervene.


More importantly, wp_get_image_editor creates a new instance of the editor. WebP_Uploads_Image_Editor_Imagick::load() calls parent::load(). If parent::load() does heavy lifting (loading the image into memory), doing this just to check transparency might be expensive if not careful.

The function tries to optimize by checking WebP_Uploads_Image_Editor_Imagick::$current_instance when $filename is null.

Issue: When $filename is passed (which is the case in webp_uploads_get_upload_image_mime_transforms), you are creating a new editor instance.

$editor = wp_get_image_editor( $filename, ... );
This loads the image from disk again.

f webp_uploads_get_upload_image_mime_transforms is called multiple times (e.g. for every subsize generation), we might be re-loading the image into Imagick multiple times just to check transparency.

webp_uploads_check_image_transparency does have a static $processed_images cache, which mitigates this significantly.

When the filename is null, it is most likely during sub-size generation. In that case, we use the current instance to get the file name. Since it’s a sub-size, the file name will be the same as the original image file name, which has already been processed.

For sub-sizes, we don’t create a new editor instance because the static property has already cached it, so we just return the result from it.


Use of wp_image_editor_supports:

if ( ! class_exists( 'WebP_Uploads_Image_Editor_Imagick' ) ) {
// Calls filter wp_image_editors internally which makes sure webp_uploads_set_image_editors is called.
wp_image_editor_supports();
}
This is a clever (if slightly hacky) way to ensure your class is loaded. It relies on wp_image_editor_supports calling _wp_image_editor_choose which calls the filter.

I would like to highlight that the wp_image_editors filter is almost always called before our code reaches this point. This will only execute in rare cases where the function is called directly or the wp_image_editors filter has not been called, which is still very rare.

Regarding the hacky part, this was the cleanest way to ensure our custom class is loaded. Alternatively, we could call the filter directly here or call the hooked function directly.


Pixel Iteration: The fallback getImagePixelColor in a nested loop is extremely slow for large images.

for ( $x = 0; $x < $w; $x++ ) {
for ( $y = 0; $y < $h; $y++ ) { ... }
}
If getImageChannelMean is not available (rare in modern setups, but possible), this could time out.
However, given the constraint (Imagick < 7.0.25), we are dealing with "older" versions, so this fallback might actually be hit.

Suggestion: Consider if there's a way to avoid the pixel-by-pixel loop, or limit it to a sampling if absolute precision isn't required (though missing a single transparent pixel usually counts as "has transparency"). Alternatively, exportImagePixels might be faster than method calls per pixel.

The exportImagePixels method was introduced along with getImageChannelRange and getImageChannelMean, so if those fail, exportImagePixels could also fail. In that case, the fallback could also fail.

@westonruter westonruter modified the milestones: webp-uploads 2.6.2, webp-uploads n.e.x.t Feb 26, 2026
@westonruter

Copy link
Copy Markdown
Member

@mindctrl Would you please test this?

Here's a build for convenience: webp-uploads.zip

@westonruter westonruter modified the milestones: webp-uploads n.e.x.t, webp-uploads 2.6.2 Feb 27, 2026
@b1ink0

b1ink0 commented Feb 27, 2026

Copy link
Copy Markdown
Contributor Author

These new test failure are really confusing this is what is output for the mean and alpha range for PHP 7.3, 7.4 and 8.0:

.[27-Feb-2026 08:27:37 UTC] /var/www/html/wp-content/plugins/performance/plugins/webp-uploads/tests/data/images/transparent.png - RGB Mean: Array
(
    [mean] => 16383.75
    [standardDeviation] => 0
)

[27-Feb-2026 08:27:37 UTC] Array
(
    [minima] => 0
    [maxima] => 0
)

And for PHP 8.0+ and 7.2:

.[27-Feb-2026 08:44:35 UTC] /var/www/html/wp-content/plugins/performance/plugins/webp-uploads/tests/data/images/transparent.png - RGB Mean: Array
(
    [mean] => 0
    [standardDeviation] => 0
)

[27-Feb-2026 08:44:35 UTC] Array
(
    [minima] => 0
    [maxima] => 0
)

It should be all zero for fully transparent image but somehow its not for some PHP version.

This again seems like issue with the specific ImageMagick version installed on these PHP Docker images I will do some debugging to find what is the core cause.

The issue was due to a difference in the ImageMagick version across these different PHP versions, and the value of Imagick::CHANNEL_ALL being different between ImageMagick versions 7 and 6. I replaced it with Imagick::CHANNEL_DEFAULT, which fixed all the tests.

@mindctrl

mindctrl commented Mar 2, 2026

Copy link
Copy Markdown

@mindctrl Would you please test this?
Here's a build for convenience: webp-uploads.zip

@westonruter thanks for the build. It seems to work fine. On my end, the PHP 7.4 stack I was using to test this was updated to include a newer version of ImageMagick. In this case, it means I can't test the same scenario where:

  • ImageMagick is there and supports AVIF
  • but doesn't support transparent AVIF

I was able to confirm that if AVIF isn't supported at all, the logic that ties into Site Health and the Media settings page shows the new notices as expected.

I'll see if I can replicate the previous stack with the older version of ImageMagick.

@b1ink0

b1ink0 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

There was previously no practical way to test the exact issue this PR is intended to solve.

I had attempted several times to create a Docker image with a broken ImageMagick version that reproduces the issue, but was unsuccessful because most search results and articles pointed to an incorrect commit as the fix. I eventually found a reliable way to reproduce the issue with the help of Codex.

Background

Alex Chan's write-up correctly identifies the fixed release boundary as 6.9.12-68, but the commit linked in that article is not the commit that fixed the issue:

Article: https://alexwlchan.net/2023/check-for-transparency/

While the version information is accurate, the linked commit should not be considered authoritative.

Root Cause In Code of ImageMagick

Broken behavior in older IM6

In the broken ImageMagick 6 AVIF writer, transparent images are still encoded through the older YCbCr path:

  • heif_colorspace_YCbCr
  • heif_chroma_420

That path writes Y, Cb, and Cr image planes, but does not preserve alpha correctly for transparent PNG input. The result is that transparent pixels become opaque in the output AVIF.

What the fix changed

The fix adds a matte-aware branch for AVIF writing.

For images with transparency, the code switches to an RGB/RGBA path instead of the older YCbCr 4:2:0 path, using libheif modes such as:

  • heif_colorspace_RGB
  • heif_chroma_interleaved_RGBA
  • heif_chroma_interleaved_RRGGBBAA_LE

That is the meaningful code change: the writer starts emitting RGBA data for matte images, which preserves the alpha channel instead of discarding it.

  • AVIF support first appears in ImageMagick 6 at commit with the bug e353f91e6c43e29669d1d4e445c6452c16463130:
    ImageMagick/ImageMagick6@e353f91

  • The practical broken range for ImageMagick 6 is:6.9.11-20 through 6.9.12-67

  • The first fixed ImageMagick 6 release is: 6.9.12-68


Reproducing the Issue

To properly test this PR, I created a separate branch based on the latest commit in this PR:

Branch: https://github.com/b1ink0/performance/tree/fix/imagemagick-old-version-avif-transparency-loss-test ( b1ink0@06a01e8)

This branch adds support for overriding the base Docker image used by @wordpress/env through a small patch, making it possible to test the issue directly within wp-env.

Build and Test Instructions

# Clone the repo
git clone --depth 1 --single-branch --branch trunk https://github.com/WordPress/performance.git

# Fetch the branch
git fetch https://github.com/b1ink0/performance.git \
  fix/imagemagick-old-version-avif-transparency-loss-test:test-avif-test

git switch test-avif-test

# Patch wp-env
npm install
npm run postinstall
npm run build

# Build and start wp-env
npm run wp-env:build-im6-broken
npm run wp-env:start:im6-broken

Verification Steps

  • Upload a PNG image without transparency and verify that an AVIF image is generated.
Screen.Recording.2026-06-17.at.1.53.02.PM.mov
  • Upload a PNG image with transparency and verify that a WebP image is generated.
Screen.Recording.2026-06-17.at.1.53.38.PM.mov

To observe the broken behavior directly, temporarily disable the protection added in this PR by applying the following patch:

Note: please copy using the copy button provided by GitHub else applying patch won't work.

cat <<'PATCH' | git apply
diff --git a/plugins/webp-uploads/helper.php b/plugins/webp-uploads/helper.php
index cdebb2f4..460884c6 100644
--- a/plugins/webp-uploads/helper.php
+++ b/plugins/webp-uploads/helper.php
@@ -528,6 +528,7 @@ function webp_uploads_get_attachment_file_mime_type( int $attachment_id, string
  * @return bool True if Imagick has AVIF transparency support, false otherwise.
  */
 function webp_uploads_imagick_avif_transparency_supported( ?string $version = null ): bool {
+	return true;
 	$supported       = false;
 	$imagick_version = $version;
 
PATCH

After applying the patch:

  • Upload a transparent PNG image.
  • An AVIF image will be generated.
  • The resulting AVIF image will exhibit the transparency loss issue that this PR is intended to prevent.
Screen.Recording.2026-06-17.at.1.57.46.PM.mov

For more detailed instructions, see: https://github.com/b1ink0/performance/blob/fix/imagemagick-old-version-avif-transparency-loss-test/tools/wp-env/README.md


I used Codex to help identify the exact commits where the issue was introduced and fixed, and to generate the Docker image patch required to test both the broken and fixed ImageMagick versions.


cc: @adamsilverstein, @westonruter, @mindctrl

Comment on lines +26 to +29
$tests['direct']['imagick_avif_transparency_supported'] = array(
'label' => __( 'Imagick AVIF Transparency Support', 'webp-uploads' ),
'test' => 'webp_uploads_imagick_avif_transparency_supported_test',
);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this test only be added if the AVIF format is enabled?

Also, should the settings screen show a warning with the format dropdown to advise against AVIF if transparency is not supported?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relevant code:

$selected = webp_uploads_get_image_output_format();
$avif_supported = webp_uploads_mime_type_supported( 'image/avif' );
$webp_supported = webp_uploads_mime_type_supported( 'image/webp' );
// If neither format is support, the entire field is not shown.
if ( ! $avif_supported && ! $webp_supported ) {
?>
<br />
<div class="notice notice-warning inline">
<p><b><?php esc_html_e( 'Modern image support is not available.', 'webp-uploads' ); ?></b></p>
<p><?php esc_html_e( 'WebP or AVIF support can only be enabled by your hosting provider, so contact them for more information.', 'webp-uploads' ); ?></p>
</div>
<?php
return;
}

The default should be webp if AVIF is not fully supported. Alternatively, we could make it so that AVIF is considered not supported at all if transparency isn't supported. That would make it simpler and less prone to a having a bad experience. Relevant code:

function webp_uploads_mime_type_supported( string $mime_type ): bool {
if ( ! wp_image_editor_supports( array( 'mime_type' => $mime_type ) ) ) {
return false;
}
// In certain server environments Image editors can report a false positive for AVIF support.
if ( 'image/avif' === $mime_type ) {
$editor = _wp_image_editor_choose( array( 'mime_type' => 'image/avif' ) );
if ( false === $editor ) {
return false;
}
if ( is_a( $editor, WP_Image_Editor_GD::class, true ) ) {
return function_exists( 'imageavif' );
}
if ( is_a( $editor, WP_Image_Editor_Imagick::class, true ) && class_exists( 'Imagick' ) ) {
return 0 !== count( Imagick::queryFormats( 'AVIF' ) );
}
}
return true;
}

Additionally, this Site Health test can be omitted if AVIF isn't supported in the first place.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default should be webp if AVIF is not fully supported. Alternatively, we could make it so that AVIF is considered not supported at all if transparency isn't supported. That would make it simpler and less prone to a having a bad experience.

Yes, I had previously mentioned the same concern in the PR.

@adamsilverstein I was just thinking all this complex logic is just so that if an image does not have transparency and the site has an AVIF transparency unsupported version of ImageMagick, we allow the AVIF conversion. The simplest way could be to turn off AVIF conversion completely, even for non-transparent images.

#2245 (comment)

I had previously mentioned the same concern in the PR but did not receive a response, so I continued working on the approach where only images with transparency are converted to WebP, while non-transparent images continue to be converted to AVIF.

That said, I do not think the current implementation is the best solution. It feels more like a collection of workarounds due to the complexity of the underlying issue we are trying to solve. This code could potentially introduce more bugs than the number of users who would actually encounter the transparency-loss issue.

As you suggested, a simpler approach might be to disable AVIF when transparency support is not available and display a warning below the setting explaining why AVIF cannot be selected and a site health test if needed. That would be much easier to understand and maintain.

Regarding the current implementation, we could remove the workaround code entirely and rely on Git history if we ever need to revisit it. However, since this PR already contains 54 commits, I think it would be better to close this PR and I will create a new one if we decide to pursue the simpler approach.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this test only be added if the AVIF format is enabled?

Also, should the settings screen show a warning with the format dropdown to advise against AVIF if transparency is not supported?

Yes I think both are valid.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, let's go with the simpler approach. We sniff out for whether there are any issues with AVIF at all, and if so, we don't allow AVIF and show a notice explaining why AVIF isn't available. The Site Health test can also surface the fact that AVIF isn't available. Although, this would be somewhat redundant with the warning on the settings screen.

Sorry for the long review cycle on this. Glad we're getting close!

@b1ink0

b1ink0 commented Jun 18, 2026

Copy link
Copy Markdown
Contributor Author

Based on comment #2245 (comment)

Closing this in favor of the simpler approach implemented in #2540. If we need to revisit the more targeted workaround later, we can refer back to this PR.

@b1ink0 b1ink0 closed this Jun 18, 2026
@westonruter westonruter removed this from the webp-uploads n.e.x.t milestone Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Plugin] Modern Image Formats Issues for the Modern Image Formats plugin (formerly WebP Uploads) [Type] Bug An existing feature is broken

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Transparent backgrounds lost when converting to AVIF under certain conditions

5 participants