Friends_forever / src /generate_quote_card.py
ak0601's picture
Upload generate_quote_card.py
a966aaa verified
from PIL import Image, ImageDraw, ImageFont
import textwrap
import io
def create_quote_card(text, card_type="joke", title="Memory Forever"):
"""
Generate a beautiful quote card image.
Args:
text (str): The quote/joke/memory text to display
card_type (str): Type of card - "joke", "memory", or "motivation"
title (str): Optional title text
Returns:
BytesIO: Image buffer that can be downloaded
"""
# Card dimensions
width, height = 1080, 1080
# Create image
img = Image.new('RGB', (width, height), color='white')
draw = ImageDraw.Draw(img)
# Define color schemes for different card types
gradients = {
'joke': {
'top': (255, 75, 75), # Red/Pink
'bottom': (255, 120, 150),
'accent': (255, 255, 255),
'text': (255, 255, 255),
'icon': '🎭'
},
'memory': {
'top': (255, 215, 100), # Yellow/Gold
'bottom': (255, 180, 120),
'accent': (139, 69, 19),
'text': (80, 50, 20),
'icon': 'πŸ’›'
},
'motivation': {
'top': (100, 220, 150), # Green
'bottom': (80, 200, 180),
'accent': (255, 255, 255),
'text': (255, 255, 255),
'icon': '✨'
}
}
colors = gradients.get(card_type, gradients['joke'])
# Draw gradient background
for y in range(height):
r = int(colors['top'][0] + (colors['bottom'][0] - colors['top'][0]) * y / height)
g = int(colors['top'][1] + (colors['bottom'][1] - colors['top'][1]) * y / height)
b = int(colors['top'][2] + (colors['bottom'][2] - colors['top'][2]) * y / height)
draw.rectangle([(0, y), (width, y + 1)], fill=(r, g, b))
# Add decorative elements
add_decorative_elements(draw, width, height, colors['accent'], card_type)
# Load fonts (fallback to default if custom not available)
try:
title_font = ImageFont.truetype("arial.ttf", 60)
text_font = ImageFont.truetype("arial.ttf", 45)
footer_font = ImageFont.truetype("arial.ttf", 35)
icon_font = ImageFont.truetype("seguiemj.ttf", 80) # For emoji
except:
# Fallback to default font
title_font = ImageFont.load_default()
text_font = ImageFont.load_default()
footer_font = ImageFont.load_default()
icon_font = ImageFont.load_default()
# Draw icon at top
icon = colors['icon']
icon_bbox = draw.textbbox((0, 0), icon, font=icon_font)
icon_width = icon_bbox[2] - icon_bbox[0]
draw.text(((width - icon_width) // 2, 100), icon, font=icon_font, fill=colors['text'])
# Draw title
title_bbox = draw.textbbox((0, 0), title, font=title_font)
title_width = title_bbox[2] - title_bbox[0]
draw.text(((width - title_width) // 2, 220), title, font=title_font, fill=colors['text'])
# Draw quote text with wrapping
margin = 100
max_width = width - (margin * 2)
# Wrap text
wrapped_text = wrap_text(text, text_font, max_width, draw)
# Calculate text block height
line_height = 60
text_block_height = len(wrapped_text) * line_height
# Start position for text (centered vertically)
y_text = (height - text_block_height) // 2 + 50
# Draw each line
for line in wrapped_text:
line_bbox = draw.textbbox((0, 0), line, font=text_font)
line_width = line_bbox[2] - line_bbox[0]
x = (width - line_width) // 2
draw.text((x, y_text), line, font=text_font, fill=colors['text'])
y_text += line_height
# Draw footer
footer_text = "Made with πŸ’– by Aman"
footer_bbox = draw.textbbox((0, 0), footer_text, font=footer_font)
footer_width = footer_bbox[2] - footer_bbox[0]
draw.text(((width - footer_width) // 2, height - 120), footer_text, font=footer_font, fill=colors['text'])
# Save to buffer
buffer = io.BytesIO()
img.save(buffer, format='PNG')
buffer.seek(0)
return buffer
def wrap_text(text, font, max_width, draw):
"""Wrap text to fit within max_width."""
words = text.split()
lines = []
current_line = []
for word in words:
test_line = ' '.join(current_line + [word])
bbox = draw.textbbox((0, 0), test_line, font=font)
text_width = bbox[2] - bbox[0]
if text_width <= max_width:
current_line.append(word)
else:
if current_line:
lines.append(' '.join(current_line))
current_line = [word]
else:
# Word is too long, force it
lines.append(word)
if current_line:
lines.append(' '.join(current_line))
return lines
def add_decorative_elements(draw, width, height, color, card_type):
"""Add decorative elements to the card."""
# Add subtle corner decorations
corner_size = 100
# Top left corner
draw.arc([20, 20, corner_size, corner_size], start=180, end=270, fill=color, width=3)
# Top right corner
draw.arc([width - corner_size, 20, width - 20, corner_size], start=270, end=360, fill=color, width=3)
# Bottom left corner
draw.arc([20, height - corner_size, corner_size, height - 20], start=90, end=180, fill=color, width=3)
# Bottom right corner
draw.arc([width - corner_size, height - corner_size, width - 20, height - 20], start=0, end=90, fill=color, width=3)
# Add small hearts or stars based on card type
if card_type == 'memory':
# Add small heart shapes
for i in range(3):
x = 80 + (i * 300)
y = height - 200
draw.ellipse([x, y, x + 20, y + 20], fill=color)
elif card_type == 'motivation':
# Add star-like dots
for i in range(4):
x = 100 + (i * 250)
y = 320
draw.ellipse([x, y, x + 15, y + 15], fill=color)