为什么更新图像后,Exif标记的编码失败

问题描述 投票:0回答:1

我必须在将新标签添加到图像的Exif数据中遇到问题。

设置

我创建了一个PySimpleGUI python脚本来进行简单的图像处理,并完成了除最后步骤以外的所有步骤。

脚本显示图像(jpg,jepg)和关键的Exif数据。该脚本使用一系列复选框来快速“标记”和图像来自选择(列表)。我有一组复选框,可以正确更新图像。因此我可以正确解码Exif数据,但是当我想更新图像时遇到问题。

[我将Windows 10与Python3配合使用,并从PIL,PySimpleGUI导入。

元数据:

  • 40094(我要更新的密钥的Exif ID)
  • Exif.Image.XPKeywords
  • 字节(变量类型)
  • Windows使用的关键字标签(以UCS2编码)

我找到了一些帮助: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 python-imaging-library exif pysimplegui
1个回答
0
投票

我想出了问题所在。编码是字节顺序的先验。

要获得我想要的格式,我需要一点尾数法。在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数据是按低位字节序排序的。

© www.soinside.com 2019 - 2024. All rights reserved.