Jump to content
jacmaes

Webp support

Recommended Posts

Another update to the PageImage class, comes in handy during the webp work. But it is not only useful for WebP copies, but for everything in regards of experimenting and debugging with images. I added a new method: ->getDebugInfo($options). See examples here: https://biriba.de/pw_pop3/pw_pageimage_getdebuginfo/

 

  • Like 4

Share this post


Link to post
Share on other sites

Please can someone test the .htaccess solution for WebP support in other environments?

It is not much work, you don't have to install test branches or anything else. You only need to copy some lines into your .htaccess file and create a single webp image with the tool of your choice. Or if you don't have a converter tool for webp, simply make a copy of a jpeg and rename it with type .webp instead of .jpg.

Steps to proceed:

  1. Copy the rewrite directives into the top of your .htaccess file 
  2. Grab any image variation you already have embedded into a PW site, create a webp variation of and save it into the same assets/files/{ID}/ folder.
    (Maybe you want to invert the colors of the webp copy for better detection!)
  3. Create or go to a page where this image should be rendered as jpeg in a regular img tag, and look if the webp copy is served and displayed.
    (Don't forget to flush browser caches)

The .htaccess code:

Spoiler

AddType image/webp .webp

<IfModule mod_rewrite.c>

    RewriteEngine On
    AddDefaultCharset UTF-8

    ### Redirect regular PW JPEGs and PNGs to their WEBP image copies,
    ### if available and if the Browser supports WEBP:

        ## Does Browser accept WEBP images?
        RewriteCond %{HTTP_ACCEPT} image/webp

        ## Is it an existing file?
        RewriteCond %{REQUEST_FILENAME} -f

        ## Does a WEBP copy exist for it?
        RewriteCond %{DOCUMENT_ROOT}/$1$2$3/$4.webp -f

        ## With an added GET var or GET value of skiprewrite we do send the original JPEG or PNG
        RewriteCond expr "! %{QUERY_STRING} -strmatch '*skiprewrite*'"
        ## With an added GET var or GET value from the PW Page Editor, we do send the original JPEG or PNG
        RewriteCond expr "! %{QUERY_STRING} -strmatch 'nc=*'"

    ## Is it a regular PW JPEG or PNG image, stored under site/assets/files?
    RewriteRule ^(.*?)(site/assets/files/)([0-9]+)/(.*)\.(jpe?g|png)(.*)$  /$1$2$3/$4.webp [L]


	## Test that should show the original jpeg or png
    ###RewriteRule ^(.*?)(site/assets/files/)([0-9]+)/(.*)\.(jpe?g|png)$  /$1$2$3/$4.$5 [L]
  
	## Test with a PHP file in web root, that shows the references builded by the conditions. Useful for debugging with a direct call to a image url.
    ###RewriteRule ^(.*?)(site/assets/files/)([0-9]+)/(.*)\.(jpe?g|png)$  /matched.php?1=$1&2=$2&3=$3&4=$4&5=$5  [L]

</IfModule>

 

My matched.php for debugging:

Spoiler

<?php namespace ProcessWire;

echo "<ol>";
foreach($_GET as $item) echo "<li>{$item}</li>";
echo "</ol>";

$fn = $_SERVER['DOCUMENT_ROOT'] . '/' . $_GET[1] . $_GET[2] . $_GET[3] . '/' . $_GET[4] . '.webp';

echo "<p>{$fn} :: " . (file_exists($fn) ? 'yes' : 'no') . "</p>";

 

 

Examples in Opera with opened Network-Tab, requesting one image that has a webp copy, and requesting the second image that do not have a webp copy:

pw_htaccess_webp_support.thumb.gif.7791ff59d467fc7ee3dfaf0ea9aaf2d7.gif

Same page in Opera and old IE11:

pw_htaccess_webp_support.png.d110db833030e6825bb9c426f6bbcf0b.png

 

If we have a wider test case, the chance that this can be embedded into the PW .htaccess file for optional usage (commented by default) would be helpful for many users to support webp with less effort on their sites!

 

  • Like 3

Share this post


Link to post
Share on other sites
11 hours ago, horst said:

Please can someone test the .htaccess solution for WebP support in other environments?

It's working here in Laragon, Windows.

But won't this have the effect that if a visitor saves the image from their browser they will be saving a WEBP image with a JPG (PNG, GIF, etc) file extension? Might cause some confusion.

  • Like 2

Share this post


Link to post
Share on other sites

Thanks for your effort on this. I'll check it out this week and let you know my test findings.

  • Like 1

Share this post


Link to post
Share on other sites
On 4/28/2019 at 7:44 AM, Robin S said:

But won't this have the effect that if a visitor saves the image from their browser they will be saving a WEBP image with a JPG (PNG, GIF, etc) file extension? Might cause some confusion.

Thanks for testing. And yes, this is right.

But for me personally, (and for most of my clients), the main goal is to present pages with text and images on the screen, and not to let the visitors save images for later use. I think, if a visitor need a visual copy of a page, he still can save the complete page with his browser, or he can do screenshots. On photographer sites, the use of images independend from viewing the site / page are often prohibited. There it even should not be recognized that images with filetype jpeg in real are weppys. But that is my personal opinion, and maybe thats not a sufficient reason to include this into the PW htaccess.

But it also could be done the other way round: send .webp in markup and let the htaccess directives change this to (png|jpg) if a) the browser doesn't support this, or b) if there is no webp file available. This way round, in a 100% perfect site, all newer browsers would get 100% webp with correct file type. Only older browsers would get jpegs or pngs with file type webp. 🙂

  • Like 6

