diff --git a/levelup/generator/styles/default.py b/levelup/generator/styles/default.py index 34654d5..a9a2342 100644 --- a/levelup/generator/styles/default.py +++ b/levelup/generator/styles/default.py @@ -240,119 +240,85 @@ def generate_default_profile( # Create the stats layer with glass effect stats_layer = Image.new("RGBA", desired_card_size, (0, 0, 0, 0)) - # Define the stats area to be larger and more prominent + # Define the stats area (right side of the card) stats_area = ( - 450, # x1 - Start from the middle - 50, # y1 - Start higher up - 950, # x2 - Extend further right - 400 # y2 - Extend lower down + 400, # x1 - Start after profile picture + 20, # y1 - Start near top + 1000, # x2 - End near right edge + 430 # y2 - End near bottom ) # Create glass effect for stats area stats_bg = card.crop(stats_area) if stats_bg.mode != "RGBA": stats_bg = stats_bg.convert("RGBA") - glass_bg = imgtools.create_glass_effect(stats_bg, opacity=0.3, blur_radius=20) - stats_layer.paste(glass_bg, stats_area, glass_bg) # Use glass_bg as mask + glass_bg = imgtools.create_glass_effect(stats_bg, opacity=0.25, blur_radius=15) # Add rounded corners to the glass effect - stats_mask = imgtools.get_rounded_corner_mask(glass_bg, radius=30) + stats_mask = imgtools.get_rounded_corner_mask(glass_bg, radius=20) glass_bg.putalpha(stats_mask) - stats_layer.paste(glass_bg, stats_area, glass_bg) # Use glass_bg as mask again + stats_layer.paste(glass_bg, stats_area, glass_bg) # Draw stats with improved styling draw = ImageDraw.Draw(stats_layer) - font_size = 32 # Increased font size - font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), font_size) - # Add stats with icons and modern layout - icon_size = font_size + 8 # Slightly larger icons - spacing = icon_size + 15 # More spacing between items - - # Messages stat with icon - msg_y = stats_area[1] + 50 # Start lower down - msg_icon = "💬" - draw.text( - (stats_area[0] + 30, msg_y), - msg_icon, - font=font, - fill=stat_color, - ) - draw.text( - (stats_area[0] + 30 + spacing, msg_y), - f"{humanize_number(messages)}", - font=font, - fill=stat_color, - ) - - # Voice time stat with icon - voice_y = msg_y + spacing + 20 # Add extra padding between stats - voice_icon = "🎤" - draw.text( - (stats_area[0] + 30, voice_y), - voice_icon, - font=font, - fill=stat_color, - ) - draw.text( - (stats_area[0] + 30 + spacing, voice_y), - imgtools.abbreviate_time(voicetime), - font=font, - fill=stat_color, - ) - - # Stars stat with icon - star_y = voice_y + spacing + 20 # Add extra padding between stats - star_icon = "⭐" - draw.text( - (stats_area[0] + 30, star_y), - star_icon, - font=font, - fill=stat_color, - ) - draw.text( - (stats_area[0] + 30 + spacing, star_y), - f"{humanize_number(stars)}", - font=font, - fill=stat_color, - ) - - # Add XP progress bar with enhanced glass effect - progress = (current_xp - previous_xp) / (next_xp - previous_xp) - bar_width = stats_area[2] - stats_area[0] - 60 # Slightly narrower for padding - bar_height = 30 # Taller bar - progress_bar = imgtools.make_progress_bar( - bar_width, - bar_height, - progress, - color=level_bar_color, - background_color=(100, 100, 100, 160) # More visible background - ) - progress_bar_y = stats_area[3] - 60 # Move up slightly - stats_layer.paste(progress_bar, (stats_area[0] + 30, progress_bar_y), progress_bar) - # Add level text with enhanced modern styling level_text = f"LEVEL {level}" if prestige > 0: level_text = f"P{prestige} • {level_text}" - level_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), 48) # Larger font - level_y = stats_area[1] + 10 # Position at the top of stats area + level_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), 48) + level_y = stats_area[1] + 20 draw.text( - (stats_area[0] + 30, level_y), + (stats_area[0] + 20, level_y), level_text, font=level_font, fill=user_color, - stroke_width=3, # Thicker stroke + stroke_width=2, stroke_fill=(0, 0, 0) ) - # Add XP text below progress bar + # Stats section + font_size = 32 + font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), font_size) + spacing = 50 # Vertical spacing between stats + + # Starting positions + start_x = stats_area[0] + 20 + start_y = level_y + 80 + + # Messages stat + draw.text((start_x, start_y), "💬", font=font, fill=stat_color) + draw.text((start_x + 40, start_y), f"{humanize_number(messages)}", font=font, fill=stat_color) + + # Voice time stat + draw.text((start_x, start_y + spacing), "🎤", font=font, fill=stat_color) + draw.text((start_x + 40, start_y + spacing), imgtools.abbreviate_time(voicetime), font=font, fill=stat_color) + + # Stars stat + draw.text((start_x, start_y + spacing * 2), "⭐", font=font, fill=stat_color) + draw.text((start_x + 40, start_y + spacing * 2), f"{humanize_number(stars)}", font=font, fill=stat_color) + + # Progress bar + progress = (current_xp - previous_xp) / (next_xp - previous_xp) + bar_width = stats_area[2] - stats_area[0] - 40 + bar_height = 25 + bar_y = stats_area[3] - 60 + + progress_bar = imgtools.make_progress_bar( + bar_width, + bar_height, + progress, + color=level_bar_color, + background_color=(100, 100, 100, 160) + ) + stats_layer.paste(progress_bar, (start_x, bar_y), progress_bar) + + # XP text xp_font = ImageFont.truetype(str(font_path or imgtools.DEFAULT_FONT), 24) xp_text = f"{humanize_number(current_xp)} / {humanize_number(next_xp)} XP" - xp_y = progress_bar_y + bar_height + 5 draw.text( - (stats_area[0] + 30, xp_y), + (start_x, bar_y + bar_height + 5), xp_text, font=xp_font, fill=stat_color, @@ -363,32 +329,31 @@ def generate_default_profile( # Composite the layers if not render_gif or (not pfp_animated and not bg_animated): if card.mode != "RGBA": - log.debug(f"Converting card mode '{card.mode}' to RGBA") card = card.convert("RGBA") if pfp.mode != "RGBA": - log.debug(f"Converting pfp mode '{pfp.mode}' to RGBA") pfp = pfp.convert("RGBA") # Fit the background to the desired size card = imgtools.fit_aspect_ratio(card, desired_card_size) - if blur: - blur_section = imgtools.blur_section(card, (blur_edge, 0, card.width, card.height)) - card.paste(blur_section, (blur_edge, 0), blur_section) - # Round the card corners - card = imgtools.round_image_corners(card, 45) + card = imgtools.round_image_corners(card, 20) # Create circular profile picture - pfp_size = (350, 350) # Set fixed size for profile picture + pfp_size = (320, 320) # Profile picture size pfp = pfp.resize(pfp_size, Image.Resampling.LANCZOS) pfp = imgtools.make_profile_circle(pfp) - # Calculate position to center the profile picture in the left section - pfp_x = (450 - pfp_size[0]) // 2 # Center in left section - pfp_y = (card.height - pfp_size[1]) // 2 # Center vertically + # Position profile picture on the left + pfp_x = 40 + pfp_y = (card.height - pfp_size[1]) // 2 - # Paste the items onto the card + # Add blur effect if enabled + if blur: + blur_section = imgtools.blur_section(card, (stats_area[0], 0, card.width, card.height)) + card.paste(blur_section, (stats_area[0], 0), blur_section) + + # Paste the layers card.paste(stats_layer, (0, 0), stats_layer) card.paste(pfp, (pfp_x, pfp_y), pfp)