Closed mxbclang closed 2 months ago
I think it's definitely a good idea 💯 if jpgs are not always the ideal source for webp encoding, because the result vary depending on the source quality, pngs would give amazing results -- especially considering that a lossy webp weighs up to 20 times less than a png (png -> webp lossy). This would be a nice performance boost! Another advantage is that in this case there we have generation loss so, at the same SSIM, the images will weight about the 30% compared to a standard jpg.
there would be two options:
My vote goes for png->lossy because the images of websites aren't intended to be 1:1 with the original so we can take the advantage of the compression techniques like chroma subsampling that decimates the image filesize.
Another suggestion is to use the png as the source image and not to create the subsizes in png. I currently use exactly this way: I upload png images that I keep it only as source in order to create the copy and subsizes in webp. In this way I get much higher quality than a jpg, it takes up less space, and I only have one extra image (the source png).
EDIT: the bug of the webp missing transparency is related to versions before gd 2.1.1 (6 years ago, php 5.6)... I forgot to mention about, but i guess actually isn't a real issue since it's deprecated. here more info
@felixarntz Any news about this, I loved the plugin, but most of my images are .png and that would be very good, I did an online conversion test and saw that the images would be half the size!
Thanks
Any update on this yet?
Any plans on this feature? First post in this thread is dated Jun 13, 2022... Is there any progress made or it's just "planned for the future"?
@ficod, yeah, I decided to convert them manually with Imagick:
<?php
namespace App\Media;
/**
* Set image quality based on mime type.
*
* @param int $quality The image quality level.
* @param string $mime_type The mime type of the image.
*
* @return int The modified image quality level.
*/
function set_image_quality($quality, $mime_type)
{
// Check if the mime type is 'image/webp'
if ('image/webp' === $mime_type) {
// Set a higher quality level for 'image/webp'
return 86;
}
// Return the original quality level for other mime types
return $quality;
}
// Add a filter to set image quality
add_filter('wp_editor_set_quality', __NAMESPACE__ . '\\set_image_quality', 10, 2);
///
/**
* Scale down and optimize uploading image.
*
* @param array $file The uploading file information.
* @return array The modified file information.
*/
function resize_preupload_image($file)
{
$allowed_types = array('image/png', 'image/bmp', 'image/jpeg', 'image/jpg', 'image/webp');
// Check mime type
// Check if Imagick extension is available
if (!in_array($file['type'], $allowed_types) || !class_exists('Imagick', false) || !class_exists('ImagickPixel', false)) {
return $file;
}
// Check size limit
$limit = 24000;
$size = $file['size'] / 1024;
if ($size > $limit) {
$file['error'] = "Image files must be smaller than {$limit}kb";
return $file;
}
// Get the temporary image path
$filepath = $file['tmp_name'];
// Get the file's dimensions
list($image_width, $image_height) = @getimagesize($filepath);
// Calculate the new dimensions for scaling
$max_width = <YOUR_MAX_WIDTH_NUMBER>;
$max_height = intval($image_height * ($max_width / $image_width));
// Create a new Imagick object from the uploaded image
$image = new \Imagick($filepath);
// Get original image size
$original_size = strlen($image->getImageBlob());
// Check if image already has webp format (do not change quality)
if ('image/webp' === $file['type']) {
$image->setImageCompressionQuality(100);
} else {
// Set webp format (support transparency)
$image->setImageFormat('webp');
// Set image compression quality
$image->setImageCompressionQuality(86);
}
// Scale down the image to the new dimensions
$image->resizeImage(min($image_width, $max_width), min($image_height, $max_height), \Imagick::FILTER_CATROM, 1);
// Get resized (webp converted) image size
$resized_size = strlen($image->getImageBlob());
// Check if the resized image has a larger file size than the original
if ($resized_size >= $original_size) {
// Original image has smaller or equal size, so keep it
$image->clear();
return $file;
}
// Save the resized image, overwrite the original file
$image->writeImage($filepath);
$file['size'] = $resized_size;
$image->clear();
// Return result
return $file;
}
add_action('wp_handle_upload_prefilter', __NAMESPACE__ . '\\resize_preupload_image', 10, 1);
Now that we have landed AVIF support in core, the current "WebP Uploads" image plugin could be expanded to include support for AVIF. This would also be good opportunity to add some more flexibility around input formats we handle, or progressive encoding (also new in 6.5).
@ficod, yeah, I decided to convert them manually with Imagick:
@predaytor - Here is are some alternate approaches:
To filter the mime types that the WebP Uploads
plugin transforms, use the webp_uploads_upload_image_mime_transforms
filter:
add_filter( 'webp_uploads_upload_image_mime_transforms', function( $transforms ) {
$transforms['image/png'] = array( 'image/png', 'image/webp' );
return $transforms;
} );
To leverage the core filter directly:
add_filter( 'image_editor_output_format', function( $mappings ) {
$mappings['image/png'] = 'image/webp';
return $mappings;
} );
@adamsilverstein @predaytor Thank you all for your replies.
What I don't understand is why this plugin can't receive an official update to solve the issue. This issue is totally not taken care of, is it considered not important or the project is not being actively developed?
I ended up preferring another plugin: WebP Express
AVIF do not support transparency like the PNG format.
AVIF is a good alternative for JPEG files
And WebP is the best alternative for PNG files because WebP support transparency.
So, this plugin being to be useless since the AVIF is now supported by the core and since this plugin do not support convert PNG files to WebP.
We just need a new plugin to convert automaticly WEBP, JPEG and PNG files into AVIF
Sorry but this is wrong! avif image format fully support alpha channel (the transparency)
https://avif.io/blog/faq/avif-transparency/
Addy Osmani has written a nice book on the argument, recommended https://www.smashingmagazine.com/2021/09/modern-image-formats-avif-webp/
Now that the Modern Images Formats plugin will support AVIF format (output), thanks to @adamsilverstein on #1151. I think the next logical evolution is to support more input like the PNG format.
Adam make this one, for his plugin, what do you think about that setting page ?
Leave the choice for users to convert a JPEG input into AVIF, PNG input into WebP, and WebP input into AVIF (for example) that can be a great evolution for our Modern Images Formats plugin and it will be more consistent with the new plugin name 😉
Two support topics have raised this the past couple days:
Please update the topic to add PNG to Avif image format conversion
This is the only reason why i don't use this plugin. No .png support :(
Let's try to land wider support for uploaded images, including PNGs.
The biggest question I have is about the best UI to provide.
For my plugin (pictured above) I went with giving users full control of the output format they want for each input format, but that me a bit over the top for this plugin? Maybe we can use a simplified approach where you choose an output format, then you choose from a checkbox list of input formats, choosing the ones you want to transform? Or maybe just automatically transform any uploaded images when we can reasonably do so?
@adamsilverstein Yeah, I do think that would be over-the-top to provide such granularity. With considering decisions not options, should JPEG and PNG always be converted to AVIF? Or would there be scenarios where one should rather be converted to WebP? Like, as I understand, only lossless AVIF supports transparency. So would perhaps all JPEGs be converted to AVIF as well as all non-transparent PNGs, but then leave transparent PNGs to converted to WebP (lossless or lossy)?
For sites that want to have fine-tuned control, I'd think that we'd perhaps offer a filter instead of a UI for that.
For sites that want to have fine-tuned control, I'd think that we'd perhaps offer a filter instead of a UI for that.
that makes sense, possibly a filter against whatever we decide are the defaults. existing core filters the plugin itself uses could already be used to fine tune the final behavior.
only lossless AVIF supports transparency. So would perhaps all JPEGs be converted to AVIF as well as all non-transparent PNGs, but then leave transparent PNGs to converted to WebP (lossless or lossy)?
interesting point, for transparent images, WebP lossy is probably the best choice. I like the general direction of mapping to what we think is the best available output type for the input type. I will work on a PR with that approach and we can discuss further.
Like, as I understand, only lossless AVIF supports transparency
Afaik (but I can be wrong) lossy avifs also support the alpha channel (the transparency). you can give a try with squoosh and converting a transparent image to avif (for me has worked)
As to which is "preferred" I prepared this which converts random images and measures their PSNR / SSIM ( spoiler: in the end avif always wins) https://gist.github.com/erikyo/d6ef961adc95a5c74e376a0216b29f69
the only doubts about whether to use avif or not is the time it takes to convert images which is hundreds of times longer than converting a jpeg, this in some cases (e.g. image regeneration by woocommerce) leads to unexpected results
I was wondering if you could address this request when it launches with WordPress 6.6? This request has been raised and pending for 2 years and still has not been resolved.
@erikyo
Afaik (but I can be wrong) lossy avifs also support the alpha channel (the transparency). you can give a try with squoosh and converting a transparent image to avif (for me has worked)
Interesting. I was just going off of what I found in search. For example via shortpixel.com:
AVIF supports transparency for lossless images but doesn’t support transparency for lossy images. On the other hand, WebP is the only image format that supports RGB channel transparency for lossy images.
I guess that's just wrong.
the only doubts about whether to use avif or not is the time it takes to convert images which is hundreds of times longer than converting a jpeg, this in some cases (e.g. image regeneration by woocommerce) leads to unexpected results
That's a great point. I've seen approaches where the WebP is generated first since it is fast, with the AVIF generation then sent to a background process since it can take a long time.
the only doubts about whether to use avif or not is the time it takes to convert images which is hundreds of times longer than converting a jpeg, this in some cases (e.g. image regeneration by woocommerce) leads to unexpected results
Encoding speed has improved dramatically over time for AVIF so this will depend to some degree on what version of the encoder you are using.
While libaom has indeed improved over time, encoding an image in AVIF format remains extremely complex, especially in server environments. GPU acceleration is not available, and in many cases, even multicore processing is not feasible.
I attempted to give AVIF a fair chance by modifying the Colab script to record the time used for each step. Here are the results:
Time taken to save 85% quality webp: 0.43184375762939453 seconds
Time taken to save 85% quality jpg: 0.046629905700683594 seconds
Time taken to save 85% quality jxl: 1.72273588180542 seconds
Time taken to save 85% quality avif: 40.48055696487427 seconds
As you can see from these numbers, avif takes significantly longer than other formats, making the avif format unsuitable for large batches of images.
using my server's CPU, I get better results (linearly) of x0.1.
I can be wrong, of course, that's why I would like others in this chat to do the same experiment. please let me know
EDIT: I conducted further tests and also [implemented image resizing](https://gist.github.com/erikyo/d6ef961adc95a5c74e376a0216b29f69 then clic "open in colab"). Here are the results:
Time taken to save 85% quality webp at size 300x300: 0.01772332191467285 seconds
Time taken to save 85% quality jpg at size 300x300: 0.0024929046630859375 seconds
Time taken to save 85% quality jxl at size 300x300: 0.06117439270019531 seconds
Time taken to save 85% quality avif at size 300x300: 2.21492600440979 seconds
Time taken to save 85% quality webp at size 1024x1024: 0.27861666679382324 seconds
Time taken to save 85% quality jpg at size 1024x1024: 0.03254413604736328 seconds
Time taken to save 85% quality jxl at size 1024x1024: 0.9864084720611572 seconds
Time taken to save 85% quality avif at size 1024x1024: 14.245483875274658 seconds
Time taken to save 85% quality webp at size 4k: 1.7801191806793213 seconds
Time taken to save 85% quality jpg at size 4k: 0.23264503479003906 seconds
Time taken to save 85% quality jxl at size 4k: 6.623462438583374 seconds
Time taken to save 85% quality avif at size 4k: 183.6950123310089 seconds
I must say that while small images can achieve a decent processing time, when we going to upload a large image, the result is definitely disastrous :(
While it is true that on a fast server, a single image can be converted in a fraction of the time (about 1/10), it is also important to consider that we often need to generate multiple resizes for each image. This becomes significantly more time-consuming when multiplied by the number of images in the gallery, especially in scenarios like WooCommerce where all images are (sometimes) regenerated.
@erikyo wow, that's indeed a problematic duration difference. I've not used avif yet myself, and looking at those processing times, I'll probably stick with webp for some time longer.
If you happen to still have those files handy, I would be interested in seeing what the end resulting file sizes were, of those first 4 you mentioned.
Wow @erikyo - those times are surprisingly large. Thanks for sharing the colab, that is great! I'd like to run similar timing tests in WordPress to see how the PHP libraries compare when processing images. They use the same underlying libraries, so probably not going to be much different though.
cc: @y-guyon for any feedback on the processing time, maybe there is something about the config that could be optimized
@adamsilverstein, it would be great if you could test AVIF vs. WebP encoding and decoding with WordPress. As you’ve seen, my tests use ImageMagick (like WordPress), but it’s always better to have real-world tests!
The standard CPU offered by Colab isn’t very fast. On my server, it’s about 10 times faster (so what takes 20 seconds for a single encoded image on Colab only takes 2 seconds on my server), but the difference between formats is still huge. For that reason, after trying to convert all the images in my media library, I found it unreasonable 😔.
@erikyo, with ImageMagick you can try setting 'heic:speed' to 6 or 7 for AVIF. libheif looks like it defaults libaom to speed 0, the slowest setting.
after trying to convert all the images in my media library, I found it unreasonable
@erikyo I'm curious if you saw particular slowness with lossless images (since thats the focus of this ticket) or all AVIF images?
@erikyo, with ImageMagick you can try setting 'heic:speed' to 6 or 7 for AVIF. libheif looks like it defaults libaom to speed 0, the slowest setting.
@jzern interesting! We should probably fix that in WordPress as well when using Imagick. Also: I wonder why the default is so slow, wouldn't a higher default for Imagick heic:speed make sense?
cc: @y-guyon for any feedback on the processing time, maybe there is something about the config that could be optimized
I think so. This comparison uses libavif+aom instead of libheif+aom but I expect AVIF to be around 5 times slower to encode than WebP at default speeds for 2K images in a lossy setting.
Afaik (but I can be wrong) lossy avifs also support the alpha channel (the transparency)
Yes, AVIF supports translucency. The alpha channel can be compressed with or without loss, no matter if the color channels are compressed with or without loss.
I would recommend using lossy AVIF (even for transparency) or keeping the original file format. There are very few use cases requiring lossless conversion in a WordPress context in my opinion.
For non-photo content (screen capture, UI elements etc.), other formats such as WebP may give smaller file sizes than AVIF.
@erikyo, with ImageMagick you can try setting 'heic:speed' to 6 or 7 for AVIF. libheif looks like it defaults libaom to speed 0, the slowest setting.
Imagick says it uses 5 as the default value - although I didn't see that default in the code.
I created a simple PR to change the default for WordPress Imagick AVIF handling to 7 - https://github.com/WordPress/wordpress-develop/pull/7068
@adamsilverstein, it would be great if you could test AVIF vs. WebP encoding and decoding with WordPress. As you’ve seen, my tests use ImageMagick (like WordPress), but it’s always better to have real-world tests!
@erikyo -
I created this mini plugin to test processing time by mime type using WordPress - https://gist.github.com/adamsilverstein/b4e91c9ab1e6f546ec98e3dcc53afb7d
Times were too fast in my local to me meaningful to measure. I need to test it in a slower environment to measure actual performance, or modify to run the process repeatedly.
@jzern Below the tests using different speeds and quality settings for the AVIF format. It seems you are right about that, the "heic:speed" option greatly reduces time without interfering with quality too much.
avif / testing quality + heic:speed (updated with some line charts at the end of the file)
@adamsilverstein thanks again, here are the results:
a small consideration about this. the 300x300 images takes more time to be processed, probably due to the time required time to resize the image with the sinc-lanczos filter. this pattern is repeated for all of these formats as well
@y-guyon Thanks so much for providing such interesting information! will try asap also with the avif codec. I have chosen the heic one since that Colab script is from 2 years ago, and at that time the heic codec was much more widespread and (if I remember correctly) was also faster
I would, however, like to point out that the command from the command line is used and instead WordPress uses Imagick, which is not performing in the same way. The biggest limitation in this case would be the number of cores used to convert the image than with imagemagick it should only use 1 core for each file converted
@erikyo thanks for sharing those results. Clearly the AVIF generation is taking much longer than the other formats - still the slowest time was well under a second, so for average use in WordPress this might be OK. I'll try to repeat the experiment on a lower end server as well as expanding the code to run a large number of repetitions.
@jzern Bellow the tests using different speeds and quality settings for the AVIF format. It seems you are right about that, the "heic:speed" option greatly reduces time without interfering with quality too much.
Seems likely we should change the default for WordPress (from 5) to 7
@jzern Bellow the tests using different speeds and quality settings for the AVIF format. It seems you are right about that, the "heic:speed" option greatly reduces time without interfering with quality too much.
Thanks for testing it out. The results look reasonable.
Seems likely we should change the default for WordPress (from 5) to 7
libavif's default is 6; either that or 7 should be a good default.
To verify, I modified the script so that it now uses only the full-size image and tests the quality vs ‘heif:speed’ vs time
It is even clearer that there is no quality loss with speed = 7. However, since the default speed for ImageMagick is 6, changing it to 7 is unlikely to affect the encoding performance significantly.
It is even clearer that there is no quality loss with speed = 7. However, since the default speed for ImageMagick is 6, changing it to 7 is unlikely to affect the encoding performance significantly.
Somewhere I saw a default of 5 mentioned for Imagick (although I didn't find the code), perhaps it is readable so I will try to check it. Still if quality isn't adversely affected, probably worth raising given the very slow encoding speed.
Somewhere I saw a default of 5 mentioned for Imagick (although I didn't find the code), perhaps it is readable so I will try to check it. Still if quality isn't adversely affected, probably worth raising given the very slow encoding speed.
https://imagemagick.org/script/defines.php
heic:speed=value set the HEIC speed parameter. Integer value from 0-9. Default is 5.
It would be good to verify this though.
It would be good to verify this though.
I couldn't find the default anywhere in the codebase, but I did see a 22% speed improvement when explicitly setting the speed variable to 7 (comments on the PR). I can re-test with 5 to verify this is the same speed as not setting a speed - this will confirm the default.
In the meantime, I plan to resume work here on the PNG -> AVIF/WebP conversion support.
I created a PR that adds PNG upload to AVIF (or WebP) output - https://github.com/WordPress/performance/pull/1421
@mukeshpanchal27 friday release? ðŸ¤
The next Performance Lab release is planned for the week after WordCamp US. See https://make.wordpress.org/core/2024/09/03/performance-chat-summary-03-september-2024/
@chrillep You can still use a pre-release version of the plugin though. I just created a build via npm run build-plugins:zip
: webp-uploads.zip
Your early testing and feedback would be much appreciated!
@chrillep You can still use a pre-release version of the plugin though. I just created a build via
npm run build-plugins:zip
: webp-uploads.zipYour early testing and feedback would be much appreciated!
Thank you very much, i make some tests with your file and all is working good for me :) 🚀
@jzern While compiling a list of contributors that helped with the upcoming WordPress 6.7 release using the project's "Prop" script, your account came up as not having linked their WordPress.org and GitHub accounts.
In the WordPress project, all credit given out must be attached to a WordPress.org account. After creating a W.org account (or logging in to your preexisting one), you can link your GitHub account following these steps in the Core Handbook. If you could kindly link your .org account and just share your .org username, we can ensure you receive proper attribution! cc/@jeffpaul
@jzern While compiling a list of contributors that helped with the upcoming WordPress 6.7 release using the project's "Prop" script, your account came up as not having linked their WordPress.org and GitHub accounts.
I signed up for an account, just waiting on the approval to be able to set a password. I didn't really contribute all that much here, so feel free to leave me out if you're about to finalize the release.
@jzern All constructive activity deserves recognition and WordPress tries to practice giving props liberally. You gave several tips and suggestions that helped arrive at an eventual solution. 🙂
I signed up for an account, just waiting on the approval to be able to set a password.
I still haven't seen an email for this. Nothing obvious in spam either. login.wordpress.org says it's still pending.
I still haven't seen an email for this. Nothing obvious in spam either. login.wordpress.org says it's still pending.
The account is setup now. It's jzern@ and linked to my github account.
As noted in this support topic, add the ability to automatically convert PNG images to WebP.