Share this post


Link to post
Share on other sites
5 hours ago, horst said:

I think, if a visitor need a visual copy of a page, he still can save the complete page with his browser, or he can do screenshots.

Because of this, is it worth also confusing the maintainers of the site? When debugging issues, it is easy to trip over files named in misleading ways.

  • Like 2

Share this post


Link to post
Share on other sites
3 hours ago, szabesz said:

When debugging issues,

you may use the new debug info for images.

and / or skip the rewrite: /site/assets/files/1/basename.jpg?skiprewrite 

On 4/27/2019 at 8:37 PM, horst said:

## With an added GET var or GET value of skiprewrite we do send the original JPEG or PNG
RewriteCond expr "! %{QUERY_STRING} -strmatch '*skiprewrite*'"

And: nobody is forced to use it this way. You always can create conditional markup. My goal is to collect different solutions, and with the .htaccess only, to show and discuss a solution that would not need a rewrite for existing sites, or at least, makes the rewrite as small as possible. (change all image variations in markup from .jpg to .webp).

EDIT:

3 hours ago, szabesz said:

confusing the maintainers

I think maintainers should know about the fact if they have implemented a webp solution and if so, wich one. If, for what ever reason, someone don't like this solution in a site, he shouldn't use it.

  • Like 3

Share this post


Link to post
Share on other sites

Hi @horst,
My ImageSizerEngineVips is based on your ImageSizerEngineIMagickCLI with code from other sizers. The module works fine, but at the moment only for my needs, because I optimized for speed and left some options like sharpening. But if I have the time and interest, I can polish it.
Another thing:
I only use WebP in pages with lazy loading and srcset. Because of that I have only variations as WebP, not the uploaded pageimage. Your change here checks not only variations, right? For me, it changes many variations that already exist. 

  • Like 1

Share this post


Link to post
Share on other sites

Hi Horst, I'm late on that one, thx for all your work! 🙂 

$image = $page->images->first()->size(300, 300);

?>
<picture>
    <?php if($image->hasWebp) { ?>
    <source srcset="<?=$image->srcWebp?>" type="image/webp" />
    <?php } ?>
    <source srcset="<?=$image->src?>" type="image/jpeg" />
    <img src="<?=$image->url?>" alt="Alt Text!" />
</picture>

What about something like this to ?

$image = $page->images->first()->size(300, 300);
echo $image->hasWebp(
  "<source srcset='{srcWebp}' type='image/webp'/>",
  "<source srcset='{src}' type='image/jpeg'/><img src='{url}' alt='{description}'/>"
);

Such a method could even be extended with custom templates set via $config->webp or the like and could also get a third argument for options. Then the example above could be:

echo $page->images->first()->size(300, 300)->hasWebp();

...and produce the exact same output as your example. Maybe $img->webp(...) would be a better name for such a method than $img->hasWebp(...)

Share this post


Link to post
Share on other sites
On 4/29/2019 at 9:38 PM, Noboru said:

I only use WebP in pages with lazy loading and srcset. Because of that I have only variations as WebP, not the uploaded pageimage. Your change here checks not only variations, right? For me, it changes many variations that already exist. 

@Noboru I now have changed it to work with all regular use cases in PW. But this includes to have a regular file and optionally a webp file. But this is/was the behave before the core webp addition too.

Please try if it now works for you, or report back. If not, we can define a custom hook or a custom function to suite your setup.

  • Like 2

Share this post


Link to post
Share on other sites

If you have mod_pagespeed on your server it can convert jpg to webp on the fly. Can do lots of other amazing stuff also.

  • Like 1

Share this post


Link to post
Share on other sites

This is great work here in this thread tho, awesome stuff.

  • Like 1

Share this post


Link to post
Share on other sites

Hello @horst,

thank you for your efforts to bring WebP to ProcessWire.

I can't wait till it is implemented in the core and want to try it out, but have some problems getting it to work. I hope you can help me:

I have downloaded your modified ProcessWire from your pull request and replaced the wire folder with your wire folder, because I don't want to mess up the Git development branch of my project. Maybe I don't understand the concept of pull requests right. 😀

Following files have changed:

  • wire/config.php
  • wire/core/ImageSizerEngine.php
  • wire/core/ImageSizerEngineGD.php
  • wire/core/Pageimage.php
  • wire/modules/Image/ImageSizerEngineIMagick/ImageSizerEngineIMagick.module

Now if I have understood correctly, I should be able to generate a WebP of an image with:

<?php

$options = [
	"webpAdd" => true,
	"webpQuality"=> 90
];

page()->image->size(800, 600, $options);

Now I get the error:

image.png.a580d1a56e219be19b70d247563286a9.png

Am I missing something or has it to do with my local MAMP?

Regards, Andreas

Share this post


Link to post
Share on other sites

Hi Andreas,

my first idea is that your local IMagick installation lacks webp support. Can you check this in phpinfo().

Opera_Momentaufnahme_2019-05-03_105059_kawobi.local.png.13ace311687d29995330d169d572393e.png

Share this post


Link to post
Share on other sites

Thank you for the hint, that seems to be it. Here is a screenshot of my local ImageMagick installed with Homebrew on MacOS:

image.png.ee146d3e6dd774c575def84476fb8d5a.png

But even when I uninstall the core module IMagick Image Sizer, I cannot create a WebP image with ImageSizerEngineGD.

Our hoster doesn't seem to support WebP either unfortunately.

Not so easy to use WepP at the moment. 😀

  • Sad 1

Share this post


Link to post
Share on other sites

@AndZyk I have sent a new commit to github to cover this. Please can you download the 3 new files:

core/Pageimage.php
core/ImageSizerEngineGD.php
modules/Image/ImageSizerEngineIMagick.module

If you want to test / debug the webp functionality of both engines in one call, please use code like this in a template file:

    $options = [
        'forceEngine' => 'ImageSizerEngineGD',
        'suffix' => 'gd',
        'forceNew' => true,
        'webpAdd' => true,
        'webpQuality' => 90,
        ];
    $img = $page->images->first->size(150, 150, $options);
	echo $img->getDebugInfo();

    $options = [
        'forceEngine' => 'ImageSizerEngineIMagick',
        'suffix' => 'im',
        'forceNew' => true,
        'webpAdd' => true,
        'webpQuality' => 90,
        ];
    $img = $page->images->first->size(150, 150, $options);
	echo $img->getDebugInfo();

