174 lines
5.3 KiB
Python
174 lines
5.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
TRANSPARENCY WIPE SCRIPT
|
|
Removes solid color backgrounds from PNG images
|
|
Author: HIPO
|
|
Date: 12.01.2026
|
|
"""
|
|
|
|
import os
|
|
from PIL import Image
|
|
import numpy as np
|
|
from pathlib import Path
|
|
|
|
def remove_solid_background(image_path, output_path, tolerance=30):
|
|
"""
|
|
Remove solid color background from image
|
|
|
|
Args:
|
|
image_path: Path to input image
|
|
output_path: Path to save output
|
|
tolerance: Color difference tolerance (0-255)
|
|
"""
|
|
try:
|
|
# Open image
|
|
img = Image.open(image_path).convert("RGBA")
|
|
data = np.array(img)
|
|
|
|
# Get corner colors (likely background)
|
|
corners = [
|
|
data[0, 0], # Top-left
|
|
data[0, -1], # Top-right
|
|
data[-1, 0], # Bottom-left
|
|
data[-1, -1] # Bottom-right
|
|
]
|
|
|
|
# Find most common corner color
|
|
bg_color = corners[0][:3] # Use top-left as default
|
|
|
|
# Create mask for background color
|
|
r, g, b, a = data.T
|
|
bg_r, bg_g, bg_b = bg_color
|
|
|
|
# Find pixels matching background color (within tolerance)
|
|
mask = (
|
|
(np.abs(r - bg_r) < tolerance) &
|
|
(np.abs(g - bg_g) < tolerance) &
|
|
(np.abs(b - bg_b) < tolerance)
|
|
)
|
|
|
|
# Make background transparent
|
|
data[..., 3][mask.T] = 0
|
|
|
|
# Save
|
|
result = Image.fromarray(data)
|
|
result.save(output_path, "PNG")
|
|
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"❌ Error processing {image_path}: {e}")
|
|
return False
|
|
|
|
def is_solid_background(image_path):
|
|
"""
|
|
Check if image likely has solid background
|
|
Returns: True if corners are similar color
|
|
"""
|
|
try:
|
|
img = Image.open(image_path).convert("RGBA")
|
|
data = np.array(img)
|
|
|
|
corners = [
|
|
tuple(data[0, 0]),
|
|
tuple(data[0, -1]),
|
|
tuple(data[-1, 0]),
|
|
tuple(data[-1, -1])
|
|
]
|
|
|
|
# Check if all corners are similar
|
|
first = corners[0][:3]
|
|
similar = all(
|
|
abs(c[0] - first[0]) < 30 and
|
|
abs(c[1] - first[1]) < 30 and
|
|
abs(c[2] - first[2]) < 30
|
|
for c in corners
|
|
)
|
|
|
|
# Also check if corner is white/black/gray
|
|
r, g, b = first
|
|
is_white = r > 240 and g > 240 and b > 240
|
|
is_black = r < 15 and g < 15 and b < 15
|
|
is_gray = abs(r - g) < 20 and abs(g - b) < 20
|
|
|
|
return similar and (is_white or is_black or is_gray)
|
|
|
|
except Exception as e:
|
|
return False
|
|
|
|
def batch_process_folder(folder_path, dry_run=True):
|
|
"""
|
|
Process all PNG images in folder
|
|
|
|
Args:
|
|
folder_path: Folder to process
|
|
dry_run: If True, only report what would be done
|
|
"""
|
|
folder = Path(folder_path)
|
|
processed = 0
|
|
skipped = 0
|
|
errors = 0
|
|
|
|
print(f"\n{'🔍 DRY RUN' if dry_run else '🔥 PROCESSING'}: {folder_path}")
|
|
print("=" * 60)
|
|
|
|
for img_path in folder.rglob("*.png"):
|
|
# Skip backup folders
|
|
if "BACKUP" in str(img_path) or "_backup" in str(img_path):
|
|
continue
|
|
|
|
# Check if needs processing
|
|
if is_solid_background(img_path):
|
|
if dry_run:
|
|
print(f"✅ Would process: {img_path.name}")
|
|
processed += 1
|
|
else:
|
|
print(f"🔄 Processing: {img_path.name}")
|
|
if remove_solid_background(img_path, img_path):
|
|
processed += 1
|
|
else:
|
|
errors += 1
|
|
else:
|
|
skipped += 1
|
|
|
|
print("\n" + "=" * 60)
|
|
print(f"📊 RESULTS:")
|
|
print(f" ✅ {'Would process' if dry_run else 'Processed'}: {processed}")
|
|
print(f" ⏭️ Skipped (already transparent): {skipped}")
|
|
if errors > 0:
|
|
print(f" ❌ Errors: {errors}")
|
|
print("=" * 60)
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
|
|
print("""
|
|
╔═══════════════════════════════════════════════════════════╗
|
|
║ 🎨 TRANSPARENCY WIPE TOOL v1.0 ║
|
|
║ By HIPO - Hipodevil666 Studios™ ║
|
|
╚═══════════════════════════════════════════════════════════╝
|
|
""")
|
|
|
|
if len(sys.argv) < 2:
|
|
print("Usage:")
|
|
print(" DRY RUN (safe): python3 transparency_wipe.py assets/references/ --dry-run")
|
|
print(" LIVE RUN: python3 transparency_wipe.py assets/references/ --live")
|
|
print("\nWARNING: ALWAYS run dry-run first!")
|
|
sys.exit(1)
|
|
|
|
folder = sys.argv[1]
|
|
dry_run = "--live" not in sys.argv
|
|
|
|
if not dry_run:
|
|
print("\n⚠️ WARNING: LIVE RUN MODE! This will modify images!")
|
|
response = input("Are you sure? Type 'YES' to continue: ")
|
|
if response != "YES":
|
|
print("❌ Cancelled.")
|
|
sys.exit(0)
|
|
|
|
batch_process_folder(folder, dry_run=dry_run)
|
|
|
|
print("\n✅ Done!")
|
|
if dry_run:
|
|
print("💡 Run with --live to actually process images")
|