我希望在缩小较大图像时,尽可能快地将以变量形式保存的图像转换为WebP格式,但不要放大较小的图像。基本系统是Debian9.9和PHP7.3。我试图测量以下技术的速度:imagejpeg、imagewebp、使用cwep和php-vips。我使用了以下代码:
$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()十次,几秒钟内调用了运行时如下:
JPEG: 0.65100622177124
WEBP: 1.4864070415497
CWEBP: 0.52562999725342
VIPS: 1.1211001873016因此,调用cwebp CLI工具似乎是最快的方法,这是令人惊讶的。我已经读过很多次了,vips是一个非常快的工具(大部分比imagemagick快),所以我想集中讨论vips。
有人能帮我优化$vips()以获得更好的性能吗?也许writeToBuffer()或resize()有一些我不知道的选项。非常重要的是,所有操作只在内存中工作,而不从磁盘读取文件或将文件存储在磁盘上。
发布于 2019-12-07 23:15:14
为了速度,不要使用resize,使用thumbnail_buffer。它将打开和调整大小结合在一个操作中,这样就可以利用诸如在加载时收缩之类的功能。你可以得到一个巨大的加速,取决于图像格式和大小。
您可以将cwebp设置与以下内容匹配:
$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压缩中似乎要慢一些。我试过:
$ time cwebp -m 0 -q 75 ~/pics/k2.jpg -o x.webp
real 0m0.102s
user 0m0.087s
sys 0m0.012s匹配的vips命令是:
$ 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像素图像并调整大小:
$ /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,与之相比:
$ /usr/bin/time -f %M:%e vipsthumbnail ~/pics/wtc.jpg -s 1920 -o x.webp[Q=75,reduction-effort=0,strip]
64024:1.0864 of内存和1.1s。
因此libvips出现得更快,需要的内存也更少,尽管在webp压缩时速度较慢,因为它可以快速调整大小。libvips也在进行更高质量的调整(自适应lanczos3),而不是cwebp的简单立方(我认为)。
https://stackoverflow.com/questions/59136001
复制相似问题