【问题标题】:Python Encoding: Open/Read Image File, Decode Image, RE-Encode ImagePython 编码:打开/读取图像文件、解码图像、重新编码图像
【发布时间】:2015-09-06 17:41:51
【问题描述】:

注意:我对编码/解码知之甚少,但在我遇到这个问题后,这些词现在对我来说已经完全是行话了。

问题: 我在这里有点困惑。我正在玩编码/解码图像,将图像存储为 django 模型中的TextField,环顾 Stack-Overflow,我发现我可以从ascii 解码图像(我认为还是二进制?随便open('file', 'wb')用作编码。我假设默认的ascii) 为latin1 并将其存储在数据库中没有问题。

问题来自于从latin1 解码数据创建图像。尝试写入文件句柄时,我收到 UnicodeEncodeErrorascii 编码失败。

我认为问题在于将文件作为二进制数据 (rb) 打开时,它不是正确的 asciiencoding,因为它包含二进制数据。然后我将二进制数据解码为latin1,但是当转换回ascii(尝试写入文件时自动编码)时,由于某些未知原因,它失败了。

我的猜测是,当解码为latin1 时,原始二进制数据会转换为其他内容,然后在尝试编码回ascii 时,它无法识别曾经是原始二进制数据的内容。 (尽管原始数据和解码数据具有相同的长度)。 或者问题不在于对latin1 的解码,而是我试图对二进制数据进行ascii 编码。在这种情况下,我将如何编码 latin1 数据返回到图像。

我知道这很令人困惑,但我对这一切都感到困惑,所以我无法很好地解释它。如果有人能回答这个问题,那可能是谜语大师。

一些可视化的代码:

>>> image_handle = open('test_image.jpg', 'rb')
>>> 
>>> raw_image_data = image_handle.read()
>>> latin_image_data = raw_image_data.decode('latin1')
>>> 
>>> 
>>> # The raw data can't be processed by django 
... # but in `latin1` it works
>>> 
>>> # Analysis of the data
>>> 
>>> type(raw_image_data), len(raw_image_data)
(<type 'str'>, 2383864)
>>> 
>>> type(latin_image_data), len(latin_image_data)
(<type 'unicode'>, 2383864)
>>> 
>>> len(raw_image_data) == len(latin_image_data)
True
>>> 
>>> 
>>> # How to write back to as a file?
>>> 
>>> copy_image_handle = open('new_test_image.jpg', 'wb')
>>> 
>>> copy_image_handle.write(raw_image_data)
>>> copy_image_handle.close()
>>> 
>>> 
>>> copy_image_handle = open('new_test_image.jpg', 'wb')
>>> 
>>> copy_image_handle.write(latin_image_data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
>>> 
>>> 
>>> latin_image_data.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
>>> 
>>> 
>>> latin_image_data.decode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)

【问题讨论】:

  • 我会先在维基百科上查找 jpg,然后再查找纯文本文件。图像文件不会有任何可以编码为 ascii 的纯文本数据。它们只是不同类型的数据,苹果和橘子,纯文本文件和二进制文件
  • 所以我可以从 ascii 解码图像数据,但不能返回它?这意味着这是一种单向转换?
  • 等等,当打开一个二进制文件时,它的编码是什么?我知道python默认为ascii,但这是原始数据正确吗?妈的,我过不了这个。
  • 二进制文件没有文本编码。格式可能是一个更好的术语。 jpg 中的二进制数据与任何类型的文本编码都没有关系。您可以尝试将二进制文件作为文本文件读取。 Python 将读取文件并显示 unicode 字符,但它实际上只是乱码。要打开二进制文件,您需要准备好处理文件格式的程序。 Microsoft Word 文本文档被视为二进制文件,因为它们添加了额外的格式,并且您需要专门使用 Word 打开文件。可以使用记事本等通用文本编辑器读取文本文件。
  • 啊,有道理。没有编码是完美的答案。

标签: python image encoding character-encoding


【解决方案1】:

与普通/痛苦文本文件不同,图像文件没有任何编码,显示的数据是图像的二进制等价物的视觉表示。就像@cameron-f 在上面的问题 cmets 中所说的那样,这基本上是胡言乱语,所做的任何编码都会破坏图像文件,所以不要尝试。

但这并不意味着失去所有希望。这是我通常将图像转换为字符串并返回图像的一种方式。

from base64 import b64decode, b64encode

image_handle = open('test_image.jpg', 'rb')

raw_image_data = image_handle.read()

encoded_data = b64encode(raw_image_data)
compressed_data = zlib.compress(encoded_image, 9) 

uncompressed_data = zlib.decompress(compressed_data)
decoded_data = b64decode(uncompressed_data)

new_image_handle = open('new_test_image.jpg', 'wb')

new_image_handle.write(decoded_data)
new_image_handle.close()
image_handle.close()


# Data Types && Data Size Analysis
type(raw_image_data), len(raw_image_data)
>>> (<type 'str'>, 2383864)

type(encoded_image), len(encoded_image)
>>> (<type 'str'>, 3178488)

type(compressed_data), len(compressed_data)
>>> (<type 'str'>, 2189311)

type(uncompressed_data), len(uncompressed_data)
>>> (<type 'str'>, 3178488)

type(decode_data), len(decode_data)
>>> (<type 'str'>, 2383864)



# Showing that the conversions were successful
decode_data == raw_image_data
>>> True

encoded_data == uncompressed_data
>>> True

【讨论】:

    【解决方案2】:

    弹出 UnicodeEncodeError 是因为 jpeg 是二进制文件,而 ASCII 编码适用于纯文本文件中的纯文本。

    可以使用通用文本编辑器创建纯文本文件,例如 Windows 的记事本或 Linux 的 nano。大多数将使用 ASCII 或 Unicode 编码。当文本编辑器读取 ASCII 文件时,它会抓取一个字节,比如 01100001(十进制为 97),并找到相应的字形“a”。

    因此,当文本编辑器尝试读取 jpg 时,它会抓取相同的字节 01100001 并获得“a”,但由于文件包含用于显示照片的信息,因此文本将只是乱码。尝试在记事本或 nano 中打开 jpeg。

    至于编码这里有一个解释:What is the difference between encode/decode?

    【讨论】:

    • 感谢您发布答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多