15

我对存储有 EXIF/IPTC 数据的图像有一些问题。
当我使用imageCreateFromJpeg(旋转/裁剪等)时,新存储的文件不会保留 EXIF/IPTC 数据。

我当前的代码如下所示:

<?php
// Before executing - EXIF/IPTC data is there (checked)
$image = "/path/to/my/image.jpg";
$source = imagecreatefromjpeg($image);
$rotate = imagerotate($source,90,0);
imageJPEG($rotate,$image);
// After executing  - EXIF/IPTC data doesn't exist anymore. 
?>

难道我做错了什么?

4

3 回答 3

9

您没有做错任何事情,但是 GD 根本不处理 IPTC 数据的 Exif,因为它超出了 GD 的范围。

您必须使用 3rd 方库或其他 PHP 扩展从源图像中读取数据并将其重新插入到由imagejpeg.

以下是一些感兴趣的库:pel(php exif 库),php.net 上的一个示例,展示了如何使用 pel来做你想做的事情,php metadata toolkitiptcembed() function

于 2012-04-16T23:14:23.093 回答
8

下面是一个使用 gd 缩放图像,以及使用 PEL 复制 Exif 和 ICC 颜色配置文件的示例:

function scaleImage($inputPath, $outputPath, $scale) {
    $inputImage = imagecreatefromjpeg($inputPath);
    list($width, $height) = getimagesize($inputPath);
    $outputImage = imagecreatetruecolor($width * $scale, $height * $scale);
    imagecopyresampled($outputImage, $inputImage, 0, 0, 0, 0, $width * $scale, $height * $scale, $width, $height);
    imagejpeg($outputImage, $outputPath, 100);
}

function copyMeta($inputPath, $outputPath) {
    $inputPel = new \lsolesen\pel\PelJpeg($inputPath);
    $outputPel = new \lsolesen\pel\PelJpeg($outputPath);
    if ($exif = $inputPel->getExif()) {
        $outputPel->setExif($exif);
    }
    if ($icc = $inputPel->getIcc()) {
        $outputPel->setIcc($icc);
    }
    $outputPel->saveFile($outputPath);
}

copy('https://i.stack.imgur.com/p42W6.jpg', 'input.jpg');
scaleImage('input.jpg', 'without_icc.jpg', 0.2);
scaleImage('input.jpg', 'with_icc.jpg', 0.2);
copyMeta('input.jpg', 'with_icc.jpg');

输出图像:

无ICC输出 使用复制的 ICC 输出

输入图像:

原始图像

于 2019-06-01T19:17:26.637 回答
1

@drew010 的回答是正确的,因为没有外部库或其他程序就无法做到这一点。然而,这个答案已经很老了,现在至少有两种很好的方法。@Thiago Barcala 使用 PEL 给出了一个答案。

这是一个完全不同的使用不同的工具,即Paul Harvey 的 PERL 脚本 exiftool。我更喜欢这个解决方案,因为 exiftool 的开发和使用历史更长,文档更好,对我来说似乎更稳定可靠。PEL 更新了近 10 年,API 不稳定,有项目易手的历史,还没有达到 1.0 版本。我尝试设置它并遇到了一些障碍,但没有找到克服它们的文档,而设置 exiftool 是开箱即用的。

安装 exiftool,然后在将旧图像保存到新路径后运行:

exec('exiftool -TagsFromFile /full/path/to/original_image.jpg /full/path/to/newly_saved_image.jpg');

您必须保留这两个文件才能正常工作;如果您像原始代码一样覆盖文件,则 EXIF 数据将丢失。

确保您php.ini允许 exec() 调用;有时出于安全原因不允许这样做。此外,请注意不要在传递给该调用的任何参数中允许任何用户生成的输入,因为它可能允许攻击者在 Web 服务器的权限下执行任意命令。如果您的脚本根据某些公式生成文件名,例如只有字母数字字符,具有固定的目录路径,则 exec 调用是最安全的,然后将它们提供给 exec 调用。

如果你不想全局安装 exiftool,你可以用exiftool它的完整路径替换。如果您使用的是 SELinux,请确保在文件上为 exiftool 脚本设置上下文httpd_exec_t以允许它由 Web 服务器执行,并确保整个脚本所在的目录具有上下文httpd_sys_content_t或其他允许访问的上下文由网络服务器。

于 2021-08-11T19:20:27.310 回答