feat(gamedev): ronda 1 — pixelize + luma→alpha + export-godot (grupo gamedev)
Tres funciones CPU-only del lote gamedev 2D + 2 helpers puros + grupo de capacidad: - comfyui_pixelize_image_py_ml (impure): Fase 2 pixelart — downscale nearest + cuantizacion a N colores / paleta fija (game-boy/pico-8/nes) + re-upscale nearest. - comfyui_matting_luma_to_alpha_py_ml (impure): frame VFX sobre negro -> RGBA por luminancia ponderada (translucidos con additive blend). - comfyui_export_asset_to_godot_py_pipelines (impure): puente ComfyUI -> Godot 4 — copia a res://assets/<dir> por kind + .import por tipo + filtro Nearest si pixelart + reimport headless best-effort. Compone los 2 helpers puros. - godot_map_asset_dir_py_core, godot_clean_asset_name_py_core (pure): nucleos reutilizables del pipeline. - docs/capabilities/gamedev-2d.md + INDEX: grupo nuevo gamedev. Tests 33/33 verdes (offline PIL/numpy). Golden real verificado: asset de ~/ComfyUI/output -> /tmp/godot_test_proj con .import correcto y reimport headless real de Godot 4.7. Sin GPU, sin red, sin tocar proyectos del usuario. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
"""Tests de comfyui_pixelize_image (offline, sin red ni GPU; PIL/numpy)."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from ml.comfyui_pixelize_image import comfyui_pixelize_image # noqa: E402
|
||||
|
||||
|
||||
def _noisy_png(path, w=256, h=256):
|
||||
"""PNG ruidoso con cientos de colores (simula crudo borroso de IA)."""
|
||||
rng = np.random.default_rng(7)
|
||||
arr = rng.integers(0, 256, size=(h, w, 3), dtype=np.uint8)
|
||||
Image.fromarray(arr, "RGB").save(path)
|
||||
return path
|
||||
|
||||
|
||||
def test_golden_downscale_quantize(tmp_path):
|
||||
src = _noisy_png(str(tmp_path / "raw.png"))
|
||||
dst = str(tmp_path / "pixel.png")
|
||||
res = comfyui_pixelize_image(src, dst, downscale=8, colors=16)
|
||||
assert res["ok"] is True, res["error"]
|
||||
assert os.path.isfile(dst)
|
||||
assert res["size"] == [256, 256] # upscale_back=True conserva tamano
|
||||
assert res["n_colors_final"] <= 16 # cuantizado a <=16 colores
|
||||
|
||||
|
||||
def test_no_upscale_back_keeps_small(tmp_path):
|
||||
src = _noisy_png(str(tmp_path / "raw.png"))
|
||||
dst = str(tmp_path / "small.png")
|
||||
res = comfyui_pixelize_image(src, dst, downscale=8, colors=16, upscale_back=False)
|
||||
assert res["ok"] is True
|
||||
assert res["size"] == [32, 32] # 256//8
|
||||
|
||||
|
||||
def test_edge_fixed_palette_game_boy(tmp_path):
|
||||
src = _noisy_png(str(tmp_path / "raw.png"))
|
||||
dst = str(tmp_path / "gb.png")
|
||||
res = comfyui_pixelize_image(src, dst, palette="game-boy")
|
||||
assert res["ok"] is True, res["error"]
|
||||
assert res["n_colors_final"] <= 4 # paleta Game Boy = 4 colores
|
||||
|
||||
|
||||
def test_edge_palette_list_hex(tmp_path):
|
||||
src = _noisy_png(str(tmp_path / "raw.png"))
|
||||
dst = str(tmp_path / "pal.png")
|
||||
res = comfyui_pixelize_image(src, dst, palette=["#000000", "#ffffff", "#ff0000"])
|
||||
assert res["ok"] is True
|
||||
assert res["n_colors_final"] <= 3
|
||||
|
||||
|
||||
def test_edge_downscale_1_only_quantizes(tmp_path):
|
||||
src = _noisy_png(str(tmp_path / "raw.png"))
|
||||
dst = str(tmp_path / "q.png")
|
||||
res = comfyui_pixelize_image(src, dst, downscale=1, colors=8)
|
||||
assert res["ok"] is True
|
||||
assert res["size"] == [256, 256]
|
||||
assert res["n_colors_final"] <= 8
|
||||
|
||||
|
||||
def test_error_missing_src(tmp_path):
|
||||
res = comfyui_pixelize_image(str(tmp_path / "nope.png"), str(tmp_path / "o.png"))
|
||||
assert res["ok"] is False
|
||||
assert "no existe" in res["error"]
|
||||
|
||||
|
||||
def test_error_downscale_zero(tmp_path):
|
||||
src = _noisy_png(str(tmp_path / "raw.png"))
|
||||
res = comfyui_pixelize_image(src, str(tmp_path / "o.png"), downscale=0)
|
||||
assert res["ok"] is False
|
||||
assert "downscale" in res["error"]
|
||||
|
||||
|
||||
def test_error_bad_palette(tmp_path):
|
||||
src = _noisy_png(str(tmp_path / "raw.png"))
|
||||
res = comfyui_pixelize_image(src, str(tmp_path / "o.png"), palette="not-a-palette")
|
||||
assert res["ok"] is False
|
||||
assert "paleta" in res["error"].lower()
|
||||
Reference in New Issue
Block a user