使用 Pillow 和 Python 3 从 RGB 列表创建图像
Create image from RGB list with Pillow and Python 3
我有一个 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))
但无法使其与我在上面构建的字符串一起使用。有没有更聪明的方法来做到这一点?非常感谢您的帮助。
使用Image.frombytes
。 Image.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)
这是一个使用 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')
输出
如果你想拥有漂亮的 Python2 和 Python3 兼容代码,你可以使用结构或数组模块:
# 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
我有一个 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))
但无法使其与我在上面构建的字符串一起使用。有没有更聪明的方法来做到这一点?非常感谢您的帮助。
使用Image.frombytes
。 Image.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)
这是一个使用 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')
输出
如果你想拥有漂亮的 Python2 和 Python3 兼容代码,你可以使用结构或数组模块:
# 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