Adding text to a image using PIL - python

So, I want the bot to send a welcome card with the user's profile picture & text saying " Welcome {user.name} ", but the text part isn't working. I have got no error in the console.
Here's my code:
from PIL import Image, ImageFilter, ImageFont, ImageDraw
from io import BytesIO
#client.event
async def on_member_join(member):
wc = Image.open("wc.jpg")
asset = member.avatar_url_as(size=128)
data = BytesIO(await asset.read())
pfp = Image.open(data)
draw = ImageDraw.Draw(wc)
font = ImageFont.truetype("Littlecandy.ttf", 24)
pfp = pfp.resize((474,382))
draw.text((549,284), f"{member.display_name}", (171, 5, 171), font=font)
wc.paste(pfp, (727,209))
wc.save("wcm.jpg")
await client.get_channel(850634788633182218).send(file = discord.File('wcm.jpg'))

So, i have not got the answer but when i removed the RGB code that is this (171, 5, 171) than i tested it & it worked.
Here's my changed code:
from PIL import Image, ImageFilter, ImageFont, ImageDraw
from io import BytesIO
#client.comamnd()
async def on_member_join(member):
wc2 = Image.open("wc2.jpg")
asset = member.avatar_url_as(size=64)
data = BytesIO(await asset.read())
pfp = Image.open(data)
draw = ImageDraw.Draw(wc2)
font = ImageFont.truetype("BalsamiqSans-BoldItalic.ttf", 45)
text = f"{member}"
pfp = pfp.resize((211,181))
wc2.paste(pfp, (30,28))
draw.text((26,235),text,font=font,fill='orange')
wc2.save("wcm.jpg")
await client.get_channel(850634788633182218).send(file = discord.File('wcm.jpg'))

Related

How to get image size in async function?

I want to get the size of the image from a buffer.
import io
from PIL import Image
class Scraper:
asnyc _save_image(res):
buffer = await res.body()
img = Image.open(io.BytesIO(buffer))
img_w, img_h = img.size
async def scrape():
playwright = await async_playwright().start()
browser = await playwright.chromium.launch( headless = True, devtools = False )
page = browser.new_page()
page.on('response', _save_image)
await page.goto('https://www.example.com')
scraper = Scraper(key, id)
asyncio.run(scraper.scrape())
img = Image.open(io.BytesIO(buffer))
This code above is not an async function. I want know the size of images from the buffer asynchronously. How to so this?

How can I get a random image from image search using a command discord.py

I know I can make a command like:
async def cat(self, ctx):
response = requests.get('https://aws.random.cat/meow')
data = response.json()
embed = discord.Embed(
title = 'Kitty Cat 🐈',
description = 'Cat',
colour = discord.Colour.purple()
)
embed.set_image(url=data['file'])
embed.set_footer(text="")
await ctx.send(embed=embed)
not my code btw
But how do I make a command to search like !image computer and it gets a random computer image from image search and sends it to the channel
You can use the Unsplash Source API, as suggested by Bagle.
#command(name = "img")
async def cat(self, ctx, arg):
embed = discord.Embed(
title = 'Random Image 🐈',
description = 'Random',
colour = discord.Colour.purple()
)
embed.set_image(url='https://source.unsplash.com/1600x900/?{}'.format(arg))
embed.set_footer(text="")
await ctx.send(embed=embed)
And execute the command with
{bot_prefix}img computers

AttributeError: 'Image' object has no attribute 'getvalue' (PIL)

I currently am working on a program that pastes two images together with PIL, but PIL is weird, so I had to do a bunch of extra stuff so that I could use links. Anyways, now I can't use what PIL outputted because:
AttributeError: 'Image' object has no attribute 'getvalue'
here's the important chunk of my code:
async with aiohttp.ClientSession() as session:
async with session.get(avurl) as second_image:
image_bytes = await second_image.read()
with Image.open(BytesIO(image_bytes)).convert("RGB") as first_image:
output_buffer = BytesIO()
first_image.save(output_buffer, "png")
output_buffer.seek(0)
async with aiohttp.ClientSession() as session:
async with session.get("https://i.imgur.com/dNS0WJO.png") as second_image:
image_bytes = await second_image.read()
with Image.open(BytesIO(image_bytes)) as second_image:
output_buffer = BytesIO()
second_image.save(output_buffer, "png")
output_buffer.seek(0)
first_image.paste(second_image, (0, 0))
buf = io.BytesIO()
first_image.save(buf, "png")
first_image = first_image.getvalue()
could anyone tell me what line of code i'm missing to fix this? or maybe what i did incorrectly?
Image objects indeed do not have a getvalue method, it's BytesIO instances that do.
Here you should be calling buf.getvalue instead of first_image.getvalue.
buf = io.BytesIO()
first_image.save(buf, "png")
first_image = first_image.getvalue()
Your code looks a bit like this: https://stackoverflow.com/a/33117447/7051394 ; but if you look at the last three lines of that snipper, imgByteArr is still a BytesIO, so imgByteArr.getvalue() is valid.
Here's a simpler and possibly faster reformulation of your code:
async with aiohttp.ClientSession() as session:
image1data = await session.get(avurl).read()
image2data = await session.get("https://i.imgur.com/dNS0WJO.png").read()
image1 = Image.open(BytesIO(image1data)).convert("RGB")
image2 = Image.open(BytesIO(image2data))
image1.paste(image2, (0, 0))
buf = BytesIO()
image1.save(buf, "png")
composite_image_data = buf.getvalue()
You'll end up with composite_image_data containing PNG data for the composited image.

