使用imagewebp将jpg转换为webp

13

我有困难使用imagewebp将图像转换为webp格式。

我使用以下代码:

$filename = dirname(__FILE__) .'/example.jpg';

$im = imagecreatefromjpeg($filename);

$webp =imagewebp($im, str_replace('jpg', 'webp', $filename));
imagedestroy($im);

var_dump($webp);

$webp返回的结果为true,但是我在Chrome中尝试查看Webp图片时却只显示空白,但大小正确。如果我使用PHP加载图像并设置标头(见下文),则会显示出来,但颜色不正确(太黄了)。

$im = imagecreatefromwebp('example.webp');
header('Content-Type: image/webp');
imagewebp($im);
imagedestroy($im);

如果我使用命令行转换相同的图像,它的效果如预期。

cwebp -q 100 example.jpg -o example.webp

我正在Ubuntu 14、Apache 2.4.7和PHP 5.5.9-1ubuntu4.4上进行测试。


@StefanEdberg:我正在将webp转换为jpg。转换后,图片中出现了太多的黄色。我该如何避免这种情况?请帮忙... - Basher51
你解决过这个问题吗?我也遇到了同样的问题。 - Paul Phillips
不,自从我写下这个问题后,我还没有看过它。抱歉。 - Stefan Edberg
似乎已经/将会被修复: https://bugs.php.net/bug.php?id=66590 https://github.com/libgd/libgd/issues/176 - Stefan Edberg
在我的电脑上使用5.6.4-4ubuntu6.3可以正常工作。 - Stefan Edberg
显示剩余4条评论
4个回答

11

我使用这个

function webpConvert2($file, $compression_quality = 80)
{
    // check if file exists
    if (!file_exists($file)) {
        return false;
    }
    $file_type = exif_imagetype($file);
    //https://www.php.net/manual/en/function.exif-imagetype.php
    //exif_imagetype($file);
    // 1    IMAGETYPE_GIF
    // 2    IMAGETYPE_JPEG
    // 3    IMAGETYPE_PNG
    // 6    IMAGETYPE_BMP
    // 15   IMAGETYPE_WBMP
    // 16   IMAGETYPE_XBM
    $output_file =  $file . '.webp';
    if (file_exists($output_file)) {
        return $output_file;
    }
    if (function_exists('imagewebp')) {
        switch ($file_type) {
            case '1': //IMAGETYPE_GIF
                $image = imagecreatefromgif($file);
                break;
            case '2': //IMAGETYPE_JPEG
                $image = imagecreatefromjpeg($file);
                break;
            case '3': //IMAGETYPE_PNG
                    $image = imagecreatefrompng($file);
                    imagepalettetotruecolor($image);
                    imagealphablending($image, true);
                    imagesavealpha($image, true);
                    break;
            case '6': // IMAGETYPE_BMP
                $image = imagecreatefrombmp($file);
                break;
            case '15': //IMAGETYPE_Webp
               return false;
                break;
            case '16': //IMAGETYPE_XBM
                $image = imagecreatefromxbm($file);
                break;
            default:
                return false;
        }
        // Save the image
        $result = imagewebp($image, $output_file, $compression_quality);
        if (false === $result) {
            return false;
        }
        // Free up memory
        imagedestroy($image);
        return $output_file;
    } elseif (class_exists('Imagick')) {
        $image = new Imagick();
        $image->readImage($file);
        if ($file_type === "3") {
            $image->setImageFormat('webp');
            $image->setImageCompressionQuality($compression_quality);
            $image->setOption('webp:lossless', 'true');
        }
        $image->writeImage($output_file);
        return $output_file;
    }
    return false;
}

8

它有效:

$jpg=imagecreatefromjpeg('filename.jpg');
$w=imagesx($jpg);
$h=imagesy($jpg);
$webp=imagecreatetruecolor($w,$h);
imagecopy($webp,$jpg,0,0,0,0,$w,$h);
imagewebp($webp, 'filename.webp', 80);
imagedestroy($jpg);
imagedestroy($webp);

4
谢谢您提供的这段代码片段,它可能会提供一些有限的、即时的帮助。一个适当的解释可以大大提高它的长期价值,因为它能够展示为什么这是一个好的解决方案,并使其对未来遇到类似问题的读者更有用。请[编辑]您的答案并添加一些解释,包括您所做的假设。 - jasie
这比ob_get_contents()方法快约10%,并且输出更小,因为质量设置为80。 - Bartosh

7

我遇到了同样的问题,我的解决方案是:

$file='hnbrnocz.jpg';
$image=  imagecreatefromjpeg($file);
ob_start();
imagejpeg($image,NULL,100);
$cont=  ob_get_contents();
ob_end_clean();
imagedestroy($image);
$content =  imagecreatefromstring($cont);
imagewebp($content,'images/hnbrnocz.webp');
imagedestroy($content);

谢谢你的回复。当我用提交错误时的其中一张图片进行测试时,它对我不起作用。 - Stefan Edberg

0

这是一个易于理解的示例,使用类型声明(PHP 7.1.0+)

此函数将常见图像格式(PNGJPG/JPEGGIF)的任何文件转换为WEBP

/**
 * @param string $inputFile: relative or absolute path
 * @param string $outputFile: relative or absolute path
 * @param int $quality of output: 0 is worst, 100 is best
 * @return void
 */
function convertImageToWebp(string $inputFile, string $outputFile, int $quality = 100): void
{
    $fileType = exif_imagetype($inputFile);

    switch ($fileType) {
        case IMAGETYPE_GIF:
            $image = imagecreatefromgif($inputFile);
            imagepalettetotruecolor($image);
            imagealphablending($image, true);
            imagesavealpha($image, true);
            break;
        case IMAGETYPE_JPEG:
            $image = imagecreatefromjpeg($inputFile);
            break;
        case IMAGETYPE_PNG:
            $image = imagecreatefrompng($inputFile);
            imagepalettetotruecolor($image);
            imagealphablending($image, true);
            imagesavealpha($image, true);
            break;
        case IMAGETYPE_WEBP:
            rename($inputFile, $outputFile);
            return;
        default:
            return;
    }

    imagewebp($image, $outputFile, $quality);

    imagedestroy($image);
}

使用方法:

convertImageToWebp('image.png', 'image.webp');
convertImageToWebp('/var/www/app/assets/image.jpg', '/var/www/app/assets/image.webp');
convertImageToWebp('/home/paul/image.gif', 'image.webp', 90);

要求:(在composer.json文件中的require部分添加)

"ext-exif": "*",
"ext-gd": "*"

需要exif扩展来支持exif_imagetype函数。
其他函数需要gd扩展imagecreatefromxyzimagewebpimagedestroy

解释:

  • exif_imagetype函数从图像的元数据中读取文件类型
  • 如果$inputFile已经是
    • WEBP格式:它只是被移动到$outputFile的位置
    • PNG/JPG/JPEGGIF格式:图像会被
      1. 通过imagecreatefromxyz加载
      2. 转换并使用imagewebp函数写入$outputFile(是的,它既转换又写入)
      3. 最后通过imagedestroy销毁(图像对象,以释放内存)
    • 其他情况:直接退出
  • 如果$outputFile已经存在,它将被覆盖(renameimagewebp函数都会这样做)
  • GIFPNG需要额外的3行代码,因为它们具有特殊的特性(颜色表示,透明度)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接