2
votes

Whenever Silverstripe creates from an image a resized version the system will also generate a webp version of this image. Via .htaccess I can then forward user with chrome browser to this webp image.

My idea was so far to extend the image.php class, the problem is, that an extension can not overwrite an existing method.

Is there any way that I can do something so that I can do this still when I call $Image.setWidth(200) from the template, my function will be run?

My aim is still to prevent changing all methodnames which would work. $Image.webpSetWidth(200) would work with a normal image extension. But if somehow possible I would avoid this.

Checked the Image.php (and GD.php) for possibilities to extend it, but at least in Silverstripe 3.6 it is not possible.

UPDATE:

Thanks to the hints of Brett I got pointed into the right direction.

<?php

    class WebPGDBackend extends GDBackend
    {
        public function writeTo($filename)
        {
            parent::writeTo($filename);

            if (function_exists('imagewebp')) {
                $picname = pathinfo($filename, PATHINFO_FILENAME);
                $directory = pathinfo($filename, PATHINFO_DIRNAME);

                list($width, $height, $type, $attr) = getimagesize($filename);
                switch ($type) {
                            case 2:
                                if (function_exists('imagecreatefromjpeg')) {
                                    $img = imagecreatefromjpeg($filename);
                                    $webp = imagewebp($img, $directory.'/'.$picname.'.webp');
                                    $gif = imagegif($img, $directory.'/'.$picname.'.gif');
                                }
                                break;
                            case 3:
                                if (function_exists('imagecreatefrompng')) {
                                    $img = imagecreatefrompng($filename);
                                    imagesavealpha($img, true); // save alphablending setting (important)
                                    $webp = imagewebp($img, $directory.'/'.$picname.'.webp');
                                }
                }
            }
        }
    }

This will create, whenever a resized image is saved (in jp(e)g/png format) a webp copy. In order that this works it is necessary that gdlib is compiled with the appropriate flag. Furthermore you will have to add the class to the config.php via Image::set_backend("WebPGDBackend");.

Keep in mind this will just work right now for graphics which gets newly resized.

With that above it would be possible to configure the .htaccessto forward jpeg/png requests for browsers which understand webp to the new graphic.

I realized that with the following snippet:

<IfModule mod_rewrite.c>
RewriteEngine On

# Check if browser support WebP images
RewriteCond %{HTTP_ACCEPT} image/webp

# Check if WebP replacement image exists
RewriteCond %{DOCUMENT_ROOT}/$1.webp -f

# Serve WebP image instead
RewriteRule (assets.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=accept:1]
</IfModule>

<IfModule mod_headers.c>
Header append Vary Accept env=REDIRECT_accept
</IfModule>

<IfModule mod_mime.c>
AddType image/webp .webp
</IfModule>
1

1 Answers

0
votes

I'm not sure if SS 3.6 has out of the box functionality which would generate this, however you can use the ImagickBackend and modify it through extensions to suit.

E.g.

<?php

if(class_exists('Imagick')) { 
class MyImagickBackend extends ImagickBackend {

    // default format to use
    private static $format = 'webp';

    public function __construct($filename = null) {
        parent::__construct($filename);
        $this->setImageFormat( Config::inst()->get('MyImagickBackend','format') );
    }
}

then in _config.php you just set the backend to use for Images

Image::set_backend("MyImagickBackend");

NOTE: This does require ImageMagick to be installed and the PHP module to be enabled.

NOTE: This has not been tested directly, so you may need to set other ImageMagick parameters for webp

References:

Imagemagick Specific webp calls in PHP

http://php.net/manual/en/book.imagick.php

https://github.com/silverstripe/silverstripe-framework/blob/3.6/filesystem/ImagickBackend.php