我想将以字符串形式保存在变量中的图像尽快转换为WebP格式,同时缩小较大的图像,但不放大较小的图像。基本系统是带有PHP 7.3的Debian 9.9。我尝试使用以下技术来测量速度: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()
有一些我不知道的选项。非常重要的是,所有操作都只能在内存中工作,而不要从磁盘读取文件或将文件存储在磁盘上。
正如@ADyson所说,最好在libvips跟踪器上询问:https://github.com/libvips/libvips/issues
对于速度,请不要使用resize
,请使用thumbnail_buffer
。它在单个操作中结合了打开和调整大小,因此可以利用诸如负载收缩之类的优势。根据图像的格式和大小,可以大大提高速度。
我还将检查您是否正在使用libjpeg-turbo。它比标准IJG libjpeg快3或4倍。
比较速度时,请记住调整大小。 php-vips默认使用lanczos3,这是一种非常高质量的调整大小。 cwebp使用的是更简单的方法。
检查输出文件的大小。在webp压缩过程中,您可以旋转许多旋钮,并且编码器可能未使用相同的设置。尤其要检查reduction-effort
和无损/有损模式。
尝试(未试用):
$vips = function() use ($image) {
$image = Vips\Image::thumbnail_buffer($image, 1920);
$image = $image->writeToBuffer('.webp[Q=75]');
};