Jump to content
jacmaes

Webp support

Recommended Posts

One of PW 3.010's major novelty was the introduction of Horst's new image resizing engine that uses ImageMagick. Now I understand that ImageMagick can convert images to Webp, the image format that Google says can reduce image size up to 34% compared to JPEG.

Mozilla is apparently adding support to Firefox, and even the Safari team is playing with it, so it looks like Webp is soon going to be available in most major browsers. If Horst's module can be extended to add Webp conversion, that would be a great addition to PW's already very powerful image manipulation arsenal. 

I'm currently using the free ImageEngine Lite to serve Webp images to supporting browsers, and the results are impressive. I routinely get images that are between 25 and 60% smaller compared to JPEG, with the same visual quality. I would love to eliminate the need to rely on a third-party service though. 

  • Like 16

Share this post


Link to post
Share on other sites

Is there any update on this, doesn't look like many of the browsers have followed the google team by implementing. Love to have a simply solution for converting to webp in PW too if that might be available, even if its for opera and chrome users. something like

image->size(1000,0,"webp");

or

webp = image->convert("webp")

 

Share this post


Link to post
Share on other sites

We need WebP support in the core as it only has advantages (and one disadvantage): Edge (yes, Edge) supports it, as well as Chrome, the Android Browser (since 4.2) and Opera. Firefox 65 which will be released in January 2019 will implement it very soon and the Safari team is also experimenting with it.

