PHP读取图片EXIF/IPTC元数据出现乱码问题排查与解决
读取图片EXIF和IPTC元数据时出现乱码的原因及解决方法
问题背景
我尝试读取图片的EXIF和IPTC元数据,但部分内容显示为一串?乱码,怀疑是编码问题但不确定。
复现代码
<?php $path = 'no_exif.jpg'; $exif = @exif_read_data($path, '', true); var_dump($exif); getimagesize($path, $image_info); foreach($image_info as $k => $v) { var_dump($k); if ($k === 'APP13') { var_dump(iptcparse($v)); } else { var_dump ($v); } }
测试情况
测试图片包含XPTitle等标签,在线元数据解析工具可正常读取,但本地PHP代码输出乱码。我曾尝试用自动检测编码转UTF-8,但没有效果:
array_walk_recursive($entries, function (&$entry) { $source_encoding = mb_detect_encoding($entry); $source_encoding = ($source_encoding) ? ($source_encoding) : 'ISO-8859-1'; $entry = mb_convert_encoding($entry, 'UTF-8', $source_encoding); });
乱码原因
- XP系列标签的特殊编码:微软定义的
XPTitle、XPComment等EXIF标签,使用UTF-16LE编码存储,但PHP的exif_read_data默认按单字节编码(如ISO-8859-1)读取,直接输出就会显示为乱码或问号。 - 自动编码检测失效:
mb_detect_encoding无法准确识别UTF-16LE的字节特征,导致转码时用错源编码,无法修复乱码。 - IPTC元数据的编码默认值:IPTC数据通常采用ISO-8859-1编码,若按其他编码读取也会出现乱码。
解决方法
1. 修复XP系列标签的编码
直接指定源编码为UTF-16LE转码,同时处理可能存在的BOM:
function fixExifXPTags($exifData) { // 定义需要修复的XP标签列表 $xpTagNames = ['XPTitle', 'XPComment', 'XPAuthor', 'XPKeywords', 'XPSubject']; foreach ($xpTagNames as $tag) { if (isset($exifData['IFD0'][$tag])) { $rawValue = $exifData['IFD0'][$tag]; // 移除UTF-16的BOM(LE或BE) $rawValue = preg_replace('/^\xFE\xFF|\xFF\xFE/', '', $rawValue); // 转码为UTF-8 $exifData['IFD0'][$tag] = mb_convert_encoding($rawValue, 'UTF-8', 'UTF-16LE'); } } return $exifData; } // 使用示例 $path = 'no_exif.jpg'; $exif = @exif_read_data($path, '', true); $fixedExif = fixExifXPTags($exif); var_dump($fixedExif);
2. 处理IPTC元数据编码
IPTC数据默认用ISO-8859-1编码,直接指定转码:
getimagesize($path, $image_info); foreach($image_info as $k => $v) { if ($k === 'APP13') { $iptcData = iptcparse($v); // 递归转码所有IPTC内容 array_walk_recursive($iptcData, function (&$entry) { $entry = mb_convert_encoding($entry, 'UTF-8', 'ISO-8859-1'); }); var_dump($iptcData); } else { var_dump($v); } }
3. 环境检查
确保PHP的mbstring扩展已启用,这是转码函数正常工作的前提。
内容的提问来源于stack exchange,提问作者StackOverflowNewbie
相关产品推荐
相关产品推荐

