Betzpp / app.py
Reaperxxxx's picture
Update app.py
4a2292e verified
import os
import uuid
from flask import Flask, request, send_file
from PIL import Image, ImageDraw, ImageFont
app = Flask(__name__)
# Ensure temp directory exists
TEMP_DIR = "temp"
os.makedirs(TEMP_DIR, exist_ok=True)
# Available images
PFP_OPTIONS = {str(i): f"pfp{i}.png" for i in range(1, 6)}
BG_OPTIONS = {str(i): f"bg{i}.png" for i in range(1, 4)}
# Load fonts safely
def load_font(font_path, size):
try:
return ImageFont.truetype(font_path, size)
except IOError:
return ImageFont.load_default()
@app.route('/api')
def generate_profile():
""" Generate a profile card with user details and a chosen profile picture & background. """
# 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_choice = request.args.get('pfp', '1')
bg_choice = request.args.get('bg', '1')
# Validate and load background
bg_path = BG_OPTIONS.get(bg_choice, "bg1.png")
if not os.path.exists(bg_path):
return f"Error: Background '{bg_choice}' not found.", 400
bg = Image.open(bg_path).convert("RGBA")
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
pfp_y = 80 # Adjusted to align better
# Validate and load profile picture
pfp_path = PFP_OPTIONS.get(pfp_choice, "pfp1.png")
if not os.path.exists(pfp_path):
return f"Error: Profile picture '{pfp_choice}' not found.", 400
pfp = Image.open(pfp_path).convert("RGBA")
# Resize and mask the profile picture (circular crop)
pfp = pfp.resize((pfp_size, pfp_size), Image.LANCZOS)
mask = Image.new("L", (pfp_size, pfp_size), 0)
mask_draw = ImageDraw.Draw(mask)
mask_draw.ellipse((0, 0, pfp_size, pfp_size), fill=255)
# Create a circular profile picture
circular_pfp = Image.new("RGBA", (pfp_size, pfp_size), (0, 0, 0, 0))
circular_pfp.paste(pfp, (0, 0), mask)
# Create a white border
border_size = 10
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(circular_pfp, (border_size // 2, border_size // 2), mask)
# Paste profile picture onto background
bg.paste(border, (pfp_x - border_size // 2, pfp_y - border_size // 2), border_mask)
# **TEXT POSITIONING**
name_x = pfp_x + pfp_size + 40 # Name beside profile picture
name_y = pfp_y + (pfp_size // 3) # Align vertically with profile picture
text_color = (255, 255, 255)
# Function to resize text dynamically
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
max_text_width = W - name_x - 50
name_font = fit_text(name, max_text_width, font_large)
# **Draw name beside profile picture**
draw.text((name_x, name_y), name, font=name_font, fill=text_color)
# **Other details BELOW profile picture**
info_x = pfp_x
info_y = pfp_y + pfp_size + 70 # Below the profile picture
text_spacing = 45 # Space between text lines
draw.text((info_x, info_y), f"Rank: {rank}", font=font_medium, fill=text_color)
draw.text((info_x, info_y + text_spacing), f"Balance: {balance}", font=font_medium, fill=text_color)
draw.text((info_x, info_y + 2 * 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 image
response = send_file(output_path, mimetype='image/png')
# Cleanup saved files
if os.path.exists(output_path):
os.remove(output_path)
return response
if __name__ == '__main__':
app.run(host='0.0.0.0', port=7860, debug=True)