Spaces:
Running
Running
import os | |
import uuid | |
import requests | |
from flask import Flask, request, send_file | |
from PIL import Image, ImageDraw, ImageFont | |
from io import BytesIO | |
app = Flask(__name__) | |
# Ensure temp directory exists | |
TEMP_DIR = "temp" | |
os.makedirs(TEMP_DIR, exist_ok=True) | |
def load_font(font_path, size): | |
"""Load a font or fallback to default Arial.""" | |
try: | |
return ImageFont.truetype(font_path, size) | |
except IOError: | |
return ImageFont.truetype("arial.ttf", size) | |
def generate_profile(): | |
# Get query parameters | |
name = request.args.get('name', 'Unknown') | |
rank = request.args.get('rank', 'Unranked') | |
balance = request.args.get('balance', '0') | |
next_rank = request.args.get('next_rank', 'Unknown') | |
pfp_url = request.args.get('pfp', None) | |
# Load background image | |
try: | |
bg = Image.open("bg.png").convert("RGBA") # Ensure transparency support | |
except IOError: | |
return "Error: Background image 'bg.png' not found.", 500 | |
draw = ImageDraw.Draw(bg) | |
W, H = bg.size # Get background dimensions | |
# Load fonts | |
font_large = load_font("font.ttf", 45) # Name | |
font_medium = load_font("font.ttf", 35) # Rank, Balance | |
font_small = load_font("font.ttf", 30) # Next Rank | |
# Profile picture settings | |
pfp_size = 170 | |
pfp_x = 50 # Align profile picture to the left | |
pfp_y = 50 | |
pfp_path = os.path.join(TEMP_DIR, f"pfp_{uuid.uuid4().hex}.png") | |
# Load profile picture | |
try: | |
if pfp_url: | |
response = requests.get(pfp_url, timeout=5) | |
if response.status_code == 200: | |
pfp = Image.open(BytesIO(response.content)).convert("RGBA") | |
else: | |
raise ValueError("Invalid profile picture URL") | |
else: | |
pfp = Image.open("fallback.png").convert("RGBA") | |
# Resize profile picture | |
pfp = pfp.resize((pfp_size, pfp_size), Image.LANCZOS) | |
# Create circular mask | |
mask = Image.new("L", (pfp_size, pfp_size), 0) | |
draw_mask = ImageDraw.Draw(mask) | |
draw_mask.ellipse((0, 0, pfp_size, pfp_size), fill=255) | |
# Create a white border | |
border_size = 8 | |
border = Image.new("RGBA", (pfp_size + border_size, pfp_size + border_size), (255, 255, 255, 255)) | |
border_mask = Image.new("L", (pfp_size + border_size, pfp_size + border_size), 0) | |
border_draw = ImageDraw.Draw(border_mask) | |
border_draw.ellipse((0, 0, pfp_size + border_size, pfp_size + border_size), fill=255) | |
border.paste(pfp, (border_size // 2, border_size // 2), mask) | |
# Paste profile picture with border | |
bg.paste(border, (pfp_x - border_size // 2, pfp_y - border_size // 2), border_mask) | |
except Exception as e: | |
print(f"Error loading profile picture: {e}") | |
# Define text positions | |
text_x = pfp_x + pfp_size + 30 # Start text next to profile picture | |
text_y_start = pfp_y + 30 | |
text_spacing = 60 | |
text_color = (255, 255, 255) | |
# Function to handle text resizing for long names | |
def fit_text(text, max_width, base_font): | |
font = base_font | |
while draw.textlength(text, font=font) > max_width and font.size > 20: | |
font = load_font("font.ttf", font.size - 2) | |
return font | |
# Adjust name font size dynamically | |
name_font = fit_text(name, W - text_x - 50, font_large) | |
# Draw aligned text | |
draw.text((text_x, text_y_start), name, font=name_font, fill=text_color) | |
draw.text((text_x, text_y_start + text_spacing), f"Rank: {rank}", font=font_medium, fill=text_color) | |
draw.text((text_x, text_y_start + 2 * text_spacing), f"Balance: {balance}", font=font_medium, fill=text_color) | |
draw.text((text_x, text_y_start + 3 * text_spacing), f"Next Rank: {next_rank}", font=font_small, fill=text_color) | |
# Save final image | |
output_path = os.path.join(TEMP_DIR, f"profile_{uuid.uuid4().hex}.png") | |
bg.save(output_path) | |
# Send and delete image | |
response = send_file(output_path, mimetype='image/png') | |
# Cleanup saved files | |
if os.path.exists(output_path): | |
os.remove(output_path) | |
if os.path.exists(pfp_path): | |
os.remove(pfp_path) | |
return response | |
if __name__ == '__main__': | |
app.run(host='0.0.0.0', port=7860, debug=True) |