Jump to content

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
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
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
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
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
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
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
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(...)

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
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

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

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
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
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. 😉

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?

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
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
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
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
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 spercy16
      These issues should be fairly easy for any intermediate to advanced ProcessWire developer to answer. I'm new to PHP and relatively new to ProcessWire and just need a bit of help. What I'm trying to do is bring in a couple of cards from my Projects page to display on my home page. I finally got the code right to bring in the cards but right now they're using my original images instead of my resized "variations". So firstly, I would like to know how to reference the variations of my images instead of using the original. Secondly, I need to grab only four of the cards from the Project page and not import in all ten. It should be just two small changes to my code to do these things (I would imagine). Here is the code I currently have for that section:
      <?php // https://processwire.com/api/arrays/ // check if the array of images has items if (count($pages->get("/projects/")->images)) : // get array of images from the field $images = $pages->get("/projects/")->images; $count = 0; // iterate over each one foreach ($images as $image) : $count++; $sectionText = $pages->get("/projects/")->get("paragraph_$count"); $img = $image; $buttonCode = $pages->get("/projects/")->get("url_$count"); ?> <span id="card<?php echo $count?>" class="card"> <img class="cardThumb" src="<?php echo $img->url; ?>" alt="<?php echo $image->description; ?> Thumbnail" /> <div class="cardBody"> <div class="cardText"> <h2><?php echo $img->description; ?></h2> <?php echo $sectionText; ?> </div> <div class="primaryBtn"> <a href="https://www.paypal.com/donate?hosted_button_id= <?php echo $buttonCode; ?> &source=url"> <button> <i class="fas fa-donate"></i> Donate </button> </a> </div> </div> </span> <?php endforeach; endif; ?> Thanks in advance for any help!
    • By skeltern
      WebP image support is great and works fine. But once created I've issues to get rid of all API generated WebP variations.
      The backend image field variations "Delete" works and I can remove all variations JPEG plus WebP. Image list is clean but all WebP API variations are still stored in file system (for instance files/12345/84.900x675.webp etc). I can only use ImageSizer with temp 'force' option to request fresh WebP variations or have to delete WebP files from folders. No other way so far. Tested with 2 sites and latest master PW 3.0.165.
      Is there somewhere a "magic button" or config/setup thing to solve my sticky WebP issue?
    • By psy
      I've searched, and maybe missed, the solution. I have a 'normal' images field and uploading images with a file size greater than 10Kb is fine. Any image size smaller results in the never-ending spinner and no upload.
      No min/max width/height set on image uploads in admin, ie just the defaults.
      Any ideas on how to fix?
      Using:
      PW: 3.0.175
      PHP: 7.3
      Marking it as "Resolved" rather than "Solved" as it auto-magically fixed itself. No idea whether PW, PHP, or just an internet hiccough... All good now 🤞
    • By totoff
      Dear all,
      tomorrow I'll have to introduce some editors on how to upload and edit images in image fields in Processwire. The site in question is quite image rich and I've spent some time to serve the appropriate images via scrcset already cropped for different screen sizes.
      However, the backend offers a lot of possibilities to manipulate images and most of them I'm not familiar with because as a developer I've never spent much thinking on what all the features might be good for … Yet I'm concerned that my editors work on images in the backend may interfere with my optimization strategies in the templates.
      Is there a general rule of thumb what content editors should do or not do with images in order not to break srcset strategies etc.? Maybe there is already a source of information you could point me to?
      Your recommendations are much appreciated!
    • By totoff
      Dear all,
      I'm upgrading an older side with the new custom fields for images feature as of 3.0.142. My image field is set to "Automatic" and holds a bunch of images together with their respective description on each page. New custom fields include "caption" among others and to make my live easier I I'm trying to populate "caption" with the value from the (default) description field. But unfortunately I can't seem to find out how to save the newly set values. This is my code:
      <?php foreach (page()->images as $image) { $image->set('caption', $image->description); bd($image->caption); echo files()->render("markup/views/view-card-image-fancybox.php", array('image'=>$image)); } ?> <?php $page->save(); bd($page->save()); ?> This sets the value as intended (see screenshot) but doesn't save it permanently to the database. What am I doing wrong?
      Thanks!
       

×
×
  • Create New...