Skip to content

Instantly share code, notes, and snippets.

@Sp5rky
Created June 9, 2024 05:54
Show Gist options
  • Save Sp5rky/40576615a6ef502eee9abfe3623a6709 to your computer and use it in GitHub Desktop.
Save Sp5rky/40576615a6ef502eee9abfe3623a6709 to your computer and use it in GitHub Desktop.
Gif to Text
from PIL import Image, ImageDraw, ImageFont, ImageSequence
import math
import moviepy.editor as mp
import os
# this code is really ugly, just learning Python and ImageDraw
# Set the path to your font file (adjust if necessary)
font_path = "C:\\Windows\\Fonts\\CascadiaCode.ttf"
chars = ''.join(chr(i) for i in range(32, 127) if not 48 <= i <= 57 and not 65 <= i <= 90 and not 97 <= i <= 122)
charArray = list(chars)
charLength = len(charArray)
interval = charLength / 256
scaleFactor = 0.25
oneCharWidth = 10
oneCharHeight = 18
grayscale_mode = True
text_overlay = False
overlay_text = "SAMPLE"
both_bwcolour = True
input_directory = "path_to_gifs" # Replace with your directory path
def getChar(inputInt):
return charArray[math.floor(inputInt * interval)]
def process_image(im, grayscale):
fnt = ImageFont.truetype(font_path, 15)
width, height = im.size
im = im.resize(
(
int(scaleFactor * width),
int(scaleFactor * height * (oneCharWidth / oneCharHeight)),
),
Image.NEAREST,
)
width, height = im.size
pix = im.load()
outputImage = Image.new(
"RGB", (oneCharWidth * width, oneCharHeight * height), color=(0, 0, 0)
)
d = ImageDraw.Draw(outputImage)
for i in range(height):
for j in range(width):
r, g, b = pix[j, i]
h = int(r / 3 + g / 3 + b / 3)
pix[j, i] = (h, h, h)
color = (h, h, h) if grayscale else (r, g, b)
d.text(
(j * oneCharWidth, i * oneCharHeight), getChar(h), font=fnt, fill=color
)
return outputImage
def add_text_to_frame(frame, text, font, position, free_space=5):
draw = ImageDraw.Draw(frame)
bbox = draw.textbbox((0, 0), text, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
x = position[0] - text_width // 2
y = position[1] - text_height // 2
x = max(free_space, x)
y = max(free_space, y)
if x + text_width + free_space > frame.width:
x = frame.width - text_width - free_space
if y + text_height + free_space > frame.height:
y = frame.height - text_height - free_space
draw.text((x, y), text, font=font, fill=(255, 255, 255))
def process_gif(im, output_file, grayscale):
frames = []
font = ImageFont.truetype(font_path, 120)
for frame in ImageSequence.Iterator(im):
frame = frame.convert("RGB")
processed_frame = process_image(frame, grayscale)
if text_overlay:
add_text_to_frame(
processed_frame,
overlay_text,
font,
(processed_frame.width // 2, processed_frame.height // 2),
)
frames.append(processed_frame)
frames[0].save(
output_file,
save_all=True,
append_images=frames[1:],
loop=0,
duration=im.info["duration"],
)
def process_mp4(input_file, output_file, grayscale):
clip = mp.VideoFileClip(input_file)
frames = []
font = ImageFont.truetype(font_path, 120)
for frame in clip.iter_frames(fps=10):
im = Image.fromarray(frame)
processed_frame = process_image(im, grayscale)
if text_overlay:
add_text_to_frame(
processed_frame,
overlay_text,
font,
(processed_frame.width // 2, processed_frame.height // 2),
)
frames.append(processed_frame)
frames[0].save(
output_file,
save_all=True,
append_images=frames[1:],
loop=0,
duration=100,
)
def process_and_save(input_file, grayscale_mode):
base_output_file = f"{os.path.splitext(input_file)[0]}-output{'-colour' if not grayscale_mode else ''}.gif"
if input_file.lower().endswith('.gif'):
im = Image.open(input_file)
process_gif(im, base_output_file, grayscale_mode)
elif input_file.lower().endswith('.mp4'):
process_mp4(input_file, base_output_file, grayscale_mode)
else:
im = Image.open(input_file)
processed_image = process_image(im, grayscale_mode)
if text_overlay:
font = ImageFont.truetype(font_path, 120)
add_text_to_frame(
processed_image,
overlay_text,
font,
(processed_image.width // 2, processed_image.height // 2),
)
processed_image.save(f"{os.path.splitext(input_file)[0]}-output{'-colour' if not grayscale_mode else ''}.png")
print(f"Output saved as {base_output_file}")
def process_directory(directory):
for filename in os.listdir(directory):
if filename.lower().endswith(('.gif', '.mp4')):
input_file = os.path.join(directory, filename)
if both_bwcolour:
process_and_save(input_file, True)
process_and_save(input_file, False)
else:
process_and_save(input_file, grayscale_mode)
process_directory(input_directory)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment