diff options
| author | Paul Buetow <paul@buetow.org> | 2025-06-22 22:14:11 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-06-22 22:14:11 +0300 |
| commit | 2b78e5fcdf303f7055a67e13c5968e9ed92f56df (patch) | |
| tree | aa64ddf518419c807782ce302a62ff36da79fca2 /extras/html/themes/create_retro_screenshots.py | |
| parent | 3af674aebad9e3792fbf13b3cbda7b1691b1f4f3 (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-x | extras/html/themes/create_retro_screenshots.py | 195 |
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 |
