summaryrefslogtreecommitdiff
path: root/extras/html/themes/create_retro_screenshots.py
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-06-22 22:14:11 +0300
committerPaul Buetow <paul@buetow.org>2025-06-22 22:14:11 +0300
commit2b78e5fcdf303f7055a67e13c5968e9ed92f56df (patch)
treeaa64ddf518419c807782ce302a62ff36da79fca2 /extras/html/themes/create_retro_screenshots.py
parent3af674aebad9e3792fbf13b3cbda7b1691b1f4f3 (diff)
Replace themes with 50 retro-futuristic single-column themes
- Removed previous multi-layout themes - Generated 50 new retro/retro-futuristic themes with: - Single column layout only - Minimum 1200px width for modern displays - Retro computing aesthetics (terminal, CRT, synthwave, etc.) - Various visual effects: scanlines, CRT, grid, dots, terminal - Monospace typography throughout - Theme palettes include: - Classic terminal green - Amber CRT monitors - Synthwave purple/pink - Matrix green - DOS blue/white - Cyberpunk neon - And more retro color schemes - Updated index.html with retro-themed gallery interface - All themes W3C CSS validated - Proper font licensing maintained - Screenshot previews for all themes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Diffstat (limited to 'extras/html/themes/create_retro_screenshots.py')
-rwxr-xr-xextras/html/themes/create_retro_screenshots.py195
1 files changed, 195 insertions, 0 deletions
diff --git a/extras/html/themes/create_retro_screenshots.py b/extras/html/themes/create_retro_screenshots.py
new file mode 100755
index 0000000..0b7d55e
--- /dev/null
+++ b/extras/html/themes/create_retro_screenshots.py
@@ -0,0 +1,195 @@
+#!/usr/bin/env python3
+
+import os
+from pathlib import Path
+from PIL import Image, ImageDraw, ImageFont
+import re
+import json
+
+def extract_theme_colors(css_file):
+ """Extract color scheme from CSS file"""
+ with open(css_file, 'r') as f:
+ css_content = f.read()
+
+ colors = {}
+ patterns = {
+ 'background': r'--color-bg:\s*([#\w]+);',
+ 'text': r'--color-text:\s*([#\w]+);',
+ 'primary': r'--color-primary:\s*([#\w]+);',
+ 'secondary': r'--color-secondary:\s*([#\w]+);',
+ 'accent': r'--color-accent:\s*([#\w]+);',
+ 'glow': r'--color-glow:\s*([#\w]+);'
+ }
+
+ for name, pattern in patterns.items():
+ match = re.search(pattern, css_content)
+ if match:
+ colors[name] = match.group(1)
+
+ return colors
+
+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_retro_preview(theme_name, colors, effect_type, output_path):
+ """Create a retro-themed preview"""
+ width, height = 400, 300
+
+ # Convert colors
+ bg_rgb = hex_to_rgb(colors.get('background', '#000000'))
+ text_rgb = hex_to_rgb(colors.get('text', '#00ff00'))
+ primary_rgb = hex_to_rgb(colors.get('primary', '#00ff00'))
+ secondary_rgb = hex_to_rgb(colors.get('secondary', '#00cc00'))
+
+ # Create base image
+ img = Image.new('RGB', (width, height), color=bg_rgb)
+ draw = ImageDraw.Draw(img)
+
+ # Load monospace font
+ font_paths = [
+ "/usr/share/fonts/truetype/liberation/LiberationMono-Bold.ttf",
+ "/usr/share/fonts/truetype/dejavu/DejaVuSansMono-Bold.ttf",
+ "/System/Library/Fonts/Monaco.ttf",
+ "C:\\Windows\\Fonts\\consola.ttf"
+ ]
+
+ title_font = None
+ body_font = None
+ small_font = None
+
+ for font_path in font_paths:
+ if os.path.exists(font_path):
+ try:
+ title_font = ImageFont.truetype(font_path, 20)
+ body_font = ImageFont.truetype(font_path, 12)
+ small_font = ImageFont.truetype(font_path, 10)
+ break
+ except:
+ continue
+
+ if not title_font:
+ title_font = ImageFont.load_default()
+ body_font = ImageFont.load_default()
+ small_font = ImageFont.load_default()
+
+ # Add effect overlay
+ if effect_type == "scanlines":
+ for y in range(0, height, 4):
+ draw.line([(0, y), (width, y)], fill=(255, 255, 255, 10), width=1)
+ elif effect_type == "grid":
+ for x in range(0, width, 20):
+ draw.line([(x, 0), (x, height)], fill=(255, 255, 255, 8), width=1)
+ for y in range(0, height, 20):
+ draw.line([(0, y), (width, y)], fill=(255, 255, 255, 8), width=1)
+ elif effect_type == "dots":
+ for x in range(10, width, 20):
+ for y in range(10, height, 20):
+ draw.ellipse([(x-1, y-1), (x+1, y+1)], fill=primary_rgb + (30,))
+ elif effect_type == "crt":
+ # Curved edges effect
+ overlay = Image.new('RGBA', (width, height), (0, 0, 0, 0))
+ overlay_draw = ImageDraw.Draw(overlay)
+ for i in range(20):
+ alpha = int(255 * (i / 20))
+ overlay_draw.rectangle([(i, i), (width-i, height-i)],
+ fill=(0, 0, 0, 0),
+ outline=(0, 0, 0, alpha),
+ width=2)
+ img = Image.alpha_composite(img.convert('RGBA'), overlay).convert('RGB')
+ draw = ImageDraw.Draw(img)
+
+ # Terminal prompt style header
+ if effect_type == "terminal" or "terminal" in theme_name:
+ draw.text((10, 10), f"$ theme --preview {theme_name}",
+ fill=primary_rgb, font=body_font)
+ draw.text((10, 30), "> LOADING...", fill=secondary_rgb, font=small_font)
+ y_offset = 60
+ else:
+ # Regular header
+ draw.text((10, 10), theme_name.replace('_', ' ').upper(),
+ fill=primary_rgb, font=title_font)
+ y_offset = 40
+
+ # Draw retro-style content
+ draw.text((10, y_offset), "SYSTEM: RETRO THEME",
+ fill=secondary_rgb, font=body_font)
+
+ # Status lines
+ y_offset += 30
+ status_lines = [
+ "WIDTH: 1200PX MIN",
+ "LAYOUT: SINGLE COLUMN",
+ f"EFFECT: {effect_type.upper()}",
+ "STATUS: ACTIVE"
+ ]
+
+ for line in status_lines:
+ draw.text((10, y_offset), f"> {line}", fill=text_rgb, font=small_font)
+ y_offset += 15
+
+ # Draw some decorative elements
+ y_offset += 20
+ draw.rectangle([(10, y_offset), (width-10, y_offset+2)], fill=primary_rgb)
+
+ # Footer
+ draw.text((10, height-30), f"[{effect_type.upper()}]",
+ fill=secondary_rgb, font=small_font)
+ draw.text((width-100, height-30), "RETRO MODE",
+ fill=secondary_rgb, font=small_font)
+
+ # Add glow effect to text
+ if colors.get('glow'):
+ # Create a glow layer
+ glow_layer = Image.new('RGB', (width, height), bg_rgb)
+ glow_draw = ImageDraw.Draw(glow_layer)
+ glow_draw.text((10, 10), theme_name.replace('_', ' ').upper(),
+ fill=primary_rgb, font=title_font)
+ glow_layer = glow_layer.filter(ImageFilter.GaussianBlur(radius=2))
+ img = Image.blend(img, glow_layer, 0.3)
+
+ # Save image
+ img.save(output_path, quality=95, optimize=True)
+
+def main():
+ themes_dir = Path("/home/paul/git/gemtexter/extras/html/themes")
+ screenshots_dir = themes_dir / "screenshots"
+
+ # Load metadata
+ with open(themes_dir / "retro_themes_metadata.json", "r") as f:
+ themes_metadata = json.load(f)
+
+ print(f"Creating screenshots for {len(themes_metadata)} retro themes...")
+
+ for i, theme_info in enumerate(themes_metadata):
+ theme_name = theme_info['name']
+ theme_dir = themes_dir / theme_name
+
+ if not theme_dir.exists():
+ continue
+
+ # Extract colors from CSS
+ css_file = theme_dir / "style.css"
+ if css_file.exists():
+ colors = extract_theme_colors(css_file)
+ effect_type = theme_info.get('effect', 'none')
+
+ # Create screenshot
+ output_path = screenshots_dir / f"{theme_name}.png"
+ create_retro_preview(theme_name, colors, effect_type, output_path)
+
+ print(f"✓ [{i+1}/{len(themes_metadata)}] {theme_name}")
+
+ print("\nRetro theme screenshots created!")
+
+if __name__ == "__main__":
+ # Import after checking
+ try:
+ from PIL import ImageFilter
+ except ImportError:
+ print("Installing Pillow for image filtering...")
+ os.system("pip install Pillow")
+ from PIL import ImageFilter
+
+ main() \ No newline at end of file