The disadvantage is, that images that are being downloaded can not be opened with standard OS applications, but with tools like IrfanView or XnView you can also view WebP files. This makes it also hard to share these images and is why Facebook removed WebP from their service, as people tend to download and share the images. But I think thats not the case for most websites. And also it is a decision of the developer, if he uses WebP or another image format. So we have no drawbacks if this would be in the core (or a module, but I don't see why it should be a module).

Share this post


Link to post
Share on other sites

Some thoughts / infos in no special order:

it has to be a module because all our image engines are modules. 

As long as the GD library does not support webp, it cannot be a core fileformat. 

I haven't tested anything in regard of webp til now. If imagick supports it as outputformat, I can start testing it as a image engine module that extends the core imagick module to provide something like a options variable to return the final variation image as webp. 

Earliest start can be around christmas time 2018. 

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites
1 hour ago, horst said:

As long as the GD library does not support webp, it cannot be a core fileformat.

GD supports webp: http://php.net/manual/en/image.installation.php

Quote

To enable support for webp add --with-vpx-dir=DIR . Available as of PHP 5.5. As of PHP 7.0.0 --with-webp-dir=DIR has to be added, i.e. support for libvpx has been removed in favor of libwebp.

 

  • Like 2

Share this post


Link to post
Share on other sites
1 hour ago, Beluga said:

GD supports webp

Ah, a quick test showed that I can use this already with my local dev environment:

$cai3 = $page->croppable_images->first()->getCrop('thumb100');
// WebP with GD-lib bundled with PHP 7
$im = imagecreatefromjpeg($cai3->filename);
imagewebp($im, str_replace('.jpg', '.webp', $cai3->filename));
imagedestroy($im);

😄

  • Like 5

Share this post


Link to post
Share on other sites

@horst Niiiice! I've just tried on a live server with PHP 7.2 installed. Your code works great. The Webp image is successfully generated from the original JPEG. Here's how I've echoed it:

 

		$main_image = $page->image->first->getCrop('grande'); // (using Horst's Croppable Image module in this example)
		$image = imagecreatefromjpeg($main_image->filename);
		imagewebp($image, str_replace('.jpg', '.webp', $main_image->filename));
		imagedestroy($image);
		$webp_image = str_replace('.jpg', '.webp', $main_image->url);
		echo "<img class='responsive-image' src='$webp_image' alt=''>";

 

Note: for those using the Plesk control panel, webp support for GD seems to be disabled by default.

  • Like 2

Share this post


Link to post
Share on other sites

Probably not news to anyone familiar with webp, but I just tried it and the reduction in file size is impressive indeed. WEBP image on the left generated from variation with 100% quality, JPG on the right with default PW quality setting. Interesting that there is a slight but perceptible difference in colour though.

2018-11-30_110000.jpg.b49940d9d841016dac1502d725c45561.jpg

  • Like 4

Share this post


Link to post
Share on other sites

What we really will need is to detect if a browser supports it. 

If someone knows about workarounds, polyfills or others, please drop links here. 

Share this post


Link to post
Share on other sites
8 minutes ago, horst said:

If someone knows about workarounds, polyfills or others, please drop links here.

This seems like a pretty good approach to both inline and CSS images: https://css-tricks.com/using-webp-images/

For inline images in a textarea a textformatter module could prepare the picture/srcset.

  • Like 4

Share this post


Link to post
Share on other sites

Yeah, there are ways to use webp as progressive enhancement, so there's no need to detect browser support on the server side.

Share this post


Link to post
Share on other sites

Yes, Webp is impressive.

This is my dinner from the day before yesterday.

The JPEG (2394 x 1671 px) has 1.8 MiB, the Webp has 150.9 KiB

wizardl.webp

Share this post


Link to post
Share on other sites

@arjen the support via lazyload sounds very interesting. This way we only have to care that both fileformats are available on the server. There is no extra markup needed. Only downside is the missing noscript support. So the usefulness depends on the usecase. 

😀

  • Like 2

Share this post


Link to post
Share on other sites

Want to announce that I started with embedding support for the WebP format into the core.

Current state in my dev-branch is, that you can call / create additional image variations in the WebP format by passing this param within an options array to any size call:

// mandatory is: 'webpAdd' => true
// optionally define a quality for WebP: 'webpQuality' => 80
// currrently it only is implemented in the GD-Engine, so you need to force its use,

$options = [
    'forceEngine' => 'ImageSizerEngineGD',
    'forceNew' => true,
    'webpAdd' => true,
    'webpQuality' => 80
    ];
$image = $page->images->first->size(700, 700, $options);

 

If you want to be an early tester, you can get a fork from here (patch-1), or you grap these three files:

More will be done between christmas and new year!

 

screen-webp-start.thumb.jpg.20d914371b40284314569ff6746627fd.jpg

  • Like 4
  • Thanks 5

Share this post


Link to post
Share on other sites

Can we make the api a bit more flexible like:

$options = [
  'additionalFormats': ['webp'],
  'webp' => [
    'quality' => 80
  ]
];

This way we can easily add any other formats, which might emerge and have the possibility to not only have a single additional format generated. And as soon as we might generate multiple formats / images per sizing operation I feel like namespacing options like quality might prevent an explosion of possible root level options.

  • Like 2

Share this post


Link to post
Share on other sites
1 hour ago, LostKobrakai said:

Can we make the api a bit more flexible

I believe that this would need a huge rewriting of the complete images files (Pageimage and the SizerEngines). My first thought also was to enhance it to use different outputformats, as you can read above, (or maybe only in the github issues).

But with this first take, I definetly want to use only webp and only as a sidecar file. Other things, like selectable and multiple outputformats are not in the first line.

Thats because I have not that much time atm to start a huge rewrite, but want to have the compression advantage of webp integrated directly in PW, as this will be the first possibility included in the core, without usage of external tools and also without extra manipulation steps. And for that purpose, it seems to me enough to implement just another single param.

 

1 hour ago, LostKobrakai said:

This way we can easily add any other formats, which might emerge and have the possibility to not only have a single additional format generated

It will be definetly not "easily", as the imagesizer was and is designed to only resize and crop a single image. It is not an image manipulator. And the todo work not will be the ImageSizerEngines but the Pageimage.php, the tempfiles generation and how all this currently works together.

  • Like 1

Share this post


Link to post
Share on other sites

@horst As you wrote the webP will be generated in addition to the normal resized image, is that correct? 

How would I echo the different formats? Are there different URLs for the normal jpg image and another URL for the WebP image?

For example to use it in a picture element like I discribed in the Github issue

<picture>
  <source srcset="{$image->size(700,700,$options)->url('webp')}" type="image/webp">
  <source srcset="{$image->size(700,700,$options)->url}" type="image/jpeg"> 
  <img src="{$image->url}" alt="Alt Text!">
</picture>

 

Share this post


Link to post
Share on other sites

Current state is that only the images are created and removed.

There is no markup generation or additional url output implemented yet. But will be added soon.

  • Like 1

Share this post


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

But with this first take, I definetly want to use only webp and only as a sidecar file.

That's totally fine. We could simply not support different formats besides webp for now. I was really just talking about the configuration, so if there is time in the future to have a more extensive featureset supported we don't need to change the configuration, but can just add the features / remove warnings.

  • Like 3

Share this post


Link to post
Share on other sites
8 hours ago, LostKobrakai said:

I was really just talking about the configuration, so if there is time in the future to have a more extensive featureset supported we don't need to change the configuration, but can just add the features / remove warnings.

That's the part that is bound to the Pageimage class. Maybe it could be takled by a little extra layer / function, that maps a new configuration API to the old cryptic one, as I do with PIA and her selector strings?

Share this post


Link to post
Share on other sites
15 hours ago, jmartsch said:

How would I echo the different formats?

With a hook in site/ready.php like this one,

// hook for pageimages to return a webp url
$wire->addHookProperty('Pageimage::urlWebp', function($event) {
    $image = $event->object;
    $path_parts = pathinfo($image->filename);
    $webpFilename = $path_parts['dirname'] . '/' . $path_parts['filename'] . '.webp';
    if(!is_readable($webpFilename)) {
        $event->return = '#';  // what should be returned for none existing webp variations ?
        return;
    }
    $path_parts = pathinfo($image->url);
    $webpUrl = $path_parts['dirname'] . '/' . $path_parts['filename'] . '.webp';
    $event->return = $webpUrl;
});

you can use it for testing purposes right now.

screen-webp-url-property.jpg.69c6dc0d25b51bc9bd6245632480a563.jpg

  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Kiwi Chris
      In the RTE, when inserting a link, there are several input fields that can be used to select a page, including a text input field that will auto-complete with pages on the site.
      When inserting an image, there is only an option to navigate the page tree. (equivalent to the second input option 'Select Page...' on the Insert Link screen from the RTE.
      When inserting an image from another page buried somewhere in the page tree, if you know the name of the page, it would often be quicker to use an auto-complete text field than 'Select Page...' option.
      It would be nice if the image insertion dialog offered the same functionality as the link insertion dialog so that when selecting a page it's possible to choose either to navigate the page tree, or have a text auto-complete field.
    • By Brian Scramlin
      I just wanted to share that I added an AJAX-powered gallery to an artist website that I developed and host: https://jackpinecreations.com/gallery/

      There were two things that frustrated me about creating this. Perhaps you can show me a better way.
      1. After creating my processing script, which I placed under /templates/scripts/get-items.php, I realized that I would get a 403, due to ProcessWire's routing and security. This forced me to have to create a template and page for this little script. This was frustrating simply because it seemed unnecessarily confusing. But worse, see #2.
      2. I usually use config.php to prepend and append each of my templates with a head.inc and foot.inc, which keeps my templates easy to use and I don't have to go and use the GUI to do so on each template separately. However, since I realized I needed to create a new template and page so as to access it, whenever I sent POST params to it, I would get the header and footer along with it!!! I could find no workarounds and had to remove the pre/append calls in config.php and use the GUI on each template individually.  
      Code Below if you're interested:
      HTML and JavaScript (forgive my sad JavaScript skills, I know this can be tightened up)
      <!-- Begin Grid --> <div class="container mt-4"> <div id="gallery" class="row"> <?php foreach ($page->children("limit=9") as $child): ?> <div class="col-6 col-md-4 gallery-item"> <a href="<?= $child->url ?>" title="View <?= $child->title ?>"> <img class="gallery-item" src="<?= $child->item_featured_image->size(640, 640)->url ?>" alt="<?= $child->title ?> Image"> </a> </div> <?php endforeach; ?> </div> </div> <!-- End Grid --> <div class="center-block text-center"> <button id="get-more-items" type="button" name="get-more-items" class="btn-vintage">Load More</button> </div> <script type="text/javascript"> var buttonGetItems = document.getElementById("get-more-items"); var indexStart = 0; buttonGetItems.addEventListener("click", function() { indexStart += 9; $.ajax({ url: '<?= $pages->get(1186)->url ?>', type: "POST", dataType:'json', // add json datatype to get json data: ({page_id: <?= $page->id ?>, index_start: indexStart}), success: function(data){ console.log(data); if (data[1]) { //for each element, append it. $.each(data, function(key, value) { $("#gallery").append(value); }); } else { $("#get-more-items").after('<p class="center-block text-center">There are no more items to load.</p>'); $("#get-more-items").remove(); } } }); }); </script> Processing Script
      <?php $items_array = []; $i = 0; foreach ($pages->get($input->post->page_id)->children->slice($input->post->index_start, 9) as $child) { $i++; $items_array[$i] = "<div class='col-6 col-md-4 gallery-item'> <a href='$child->url' title='View $child->title'> <img src='{$child->item_featured_image->size(640,640)->url}' alt='$child->title Image'> </a> </div>"; } echo json_encode($items_array); I love ProcessWire for hundreds of reasons, but I've been using AJAX more and more, and I'm not liking having to create templates to access scripts. 
      Any advice?
    • By Inxentas
      I have an image gallery based on an Image field with about 300 images in it. That caused a little issues with uploading, since it's on a shared host I had to do that piecemeal in order to not overload the server. I kept refreshing the frontend of that page to make sure the server doesn't run out of memory compressing the images, as such an amount obviously requires thumbnails. After 160 images the frontend no longer updates. I can add images to the backend, but they are not shown on the frontend. The images field is not limited in any way. Is there a cap to the amount of images uploaded to a single field? Or any other aspect that might explain such behaviour?
      The images show up fine in the backend, but when I foreach() through that field I only get 160 results. Any idea what might be going on?
    • By ODDCODE
      Hi, 
      I am sure this question may been asked but I couldn’t find it in the forum. I am new to using Processwire CMS/CMF. I read great reviews on CMS blog about Processwire. So I decided to give It a try. I am trying to figure out what is the best way to structure a simple gallery. I will also need to be able to catalog the photos. 
      Thank you, 
    • By RicknRoller
      Hi there!
      I am quite new to processwire and am just finishing my first PW project. I think the whole framework is awesome and could profit a lot from all the tutorials available. One thing that I somehow can't seem to get my head around is working with images and their resizing. I have following scenario:
      A 'gallery-index' page with its 'gallery' children. Those children have an 'images' field where the user uploads his (often too big) images.
      I am working with twig. On the gallery page frontend I have a slider, a displayed collection of all the images and a hidden one where I get the source to the original image in a popup. So in total the images will be outputted 3 times in different sizes.
      First:
      <div id="slick"> {% for img in page.images %} <img src="{{ img.height(400).url }}" alt=""> {% endfor %} </div> Second:
      <div class="gallery"> {% for img in page.images %} <img src="{{ img.width(300).url }}" alt=""> {% endfor %} </div> Third:
      <div class="hidden"> {% for img in page.images %} <a href="{{ img.maxWidth(1024).url }}" data-original="{{ img.url }}"></a> {% endfor %} </div> Now, the loops basically work, and some images are displayed the right way. But not all of there are displayed at all, despite them being there in the DOM. The urls all look right but some will be displayed and some url just go to a small black box image. How comes that PW manages to have different results in displaying the images in different formats?
      URL of gallery: http://2019.hclaupersdorf.ch/fotos/hc-laupersdorf-vs-ruschlikon-chiefs/ (there are more in the DOM than displayed)
      URL of 'not working' image: http://2019.hclaupersdorf.ch/site/assets/files/2361/20180616-rueschlikon-21_42049612175_o.300x0.jpg
      Furthermore, whenever this error occurs (which usually is at every page request on the gallery page), the DOM doesn't fully load. My JS for init the slider or the popup won't be loaded and the page is basically displayed half-loaded.
      Any ideas or suggestions on how to work around it, best practice when handling images & galleries?
      Thanks!
×
×
  • Create New...