Python Pillow Image.frombytes模式'1'结果不好

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

我哪里错了?我想从字节创建一个基本的白色图片

from PIL import Image

if __name__ == "__main__":
    data = [chr(1)] * 8192
    data = "".join(data)
    im = Image.frombytes('1', (128,64), data, 'raw')
    im = im.convert("RGB")
    im.save("image.png", "PNG")

但我明白了:

python image
2个回答
0
投票

在模式1中,每个字节代表8个像素(如果宽度不除以8,则每行末尾可能有零填充)。因此,要获得白色图像,您必须仅传入字节b'\xff'

data = b'\xff' * 1024
im = Image.frombytes('1', (128,64), data)

即使Pillow文档说这个模式中每个字节有一个像素,至少对于frombytestobytes方法来说也是如此。

除了\xff(全白)或\x00(全黑)之外的任何其他重复输入都会给出某种细条纹图案,就像你问题中那样。


3
投票

只需使用Image.new代替:

im = Image.new(mode='RGB', size=(128,64), color=(255,255,255))

如果你真的想从字节中创建它,它将是这样的:

Image.frombytes(mode='RGB', size=(128,64), data=b'\xff'*128*64*3)

编辑:Image.frombytes需要字节,而不是整数列表。要将整数列表转换为正确的类型,请使用以下命令:

>>> bytes([0,1,2])  # Python 3
b'\x00\x01\x02'

>>> bytes(bytearray([0,1,2]))  # Python 2
'\x00\x01\x02'

编辑2:mode ='1'或文档有bug(参见注释线程)。假设你有一个0和1的列表,1024个元素长,并且你想将它转换为128x64单色图像(每像素一位),那么你将不得不手动打包字节:

bits = [int(not (y%13 and x%7)) for x in range(64) for y in range(128)]  
# asymmetric grid
octets = [bits[i:i+8] for i in range(0, len(bits), 8)]

def bits2byte(bits8):
    result = 0
    for bit in bits8:
        result <<= 1
        result |= bit
    return result

data = bytes(bytearray([bits2byte(octet) for octet in octets]))
im = Image.frombytes(mode='1', size=(128,64), data=data)
im.show()

结果:

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