import os from pathlib import Path from PIL import Image, ImageDraw, ImageFont import textwrap # Get the directory where the script is located SCRIPT_DIR = Path(__file__).resolve().parent def get_asset_path(filename): return str(SCRIPT_DIR / 'drake_assets' / filename) def fit_text_to_box(draw, text, font, max_width, max_height, line_spacing=1.2): font_size = 1 while True: font = ImageFont.truetype(font.path, font_size) lines = textwrap.wrap(text, width=20) line_height = font.getbbox("Ay")[3] - font.getbbox("Ay")[1] total_height = line_height * len(lines) * line_spacing max_line_width = max(font.getbbox(line)[2] - font.getbbox(line)[0] for line in lines) if max_line_width > max_width or total_height > max_height: font_size -= 1 font = ImageFont.truetype(font.path, font_size) break font_size += 1 return font, lines def create_drake_meme(items): # Load images no_image = Image.open(get_asset_path('no.jpg')) yes_image = Image.open(get_asset_path('yes.jpg')) # Set up meme dimensions panel_width, panel_height = no_image.size meme_width = panel_width * 2 meme_height = panel_height * len(items) # Create meme canvas meme = Image.new("RGB", (meme_width, meme_height), "white") # Set up font (use a proper meme font) font_path = get_asset_path('impact.ttf') try: base_font = ImageFont.truetype(font_path, 1) except OSError: # Fallback to default font if Impact is not available base_font = ImageFont.load_default() for i, (is_yes, text) in enumerate(items): # Paste the appropriate image y_offset = i * panel_height if is_yes: meme.paste(yes_image, (0, y_offset)) else: meme.paste(no_image, (0, y_offset)) # Create text panel text_panel = Image.new("RGB", (panel_width, panel_height), "white") draw = ImageDraw.Draw(text_panel) # Fit and draw text fitted_font, lines = fit_text_to_box(draw, text, base_font, panel_width - 20, panel_height - 20, line_spacing=1.2) line_height = fitted_font.getbbox("Ay")[3] - fitted_font.getbbox("Ay")[1] total_height = line_height * len(lines) * 1.2 y_text = (panel_height - total_height) // 2 for line in lines: bbox = fitted_font.getbbox(line) text_width = bbox[2] - bbox[0] x_text = (panel_width - text_width) // 2 draw.text((x_text, y_text), line, font=fitted_font, fill="black") y_text += line_height * 1.2 # Paste text panel onto meme meme.paste(text_panel, (panel_width, y_offset)) return meme default_items = [ (False, "Play Nucleares manually"), (True, "Automate it with a script"), (False, "But the web interface is tedious to use"), (True, "Write an elegant libary to interface with the game and then use that to write the script"), (False, "But I would still need to write the control policy by hand"), (True, "Let's extend the libary such that it trains a policy via Reinforcement Learning"), (False, "But RL takes a huge number of training samples"), (True, "Extend the libary to also include an efficient simulator"), (False, "But I don't know what the actual internal dynamics are"), (True, "Extend the libary once more to also include a neural network dynamics model"), (True, "And I'm gonna put a drake meme on the README"), (False, "Online meme generators only support a single yes/no pair"), (True, "Let's also add a drake meme generator to the libary"), ] if __name__ == "__main__": meme = create_drake_meme(default_items) meme.save("drake_meme.jpg") print("Meme saved as drake_meme.jpg")