从内存发送图像

Jac*_*ter 4 python byte python-imaging-library discord.py

我正在尝试为 Discord 机器人实现一个系统,该系统动态修改图像并将它们发送给机器人用户。为此,我决定使用 Pillow (PIL) 库,因为它对于我的目的来说似乎简单明了。

这是我的工作代码示例。它加载一个示例图像,作为测试修改,在其上绘制两条对角线,并将图像输出为 Discord 消息:

# Open source image
img = Image.open('example_image.png')

# Modify image
draw = ImageDraw.Draw(img)
draw.line((0, 0) + img.size, fill=128)
draw.line((0, img.size[1], img.size[0], 0), fill=128)

# Save to disk and create discord file object
img.save('tmp.png', format='PNG')
file = discord.File(open('tmp.png', 'rb'))

# Send picture as message
await message.channel.send("Test", file=file)
Run Code Online (Sandbox Code Playgroud)

这会导致来自我的机器人的以下消息:

结果与编辑后的图像不一致

这有效; 但是,我想省略将图像保存到硬盘驱动器并再次加载它的步骤,因为这似乎效率低下且不必要。经过一些谷歌搜索后,我遇到了以下解决方案;但是,它似乎不起作用:

# Save to disk and create discord file object
# img.save('tmp.png', format='PNG')
# file = discord.File(open('tmp.png', 'rb'))

# Save to memory and create discord file object
arr = io.BytesIO()
img.save(arr, format='PNG')
file = discord.File(open(arr.getvalue(), 'rb'))
Run Code Online (Sandbox Code Playgroud)

这会导致以下错误消息:

Traceback (most recent call last):
    File "C:\Users\<username>\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\client.py", line 270, in _run_event
        await coro(*args, **kwargs)
    File "example_bot.py", line 48, in on_message
        file = discord.File(open(arr.getvalue(), 'rb'))
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte
Run Code Online (Sandbox Code Playgroud)

Har*_*758 6

discord.File支持io.BufferedIOBase作为fp参数传递。
io.BytesIO继承自io.BufferedIOBase.
这意味着您可以直接将io.BytesIOas的实例传递fp给 initialize discord.File,例如:

arr = io.BytesIO()
img.save(arr, format='PNG')
arr.seek(0)
file = discord.File(arr)
Run Code Online (Sandbox Code Playgroud)

另一个例子可以在如何上传图片?discord.py 文档中的常见问题解答部分

  • 啊,我忘了 Pillow 在保存时将文件指针设置在末尾。您必须返回到缓冲区的开头。我已经更新了我的答案。 (2认同)