222 lines
8.0 KiB
Python
222 lines
8.0 KiB
Python
#!/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}")
|