A) it now should run without errors when you request a webp copy and the engine doesn't support it, and B) you can see it in the debug info if the selected engine supports webp.

engine-webp-supported.png.851f511528c85eeeac2cd50668695ad5.png

  • Like 1

Share this post


Link to post
Share on other sites

Thank you, I have downloaded your new commit and now I don't get an error anymore.

Unfortunately it seems, that the GD library and Imagick by MAMP doesn't support WebP yet. I found an tutorial how to recompile PHP for MAMP with WebP, but I rather wait for an update.

I noticed that the forceEngine option doesn't change the engine for me. I first had to uninstall the core module IMagick Image Sizer, so that the GD library would be used. Could that be a bug or have I done something wrong? 

It seems, that for now I will have to wait for more WebP support by MAMP and my hoster. But at least ProcessWire will be ready. 😉

Share this post


Link to post
Share on other sites
53 minutes ago, AndZyk said:

I noticed that the forceEngine option doesn't change the engine for me. 

Hmm, but it should. What priority settings do you have set?

Share this post


Link to post
Share on other sites

IMagick Image Sizer has priority 1. I think that is the default value.

Share this post


Link to post
Share on other sites

Yes, its the default. Weird!

Share this post


Link to post
Share on other sites

Hi @AndZyk,

you could try this:
brew install imagemagick
brew install pkg-config
pecl install imagick

For me this installs 
/Applications/MAMP/bin/php/php7.1.22/lib/php/extensions/no-debug-non-zts-20160303/imagick.so

In MAMP I switched to PHP 7.1.22 and edited in corresponding php.ini
MAMP_Imagick_MAMPextension=/Applications/MAMP/bin/php/php7.1.22/lib/php/extensions/no-debug-non-zts-20160303/imagick.so
 

Now MAMP should use a newer Imagmagick with WebP-Support.

Hope that helps.

Gruß
Armin

phpinfo().png

  • Like 2

Share this post


Link to post
Share on other sites
On 4/28/2019 at 7:44 AM, Robin S said:

But won't this have the effect that if a visitor saves the image from their browser they will be saving a WEBP image with a JPG (PNG, GIF, etc) file extension? Might cause some confusion.

This is the only disadvantage I see, but it might outweigh all the advantages.

On 4/29/2019 at 8:18 AM, arjen said:

Thanks for your effort on this. I'll check it out this week and let you know my test findings.

It works fine on my local docker environment. Nice 👍 I am moving servers, but I will check it out on a VPS but I won't see why it shouldn't work.

  • Thanks 1

Share this post


Link to post
Share on other sites

Thank you @Noboru, I will try this out. 😉

I am wondering: Can you even open WebP files in apps other than browsers without having the codec installed?

As far as I know you cannot simply open a .webp file. After all it is meant for browers. But I haven't tried it much.

In my opinion I would not serve WebP content in a .jpg or .png file. I would serve only WebP in a .webp file for browsers that support it. 😀

  • Like 2

Share this post


Link to post
Share on other sites

My favourite atm is to serve webp format in webp files and use the htaccess solution to detect missing browser support and then, as fallback, serve jpeg format in webp files. This false file types automatically will go away by time, as browser support becomes complete.

