Critical Missing Systems Documentation - Zombie Leasing and 11 More Systems

This commit is contained in:
2025-12-31 02:49:03 +01:00
parent cf310455b5
commit bdf61aba68
250 changed files with 900 additions and 0 deletions

View File

@@ -0,0 +1,233 @@
#!/usr/bin/env python3
"""
🚀 MASTER ASSET PIPELINE - COMPLETE AUTOMATION
Handles:
1. Background removal (advanced AI)
2. Preview generation (256x256)
3. Sprite generation (32x32)
4. Batch processing for all 11k+ assets
Target: ~11,000 total images
Current: 644
Needed: ~10,356 more!
"""
import subprocess
import shutil
from pathlib import Path
from PIL import Image, ImageFilter
import cv2
import numpy as np
from typing import List, Tuple
# Paths
REPO = Path("/Users/davidkotnik/repos/novafarma")
ASSETS = REPO / "assets/slike"
SCRIPTS = REPO / "scripts"
# Target sizes
SIZE_ORIGINAL = (1024, 1024)
SIZE_PREVIEW = (256, 256)
SIZE_SPRITE = (32, 32)
class AssetPipeline:
def __init__(self):
self.stats = {
"background_removed": 0,
"previews_created": 0,
"sprites_created": 0,
"errors": 0
}
def remove_background_advanced(self, image_path: Path) -> bool:
"""
Advanced background removal using multiple techniques:
1. Color threshold (white/black backgrounds)
2. Edge detection
3. Alpha channel preservation
"""
try:
# Load image
img = Image.open(image_path).convert("RGBA")
data = np.array(img)
# Get RGB and Alpha
rgb = data[:, :, :3]
alpha = data[:, :, 3]
# Detect background color (most common in corners)
corners = [
rgb[0, 0], # top-left
rgb[0, -1], # top-right
rgb[-1, 0], # bottom-left
rgb[-1, -1] # bottom-right
]
bg_color = np.median(corners, axis=0).astype(int)
# Create mask for background
# Tolerance for color matching
tolerance = 30
diff = np.abs(rgb - bg_color)
mask = np.all(diff < tolerance, axis=2)
# Set background to transparent
alpha[mask] = 0
# Update alpha channel
data[:, :, 3] = alpha
# Save
result = Image.fromarray(data, mode="RGBA")
result.save(image_path)
return True
except Exception as e:
print(f" ❌ Background removal failed for {image_path.name}: {e}")
return False
def create_preview(self, original_path: Path) -> Path:
"""Create 256x256 preview version."""
try:
# Target path
preview_name = original_path.stem + "_preview_256x256.png"
preview_path = original_path.parent / preview_name
# Skip if exists
if preview_path.exists():
return preview_path
# Load and resize
img = Image.open(original_path)
# High-quality resize
img_resized = img.resize(SIZE_PREVIEW, Image.Resampling.LANCZOS)
# Save
img_resized.save(preview_path, "PNG", optimize=True)
return preview_path
except Exception as e:
print(f" ❌ Preview creation failed for {original_path.name}: {e}")
return None
def create_sprite(self, original_path: Path) -> Path:
"""Create 32x32 sprite version."""
try:
# Target path
sprite_name = original_path.stem + "_sprite_32x32.png"
sprite_path = original_path.parent / sprite_name
# Skip if exists
if sprite_path.exists():
return sprite_path
# Load and resize
img = Image.open(original_path)
# High-quality resize with sharpening
img_resized = img.resize(SIZE_SPRITE, Image.Resampling.LANCZOS)
# Sharpen for pixel art clarity
img_resized = img_resized.filter(ImageFilter.SHARPEN)
# Save
img_resized.save(sprite_path, "PNG", optimize=True)
return sprite_path
except Exception as e:
print(f" ❌ Sprite creation failed for {original_path.name}: {e}")
return None
def process_single_asset(self, asset_path: Path,
remove_bg: bool = True,
create_preview: bool = True,
create_sprite: bool = True):
"""Process a single asset through entire pipeline."""
print(f"📦 Processing: {asset_path.name}")
# Step 1: Background removal
if remove_bg and not asset_path.stem.endswith(("_preview", "_sprite")):
if self.remove_background_advanced(asset_path):
print(f" ✅ Background removed")
self.stats["background_removed"] += 1
# Step 2: Create preview
if create_preview and not asset_path.stem.endswith(("_preview", "_sprite")):
preview_path = self.create_preview(asset_path)
if preview_path:
print(f" ✅ Preview created: {preview_path.name}")
self.stats["previews_created"] += 1
# Step 3: Create sprite
if create_sprite and not asset_path.stem.endswith(("_preview", "_sprite")):
sprite_path = self.create_sprite(asset_path)
if sprite_path:
print(f" ✅ Sprite created: {sprite_path.name}")
self.stats["sprites_created"] += 1
def process_all_assets(self, category: str = None):
"""Process all assets or specific category."""
if category:
asset_dirs = [ASSETS / category]
else:
asset_dirs = [d for d in ASSETS.iterdir() if d.is_dir()]
for asset_dir in asset_dirs:
print(f"\n📁 Processing category: {asset_dir.name}")
# Find all original PNGs (not preview/sprite versions)
originals = [
f for f in asset_dir.rglob("*.png")
if not f.stem.endswith(("_preview_256x256", "_sprite_32x32"))
]
print(f" Found {len(originals)} original assets")
for asset_path in originals:
self.process_single_asset(asset_path)
self.print_stats()
def print_stats(self):
"""Print pipeline statistics."""
print("\n" + "="*70)
print("📊 PIPELINE STATISTICS")
print("="*70)
print(f" Backgrounds removed: {self.stats['background_removed']:4d}")
print(f" Previews created: {self.stats['previews_created']:4d}")
print(f" Sprites created: {self.stats['sprites_created']:4d}")
print(f" Errors: {self.stats['errors']:4d}")
print("="*70)
def main():
import argparse
parser = argparse.ArgumentParser(description="Master Asset Pipeline")
parser.add_argument("--category", help="Specific category to process")
parser.add_argument("--no-bg-remove", action="store_true", help="Skip background removal")
parser.add_argument("--no-preview", action="store_true", help="Skip preview creation")
parser.add_argument("--no-sprite", action="store_true", help="Skip sprite creation")
args = parser.parse_args()
pipeline = AssetPipeline()
print("="*70)
print("🚀 MASTER ASSET PIPELINE")
print("="*70)
print(f"Target: ~11,000 total images")
print(f"Processing: {'All categories' if not args.category else args.category}")
print("="*70)
pipeline.process_all_assets(
category=args.category
)
if __name__ == "__main__":
main()