php 对 WEBP 图像元数据的支持

Posted

技术标签:

【中文标题】php 对 WEBP 图像元数据的支持【英文标题】:php support for WEBP image metadata 【发布时间】:2022-01-03 01:08:53 【问题描述】:

php是否支持webp图片元数据?

具体来说,我希望能够在 php 代码中本地读取和写入 webp 图像的 XMP 和 EXIF 元数据。

我一直在试验下面的代码,它给了我一个“文件不支持”的警告。

<?php

$photoSourceThumbnail = "publicAssets/images/att_galleryWebP/A0001_LSF-PHOTOS-WM-TM-WEBP/A0001-EWF-LSF-01.webp";
$photoSourceFull = "assets/images/att_galleryWebP/A0001_LSF-PHOTOS-WM-FULL-WEBP/A0001-EWF-LSF-01.webp";

echo "$photoSourceFull:<br />\n";
$exif = exif_read_data($photoSourceFull, 'IFD0');
echo $exif===false ? "No header data found.<br />\n" : "Image contains headers<br />\n";

$exif = exif_read_data($photoSourceFull, 0, true);
echo "test2.jpg:<br />\n";
foreach ($exif as $key => $section) 
    foreach ($section as $name => $val) 
        echo "$key.$name: $val<br />\n";
    
 

【问题讨论】:

到目前为止,我的网站有 6000 张图片,我使用此在线工具将这些图片从 jpg 转换为 webp。 nsspot.herokuapp.com/imagetowebp. 有 6000 张图片,我希望您对您的 Q 的答案更感兴趣... 【参考方案1】:

最好使用 ExifTool。

安装 ExifTool

https://exiftool.org/

PHP 示例

class ExifToolException extends RuntimeException

function getInfo(string $file) : object 

    $info = shell_exec('exiftool -json ' . escapeshellarg($file) . ' 2>&1');
    if(strpos($info, 'Error:') > -1) 
        throw new ExifToolException(rtrim($info, PHP_EOL));
    
    return json_decode($info)[0];


try 
    var_dump(getInfo('abc.webp')->Megapixels);
 catch(ExifToolException $e) 
    var_dump($e->getMessage());

更新:ExifTool 不支持编写 webp

相反,您可以查看 Google 的 webpmux: https://developers.google.com/speed/webp/docs/webpmux

【讨论】:

感谢有关 webpmux 的反馈。 @Douma 你有关于如何使用 webpmux 的例子吗?我觉得他们的例子太模糊了。【参考方案2】:

WebP supports both Exif and XMP 已经好几年了。该格式基于RIFF 并至少承认EXIFXMP ICCP 的块。好的软件也会读取IPTC 块。

仅仅因为一些随机软件不考虑携带元数据并不意味着目标格式不支持它 - 大多数软件都比较草率而不是雄心勃勃。由于 RIFFormat 相当简单,因此修改现有文件以包含更多块应该很容易:

每个块包含 4 个字节的标识符/FourCC(即 ASCII 字符 EXIF),然后是其大小的 4 个字节的小Endian,然后是有效负载。 The file's first chunk is similar:它以 4 个字节 RIFF 开头,然后是整个文件大小的 4 个字节减去 8,然后是 4 个字节的内容标识,这里是 WEBP(为了与其他也使用 RIFF 的格式区分开来,例如 WAV, AVI、Maya、AIF、MIDI...)。 这意味着您将新块附加到文件末尾,然后使用新文件大小修补文件的字节 5 到 8。示例:
$sExif= '...the binary data...';  // You read that off the other file, of course
$iLenExif= strlen( $sExif );  // Payload length in bytes
if( $iLenExif% 2== 1 ) $sExif.= "\0";  // RIFF needs 16bit alignment

$hFile= fopen( 'TARGET.WEBP', 'r+' );   // Read and write access
fseek( $hFile, 0, SEEK_END );  // Go to end of file

fwrite( $hFile, 'EXIF' );  // 4 bytes chunk ID
fwrite( $hFile, pack( 'V', $iLenExif ) );  // 4 bytes of payload length
fwrite( $hFile, $sExif );  // Actual data

$iFilesize= ftell( $hFile );  // Should be bigger
fseek( $hFile, 4, SEEK_SET );  // Go to 5th byte of file
fwrite( $hFile, pack( 'V', $iFilesize- 8 ) );  // Write 4 bytes, patching old filesize

fclose( $hFile );  // Store everything.

【讨论】:

【参考方案3】:

Google 最近更改了网站的图片要求,称它们应包含 IPTC 图片版权元数据。

https://developers.google.com/search/docs/advanced/appearance/image-rights-metadata

我已经成功地能够使用 EXIFTOOL 为我的 SQL 表中的 jpg 图像更新图像 XMP、EXIF 和 IPTC 元数据,以满足这些新的 google 要求。 我在 IPTC 工具上检查了测试图像,它确实包含所需的 XMP、EXIF 和 IPTC 元数据。

https://getpmd.iptc.org/getiptcpmd.html

然而…………

大量读取WEBP格式和exiv2、dwebp、webpmux等工具,只能将XMP和EXIF元数据写入webp图片。

https://www.exiv2.org/manpage.html
https://developers.google.com/speed/webp/docs/cwebp
https://developers.google.com/speed/webp/docs/webpmux
https://image.online-convert.com/convert-to-webp (drag and drop web tool that converts Jpg to webp with XMP & Exif metadata)

似乎 webp 不支持 IPTC 元数据,因此不满足这些要求:

https://developers.google.com/search/docs/advanced/appearance/image-rights-metadata

结论:

    Webp 作为我希望 google 索引的图像的图像格式,是一个死鸭子,除非/直到 google 修改 RIFF 标头以包含 IPTC。 接下来的步骤是将我网站上的图片恢复为 jpg。

对于任何对我如何从 php 修改图像 XMP、EXIF 和 IPTC 元数据感兴趣的人。

a) 这些是我最终决定使用 exiftool 命令更新它们的元数据字段。

exiftool -iptc:by-line="image creator" A0000-01.jpg
exiftool -xmp:creator="image creator" A0000-01.jpg
exiftool -exif:Artist="image creator" A0000-01.jpg

exiftool -iptc:CopyrightNotice="Copywrite 2022 websiteName.com" A0000-01.jpg
exiftool -xmp:rights="Copywrite 2022 websiteName.com" A0000-01.jpg
exiftool -exif:Copyright="Copywrite 2022 websiteName.com" A0000-01.jpg

exiftool -iptc:keywords="keyword1,keyword2,keyword3" A0000-01.jpg
exiftool -xmp:Subject="keyword1,keyword2,keyword3" A0000-01.jpg
exiftool -exif:UserComment="keyword1,keyword2,keyword3" A0000-01.jpg

exiftool -iptc:credit="image reproduced with permission from" A0000-01.jpg
exiftool -xmp:credit="image reproduced with permission from" A0000-01.jpg

exiftool -iptc:ObjectName="Image title" A0000-01.jpg
exiftool -xmp:Title="Image title" A0000-01.jpg

exiftool -iptc:Caption-Abstract="Image description" A0000-01.jpg
exiftool -xmp:description="Image description" A0000-01.jpg
exiftool -exif:ImageDescription="Image description" A0000-01.jpg

exiftool -iptc:Source="Url where image can be found" A0000-01.jpg
exiftool -xmp:Source="Url where image can be found" A0000-01.jpg

exiftool -exif:gpslatitude="44.081102" -exif:gpslatituderef=N A0000-01.jpg
exiftool -exif:gpslongitude="-35.489600" -exif:gpslongituderef=W A0000-01.jpg
exiftool -xmp:gpslatitude="44.081102 N" A0000-01.jpg
exiftool -gpslongitude="-35.489600 E" A0000-01.jpg

exiftool -xmp:AuthorsPosition="website owner & coder" A0000-01.jpg
exiftool -iptc:By-lineTitle="website owner & coder" A0000-01.jpg

exiftool -xmp:CaptionWriter="websiteName.com.com" A0000-01.jpg
exiftool -iptc:Writer-Editor="websiteName.com.com" A0000-01.jpg

b) 在 php 中,我使用以下代码生成包含 exiftool 命令的文本字符串:

$F_XmpDescriptionSt = 'exiftool -xmp:description="'.$iptcDescription.'" "'.$absoluteImgJpgFullSizePath.'"';

其中 $iptcDescription 和 $absoluteImgJpgFullSizePath 是 mysql 表中所需的元数据值

c) 然后我通过命令提示符终端使用以下代码启动命令:

$FullsizeExiftoolXmpDescriptionExecute = exec("$F_XmpDescriptionSt");

我对要更新的所有元数据字段重复上述操作,将 php 代码调整为 exiftool 命令。

我确信有一种更优雅的方式来执行此操作,例如批处理脚本?但我更喜欢将每个 exiftool 命令作为一行代码一个接一个地启动,以便为我更新的每个元数据字段获得响应消息“1 个文件已更新”。完成所有元数据字段的代码大约需要 15 秒,所以问题不大。

这行代码输出包含在变量 FullsizeExiftoolXmpDescriptionExecute 中的 exiftool 响应。

<h4>Fullsize XMP Description $FullsizeExiftoolXmpDescriptionExecute to $iptcDescription</h4>

本视频教程介绍了如何在 Windows 10 上安装 exiftool。 https://www.youtube.com/watch?v=Ku1Nx-kl7RM

【讨论】:

根据您的第一个链接,在撰写本文时,Google 建议添加 IPTC 字段,而不是他们需要它......或者我可能只是遗漏了什么? 您忽略了我的回答,甚至偶然指出了 IPTC。但是,使这个答案变得一团糟的原因是您的问题从未提及 IPTC,而 IPTC 现在对您来说是强制性的。最重要的是这里没有 PHP - 它只是启动外部程序。 你好,盖莉安。图像元数据的主题非常模糊,尤其是在谷歌开发者支持方面。我最终使用的解决方案是以 XMP 格式添加 IPTC 标签,并在可能的情况下使用 exiftool 添加 EXIF 格式,然后使用 cwebp 将图像转换为 webp。 WebP 本身不支持 IPTC 标签,我也没有找到任何可以生成 IPTC 标签的工具。我已经向 cwebp 开发团队询问了未来 IPTC 标签的支持。我绝不会将此作为正确的解决方案,而是作为我用于其他任何人阅读图像元标记的方法。 AmigoJack 感谢您的意见,我没有忽略,但已将其包含在我对图像元数据的整体研究中。问题是关于 PHP 对 webp 图像元数据的支持 PHP 无法使用现有的内置函数原生地读取或写入 webp 的图像元数据。 PHP 对 XMP 和 EXIF 具有只读支持,对 IPTC 具有读写能力。由于 php 中对图像元数据的支持有限,我觉得包含使用外部程序是相关的。 @ElliottFarmer 您已转换的文件中的元数据是否仍可在 webp 文件中使用?它也被转换了吗?

以上是关于php 对 WEBP 图像元数据的支持的主要内容,如果未能解决你的问题,请参考以下文章

php WordPress:返回图像的元数据

StorageFile.GetScaledImageAsThumbnailAsync 不支持元数据旋转图像

PHP:读取字体文件的 TrueType/OpenType 元数据

PNG 是不是支持元数据字段,如作者、相机模型等?

如何转换数据:image / webp,expo(或php)中的base64

Exif.js 读取图像的元数据