You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用GD库转换WebP时如何保留原JPG图片的元数据?

如何在JPG转WebP并缩放时保留元数据?

服务器上存储着JPG格式图片,当浏览器请求时,如果对应的WebP图片不存在,我会对原JPG进行缩放并转换为WebP格式。目前转换流程正常,但生成的WebP图片丢失了原JPG中的作者、版权、注释等元数据。请问能不能在缩放或转换过程中把原图片的元数据添加到新的WebP图片里?

原代码如下:

$image = new Image(DIR_IMAGE . $old_image);
$image->resize($width, $height);
$image->save_webp(DIR_IMAGE . $new_image_webp, $quality);

public function resize($width = 0, $height = 0, $default = '') {
    if (!$this->info['width'] || !$this->info['height']) {
        return;
    }
    $xpos = 0;
    $ypos = 0;
    $scale = 1;

    $scale_w = $width / $this->info['width'];
    $scale_h = $height / $this->info['height'];

    if ($default == 'w') {
        $scale = $scale_w;
    } elseif ($default == 'h') {
        $scale = $scale_h;
    } else {
        $scale = min($scale_w, $scale_h);
    }

    if ($scale == 1 && $scale_h == $scale_w && $this->info['mime'] != 'image/png') {
        return;
    }

    $new_width = (int)($this->info['width'] * $scale);
    $new_height = (int)($this->info['height'] * $scale);
    $xpos = (int)(($width - $new_width) / 2);
    $ypos = (int)(($height - $new_height) / 2);

    $image_old = $this->image;
    $this->image = imagecreatetruecolor($width, $height);

    if (isset($this->info['mime']) && $this->info['mime'] == 'image/png') {
        imagealphablending($this->image, false);
        imagesavealpha($this->image, true);
        $background = imagecolorallocatealpha($this->image, 255, 255, 255, 127);
        imagecolortransparent($this->image, $background);
    } else {
        $background = imagecolorallocate($this->image, 255, 255, 255);
    }

    imagefilledrectangle($this->image, 0, 0, $width, $height, $background);

    imagecopyresampled($this->image, $image_old, $xpos, $ypos, 0, 0, $new_width, $new_height, $this->info['width'], $this->info['height']);
    imagedestroy($image_old);

    $this->info['width']  = $width;
    $this->info['height'] = $height;
}

public function save_webp($file, $quality = 40) {
    if (is_resource($this->image)) {
        imagewebp($this->image, $file, $quality);
        imagedestroy($this->image);
    }
}

问题原因

你当前使用的GD库在通过imagecreatetruecolor创建新图像资源、imagecopyresampled缩放图像的过程中,不会保留原JPG的元数据;而且GD的imagewebp函数也没有提供写入元数据的参数,所以最终生成的WebP会丢失这些信息。

可行解决方案

方案1:使用cwebp命令行工具(推荐,无需扩展)

cwebp是Google官方的WebP转换工具,支持通过参数保留元数据。步骤如下:

  1. 确保服务器已安装cwebp(大部分Linux发行版可通过包管理器安装,比如apt install webp)
  2. 修改转换逻辑,先缩放原图片到临时JPG,再用cwebp转换并保留元数据:
$oldImagePath = DIR_IMAGE . $old_image;
$newWebpPath = DIR_IMAGE . $new_image_webp;
$quality = 40;

// 先缩放原图片到临时文件
$image = new Image($oldImagePath);
$image->resize($width, $height);
$tempJpg = tempnam(sys_get_temp_dir(), 'resized_jpg_') . '.jpg';
// 假设你的Image类有save方法用于保存JPG(如果没有,可补充类似save_webp的save_jpg方法)
$image->save_jpg($tempJpg, 100);

// 用cwebp转换,-metadata all表示保留所有元数据
exec("cwebp -metadata all -q $quality $tempJpg -o $newWebpPath");

// 删除临时文件
unlink($tempJpg);

方案2:使用Imagick扩展(更简洁)

如果服务器支持Imagick扩展,处理起来更直接,Imagick默认支持保留图像元数据:

$imagick = new Imagick(DIR_IMAGE . $old_image);
// 缩放图片,使用LANCZOS滤镜保证画质
$imagick->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1);
// 设置输出格式为WebP,指定压缩质量
$imagick->setImageFormat('webp');
$imagick->setImageCompressionQuality($quality);
// 写入文件,元数据会自动保留
$imagick->writeImage(DIR_IMAGE . $new_image_webp);
$imagick->destroy();

方案3:GD库手动处理(不推荐)

GD库本身没有写入WebP元数据的API,手动解析并写入WebP的元数据区块(比如EXIF、XMP)需要深入了解WebP文件格式,开发成本极高,不建议采用。

内容的提问来源于stack exchange,提问作者bobi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 12:25:42