web-dev-qa-db-ja.com

メモリから画像を送信

画像を動的に変更してボットユーザーに送信するDiscordボットのシステムを実装しようとしています。それを行うために、私はPillow(PIL)ライブラリーを使用することに決めました。

これが私の作業コードの例です。テストの変更としてサンプル画像を読み込み、2本の対角線を描画し、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)

これにより、ボットから次のメッセージが表示されます。

Discord message with the edited image as result

これは機能します。ただし、イメージをハードドライブに保存して再度ロードする手順は省略します。これは、かなり非効率的で不要なためです。いくつかグーグルした後、私は次の解決策に出くわしました。ただし、動作しないようです。

# 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'))

その結果、次のエラーメッセージが表示されます。

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
3
JackTheFoxOtter

discord.Fileio.BufferedIOBasefpパラメータとして渡すことをサポートします。
io.BytesIOio.BufferedIOBaseから継承します。
つまり、io.BytesIOのインスタンスをfpとして直接渡してdiscord.Fileを初期化できます。例:

arr = io.BytesIO()
img.save(arr, format='PNG')
arr.seek(0)
file = discord.File(arr)

この別の例は FAQ)のセクションにある画像のアップロード方法 にあります。

2
Harmon758