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

2024-05-18 12:34:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我必须解决在图像的Exif数据中添加新标记的问题

背景

我已经为简单的图像操作创建了一个PySimpleGUI python脚本,并完成了除最后几步之外的所有步骤

该脚本显示一个图像(jpg、jepg)和一个键Exif数据。脚本使用一系列复选框从选择(列表)中快速“标记”和图像。我有一系列的复选框,图像更新正确。所以我可以正确地解码Exif数据,但是当我想要更新图像时,我遇到了问题

我将Windows10与Python3一起使用,从PIL、PySimpleGUI导入

元数据:

  • 40094(我要更新的密钥的Exif ID)
  • Exif.Image.xp关键字
  • 字节(变量类型)
  • 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收集事件。该函数扫描所选“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”

编码错误,会破坏图像。“常规图像查看器”错误输出更新的图像

如果我能解决这个问题,我就能完成脚本


Tags: 数据标记图像脚本编码img关键字复选框
1条回答
网友
1楼 · 发布于 2024-05-18 12:34:40

我弄清楚了争论的焦点。 编码是字节顺序的优先顺序

为了得到我想要的格式,我需要一个小小的endian符号。在python中utf_16_lelittle和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数据的字节顺序很小

相关问题 更多 >

    热门问题