Refine profile card generation in default.py by adjusting layout dimensions for improved spacing, reducing font sizes, and enhancing the stats area design. Update the progress bar and XP text positioning for better visual clarity and overall aesthetics.
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run
This commit is contained in:
parent
4c99430d95
commit
694b91b69d
1 changed files with 68 additions and 63 deletions
|
@ -196,15 +196,15 @@ def generate_default_profile(
|
|||
if square:
|
||||
desired_card_size = (450, 450)
|
||||
else:
|
||||
# Reduce height for better proportions
|
||||
desired_card_size = (1050, 350)
|
||||
# Keep width but adjust height for better spacing
|
||||
desired_card_size = (1050, 300)
|
||||
|
||||
# Define the stats area with a modern glass effect
|
||||
stats_area = (
|
||||
400, # x1 - Start after profile picture
|
||||
20, # y1 - Start near top
|
||||
1000 if not square else 430, # x2 - End near right edge
|
||||
330 if not square else 430 # y2 - End near bottom
|
||||
380, # x1 - Start after profile picture (moved left slightly)
|
||||
15, # y1 - Start near top
|
||||
1020, # x2 - End near right edge
|
||||
285 # y2 - Reduced height
|
||||
)
|
||||
|
||||
# Create the stats layer with glass effect
|
||||
|
@ -213,7 +213,7 @@ def generate_default_profile(
|
|||
# Create a semi-transparent background for stats with modern blur effect
|
||||
glass = Image.new("RGBA", desired_card_size, (0, 0, 0, 0))
|
||||
glass_draw = ImageDraw.Draw(glass)
|
||||
glass_draw.rounded_rectangle(stats_area, radius=25, fill=(0, 0, 0, 95))
|
||||
glass_draw.rounded_rectangle(stats_area, radius=20, fill=(0, 0, 0, 95))
|
||||
|
||||
# Add a subtle gradient overlay for depth
|
||||
gradient = Image.new("RGBA", desired_card_size, (0, 0, 0, 0))
|
||||
|
@ -222,7 +222,7 @@ def generate_default_profile(
|
|||
opacity = int(60 * (1 - i/30))
|
||||
gradient_draw.rounded_rectangle(
|
||||
(stats_area[0], stats_area[1]+i, stats_area[2], stats_area[3]),
|
||||
radius=25,
|
||||
radius=20,
|
||||
fill=(255, 255, 255, opacity)
|
||||
)
|
||||
|
||||
|
@ -235,7 +235,7 @@ def generate_default_profile(
|
|||
for i in range(3):
|
||||
border_draw.rounded_rectangle(
|
||||
(stats_area[0]-i, stats_area[1]-i, stats_area[2]+i, stats_area[3]+i),
|
||||
radius=25,
|
||||
radius=20,
|
||||
outline=(155, 17, 30, 100-i*30),
|
||||
width=1
|
||||
)
|
||||
|
@ -248,68 +248,92 @@ def generate_default_profile(
|
|||
if prestige > 0:
|
||||
level_text = f"P{prestige} • {level_text}"
|
||||
|
||||
# Use larger font for level display
|
||||
level_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), 56)
|
||||
level_y = stats_area[1] + 15
|
||||
# Use smaller font for level display to prevent overlap
|
||||
level_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), 42)
|
||||
level_y = stats_area[1] + 10
|
||||
|
||||
# Add subtle text shadow for depth
|
||||
shadow_offset = 2
|
||||
draw.text(
|
||||
(stats_area[0] + 20 + shadow_offset, level_y + shadow_offset),
|
||||
(stats_area[0] + 15 + shadow_offset, level_y + shadow_offset),
|
||||
level_text,
|
||||
font=level_font,
|
||||
fill=(0, 0, 0, 100)
|
||||
)
|
||||
draw.text(
|
||||
(stats_area[0] + 20, level_y),
|
||||
(stats_area[0] + 15, level_y),
|
||||
level_text,
|
||||
font=level_font,
|
||||
fill=user_color
|
||||
)
|
||||
|
||||
# Stats section with improved layout
|
||||
title_font_size = 24
|
||||
value_font_size = 28
|
||||
title_font_size = 20 # Reduced font size
|
||||
value_font_size = 24 # Reduced font size
|
||||
title_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), title_font_size)
|
||||
value_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), value_font_size)
|
||||
spacing = 45 # Vertical spacing between stats
|
||||
spacing = 35 # Reduced spacing between stats
|
||||
|
||||
# Starting positions
|
||||
start_x = stats_area[0] + 20
|
||||
start_y = level_y + 80
|
||||
start_x = stats_area[0] + 15
|
||||
start_y = level_y + 60 # Reduced gap after level
|
||||
|
||||
# Helper function for stat rendering
|
||||
def draw_stat(y_pos, icon, title, value, color=stat_color):
|
||||
# Helper function for stat rendering with improved spacing
|
||||
def draw_stat(x_pos, y_pos, icon, title, value, color=stat_color):
|
||||
# Draw icon
|
||||
draw.text((start_x, y_pos), icon, font=value_font, fill=color)
|
||||
draw.text((x_pos, y_pos + 2), icon, font=value_font, fill=color)
|
||||
# Draw title
|
||||
draw.text((start_x + 40, y_pos), f"{title}:", font=title_font, fill=(200, 200, 200))
|
||||
title_x = x_pos + 30
|
||||
draw.text((title_x, y_pos), f"{title}:", font=title_font, fill=(200, 200, 200))
|
||||
# Calculate value position
|
||||
title_width = draw.textlength(f"{title}:", font=title_font)
|
||||
# Draw value with shadow for depth
|
||||
value_x = start_x + 40
|
||||
value_y = y_pos + title_font_size + 2
|
||||
draw.text((value_x + 1, value_y + 1), value, font=value_font, fill=(0, 0, 0, 100))
|
||||
draw.text((value_x, value_y), value, font=value_font, fill=color)
|
||||
return spacing + title_font_size + 5
|
||||
value_x = title_x + title_width + 5
|
||||
draw.text((value_x + 1, y_pos + 1), value, font=value_font, fill=(0, 0, 0, 100))
|
||||
draw.text((value_x, y_pos), value, font=value_font, fill=color)
|
||||
return spacing
|
||||
|
||||
# Draw each stat with title and value
|
||||
# Draw stats in two columns with better spacing
|
||||
left_column_x = start_x
|
||||
right_column_x = stats_area[0] + 300
|
||||
current_y = start_y
|
||||
current_y += draw_stat(current_y, "💬", "Messages", f"{humanize_number(messages)} sent")
|
||||
current_y += draw_stat(current_y, "🎤", "Voice Time", imgtools.abbreviate_time(voicetime))
|
||||
current_y += draw_stat(current_y, "⭐", "Stars", humanize_number(stars))
|
||||
|
||||
|
||||
# Left column stats
|
||||
current_y += draw_stat(left_column_x, current_y, "💬", "Messages", f"{humanize_number(messages)}")
|
||||
current_y += draw_stat(left_column_x, current_y, "🎤", "Voice", imgtools.abbreviate_time(voicetime))
|
||||
current_y += draw_stat(left_column_x, current_y, "⭐", "Stars", humanize_number(stars))
|
||||
|
||||
# Right column stats
|
||||
right_x = stats_area[0] + 300
|
||||
current_y = start_y
|
||||
if balance is not None:
|
||||
current_y += draw_stat(current_y, "💰", "Balance", f"{humanize_number(balance)} {currency_name}")
|
||||
current_y += draw_stat(current_y, "🏆", "Rank", f"#{humanize_number(position)}")
|
||||
current_y += draw_stat(right_column_x, current_y, "💰", "Balance", f"{humanize_number(balance)} {currency_name}")
|
||||
current_y += draw_stat(right_column_x, current_y, "🏆", "Rank", f"#{humanize_number(position)}")
|
||||
|
||||
# Progress bar with modern design
|
||||
bar_width = stats_area[2] - stats_area[0] - 40
|
||||
bar_height = 30
|
||||
bar_y = stats_area[3] - 60
|
||||
# Progress bar with modern design - moved down
|
||||
bar_width = stats_area[2] - stats_area[0] - 30 # Slightly narrower
|
||||
bar_height = 25 # Slightly shorter
|
||||
bar_y = stats_area[3] - 45 # Move up from bottom
|
||||
progress = (current_xp - previous_xp) / (next_xp - previous_xp)
|
||||
|
||||
# XP text above progress bar
|
||||
xp_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), 20) # Smaller font
|
||||
xp_text = f"EXP: {humanize_number(current_xp)} / {humanize_number(next_xp)}"
|
||||
xp_x = start_x + (bar_width - draw.textlength(xp_text, font=xp_font)) // 2
|
||||
|
||||
# Draw XP text with shadow
|
||||
draw.text(
|
||||
(xp_x + 1, bar_y - 25 + 1), # Moved closer to bar
|
||||
xp_text,
|
||||
font=xp_font,
|
||||
fill=(0, 0, 0, 100)
|
||||
)
|
||||
draw.text(
|
||||
(xp_x, bar_y - 25), # Moved closer to bar
|
||||
xp_text,
|
||||
font=xp_font,
|
||||
fill=(255, 255, 255)
|
||||
)
|
||||
|
||||
# Create progress bar background with gradient
|
||||
bar_bg = Image.new("RGBA", (bar_width, bar_height), (0, 0, 0, 100))
|
||||
progress_width = max(1, int(bar_width * progress))
|
||||
|
@ -341,26 +365,7 @@ def generate_default_profile(
|
|||
stats_layer.paste(bar_bg, (start_x, bar_y), bar_bg)
|
||||
stats_layer.paste(bar_progress_masked, (start_x, bar_y), bar_progress_masked)
|
||||
|
||||
# XP text with improved styling
|
||||
xp_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), 24)
|
||||
xp_text = f"EXP: {humanize_number(current_xp)} / {humanize_number(next_xp)}"
|
||||
xp_x = start_x + (bar_width - draw.textlength(xp_text, font=xp_font)) // 2
|
||||
|
||||
# Draw XP text with shadow
|
||||
draw.text(
|
||||
(xp_x + 1, bar_y - 30 + 1),
|
||||
xp_text,
|
||||
font=xp_font,
|
||||
fill=(0, 0, 0, 100)
|
||||
)
|
||||
draw.text(
|
||||
(xp_x, bar_y - 30),
|
||||
xp_text,
|
||||
font=xp_font,
|
||||
fill=(255, 255, 255)
|
||||
)
|
||||
|
||||
# Progress percentage
|
||||
# Progress percentage below bar
|
||||
percent_text = f"{int(progress * 100)}%"
|
||||
percent_x = start_x + (bar_width - draw.textlength(percent_text, font=xp_font)) // 2
|
||||
draw.text(
|
||||
|
@ -383,15 +388,15 @@ def generate_default_profile(
|
|||
card = imgtools.fit_aspect_ratio(card, desired_card_size)
|
||||
|
||||
# Round the card corners
|
||||
card = imgtools.round_image_corners(card, 25)
|
||||
card = imgtools.round_image_corners(card, 20)
|
||||
|
||||
# Create circular profile picture
|
||||
pfp_size = (300, 300) # Slightly smaller profile picture
|
||||
pfp_size = (270, 270) # Slightly smaller profile picture
|
||||
pfp = pfp.resize(pfp_size, Image.Resampling.LANCZOS)
|
||||
pfp = imgtools.make_profile_circle(pfp)
|
||||
|
||||
# Position profile picture on the left
|
||||
pfp_x = 50
|
||||
pfp_x = 55
|
||||
pfp_y = (desired_card_size[1] - pfp_size[1]) // 2
|
||||
|
||||
# Create a new image for final composition
|
||||
|
|
Loading…
Add table
Reference in a new issue