#!/usr/bin/env python3 """Generate PNG icons for card topics using PIL""" from PIL import Image, ImageDraw import os # Create png directory if it doesn't exist png_dir = r"c:\xampp\htdocs\loyaly_php\assets\images\png" os.makedirs(png_dir, exist_ok=True) # Icon size size = 200 padding = 20 # Define colors for different icons colors = { 'repeat': {'primary': '#8b5cf6', 'secondary': '#3b82f6'}, 'behavior': {'primary': '#10b981', 'secondary': '#06b6d4'}, 'highvalue': {'primary': '#f0be17', 'secondary': '#d97706'}, 'reduce': {'primary': '#ef4444', 'secondary': '#f97316'}, 'optimize': {'primary': '#8b5cf6', 'secondary': '#3b82f6'}, } def hex_to_rgb(hex_color): """Convert hex color to RGB tuple""" hex_color = hex_color.lstrip('#') return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4)) def create_repeat_visits_icon(): """Create repeat visits icon - circular arrow and store""" img = Image.new('RGBA', (size, size), (255, 255, 255, 0)) draw = ImageDraw.Draw(img) primary = hex_to_rgb(colors['repeat']['primary']) secondary = hex_to_rgb(colors['repeat']['secondary']) # Gradient-like effect with two colors # Store building draw.rectangle([20, 80, 80, 160], outline=primary, width=4) draw.rectangle([30, 100, 70, 160], outline=secondary, width=2) # Door draw.rectangle([25, 90, 45, 110], outline=primary, width=2) # Left window draw.rectangle([55, 90, 75, 110], outline=primary, width=2) # Right window # Circular arrows draw.arc([100, 30, 170, 100], 0, 270, fill=primary, width=5) draw.arc([80, 50, 180, 150], 200, 360, fill=secondary, width=5) # Arrow head draw.polygon([(170, 50), (155, 40), (160, 65)], fill=primary) img.save(os.path.join(png_dir, 'repeat_visits_icon.png')) print("✓ Created repeat_visits_icon.png") def create_behavior_icon(): """Create behavior icon - store with people tracking""" img = Image.new('RGBA', (size, size), (255, 255, 255, 0)) draw = ImageDraw.Draw(img) primary = hex_to_rgb(colors['behavior']['primary']) secondary = hex_to_rgb(colors['behavior']['secondary']) # Large store building draw.rectangle([20, 40, 180, 170], outline=primary, width=5) draw.rectangle([20, 40, 180, 60], fill=secondary) # Roof # Windows (grid) draw.rectangle([35, 55, 65, 85], outline=primary, width=2) draw.line([(50, 55), (50, 85)], fill=primary, width=1) draw.line([(35, 70), (65, 70)], fill=primary, width=1) draw.rectangle([115, 55, 145, 85], outline=primary, width=2) draw.line([(130, 55), (130, 85)], fill=primary, width=1) draw.line([(115, 70), (145, 70)], fill=primary, width=1) # Door draw.rectangle([75, 110, 105, 170], outline=secondary, width=3) draw.ellipse([98, 135, 108, 145], fill=secondary) # Door handle # People (dots) draw.ellipse([40, 95, 60, 115], outline=primary, width=2) draw.ellipse([120, 95, 140, 115], outline=primary, width=2) # Heat pattern lines draw.arc([35, 130, 165, 160], 0, 180, fill=secondary, width=2) draw.arc([40, 140, 160, 160], 0, 180, fill=secondary, width=1) img.save(os.path.join(png_dir, 'behavior_icon.png')) print("✓ Created behavior_icon.png") def create_highvalue_customer_icon(): """Create high-value customer icon - person with crown and stars""" img = Image.new('RGBA', (size, size), (255, 255, 255, 0)) draw = ImageDraw.Draw(img) primary = hex_to_rgb(colors['highvalue']['primary']) secondary = hex_to_rgb(colors['highvalue']['secondary']) # Head draw.ellipse([70, 30, 130, 90], outline=primary, width=4) # Body draw.line([(100, 90), (100, 130)], fill=primary, width=4) # Arms draw.line([(60, 110), (140, 110)], fill=primary, width=4) # Legs draw.line([(80, 130), (70, 170)], fill=primary, width=4) draw.line([(120, 130), (130, 170)], fill=primary, width=4) # Crown points draw.polygon([(40, 50), (50, 20), (60, 45)], fill=primary) draw.polygon([(75, 15), (85, 5), (95, 15)], fill=secondary) draw.polygon([(105, 15), (115, 5), (125, 15)], fill=secondary) draw.polygon([(140, 45), (150, 20), (160, 50)], fill=primary) # Crown band draw.ellipse([50, 50, 150, 70], outline=primary, width=3) # Stars def draw_star(x, y, size, color): points = [] for i in range(10): angle = i * 36 if i % 2 == 0: r = size else: r = size * 0.4 px = x + r * (1 if angle < 180 else -1) py = y + r points.append((px, py)) draw.polygon(points, fill=color) draw_star(30, 130, 12, primary) draw_star(170, 130, 12, secondary) img.save(os.path.join(png_dir, 'highvalue_customer_icon.png')) print("✓ Created highvalue_customer_icon.png") def create_reduce_waste_icon(): """Create reduce waste icon - trash can with reduction indicator""" img = Image.new('RGBA', (size, size), (255, 255, 255, 0)) draw = ImageDraw.Draw(img) primary = hex_to_rgb(colors['reduce']['primary']) secondary = hex_to_rgb(colors['reduce']['secondary']) # Trash can body draw.line([(50, 50), (70, 50)], fill=primary, width=4) # Handle left draw.line([(130, 50), (150, 50)], fill=primary, width=4) # Handle right draw.rectangle([60, 50, 140, 160], outline=primary, width=5) # Can dividers draw.line([(80, 60), (80, 160)], fill=primary, width=2) draw.line([(100, 60), (100, 160)], fill=primary, width=2) draw.line([(120, 60), (120, 160)], fill=primary, width=2) # X mark (reduction) draw.line([(75, 80), (125, 130)], fill=secondary, width=6) draw.line([(125, 80), (75, 130)], fill=secondary, width=6) # Reduction arrow draw.line([(100, 140), (100, 165)], fill=secondary, width=4) draw.polygon([(85, 155), (100, 165), (115, 155)], fill=secondary) img.save(os.path.join(png_dir, 'reduce_waste_icon.png')) print("✓ Created reduce_waste_icon.png") def create_optimize_ops_icon(): """Create optimize operations icon - gears and upward trend""" img = Image.new('RGBA', (size, size), (255, 255, 255, 0)) draw = ImageDraw.Draw(img) primary = hex_to_rgb(colors['optimize']['primary']) secondary = hex_to_rgb(colors['optimize']['secondary']) # Left gear draw.ellipse([30, 60, 90, 120], outline=primary, width=5) draw.ellipse([45, 75, 75, 105], outline=primary, width=2) # Gear teeth draw.line([(25, 90), (30, 90)], fill=primary, width=4) draw.line([(90, 90), (95, 90)], fill=primary, width=4) draw.line([(60, 55), (60, 60)], fill=primary, width=4) draw.line([(60, 120), (60, 125)], fill=primary, width=4) # Right gear draw.ellipse([ 110, 60, 170, 120], outline=primary, width=5) draw.ellipse([125, 75, 155, 105], outline=primary, width=2) # Gear teeth draw.line([(105, 90), (110, 90)], fill=primary, width=4) draw.line([(170, 90), (175, 90)], fill=primary, width=4) draw.line([(140, 55), (140, 60)], fill=primary, width=4) draw.line([(140, 120), (140, 125)], fill=primary, width=4) # Connecting line draw.line([(90, 90), (110, 90)], fill=secondary, width=5) # Upward trend arrow draw.line([(100, 160), (100, 140)], fill=secondary, width=5) draw.polygon([(100, 140), (85, 155), (115, 155)], fill=secondary) # Efficiency marks draw.ellipse([98, 50, 102, 54], fill=primary) draw.ellipse([50, 40, 54, 44], fill=secondary, outline=primary, width=1) draw.ellipse([146, 40, 150, 44], fill=secondary, outline=primary, width=1) img.save(os.path.join(png_dir, 'optimize_ops_icon.png')) print("✓ Created optimize_ops_icon.png") # Generate all icons if __name__ == '__main__': print("Generating PNG icons...") create_repeat_visits_icon() create_behavior_icon() create_highvalue_customer_icon() create_reduce_waste_icon() create_optimize_ops_icon() print(f"\nAll icons created in: {png_dir}")