Created
June 9, 2024 05:54
-
-
Save Sp5rky/40576615a6ef502eee9abfe3623a6709 to your computer and use it in GitHub Desktop.
Gif to Text
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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