首页 web服务器 正文
399

网站图片后台转webp格式

  • yiqingpeng
  • 2020-01-02
  • 2
  • webp 
webp图像格式是由谷歌开发的新一代图片格式,其具有非常高的压缩率。在无损压缩模式下,能将png图片大小压缩26%;有损压缩模式下,能将jpeg图片大小压缩25-34%。如此给力的压缩效率为那些图片重应用类型网站提供了不少的性能优势。目前,很多浏览器已经开始支持webp了(对于不支持webp的浏览器,可以考虑使用pngquant对png图片进行压缩,效果也是非常地好,使用方法:yum install pngquant; pngquant --quality 60-100 - >output_image.png < input_image.png)


那么现有网站要提供webp支持如何来做呢?笔者主要从后端入手,解决后端将原有图像文件(png, jpeg)转webp的问题。

基本思路很简单,利用apache的重写策略,将图片请求重写为相应的webp图片,如果相应的webp文件不存在,则流转给脚本进行转换处理。

1、给站点vhost段配置如下重写规则:
rewriteCond %{REQUEST_FILENAME} (.+)\.(png|jpe?g) [NC]
rewriteCond %1.webp -f [NC]
rewriteCond %{HTTP_ACCEPT} image/webp [NC]
rewriteRule (.+)\.(png|jpe?g) $1.webp

rewriteCond %1.webp !-f [NC]
rewriteCond %{HTTP_ACCEPT} image/webp [NC]
rewriteRule (.+)\.(png|jpe?g) /2webp.php
2、在网站目录下新建脚本2webp.php, 代码如下:
<?php
class WebpConverter{
    private $originFile;
    public function __construct($originFile) {
        $this->originFile = $originFile;
    }
    private function imageCreateFromAny($filepath) {
        $type = exif_imagetype($filepath); // [] if you don't have exif you could use getImageSize()
        $allowedTypes = array(
            1,  // [] gif
            2,  // [] jpg
            3,  // [] png
            6   // [] bmp
        );
        if (!in_array($type, $allowedTypes)) {
            return false;
        }
        switch ($type) {
            case 1 :
                $im = imageCreateFromGif($filepath);
                break;
            case 2 :
                $im = imageCreateFromJpeg($filepath);
                break;
            case 3 :
                $im = imageCreateFromPng($filepath);
                break;
            case 6 :
                $im = imageCreateFromBmp($filepath);
                break;
        }
        return $im;
    }
    
    private function commandExists($command) {
        $isWin = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
        $test = $isWin ? "where" : "which";
        return is_executable(trim(shell_exec("$test $command")));
    }
    
    public function save($targetFile = null){
        $this->targetFile = $targetFile;
        if (!$this->targetFile) {
            $pathInfo = pathinfo($this->originFile);
            $this->targetFile = $pathInfo['dirname'] . DIRECTORY_SEPARATOR . $pathInfo['filename'] . '.webp';
        }
        if (function_exists('imagewebp')) {
            //imagewebp 是GD库里面的函数,但是即使安装了GD库也不一定支持webp,编译php时需要指定相应的配置。
            $img = $this->imageCreateFromAny($this->originFile);
            $result = imagewebp($img, $this->targetFile);
            imagedestroy($img);
        } else if (class_exists('Imagick')) {
            //需要安装Imagick扩展
            $image = new Imagick($this->originFile);
            $image->setImageFormat('webp');
            $image->setImageAlphaChannel(Imagick::ALPHACHANNEL_ACTIVATE);
            $image->setBackgroundColor(new ImagickPixel('transparent'));
            $result = $image->writeImage($this->targetFile);
        } else if ($this->commandExists('cwebp')) {
            //需要在服务器安装libwebp-dev工具包,tools工具下载。
            $cmd = 'cwebp "' . $this->originFile . '" -o "'. $this->targetFile . '"';
            exec($cmd, $output);
        }
        return $this;
    }
    
    public function flush(){
        header('Content-Type: image/webp');
        echo file_get_contents($this->targetFile);
    }
}

$requestURI = strtok($_SERVER['REQUEST_URI'], '?');
define('BASE_ROOT', __DIR__);
if (is_file($originFile = BASE_ROOT . $requestURI)) {
    $convertor = new WebpConverter($originFile);
    $convertor->save()->flush();
}
?>

正在加载评论...