How to stream video on web browser/HTML page by aiohttp?

My project uses socket.io to send/receive data.
I added aiohttp to help display the results on the browser.
import asyncio
from aiohttp import web
sio = socketio.AsyncServer(async_mode='`aiohttp`')
app = web.Application()
sio.attach(app)
I followed
https://us-pycon-2019-tutorial.readthedocs.io/aiohttp_file_uploading.html
to upload an image but I cannot upload a video.
def gen1():
# while True:
# if len(pm.list_image_display) > 1 :
image = cv2.imread("/home/duong/Pictures/Chess_Board.svg")
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# img = PIL.Image.new("RGB", (64, 64), color=(255,255,0))
image_pil = PIL.Image.fromarray(image)
fp = io.BytesIO()
image_pil.save(fp, format="JPEG")
content = fp.getvalue()
return content
async def send1():
print("11")
return web.Response(body=gen1(), content_type='image/jpeg')
How to display video via aiohttp on browsers?
To stream a video in aiohttp you may open a StreamResponse in response to the fetching of a img HTML node:
#routes.get('/video')
async def video_feed(request):
response = web.StreamResponse()
response.content_type = 'multipart/x-mixed-replace; boundary=frame'
await response.prepare(request)
for frame in frames('/dev/video0'):
await response.write(frame)
return response
and send your frames in the form of bytes:
def frames(path):
camera = cv2.VideoCapture(path)
if not camera.isOpened():
raise RuntimeError('Cannot open camera')
while True:
_, img = camera.read()
img = cv2.resize(img, (480, 320))
frame = cv2.imencode('.jpg', img)[1].tobytes()
yield b'--frame\r\nContent-Type: image/jpeg\r\n\r\n'+frame+b'\r\n'
This may be however network demanding as the bitrate required to send each frame individually is high. For real-time streaming with further compression you may want to use WebRTC implementations like aiortc.

Sending photo from URL with Telegram Bot

I made a telegram bot which sends photo upon request from URL using pyTelegramBotAPI wrapper. So I tried putting a dummy photo URL and test if the bot can send the image but it failed with the following error.
telebot.apihelper.ApiException: sendPhoto failed. Returned result: <Response [400]>
I'm not sure what the error is, but how can I send a photo from URL using Telegram Bot API correctly? Here is my code
import telebot
import time
import urllib
from io import BytesIO
from PIL import Image
TOKEN = '<token here>'
url='http://scontent-b.cdninstagram.com/hphotos-xfa1/t51.2885-15/e15/10919672_584633251672188_179950734_n.jpg'
def listener(*messages):
for m in messages:
chatid = m.chat.id
if m.content_type == 'text':
text = m.text
name = m.fromUser.first_name
msgid = m.message_id
if(text.startswith('/photo')):
img = BytesIO(urllib.request.urlopen(url).read())
tb.send_chat_action(chatid, 'upload_photo')
tb.send_photo(chatid, img, reply_to_message_id=msgid)
tb = telebot.TeleBot(TOKEN)
tb.get_update() # cache exist message
tb.set_update_listener(listener) #register listener
tb.polling()
while True:
time.sleep(1)
I'm not sure whether I missed something though.
Try this:
import telebot
import time
import urllib
url = 'http://scontent-b.cdninstagram.com/hphotos-xfa1/t51.2885-15/e15/10919672_584633251672188_179950734_n.jpg'
f = open('out.jpg','wb')
f.write(urllib.request.urlopen(url).read())
f.close()
def listener(*messages):
for m in messages:
chat_id = m.chat.id
if m.content_type == 'text':
text = m.text
msgid = m.message_id
if text.startswith('/photo'):
tb.send_chat_action(chat_id, 'upload_photo')
img = open('out.jpg', 'rb')
tb.send_photo(chat_id, img, reply_to_message_id=msgid)
img.close()
tb = telebot.TeleBot(TOKEN)
tb.set_update_listener(listener) #register listener
tb.polling()
while True:
time.sleep(0)
or (using pyTelegramBotAPI 0.2.0)
import telebot
import time
import urllib
url='http://scontent-b.cdninstagram.com/hphotos-xfa1/t51.2885-15/e15/10919672_584633251672188_179950734_n.jpg'
f = open('out.jpg','wb')
f.write(urllib.request.urlopen(url).read())
f.close()
tb = telebot.TeleBot(TOKEN)
#tb.message_handler(commands=['photo'])
def send_photo(message):
tb.send_chat_action(message.chat.id, 'upload_photo')
img = open('out.jpg', 'rb')
tb.send_photo(message.chat.id, img, reply_to_message_id=message.message_id)
img.close()
tb.polling()
while True:
time.sleep(0)
elif 'Hi' in text:
reply(img=urllib2.urlopen('img url').read())

Categories

Resources