使用PHP imageCreateFromJpeg复制图像并保留其EXIF / IPTC数据?

时间:2012-04-16 22:59:44

标签: php gd exif iptc

我的图像中存有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. 
?>

我做错了吗?

3 个答案:

答案 0 :(得分:7)

你没有做错任何事,但GD根本不涉及IPTC数据的Exif,因为它超出了GD的范围。

您必须使用第三方库或其他PHP扩展来读取源图像中的数据,然后将其重新插入由imagejpeg创建的输出图像。

以下是一些感兴趣的图书馆:pel (php exif library),php.net上的一个示例,展示如何use pel做你想做的事,php metadata toolkitiptcembed() function

答案 1 :(得分:0)

以下是使用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');

输出图像:

Output without ICC Output with copied ICC

输入图像:

Original Image

答案 2 :(得分:0)

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

这是一个完全不同的使用不同的脚本,即 PERL 脚本 exiftool by Paul Harvey。我更喜欢这个解决方案,因为 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 服务器执行它,并确保整个脚本所在的目录具有上下文 {{ 1}} 或其他一些允许网络服务器访问的上下文。