- Phase 0: Rename all Kine references to Tabata (types, files, imports, i18n, analytics events) - Phase 1: Add test coverage for tabataProgramStore, workoutProgramStore, and color utils (47 tests) - Phase 2: Remove all `any` types from production code with proper typed replacements - Phase 3: Replace ~60 raw console.* calls with __DEV__-gated logger utility - Phase 4: Verify .DS_Store housekeeping (already clean) 0 TypeScript errors, 583/583 tests passing.
53 lines
1.3 KiB
Python
53 lines
1.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Remove background from mascot.gif frame-by-frame using rembg."""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
try:
|
|
from rembg import remove
|
|
from PIL import Image
|
|
except ImportError:
|
|
print("Missing dependencies. Install with:")
|
|
print(" pip install rembg Pillow")
|
|
sys.exit(1)
|
|
|
|
INPUT = Path(__file__).resolve().parent.parent / "assets" / "mascot.gif"
|
|
OUTPUT = Path(__file__).resolve().parent.parent / "assets" / "mascot_nobg.gif"
|
|
|
|
|
|
def main():
|
|
if not INPUT.exists():
|
|
print(f"Input not found: {INPUT}")
|
|
sys.exit(1)
|
|
|
|
print(f"Reading {INPUT}...")
|
|
original = Image.open(INPUT)
|
|
|
|
frames = []
|
|
durations = []
|
|
try:
|
|
while True:
|
|
durations.append(original.info.get("duration", 100))
|
|
frame = original.convert("RGBA")
|
|
print(f" Processing frame {len(frames) + 1}...")
|
|
frames.append(remove(frame))
|
|
original.seek(original.tell() + 1)
|
|
except EOFError:
|
|
pass
|
|
|
|
print(f"Saving {len(frames)} frames to {OUTPUT}...")
|
|
frames[0].save(
|
|
OUTPUT,
|
|
save_all=True,
|
|
append_images=frames[1:],
|
|
duration=durations,
|
|
loop=0,
|
|
disposal=2,
|
|
)
|
|
print(f"Done → {OUTPUT}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|