performance
performance copied to clipboard
PNG conversion to AVIF / WebP does not work reliably
Bug Description
When I uploaded a PNG to my website in the block editor, I ran into a problem where the image file would not be found. As the file was (supposed to be) transformed to AVIF, I suspected it might have something to do with the Modern Image Formats plugin. Indeed that appears to be the case.
Some more details on what I am experiencing:
- The thumbnail file
{orig-name}-150x150.avifwas successfully generated. But the main attachment file{orig-name}-png.avifis not to be found. - To test, I changed the target format option from "AVIF" to "WebP". After doing that, the same file doesn't get transformed at all. Obviously better than a broken image, but it's just as strange that the WebP transformation doesn't appear to even occur in this case.
- I'm seeing the warning in Site Health that "Your site does not send AVIF image headers correctly". Could that be causing it? If that's the case and we already detect it though, we should probably not be generating AVIF.
- It's strange that this happened, because literally a minute before I had uploaded another PNG image which was transformed into AVIF without any issues. So it's not consistent, but definitely seems unreliable.
There is a chance this has to do with certain server support / configuration, but in any case we should try to figure it out since we shouldn't offer transforming to AVIF in situations where it's not reliable.
Possibly caused by addition of PNG support which was done via #371. I don't have any problems with transforming JPEG into AVIF or WebP, the problems only occur with PNG files.
Steps to reproduce
- Make sure the plugin is set to transform into AVIF.
- Make sure generating fallback formats is off.
- Either edit a post in the block editor and upload a PNG image. Or upload a PNG image directly to the media library.
Additional Context
- PHP Version: 8.1
- WordPress Version: 6.7.1
- OS: Mac OS
- Browser: Chrome
- Plugin Version: 2.4.0
@adamsilverstein Any idea what might be going on here?
@adamsilverstein Any idea what might be going on here?
Could it possibly be related to the PNG itself? ie. does one PNG consistently fail to generate sub sizes while another consistently works? Can you check server logs and the browser console log for any potential errors?
I can give this a test to see if I can reproduce on my end
@adamsilverstein I can confirm it always happens with specific PNG images, but not others. So there has to be something maybe in the different PNG encodings that makes my server not want to deal with some of them.
There are no errors or Console logs when uploading them. So the problem isn't flagged, it's "silently" failing. When I try to open the full size image (for one of the PNG uploads where the problem occurs), I just get a 404.
I can confirm it always happens with specific PNG images, but not others.
Could be related to alpha channel presence, transparency or bit depth.
Can you share your site health->info->media details so we can see what version GD/Imagick you are using?
If possible, can you share a working and non-working image? these would be useful for a unit test to reproduce the issue.
We recently landed some PNG handling improvements in core that could help, if possible can you try agains trunk?
Possibly your generated images are larger that the original and so is being discarded in webp_uploads_should_discard_additional_image_file.
Do you have the "Also generate fallback images in the original upload format" option enabled under settings->media? If so, try disabling that to see if generation works for all images.
If you want both images always, you can disable the deletion behavior with:
add_filter( 'webp_uploads_discard_larger_generated_images', '__return_false' );
Here's my Site Health info for media:
image_editor: WP_Image_Editor_Imagick
imagick_module_version: 1693
imagemagick_version: ImageMagick 6.9.13-17 Q16 x86_64 18482 https://legacy.imagemagick.org
imagick_version: 3.7.0
file_uploads: 1
post_max_size: 100M
upload_max_filesize: 100M
max_effective_size: 100 MB
max_file_uploads: 50
imagick_limits:
imagick::RESOURCETYPE_AREA: 503 GB
imagick::RESOURCETYPE_DISK: 9.2233720368548E+18
imagick::RESOURCETYPE_FILE: 24576
imagick::RESOURCETYPE_MAP: 252 GB
imagick::RESOURCETYPE_MEMORY: 126 GB
imagick::RESOURCETYPE_THREAD: 1
imagick::RESOURCETYPE_TIME: 0
imagemagick_file_formats: 3FR, 3G2, 3GP, AAI, AI, APNG, ART, ARW, AVI, AVS, BGR, BGRA, BGRO, BIE, BMP, BMP2, BMP3, BRF, CAL, CALS, CANVAS, CAPTION, CIN, CIP, CLIP, CMYK, CMYKA, CR2, CR3, CRW, CUR, CUT, DATA, DCM, DCR, DCX, DDS, DFONT, DNG, DOT, DPX, DXT1, DXT5, EPDF, EPI, EPS, EPS2, EPS3, EPSF, EPSI, EPT, EPT2, EPT3, ERF, EXR, FAX, FILE, FITS, FLV, FRACTAL, FTP, FTS, G3, G4, GIF, GIF87, GRADIENT, GRAY, GRAYA, GROUP4, GV, H, HALD, HDR, HISTOGRAM, HRZ, HTM, HTML, HTTP, HTTPS, ICB, ICO, ICON, IIQ, INFO, INLINE, IPL, ISOBRL, ISOBRL6, J2C, J2K, JBG, JBIG, JNG, JNX, JP2, JPC, JPE, JPEG, JPG, JPM, JPS, JPT, JSON, K25, KDC, LABEL, M2V, M4V, MAC, MAGICK, MAP, MASK, MAT, MATTE, MEF, MIFF, MKV, MNG, MONO, MOV, MP4, MPC, MPEG, MPG, MRW, MSL, MSVG, MTV, MVG, NEF, NRW, NULL, ORF, OTB, OTF, PAL, PALM, PAM, PANGO, PATTERN, PBM, PCD, PCDS, PCL, PCT, PCX, PDB, PDF, PDFA, PEF, PES, PFA, PFB, PFM, PGM, PGX, PICON, PICT, PIX, PJPEG, PLASMA, PNG, PNG00, PNG24, PNG32, PNG48, PNG64, PNG8, PNM, POCKETMOD, PPM, PREVIEW, PS, PS2, PS3, PSB, PSD, PTIF, PWP, RADIAL-GRADIENT, RAF, RAS, RAW, RGB, RGBA, RGBO, RGF, RLA, RLE, RMF, RW2, SCR, SCT, SFW, SGI, SHTML, SIX, SIXEL, SPARSE-COLOR, SR2, SRF, STEGANO, SUN, SVG, SVGZ, TEXT, TGA, THUMBNAIL, TIFF, TIFF64, TILE, TIM, TTC, TTF, TXT, UBRL, UBRL6, UIL, UYVY, VDA, VICAR, VID, VIDEO, VIFF, VIPS, VST, WBMP, WEBM, WEBP, WMF, WMV, WMZ, WPG, X, X3F, XBM, XC, XCF, XPM, XPS, XV, XWD, YCbCr, YCbCrA, YUV
gd_version: bundled (2.1.0 compatible)
gd_formats: GIF, JPEG, PNG, WebP, BMP, AVIF, XPM
ghostscript_version: 9.27
It looks like my site's Imagemagick version does not support AVIF, but GD does, so I assume my site attempts to use GD for AVIF.
Do you have the "Also generate fallback images in the original upload format" option enabled under settings->media? If so, try disabling that to see if generation works for all images.
That option is turned off on my site, so I have the problem even with the (technically much simpler) setup of only mapping the output format.
This might be related to a GD "false positive" issue, see https://core.trac.wordpress.org/ticket/60628 which mentions zero sized image failures for some GD versions (although its odd that some sizes work).
Can you try to determine your PHP / GD versions and maybe see if you are able to get them upgraded or get imagick installed by your host?
Aside: Since the PNG to AVIF generation only fails for the original image, but not the thumbnail, I wonder whether any of the additional processing of the sub-sizes (e.g. scaling down the image) alters something in the PNG file already, which then makes the conversion to AVIF work.
Since only the originally uploaded image is failing to convert to AVIF (which of course is completely outside of WordPress's control in terms of how it's encoded etc.), I wonder whether it would work if we first did some other (temporary) processing to that image before saving it as AVIF.
Since only the originally uploaded image is failing to convert to AVIF (which of course is completely outside of WordPress's control in terms of how it's encoded etc.), I wonder whether it would work if we first did some other (temporary) processing to that image before saving it as AVIF.
Maybe - we can certainly try retracing the calls more carefully and trying to reproduce. One thing I noticed is we do call resize on the image, but the image dimensions match those of the original, so that call returns early (this conditional returns true). We could try calling with a slightly different size to test.
@felixarntz this may be related to a flaw in core's PNG processing where it explicitly skips the largest size without considering the output format, see https://core.trac.wordpress.org/ticket/62900. Possibly this logic should be remoived entirely, but for now I have made it so it only applies when PNG is both input and output format. Can you see if the linked PR there resolves the issue you reported here?
@adamsilverstein I don't think the issue here would be addressed by that PR. It's probably a different bug because in my case I do get an AVIF version for the file, but it's not found, and it's inconsistent.
There is a good chance it's related though, so it's a good catch. Maybe this image/png exclusion for big images is there for a reason, maybe it's unstable or too resource/time intensive to be reliable, and that's related to the inconsistency in the bug here.
It may also point to a problem in the Modern Image Formats plugin where maybe we assume that every image exists in the converted format, even though in a scenario like this the original image wouldn't be converted. Worth investigating further...
Maybe this image/png exclusion for big images is there for a reason, maybe it's unstable or too resource/time intensive to be reliable
The original reason appears to be that the output image is larger than the input image, however this may have been caused by a bug where 8 bit pngs were output as 24 bit pngs.
It may also point to a problem in the Modern Image Formats plugin where maybe we assume that every image exists in the converted format, even though in a scenario like this the original image wouldn't be converted.
This shouldn't happen because we store each image generated in meta as we generate them. when we build out srcset we only include images that in the meta data (although possibly some assumptions are made for the full size/original image?)
Hi, I can confirm that this issue also occurs in my case, both with and without the Modern Image Formats plugin, but using the function below.
function custom_filter_image_editor_output_format($formats) {
$formats['image/jpeg'] = 'image/avif';
$formats['image/webp'] = 'image/avif';
$formats['image/png'] = 'image/avif';
return $formats;
}
add_filter('image_editor_output_format', 'custom_filter_image_editor_output_format');
@felixarntz I tried to replicate this issue on my end, and it is very random; sometimes it works fine, and sometimes it does not for the same images, but most of the time it is working fine. I tried with large and small PNG images as well. If possible, can you share the image where you are getting this error all the time? Thanks!
Example PNG files:
Small Image:
Large Images:
@gyurmey2 I tried with the snippet you shared, the images are uploading and converting fine for me with or without your snippet, the only difference is that when I have added your snippet, the file name is not adding extension at the end of the file name, like:
- Original file name: PNG_1MB.png
- Without your snippet, new file name: PNG_1MB-png.avif
- With your snippet, new file name: PNG_1MB.avif
@gyurmey2 If possible, can you share the images which you are testing with? Thanks!
@vishalkakadiya I can't reproduce this issue now, so it looks like it has been fixed. 🤔
Thanks for the detailed write-up — this does sound like a tricky case tied to server support or inconsistent header behavior.
In the meantime, if you need a quick workaround to manually convert PNGs to AVIF (or back), https://aviftools.com/ is a handy browser-based tool. No installation or login required — could be useful for testing or uploading preconverted images when plugin behavior is unpredictable.
Hope this gets resolved in the next release!
In the meantime, if you need a quick workaround to manually convert PNGs to AVIF (or back), https://aviftools.com/ is a handy browser-based tool. No installation or login required — could be useful for testing or uploading preconverted images when plugin behavior is unpredictable.
That would work for the primary image, but ideally you want WordPress to create the sub-sized images used for the srcset attribute on the front end. Without working AVIF support on the server you can't currently get that.
I think this might be related and I can consistently reproduce the issue by running the png through pngquant. I'm not sure how to get WordPress Studio to support AVIF or I would have done some additional debugging.
Issue Uploading certain PNG files result in a 0-byte AVIF image for the original size but the resized versions are fine.
To reproduce
- Set "Image output format" to AVIF in the Modern Image Formats settings (WP_Image_Editor_GD)
- Run the PNG through
pngquant(I used the command line version on macOS) - Upload file created by
pngquant
Original image that works
Image run through pngquant that turns into 0 bytes
> file test-file.png
test-file.png: PNG image data, 200 x 50, 8-bit/color RGB, non-interlaced
> file test-file-pngquant.png
test-file-pngquant.png: PNG image data, 200 x 50, 8-bit colormap, non-interlaced
Using exiftool there are a couple of differences:
Original
File Size : 1030 bytes
Color Type : RGB
pngquant
File Size : 561 bytes
Color Type : Palette
Palette : (Binary data 51 bytes, use -b option to extract)
Could the RGB / colormap / color palette difference be what's creating problems for the conversion?
@iamjohnford The issue you are referring to could be caused by palette-based PNG, which will be fixed by #2024. For more details, see #2018.
@felixarntz - are you still able to reproduce the issue after the fix in https://github.com/WordPress/performance/pull/2024?
Thanks! Looks like the latest version (2.6.0) fixed our issue.