我必须在将新标签添加到图像的Exif数据中遇到问题。
我创建了一个PySimpleGUI python脚本来进行简单的图像处理,并完成了除最后步骤以外的所有步骤。
脚本显示图像(jpg,jepg)和关键的Exif数据。该脚本使用一系列复选框来快速“标记”和图像来自选择(列表)。我有一组复选框,可以正确更新图像。因此我可以正确解码Exif数据,但是当我想更新图像时遇到问题。
[我将Windows 10与Python3配合使用,并从PIL,PySimpleGUI导入。
元数据:
我找到了一些帮助:Encode UCS2
使用上方的帮助,我可以获得此:
Exif: b'O\x00u\x00t\x00d\x00o\x00o\x00r\x00;\x00a\x00r\x00t\x00\x00\x00'
转换为Outdoor;art
<i = 40094>
img = Image.open(pathname + '\\' + filename)
exifDataRaw = img._getexif()
if exifDataRaw.get(i):
if exifDataRaw[i]:
print("Exif:", exifDataRaw[i])
return str(exifDataRaw[i].decode('utf-16'))
好,我可以将str
转换为列表并更新复选框。
我将更多关键字添加到str
。现在:Outdoor;art;box;machine;
要更新键,我具有此功能。选中的复选框为True,未选中的复选框为False。PySimpleGUI as收集事件和vales。该功能将扫描所选“ True”的值。TaggerList是我在脚本中使用的标签的主列表。当复选框为True时,循环将标签添加到InsertString
。如上所示。
def PushTags(pathname, filename):
InsertString = ""
img = Image.open(pathname + '\\' + filename)
for Tag in TaggerList[:-1]:
if values[Tag]:
InsertString = InsertString + Tag + ";"
first = False
#Get whole dataset
exifDataRaw = img._getexif()
i = 40094
# Set new data to Exif
exifDataRaw[i] = InsertString[:-1].encode('utf-16') # remove the last ";" and encode
img.save(pathname + '\\' + filename, exif=exifDataRaw) #Update image with new values
我可以使用Image.Exif.__setitem__(i, InsertString[:-1].encode('utf-16'))
仅保存更新的关键字。
但是编码仍然给出错误。
原始:Exif: b'O\x00u\x00t\x00d\x00o\x00o\x00r\x00;\x00a\x00r\x00t\x00\x00\x00'
保存的标签:b'\xff\xfeu\x00t\x00d\x00o\x00o\x00r\x00;\x00a\x00r\x00t\x00;\x00b\x00o\x00x\x00;\x00m\x00a\x00c\x00h\x00i\x00n\x00e\x00'
编码似乎不是双向的。编码后的字符串加上'\xff\xfeu
,我假设\ xfeu是大写的'O'。
编码错误,并且会损坏图像。普通图像查看器会错误地显示更新的图像。
如果可以解决此问题,则可以完成脚本。
我想出了问题所在。编码是字节顺序的先验。
要获得我想要的格式,我需要一点尾数法。在python中,utf_16_le
少,对于大字节序编解码器则为utf_16_be
。
[utf_16_le
将数据的前8位放在开头,然后将后8位放在结尾。
i = 40094
img = Image.open(pathname + '\\' + filename)
exifDataRaw = img._getexif()
if exifDataRaw.get(i):
if exifDataRaw[i]:
print("Exif:", exifDataRaw[i])
return str(exifDataRaw[i].decode('utf_16_le'))
在这段代码中,我得到了预期的结果。 b'a\x00b\x00c\x00d\x00...
因此,图像Exif数据是按低位字节序排序的。