如何在不损失图像质量的情况下从JPG中删除exif?

2022-08-30 19:11:30

我有一个PHP照片共享应用程序,其中用户上传的图像使用ImageMagick调整为各种拇指格式。

作为节省文件大小的看似“智能”的方式,我正在从这些拇指中剥离exif信息,如下所示:

$imagick = new Imagick($image);
$imagick->stripImage();
$imagick->writeImage($image);

这有效。它确实删除了EXIF信息,其中30KB的拇指保存12KB并成为18KB。在单个页面上显示许多这样的拇指时,可以节省大量成本。

然而,问题是它工作得有点太好了。与未剥离的版本相比,生成的图像似乎丢失了很多颜色信息,并且看起来“平坦”。

根据我迄今为止的研究,我的理论是以下一个或两个都是正确的:

  • Imagick在剥离过程中丢弃了重要的颜色配置文件信息
  • Imagick 在保存图像时重新压缩图像,从而失去质量

无论问题的原因是什么,我都在寻找一种方法来删除EXIF信息,使其不会影响图像质量或颜色本身。

这有可能吗?

更新:

根据Gerald Schneider的回答,我尝试在“剥离”图像之前将质量设置强制为100%:

$imagick = new Imagick($image);
$imagick->setCompression(imagick::COMPRESSION_JPEG);
$imagick->setCompressionQuality(100);
$imagick->stripImage();
$imagick->writeImage($image);

不幸的是,问题依然存在。以下是示例输出,尽管将质量设置为100%,但图像仍然会展平。

enter image description here


答案 1

考虑保留 ICC 配置文件(这会导致颜色更丰富),同时删除所有其他 EXIF 数据:

  1. 提取 ICC 配置文件
  2. 剥离 EXIF 数据和图像配置文件
  3. 重新添加 ICC 配置文件

在 PHP + imagick 中:

$profiles = $img->getImageProfiles("icc", true);

$img->stripImage();

if(!empty($profiles))
    $img->profileImage("icc", $profiles['icc']);

(重要提示:使用ImageMagick 3.1.0测试版,我得到的结果与文档略有不同。我建议你尝试一下参数,直到你得到一个与实际配置文件的关联数组。getImageProfiles()

对于命令行 ImageMagick:

convert image.jpg profile.icm
convert image.jpg -strip -profile profile.icm output.jpg

当然,如果您使用ImageMagick,图像会被重新压缩,但至少颜色保持不变。

希望这有帮助。


答案 2

在对错误存储的文件头中的MIME类型进行了类似的更改之后,我建议您通过标准工具验证EXIF数据的长度,然后使用多字节字符串函数手动“归零”数据。

EXIF在JPEG文件中最多只能是64KB,但是如果它非常64KB,我就不肯定了,所以我会从这里开始。


推荐