首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何优化PHP中VIPS的性能

如何优化PHP中VIPS的性能
EN

Stack Overflow用户
提问于 2019-12-02 09:33:33
回答 1查看 1.2K关注 0票数 1

我希望在缩小较大图像时,尽可能快地将以变量形式保存的图像转换为WebP格式,但不要放大较小的图像。基本系统是Debian9.9和PHP7.3。我试图测量以下技术的速度:imagejpegimagewebp、使用cwepphp-vips。我使用了以下代码:

代码语言:javascript
复制
$jpeg = function() use ($image) {
    $old_image = @imagecreatefromstring($image);
    $old_width = (int)@imagesx($old_image);
    $old_height = (int)@imagesy($old_image);
    $new_width = 1920;
    $new_width = min($old_width, $new_width);
    $ratio = $new_width / $old_width;
    $new_height = $old_height * $ratio;
    $new_image = imagecreatetruecolor($new_width, $new_height);
    imagecopyresampled($new_image, $old_image, 0, 0, 0, 0, $new_width, $new_height, $old_width, $old_height);
    ob_start();
    imagejpeg($new_image, NULL, 75);
    $image = ob_get_clean();
};
$webp = function() use ($image) {
    $old_image = @imagecreatefromstring($image);
    $old_width = (int)@imagesx($old_image);
    $old_height = (int)@imagesy($old_image);
    $new_width = 1920;
    $new_width = min($old_width, $new_width);
    $ratio = $new_width / $old_width;
    $new_height = $old_height * $ratio;
    $new_image = imagecreatetruecolor($new_width, $new_height);
    imagecopyresampled($new_image, $old_image, 0, 0, 0, 0, $new_width, $new_height, $old_width, $old_height);
    ob_start();
    imagewebp($new_image, NULL, 75);
    $image = ob_get_clean();
};
$convert = function(string $image, int $width, int $height) {
    $cmd = sprintf('cwebp -m 0 -q 75 -resize %d %d -o - -- -', $width, $height);
    $fd = [
        0 => [ 'pipe', 'r' ], // stdin is a pipe that the child will read from
        1 => [ 'pipe', 'w' ], // stdout is a pipe that the child will write to
        2 => [ 'pipe', 'w' ], // stderr is a pipe that the child will write to
    ];
    $process = proc_open($cmd, $fd, $pipes, NULL, NULL);
    if (is_resource($process)) {
        fwrite($pipes[0], $image);
        fclose($pipes[0]);
        $webp = stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        $result = proc_close($process);
        if ($result === 0 && strlen($webp)) {
            return $webp;
        }
    }
    return FALSE;
};
$cwebp = function() use ($image, $convert) {
    $old_image = @imagecreatefromstring($image);
    $old_width = (int)@imagesx($old_image);
    $old_height = (int)@imagesy($old_image);
    $new_width = 1920;
    $new_width = min($old_width, $new_width);
    $ratio = $new_width / $old_width;
    $new_height = $old_height * $ratio;
    $image = $convert($image, $new_width, $new_height);
};
$vips = function() use ($image) {
    $image = Vips\Image::newFromBuffer($image);
    $old_width = (int)$image->get('width');
    $old_height = (int)$image->get('height');
    $new_width = 1920;
    $new_width = min($old_width, $new_width);
    $ratio = $new_width / $old_width;
    // $new_height = $old_height * $ratio;
    $image = $image->resize($ratio);
    $image = $image->writeToBuffer('.webp[Q=75]');
};

我在循环中调用了$jpeg()$webp()$cwebp()$vips()十次,几秒钟内调用了运行时如下:

代码语言:javascript
复制
JPEG: 0.65100622177124
WEBP: 1.4864070415497
CWEBP: 0.52562999725342
VIPS: 1.1211001873016

因此,调用cwebp CLI工具似乎是最快的方法,这是令人惊讶的。我已经读过很多次了,vips是一个非常快的工具(大部分比imagemagick快),所以我想集中讨论vips

有人能帮我优化$vips()以获得更好的性能吗?也许writeToBuffer()resize()有一些我不知道的选项。非常重要的是,所有操作只在内存中工作,而不从磁盘读取文件或将文件存储在磁盘上。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-07 23:15:14

为了速度,不要使用resize,使用thumbnail_buffer。它将打开和调整大小结合在一个操作中,这样就可以利用诸如在加载时收缩之类的功能。你可以得到一个巨大的加速,取决于图像格式和大小。

您可以将cwebp设置与以下内容匹配:

代码语言:javascript
复制
$vips = function() use ($source_bytes) {
    $image = Vips\Image::thumbnail_buffer($source_bytes, 1920);
    $dest_bytes = $image->writeToBuffer('.webp', [
        'Q' => 75,
        'reduction-effort' => 0,
        'strip' => TRUE
    ]);
};

libvips在直接的webp压缩中似乎要慢一些。我试过:

代码语言:javascript
复制
$ time cwebp -m 0 -q 75 ~/pics/k2.jpg -o x.webp
real    0m0.102s
user    0m0.087s
sys 0m0.012s

匹配的vips命令是:

代码语言:javascript
复制
$ time vips copy ~/pics/k2.jpg x.webp[Q=75,reduction-effort=0,strip]
real    0m0.144s
user    0m0.129s
sys 0m0.024s

你可以看到它可能慢了30%。这里没有图像处理,只调用libjpeg和libwebp,所以cwebp必须使用libwebp保存优化,而libvip则不是。一年前,他们以同样的速度跑--我应该再读一遍cwebp.c,看看有什么变化。

如果您也做了一些处理,那么libvips就会变得更快。我尝试使用10,000 x 10,000像素图像并调整大小:

代码语言:javascript
复制
$ /usr/bin/time -F %M:%e cwebp -m 0 -q 75 ~/pics/wtc.jpg -resize 1920 1920 -o x.webp
618716:1.37

内存为620 of和1.4s,与之相比:

代码语言:javascript
复制
$ /usr/bin/time -f %M:%e vipsthumbnail ~/pics/wtc.jpg -s 1920 -o x.webp[Q=75,reduction-effort=0,strip]
64024:1.08

64 of内存和1.1s。

因此libvips出现得更快,需要的内存也更少,尽管在webp压缩时速度较慢,因为它可以快速调整大小。libvips也在进行更高质量的调整(自适应lanczos3),而不是cwebp的简单立方(我认为)。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59136001

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档