How to send an PIL Image via telegram bot without saving it to a file
M

3

12

For my telegram bot (python-telegram-bot) i generated a PIL.Image.Image and i want to send it directly to a user.

What works is to send an image as bufferedReader from a file, but i don't want to safe the image. I don't need it again afterwards and i might generate a lot of different images at the same time, so saving is kind of messy.

bot.send_photo(chat_id=update.message.chat_id,
               photo=open(img_dir, 'rb'),
               caption='test',
               parse_mode=ParseMode.MARKDOWN)

Because i generated it myself, i cant use an URL or file_id. I thought it might be possible to convert the image to a bufferedReader, but i only managed to get a bytes object from it, which didn't work.

The image is generated like:

images = [Image.open(i) for i in dir_list]
widths, heights = zip(*(i.size for i in images))
total_width = sum(widths)
max_height = max(heights)
new_im = Image.new('RGBA', (total_width, max_height))

x_offset = 0
for im in images:
    new_im.paste(im, (x_offset, 0))
    x_offset += im.size[0]
return new_im                 # returns a PIL.Image.Image

Thanks in advance :) merry x-mas

Mauro answered 24/12, 2018 at 23:49 Comment(1)
Consider using tempfileCoffeecolored
E
17

Have a lock at this code snippet from the packages github wiki

Post an image from memory

In this example, image is a PIL (or Pillow) Image object, but it works the same with all media types.

from io import BytesIO
bio = BytesIO()
bio.name = 'image.jpeg'
image.save(bio, 'JPEG')
bio.seek(0)
bot.send_photo(chat_id, photo=bio)
Elmoelmore answered 13/1, 2019 at 1:45 Comment(1)
I've actually been on that exact page without noticing it. Anyway, works like a charm and much faster than before (obviously). Thank you very much.Mauro
N
1

Don't know if you interesting in sending animated GIF, but this code snippet should help to those who will:

from telegram import Update, ForceReply
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, CallbackContext

def echo_gif(update: Update, context: CallbackContext) -> None:
    """ Echo to /gif command """
    
    context.bot.sendAnimation(chat_id=update.message.chat_id,
               animation=open("URuEc5hnbNIGs.gif", 'rb').read(), ## some local file name
               caption='That is your gif!',
               )
    return    

def main() -> None:
    """Start the bot."""
    # Create the Updater and pass it your bot's token.
    updater = Updater(TOKEN)

    # Get the dispatcher to register handlers
    dispatcher = updater.dispatcher

    # on different commands - answer in Telegram
    dispatcher.add_handler(CommandHandler("gif", echo_gif))
    # Start the Bot
    updater.start_polling()

    # Run the bot until you press Ctrl-C or the process receives SIGINT,
    # SIGTERM or SIGABRT. This should be used most of the time, since
    # start_polling() is non-blocking and will stop the bot gracefully.
    updater.idle()
Nutpick answered 12/9, 2021 at 19:14 Comment(0)
I
0
def generateImg():
    imgBase = Image.new('RGB', (1200, 700), color=COLBLACK)
    draw = ImageDraw.Draw(imgBase)
    "..."
    img_bytes = BytesIO()
    imgBase.save(img_bytes, format='png')
    img_bytes.seek(0)

    return img_bytes

@user_pr_addEv.message(AddEventState.discriptEvent, F.text)
async def input_discriptEvent(message: types.Message, state: AddEventState, session: AsyncSession):

    img_bytesio = pilGen.generateImg()
    result = await message.answer_photo(
            types.BufferedInputFile(
                img_bytesio.read(),
                filename="buffer img.jpg"
            ),
            caption="Opisanie"
        )
Incongruity answered 29/4 at 20:42 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Mulford

© 2022 - 2024 — McMap. All rights reserved.