run image rendering in a separate thread

This commit is contained in:
leander committed 2026-10-24 18:17:25 +02:00
1 parent d6bdc4926c
commit 96aa7147de
5 files changed
+102 -25

No files matched your search

+5 -5
View File
@@ -143,12 +143,12 @@ class BingoGenerator:
player_sheets = {}
for player in players:
player_sheets[player] = await cls.generate_sheet(sample_space[player], image)
player_sheets[player] = await asyncio.to_thread(cls.generate_sheet, sample_space[player], image)
return {p: cv2.imencode(".png", sheet)[1].tobytes() for p, sheet in player_sheets.items()}
return player_sheets
@classmethod
async def generate_sheet(cls, sample_space: list, image: np.ndarray):
def generate_sheet(cls, sample_space: list, image: np.ndarray) -> bytes:
image = image.copy()
# start = 8, 294
@@ -160,7 +160,7 @@ class BingoGenerator:
for i in range(0, 5):
for j in range(0, 5):
width = 123
await misc_utils.put_text_in_box(
misc_utils.put_text_in_box(
sliced,
sample_space.pop(),
top_left=(i * width + 1, j * width + 1),
@@ -168,7 +168,7 @@ class BingoGenerator:
font_path=cls.FONT_PATH,
)
return image
return cv2.imencode(".png", image)[1].tobytes()
class BingoView(LobbyView):
+66 -11
View File
@@ -59,6 +59,24 @@ class Meme(commands.Cog):
await interaction.followup.send(embed=embed_templates.error_warning("Bildet er ugyldig"))
return
output = await asyncio.to_thread(Meme.fry, image)
await interaction.followup.send(file=discord.File(output, "deepfry.jpg"))
@staticmethod
def fry(image: Image.Image) -> BytesIO:
"""
Applies the deepfrying filters to an image
Parameters
----------
image (Image.Image): The image to deepfry
Returns
----------
(BytesIO): The deepfried image as JPEG
"""
if image.mode != "RGB":
image = image.convert("RGB")
@@ -76,7 +94,7 @@ class Meme(commands.Cog):
image.save(output, format="jpeg", quality=5)
output.seek(0)
await interaction.followup.send(file=discord.File(output, "deepfry.jpg"))
return output
@app_commands.checks.bot_has_permissions(attach_files=True)
@app_commands.checks.cooldown(1, 5)
@@ -94,13 +112,33 @@ class Meme(commands.Cog):
await interaction.response.defer()
output = await asyncio.to_thread(Meme.make_prefer_meme, dårlig_tekst, bra_tekst)
# Send image
await interaction.followup.send(file=discord.File(output, "sivert_goodbad.jpg"))
@staticmethod
def make_prefer_meme(bad_text: str, good_text: str) -> BytesIO:
"""
Draws the texts on the drake-like meme template
Parameters
----------
bad_text (str): The upper text, what's disliked
good_text (str): The lower text, what's liked
Returns
----------
(BytesIO): The meme as JPEG
"""
# Fetch meme template
template = cv2.imread("./src/assets/sivert_goodbad.jpg")
# Draw text
font = "./src/assets/fonts/comic.ttf"
await misc_utils.put_text_in_box(template, dårlig_tekst, (540, 0), (1080, 540), font)
await misc_utils.put_text_in_box(template, bra_tekst, (540, 540), (1080, 1080), font)
misc_utils.put_text_in_box(template, bad_text, (540, 0), (1080, 540), font)
misc_utils.put_text_in_box(template, good_text, (540, 540), (1080, 1080), font)
# Save image to buffer
_, buffer = cv2.imencode(".jpg", template)
@@ -108,8 +146,7 @@ class Meme(commands.Cog):
cv2.imdecode(np.frombuffer(output.getbuffer(), np.uint8), -1)
output.seek(0)
# Send image
await interaction.followup.send(file=discord.File(output, "sivert_goodbad.jpg"))
return output
@app_commands.checks.bot_has_permissions(embed_links=True, attach_files=True)
@app_commands.checks.cooldown(1, 5)
@@ -130,10 +167,32 @@ class Meme(commands.Cog):
embed = embed_templates.error_warning("Bildet må være i PNG- eller JPEG-format")
return await interaction.followup.send(embed=embed)
provided_image = await discord_utils.get_file_bytesio(file)
output = await asyncio.to_thread(Meme.make_wojakpoint, provided_image)
# Send
f = discord.File(output, filename="uio_wojak.png")
embed = discord.Embed()
embed.set_image(url="attachment://uio_wojak.png")
await interaction.followup.send(embed=embed, file=f)
@staticmethod
def make_wojakpoint(provided_image: BytesIO) -> BytesIO:
"""
Puts the pointing wojaks on top of an image
Parameters
----------
provided_image (BytesIO): The image to point at
Returns
----------
(BytesIO): The meme as PNG
"""
# Prepare template
template = Image.open("./src/assets/wojak_point.png").convert("RGBA")
provided_image = await discord_utils.get_file_bytesio(file)
provided_image = Image.open(provided_image).convert("RGBA").resize((template.width, template.height))
# Putting it all together
@@ -146,11 +205,7 @@ class Meme(commands.Cog):
provided_image.save(output, format="PNG")
output.seek(0)
# Send
f = discord.File(output, filename="uio_wojak.png")
embed = discord.Embed()
embed.set_image(url="attachment://uio_wojak.png")
await interaction.followup.send(embed=embed, file=f)
return output
# I can't be arsed to make this code good rn
# This code is absolute horse ass
+28 -7
View File
@@ -1,3 +1,4 @@
import asyncio
import random
import re
from datetime import datetime
@@ -267,13 +268,37 @@ class Misc(commands.Cog):
if bruker.id == self.bot.user.id:
match_percent = 100
# Prepare invoker avatar
invoker_avatar = await discord_utils.get_file_bytesio(interaction.user.display_avatar)
user_avatar = await discord_utils.get_file_bytesio(bruker.display_avatar)
output = await asyncio.to_thread(Misc.make_match_image, invoker_avatar, user_avatar, match_percent)
# Send
f = discord.File(output, filename=f"{interaction.user.id}_{bruker.id}_match.png")
embed = discord.Embed()
embed.set_image(url=f"attachment://{interaction.user.id}_{bruker.id}_match.png")
await interaction.response.send_message(embed=embed, file=f)
@staticmethod
def make_match_image(invoker_avatar: BytesIO, user_avatar: BytesIO, match_percent: int) -> BytesIO:
"""
Draws the two avatars with a heart and the match percent between them
Parameters
----------
invoker_avatar (BytesIO): The invoking user's avatar
user_avatar (BytesIO): The other user's avatar
match_percent (int): How much the users match
Returns
----------
(BytesIO): The image as PNG
"""
# Prepare invoker avatar
invoker = Image.open(invoker_avatar).convert("RGBA")
invoker = invoker.resize((389, 389))
# Prepare user avatar
user_avatar = await discord_utils.get_file_bytesio(bruker.display_avatar)
user = Image.open(user_avatar).convert("RGBA")
user = user.resize((389, 389))
@@ -297,11 +322,7 @@ class Misc(commands.Cog):
image.save(output, format="PNG")
output.seek(0)
# Send
f = discord.File(output, filename=f"{interaction.user.id}_{bruker.id}_match.png")
embed = discord.Embed()
embed.set_image(url=f"attachment://{interaction.user.id}_{bruker.id}_match.png")
await interaction.response.send_message(embed=embed, file=f)
return output
@app_commands.checks.cooldown(1, 2)
@app_commands.command(name="ifonlyyouknew", description="How bad things really are")
+2 -1
View File
@@ -1,3 +1,4 @@
import asyncio
from io import BytesIO
import discord
@@ -245,7 +246,7 @@ class UserFacts(commands.Cog):
if user:
others.append((user, mbti))
graph_png = self.create_mbti_graph((bruker, user_mbti), others)
graph_png = await asyncio.to_thread(self.create_mbti_graph, (bruker, user_mbti), others)
image = discord.File(BytesIO(graph_png), filename=f"{bruker.id}_mbti.png")
embed.set_image(url=f"attachment://{bruker.id}_mbti.png")
+1 -1
View File
@@ -161,7 +161,7 @@ class Paginator:
return self.get_page(self.current_page)
async def put_text_in_box(
def put_text_in_box(
image: np.ndarray,
text: str,
top_left: tuple,