【问题标题】:Create image from RGB list with Pillow and Python 3使用 Pillow 和 Python 3 从 RGB 列表创建图像
【发布时间】:2018-06-25 01:45:07
【问题描述】:

我有一个 RGB 数据列表:

cdata=[R1, G1, B1, R2, G2, B2,..., Rn, Gn, Bn]

每个值都包含在 0 到 255 之间。

我正在尝试使用 Pillow 5.0.0 将此数组重建为图像。 在 Python 2 下,我能够以这种方式将值列表转换为字节字符串:

        cdata2 = []
        gidx = len(cdata)//3
        bidx = len(cdata)//3*2
        for i in range(len(cdata)//3):
            cdata2.append(cdata[i])
            cdata2.append(cdata[i+gidx])
            cdata2.append(cdata[i+bidx])

        data = ""
        for c in cdata2:
            data += chr(c)

        im = Image.frombytes("RGB", (420, 560), data)

然后在 base64 中重新编码“im”并在 HTML 模板中将其显示为 PNG。

不幸的是,这在 Python 3 中不起作用,我遇到如下错误:

UnicodeEncodeError: 'charmap' codec can't encode characters in position 42099-42101: character maps to <undefined>

此外,Pillow 5 文档现在建议使用

im = Image.open(StringIO(data))

但不能使它与上面构建的字符串一起使用。有没有更聪明的方法来做到这一点?非常感谢您的帮助。

【问题讨论】:

  • 在 Python 3 中,纯字符串用于 (Unicode) 文本,不要尝试将它们用于二进制数据。相反,您应该使用bytearray,或者可能是bytes 对象。 Numpy 是您的选择吗?为什么你的 RGB 值的范围是 0-254 而不是 0-255?
  • 谢谢 PM 2Ring。是的,它们确实高达 255,将纠正这一点。我可以使用 Numpy。请问如何对 RGB 通道数据进行编码,然后将其与 Pillow 一起使用?

标签: python image python-imaging-library pillow stringio


【解决方案1】:

这是一个使用frombytes 的示例。这只是使用纯 Python,没有 Numpy。如果您使用 Numpy 创建 RGB 值,则可以使用 Image.fromarray 方法将 Numpy 数据转换为 PIL 图像。

这里的重要步骤是将 RGB 值列表转换为 bytes 对象,这很容易通过将其传递给 bytes 构造函数来完成。

from colorsys import hsv_to_rgb
from PIL import Image

# Make some RGB values. 
# Cycle through hue vertically & saturation horizontally
colors = []
for hue in range(360):
    for sat in range(100):
        # Convert color from HSV to RGB
        rgb = hsv_to_rgb(hue/360, sat/100, 1)
        rgb = [int(0.5 + 255*u) for u in rgb]
        colors.extend(rgb)

# Convert list to bytes
colors = bytes(colors)
img = Image.frombytes('RGB', (100, 360), colors)
img.show()
img.save('hues.png')

输出

【讨论】:

    【解决方案2】:

    使用Image.frombytesImage.open 用于打开编码图像(如 jpg 或 png),而不是原始 RGB 数据。


    使用bytes 构造函数构造所需的字节数据很简单:

    img_bytes = bytes([R1, G1, B1, R2, G2, B2,..., Rn, Gn, Bn])
    

    然后我们可以像这样创建一个图像:

    im = Image.frombytes("RGB", (width, height), img_bytes)
    

    【讨论】:

      【解决方案3】:

      如果你想拥有漂亮的 Python2 和 Python3 兼容代码,你可以使用 struct 或 array 模块:

      # Works from Python 2.5 (maybe earlier) to Python 3.x
      import struct
      cdata = [...]
      bindata = struct.pack("<%dB" % len(cdata), *cdata)
      # And then use PIL's Image.frombytes() to construct the Image() from bindata
      

      或者:

      import array
      cdata = [...]
      a = array.array("B", cdata)
      bindata = a.tostring()
      # And then use PIL's Image.frombytes() to construct the Image() from bindata
      # This should be faster than struct, but I didn't test it for speed
      

      【讨论】:

        猜你喜欢
        • 2020-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-25
        • 1970-01-01
        相关资源
        最近更新 更多