【问题标题】:convert image to byte literal in python在python中将图像转换为字节文字
【发布时间】:2015-06-13 00:17:27
【问题描述】:

我正在尝试将图像存储为文本,以便我可以为 Tk gui 执行此示例的透明图标示例:

import tempfile

# byte literal code for a transparent icon, I think
ICON = (b'\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x08\x00h\x05\x00\x00'
        b'\x16\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\x00\x01\x00'
        b'\x08\x00\x00\x00\x00\x00@\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
        b'\x00\x01\x00\x00\x00\x01') + b'\x00'*1282 + b'\xff'*64

# makes a temp file for the transparent icon and saves it
_, ICON_PATH = tempfile.mkstemp()
with open(ICON_PATH, 'wb') as icon_file:
    icon_file.write(ICON)

我已经尝试过 base 64 编码,使用 utf8 解码,转换为字节和字节数组,以及来自另一篇帖子的一些答案:(Python Script to convert Image into Byte array)

import tempfile, base64, io

# byte literal code for a transparent icon, I think
ICON = (b'\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x08\x00h\x05\x00\x00'
        b'\x16\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\x00\x01\x00'
        b'\x08\x00\x00\x00\x00\x00@\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
        b'\x00\x01\x00\x00\x00\x01') + b'\x00'*1282 + b'\xff'*64

# makes a temp file for the transparent icon and saves it
_, ICON_PATH = tempfile.mkstemp()
with open(ICON_PATH, 'wb') as icon_file:
    icon_file.write(ICON)

a = open(ICON_PATH, 'rb').read()

b = base64.b64encode(a)

print b # output does not match what ICON equals above

# doesn't work; gives error
# UnicodeDecodeError: 'utf8' codec can't decode byte 0xff in position 1342: invalid start byte
# b = bytes(a).decode('utf-8') 

c = bytearray(a)

print c # prints garbled junk


# gives error AttributeError: __exit__ on Image.open(ICON_PATH) line
with io.BytesIO() as output:
    from PIL import Image
    with Image.open(ICON_PATH) as img:
        img.convert('RGB').save(output, 'BMP')                
    data = output.getvalue()[14:]

print data

它也不适用于 b.decode('utf-8') 或 b.encode('utf-8')

【问题讨论】:

标签: python


【解决方案1】:

我想你正在寻找

print(repr(a))

对于代码中定义的a,这将打印b'\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x08\x00h\x05\x00\x00\x16\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\x00\x01\x00\x08 等等,类似于您原来的ICON 定义,但非常大,因为所有\x00s 和\xffs 都在末尾都写出来了。


在您的代码中,您包含了一些临时压缩(即+ b'\x00'*1282 + b'\xff'*64)。要自动获得压缩,因此源文件中的ICON 定义不必那么大,请利用现有的压缩库,例如 zlib:

import zlib
print(repr(zlib.compress(a)))

在我的机器上,这会打印出'x\x9cc``\x04B\x01\x01\x06 \xc9\xc1\x90\xc1\xca\xc0 \xc6\xc0\xc0\xa0\x01\xc4@!\x06\x05\x06\x888\x088\xb02 \x00#\x14\x8f\x82Q0\nF\xc1\x08\x05\xff)\x04\x00U\xf1A\x17',它非常小。解压使用zlib.decompress:

import zlib

ICON = zlib.decompress(b'x\x9cc``\x04B\x01\x01\x06 \xc9\xc1\x90\xc1\xca\xc0 '
    b'\xc6\xc0\xc0\xa0\x01\xc4@!\x06\x05\x06\x888\x088\xb02 \x00#\x14\x8f\x82'
    b'Q0\nF\xc1\x08\x05\xff)\x04\x00U\xf1A\x17')

ICON 现在与原始示例中的值相同。


如果您现在想要在源文件中更紧凑的表示,是时候应用 base 64 编码了,它摆脱了 python 中冗长的二进制编码(\x..-格式)。

编码:

import base64, zlib

print(repr(base64.b64encode(zlib.compress(a))))

这给了我'eJxjYGAEQgEBBiDJwZDBysAgxsDAoAHEQCEGBQaIOAg4sDIgACMUj4JRMApGwQgF/ykEAFXxQRc='

解码:

import base64, zlib

