Skip to content

Instantly share code, notes, and snippets.

@Nemika-Haj
Last active February 8, 2024 22:56
Show Gist options
  • Save Nemika-Haj/294b06f9fca1493443efe156697e57ac to your computer and use it in GitHub Desktop.
Save Nemika-Haj/294b06f9fca1493443efe156697e57ac to your computer and use it in GitHub Desktop.
How to make the BytesToBits welcome GIF

Since a LOT of people like the way it looks, and wanted to know how to make it, here is the code :3

Preview

Preview

import disnake
from disnake.ext import commands
from PIL import Image, ImageFont, ImageDraw, ImageStat
import textwrap
from io import BytesIO
import numpy as np
# Credit for the ascii art (it's slightly modified though) -> https://www.geeksforgeeks.org/converting-image-ascii-image-python/
gscale1 = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. "
gscale2 = ' .:-=+*#%@'
def getAverageL(image: Image):
im = np.array(image)
w,h = im.shape
return np.average(im.reshape(w*h))
def covertImageToAscii(IMAGE: Image, cols: int, scale: float, moreLevels: bool):
global gscale1, gscale2
image = IMAGE.convert('L')
W, H = image.size
w = W/cols
h = w/scale
rows = int(H/h)
if cols > W or rows > H:
return None
aimg = []
for j in range(rows):
y1 = int(j*h)
y2 = int((j+1)*h)
if j == rows-1:
y2 = H
aimg.append("")
for i in range(cols):
x1 = int(i*w)
x2 = int((i+1)*w)
if i == cols-1:
x2 = W
img = image.crop((x1, y1, x2, y2))
avg = int(getAverageL(img))
if moreLevels:
gsval = gscale1[int((avg*69)/255)]
else:
gsval = gscale2[int((avg*9)/255)]
aimg[j] += gsval
return aimg
def ascii_art(image: BytesIO, more_levels = False):
scale = .65
cols = 100
image = Image.open(image)
aimg = covertImageToAscii( image, cols, scale, more_levels )
return aimg
def brightness_level(image: Image.Image):
image = image.convert('L')
stat = ImageStat.Stat(image)
return stat.mean[0]
def create_welcome(user:disnake.Member, user_avatar, join_pos):
canvas = Image.new('RGB', (600, 250), (0,0,0,1))
image_array = [canvas]
text_color = 108, 247, 80
info_font = ImageFont.truetype("assets/fonts/terminal.ttf", size=15)
welcome_font = ImageFont.truetype("assets/fonts/terminal.ttf", size=20)
name_font = ImageFont.truetype("assets/fonts/terminal.ttf", size=30)
ascii_font = ImageFont.truetype("assets/fonts/terminal.ttf", size=3)
WELCOME_TEXT = "Welcome to BytesToBits,"
NAME_TEXT = user.name
INFO_TEXT = [
f"Subject ID: #{str(join_pos).zfill(4)}",
user.created_at.strftime("Since %B %d, %Y"),
f"Status: {user.status.name.upper()}",
f"Activity:",
] + textwrap.wrap(user.activity.name if user.activity else "UNDETECTED", 25)
for letter_range in range(len(WELCOME_TEXT)):
im = image_array[-1].copy()
draw = ImageDraw.Draw(im)
draw.text((5+(welcome_font.size-5)*letter_range, 5), WELCOME_TEXT[letter_range], fill=text_color, font=welcome_font)
image_array.append(im)
# DELAY BEFORE WRITING THE NAME
image_array += [image_array[-1] for _ in range(2)]
for letter_range in range(len(NAME_TEXT)):
im = image_array[-1].copy()
draw = ImageDraw.Draw(im)
draw.text((5+(name_font.size-10)*letter_range, 30), NAME_TEXT[letter_range], fill=text_color, font=name_font)
image_array.append(im)
# DELAY BEFORE WRITING THE INFO
image_array += [image_array[-1] for _ in range(2)]
for (index, line) in enumerate(INFO_TEXT):
for letter_range in range(len(line)):
im = image_array[-1].copy()
draw = ImageDraw.Draw(im)
draw.text((5+(info_font.size-5)*letter_range, 80+20*index), line[letter_range], fill=text_color, font=info_font)
image_array.append(im)
# DELAY BEFORE DRAWING THE IMAGE
image_array += [image_array[-1] for _ in range(2)]
brightness = brightness_level(Image.open(BytesIO(user_avatar)))
ascii = ascii_art(BytesIO(user_avatar), more_levels=brightness>170)
if not ascii: return
ascii_len = len(ascii)*ascii_font.size
ascii_image = Image.new('RGB', (ascii_len, ascii_len), (0,0,0))
draw = ImageDraw.Draw(ascii_image)
for (index, line) in enumerate(ascii):
im = ascii_image.copy()
draw = ImageDraw.Draw(im)
# draw.text((L_MARGIN, T_MARGIN+ascii_font.size*index), line, fill=text_color, font=ascii_font)
draw.text((0, ascii_font.size*index), line, fill=text_color, font=ascii_font)
ascii_image = im
im = image_array[-1].copy()
im.paste(ascii_image.resize((250,250)), (350, 0))
image_array.append(im)
img = BytesIO()
canvas.save(img, "GIF", save_all=True, append_images=image_array[1:], duration=50)
img.seek(0)
return img
class WelcomeBanner(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
@commands.Cog.listener()
async def on_member_join(self, member: disnake.Member):
avatar = await member.display_avatar.read()
# Do it like this because the welcome image might take some time to make, and the bot would freeze otherwize.
welcome_image = await self.bot.loop.run_in_executor(None, lambda: create_welcome(member, avatar, member.guild.member_count))
await member.guild.text_channels[0].send(file=disnake.File(welcome_image, "welcome.gif"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment