import os import requests from PIL import Image, ImageDraw, ImageFont import textwrap FONT_DIR = "assets/fonts" FONT_PATH = os.path.join(FONT_DIR, "Roboto-Bold.ttf") BODY_FONT_PATH = os.path.join(FONT_DIR, "Roboto-Regular.ttf") def download_fonts(): """Downloads Roboto font if not present.""" if not os.path.exists(FONT_DIR): os.makedirs(FONT_DIR) fonts = { "Roboto-Bold.ttf": "https://github.com/google/fonts/raw/main/apache/roboto/Roboto-Bold.ttf", "Roboto-Regular.ttf": "https://github.com/google/fonts/raw/main/apache/roboto/Roboto-Regular.ttf" } for name, url in fonts.items(): path = os.path.join(FONT_DIR, name) if not os.path.exists(path): try: print(f"Downloading {name}...") response = requests.get(url) if response.status_code == 200: with open(path, "wb") as f: f.write(response.content) except Exception as e: print(f"Failed to download font {name}: {e}") def format_slide(slide_image: Image.Image, slide_number: int, total_slides: int, style_config: dict) -> Image.Image: """ Formats the AI-generated slide (with text) by adding a subtle footer for navigation. """ # Ensure fonts are available (for footer) if not os.path.exists(FONT_PATH): download_fonts() target_size = (1080, 1350) img = slide_image.resize(target_size, Image.Resampling.LANCZOS) # We remove the heavy overlay because the AI image already has text and design integrated. # A very subtle gradient at the bottom might be nice for the footer, but let's keep it minimal. draw = ImageDraw.Draw(img) # Load Fonts (only for footer) try: footer_font = ImageFont.truetype(BODY_FONT_PATH, 30) except: footer_font = ImageFont.load_default() text_color = style_config["text_color"] margin = 80 # Footer (Slide Number) footer_text = f"{slide_number} / {total_slides}" bbox = draw.textbbox((0, 0), footer_text, font=footer_font) # Draw a small background for readability if needed, or just text # Let's draw text with a slight shadow or outline for readability on varied backgrounds x = target_size[0] - bbox[2] - margin y = target_size[1] - 80 # Simple shadow shadow_color = (0, 0, 0) if sum(text_color) > 300 else (255, 255, 255) draw.text((x+2, y+2), footer_text, font=footer_font, fill=shadow_color) draw.text((x, y), footer_text, font=footer_font, fill=text_color) # Branding (Optional) - REMOVED # branding = "Generated by Gemini" # draw.text((margin+2, y+2), branding, font=footer_font, fill=shadow_color) # draw.text((margin, y), branding, font=footer_font, fill=text_color) return img