ICON = zlib.decompress(base64.b64decode('eJxjYGAEQgEBBiDJwZDBy'
    'sAgxsDAoAHEQCEGBQaIOAg4sDIgACMUj4JRMApGwQgF/ykEAFXxQRc='))

同样,ICON 的值与最初指定的值相同。


呈现的最终策略适用于ico 文件。我看到您还提到了png 文件。这些已经应用了压缩,所以你可能更喜欢只使用 base 64 编码:

import base64

print(base64.b64encode(png_icon))

PNG_ICON = base64.b64decode( ** insert literal here ** )

事实证明,这些编码也可通过str.encodestr.decode API 获得。这让您无需编写imports 就可以离开。为了完整起见,它们是:

编码:

print(repr(a.encode('zlib').encode('base64')))

解码:

ICON = ('eJxjYGAEQgEBBiDJwZDBysAgxsDAoAHEQCEGBQaIOAg4sDIgACMUj4J'
    'RMApGwQgF/ykEAFXxQRc=').decode('base64').decode('zlib')

【讨论】:

    【解决方案2】:

    我认为你只是没有正确打印出数据——似乎没有必要在 base64 这样做。

    这是证据:

    from itertools import izip
    import tempfile
    
    # byte literal code for a transparent icon, I think
    ICON = (b'\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x08\x00h\x05\x00\x00'
            b'\x16\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\x00\x01\x00'
            b'\x08\x00\x00\x00\x00\x00@\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
            b'\x00\x01\x00\x00\x00\x01') + b'\x00'*1282 + b'\xff'*64
    
    # make a temp file from ICON data for testing
    _, ICON_PATH = tempfile.mkstemp()
    with open(ICON_PATH, 'wb') as icon_file:
        icon_file.write(ICON)
    
    # Convert raw data in the file into a valid Python string literal.
    
    # helper function
    def grouper(n, seq):
        "s -> (s0,s1,...sn-1), (sn,sn+1,...s2n-1), (s2n,s2n+1,...s3n-1), ..."
        for i in xrange(0, len(seq), n):
            yield seq[i:i+n]
    
    # read data file in binary mode
    a = open(ICON_PATH, 'rb').read()
    
    # create Python code to define string literal
    code = '\n'.join(['ICON2 = ('] +
                     ['    '+repr(group) for group in grouper(16, a)] +
                     [')'])
    
    print 'len(ICON): {}'.format(len(ICON))
    print 'len(a): {}'.format(len(a))
    print code
    exec(code)
    print
    print 'len(ICON2): {}'.format(len(ICON2))
    print 'ICON2 == ICON: {}'.format(ICON2 == ICON)
    

    输出:

    len(ICON): 1406
    len(a): 1406
    ICON2 = (
        '\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x08\x00h\x05'
        '\x00\x00\x16\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00'
        '\x00\x00\x01\x00\x08\x00\x00\x00\x00\x00@\x05\x00\x00\x00\x00'
        '\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00'
        '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
           ...
        '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
        '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
        '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff'
        '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
        '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
        '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
        '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
    )
    
    len(ICON2): 1406
    ICON2 == ICON: True
    

    【讨论】:

      【解决方案3】:

      我确实知道你可以这样做:

      import tempfile, base64, io
      
      # byte literal code for a transparent icon, I think
      ICON = (b'\x00\x00\x01\x00\x01\x00\x10\x10\x00\x00\x01\x00\x08\x00h\x05\x00\x00'
              b'\x16\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\x00\x01\x00'
              b'\x08\x00\x00\x00\x00\x00@\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
              b'\x00\x01\x00\x00\x00\x01') + b'\x00'*1282 + b'\xff'*64
      
      # makes a temp file for the transparent icon and saves it
      _, ICON_PATH = tempfile.mkstemp()
      with open(ICON_PATH, 'wb') as icon_file:
          icon_file.write(ICON)
      
      with open(ICON_PATH, 'rb') as imgFile:
          a = imgFile.read()
      
      b = base64.b64encode(a)
      
      print b # output does not match what ICON equals above
      
      with open('test.png','wb') as writeFile:
          writeFile.write(b.decode('base64'))
      

      但我仍然想知道如何获得与顶部的 'ICON = (...' 相同的格式

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-30
        • 1970-01-01
        • 2013-07-31
        • 2011-11-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多