58 lines
2.1 KiB
Python
58 lines
2.1 KiB
Python
"""Meme engine module for handling the generation of meme images."""
|
|
|
|
import random
|
|
from PIL import Image, ImageFont, ImageDraw
|
|
|
|
|
|
class MemeEngine:
|
|
"""Class to generate memes from images and text."""
|
|
|
|
def __init__(self, output_path):
|
|
"""Initialize meme engine with path to save generated memes."""
|
|
self.output_path = output_path
|
|
|
|
def resize_image(self, img, width=500):
|
|
"""Resize image to specified width while maintaining aspect ratio."""
|
|
if img.size[0] > width:
|
|
ratio = width / (img.size[0] * 1.0)
|
|
height = ratio * img.size[1]
|
|
img = img.resize((int(width), int(height)), Image.NEAREST)
|
|
return img
|
|
|
|
def draw_text(self, image, message):
|
|
"""Draw text on the image."""
|
|
draw = ImageDraw.Draw(image)
|
|
font = ImageFont.truetype(
|
|
"./_data/font/calibri_regular.ttf", int(image.size[1] / 20)
|
|
)
|
|
|
|
# Calculate text bounding box to ensure it fits on the image
|
|
text_bbox = draw.textbbox((0, 0), message, font=font)
|
|
text_width = text_bbox[2] - text_bbox[0]
|
|
text_height = text_bbox[3] - text_bbox[1]
|
|
|
|
# Generate random position that keeps text within image bounds
|
|
max_x = max(0, image.size[0] - text_width - 10)
|
|
max_y = max(0, image.size[1] - text_height - 10)
|
|
|
|
x = random.randint(10, max_x) if max_x > 10 else 10
|
|
y = random.randint(10, max_y) if max_y > 10 else 10
|
|
|
|
draw.text((x, y), message, font=font, fill="white")
|
|
return image
|
|
|
|
def make_meme(self, img_path, text, author, width=500) -> str:
|
|
"""Generate a meme image with given text and author."""
|
|
output_file = f"{self.output_path}/{random.randint(0, 10000)}.jpg"
|
|
message = f"{text}\n- {author}"
|
|
|
|
try:
|
|
with Image.open(img_path) as img:
|
|
image_resize = self.resize_image(img, width=width)
|
|
image_draw = self.draw_text(image_resize, message)
|
|
image_draw.save(output_file)
|
|
except Exception as err:
|
|
print(f"Error: {err}")
|
|
|
|
return output_file
|