Ubuntu 20.04环境下Python 3.8搭配PIL 7.0.0写入JPG文件EXIF数据时出现数据错位问题的求助
问题分析与解决方案
先给你吃个定心丸:这真不是你的操作错误,而是Pillow 7.0.0版本中存在的已知EXIF写入bug,不少用户都反馈过类似的EXIF字符串错位、填充错误问题。根源在于旧版本的TiffImagePlugin.py处理EXIF字符串时的字节对齐逻辑有缺陷,导致写入时字符串内容被错误截断或拼接,才出现了你看到的标签内容“串位”情况。
解决方法
1. 优先升级Pillow版本
这个bug在Pillow 8.0.0及以后的版本中已经被官方修复,最简单直接的解决方式就是升级你的Pillow库:
# 如果你用的是系统自带的Python,建议加--user避免权限冲突 pip install --upgrade pillow --user # 要是用了虚拟环境,直接运行下面这句就行 pip install --upgrade pillow
升级完成后再跑你的测试代码,EXIF数据写入就会恢复正常,不会再出现内容错位的问题。
2. 临时替代方案(无法升级时)
如果因为环境限制没法升级Pillow,可以换用piexif库来处理EXIF数据,它的EXIF读写逻辑更稳定可靠。我把你的代码修改成用piexif实现的版本,你可以直接参考:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import PIL.Image import piexif def fingerExifAndSave(source,target): im=PIL.Image.open(source) # 用piexif读取EXIF数据为字典格式 exif_dict = piexif.load(im.info["exif"]) if False : # 改成True可以测试修改标签 print("Change tag 306 (DateTime) to something wired for debugging") # DateTime在EXIF的0th组中,用piexif的常量来定位标签 exif_dict["0th"][piexif.ImageIFD.DateTime] = '2066:55:44 33:22:11' print(" Tag 306 is now set to :",exif_dict["0th"][piexif.ImageIFD.DateTime] ) else: print("NO MODIFICATION TO TAG 306 ('DateTime')!") # 修复282/283标签的问题(如果需要) if False : # 改成True启用修复 print("Repairing something for some unknown reason due to warning") for tag in (piexif.ImageIFD.XResolution, piexif.ImageIFD.YResolution): if isinstance(exif_dict["0th"][tag], tuple): exif_dict["0th"][tag] = exif_dict["0th"][tag][0] else: print("NO REAPIRING TO TAGS (282,283)!") # 将EXIF字典转为字节流,供保存时使用 exif_bytes = piexif.dump(exif_dict) rc=im.save(target, exif=exif_bytes) print("Image written to:",target," with rc =",rc ) im.close() def showSomeExifTags(myfile): showThisTags=[306,36867,36868,305] # 要展示的标签编号 im=PIL.Image.open(myfile) # 读取EXIF,没有的话用空字节流 exif_dict = piexif.load(im.info.get("exif", b"")) print("\nSome EXIF-tags from '"+myfile+"' (among other):") print("KeyNr : KeyName"+" "*21+": Value") # 遍历0th和Exif两个组的标签 for ifd_name in ["0th", "Exif"]: for k,v in exif_dict[ifd_name].items(): if k in showThisTags: # 获取标签名称 if ifd_name == "0th": tag_name = piexif.ImageIFD.get(k, str(k)) else: tag_name = piexif.ExifIFD.get(k, str(k)) if len(str(v)) > 30 : v=str(v[0:20])+"..." # 过长内容截断显示 print(f"{k:>5} : {tag_name:27} : {v}") im.close() print() def main(): source="./orig2.jpg" # 源图片路径 target="./modified.jpg" # 目标图片路径 print ("PIL.Image.__version__ in use:",PIL.Image.__version__) print ("piexif version in use:", piexif.VERSION) showSomeExifTags(source) fingerExifAndSave(source,target) showSomeExifTags(target) if __name__ == "__main__": main()
使用前需要先安装piexif:
pip install piexif --user
验证
不管是升级Pillow还是用piexif替代,重新运行代码后,新文件里的EXIF标签都会和原始内容完全一致,不会再出现内容错位的情况。
内容的提问来源于stack exchange,提问作者Feiler
相关产品推荐
相关产品推荐