Edited by horst
  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By thausmann
      Hey, I'm trying to completely switch over to WebP and noticed some strange behaviour. Let's say I upload a PNG in Processwire of size 1280x800.
      $page->image->url ➝ correct URL (filename.webp) $page->image->width(800)->url ➝ correct URL (filename.800x0.webp) $page->image->width(1280)->url ➝ wrong URL (filename.1280x0.png), webp file is not generated $page->image->width(1280)->url(false) ➝ correct URL (filename.1280x0.webp) but webp file is not generated So: When I request a size that equals the original file, no WebP conversion is happening (no webp file is created, although a new PNG is generated (...1280x0.png)).
      When I use url(false), I get the expected URL but still the file is not generated. Also interesting: this issue is only occuring with PNG, not JPG.
       
      My Configuration:
      $config->imageSizerOptions('webpAdd', true);  $config->imageSizerOptions('defaultGamma', -1); GD Pageimage::url Hook from here  Also tried to output width(1280)->webp->url, it makes no difference I checked that the PNG version is not smaller in filesize (PNG=450KB, WebP (from other tool)=60KB) Tested with Processwire 3.0.148 and 3.0.160 dev I think this post is about the same issue and where I got the url(false) from. Setting 'useSrcUrlOnFail' => false inside $config->webpOptions results in correct output URL (filename.1280x0.webp), but still the file is not generated. So maybe the webp conversion fails? Apparently I see zero webp logs in logs/image-resizer.txt  
      "Don't use resize" seems like a solution here but this is a generic approach in my code, sometimes uploaded images are simply already in the correct size. 
      Any ideas how to fix this and always get dem sweet sweet WebP images? Or did I find a bug?
      Maybe @horst has an idea what the cause of this phenomenon could be? 😇
    • By horst
      Hi, on a site I want to disable access to original images and only allow to access thumbnails and watermarked image variations.
      EDIT:
      A good solution for protecting original images can be found a bit down in this thread:
       
      Old content of this initial post:
       
    • By Guy Incognito
      I seem to be running into a repeated fatal error in a fresh PW install version 3.0.148. I can't quite put my finger on the pattern but it seems to be around deleting image fields or removing images from certain image fields.
      This is the trace from the log generated by trying to save a page and delete an image from an image field:
      Fatal Error: Uncaught Error: Cannot access protected property Pageimage::$original in /wire/core/PageimageVariations.php:256 Stack trace: 1. /wire/core/Pageimage.php(1327): PageimageVariations->getInfo() 2. /wire/core/Wire.php(386): Pageimage->___isVariation() 3. /wire/core/WireHooks.php(823): Wire->_callMethod() 4. /wire/core/Wire.php(450): WireHooks->runHooks() 5. /wire/core/Pageimage.php(1369): Wire->__call() 6. /wire/core/Pageimage.php(399): Pageimage->getOriginal() 7. /wire/core/WireData.php(333): Pageimage->get() 8. /wire/core/PageimageVariations.php(256): Pro Line 256 of /wire/core/PageimageVariations.php Earlier in the day I was experimenting with custom fields for images for the first time and kept running into this error, thinking it was me using this feature wrong and not having time to read up I deleted the custom image fields template and went about my business. So now I don't know if I triggered an issue or whether it was never related to the custom image fields in the first place?
      Any ideas?
    • By humanafterall
      I'm using some Custom fields for images: 
      https://processwire.com/blog/posts/pw-3.0.142/#custom-fields-for-files-images

      When I save the page, and return the fields are blank. When I re-add the text to the fields and save again then the fields save as expected.

      I know this is stated as being quite experimental but it's super useful feature I'd love to get working correctly.
      I have fields that are CKEditor fields but have overidden this on the image specific template. I've also tried it with regular text fields and I get the same bug.
      (currently using Processwire 3.0.155)
      **UPDATE**
      I've found this issue is specific to editing on pages using the PageTable fieldtype. The fields are not saving when I save the page in the PageTable.
    • By Robin S
      Displays image tags overlaid on the thumbnail using customisable colours. This makes it easier to see which images have which tags without needing to open the edit pane for individual images or changing to the list view.
      Screenshot

      Usage
      Enable tags for one or more image fields. Install the Image Thumbnail Tags module. Optionally configure colours for any of your tags.
       
      https://github.com/Toutouwai/ImageThumbnailTags
      https://modules.processwire.com/modules/image-thumbnail-tags/
×
×
  • Create New...