我想尽可能快地将作为字符串保存在变量中的图像转换为 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]');
};
我在一个循环中调用了 , 和 10 次,运行时在几秒钟$jpeg()
内是$webp()
:$cwebp()
$vips()
JPEG: 0.65100622177124
WEBP: 1.4864070415497
CWEBP: 0.52562999725342
VIPS: 1.1211001873016
所以调用cwebp
CLI 工具似乎是最快的方法,这令人惊讶。我已经读过很多次了,这vips
是一个非常快的工具(大部分都比 快imagemagick
),所以我想专注于vips
.
谁能帮我优化$vips()
以获得更好的性能?writeToBuffer()
也许有一些resize()
我不知道的选项。非常重要的是,所有操作都只在内存中工作,而无需从磁盘读取文件或将文件存储在磁盘上。