Bootstrap the repixelizer CLI project

This commit is contained in:
Meta Vens 2026-04-21 16:10:55 +01:00
commit aceefe46b2
24 changed files with 1398 additions and 0 deletions

18
tests/test_cli.py Normal file
View file

@ -0,0 +1,18 @@
from __future__ import annotations
from pathlib import Path
from repixelizer.cli import main
from repixelizer.io import save_rgba
from repixelizer.synthetic import fake_pixelize, make_emblem
def test_default_command_runs_without_explicit_run_subcommand(tmp_path: Path) -> None:
source = make_emblem(16, 16)
fake = fake_pixelize(source, upscale=8, phase_x=0.2, phase_y=0.25, blur_radius=0.4)
input_path = tmp_path / "input.png"
output_path = tmp_path / "output.png"
save_rgba(input_path, fake)
exit_code = main([str(input_path), "--out", str(output_path), "--steps", "8"])
assert exit_code == 0
assert output_path.exists()

22
tests/test_compare.py Normal file
View file

@ -0,0 +1,22 @@
from __future__ import annotations
from pathlib import Path
from repixelizer.compare import run_compare
from repixelizer.io import save_rgba
from repixelizer.synthetic import fake_pixelize, make_emblem
def test_compare_writes_comparison_artifacts(tmp_path: Path) -> None:
source = make_emblem(32, 32)
fake = fake_pixelize(source, upscale=10, phase_x=0.2, phase_y=0.3, blur_radius=0.5)
input_path = tmp_path / "input.png"
output_path = tmp_path / "output.png"
diagnostics_dir = tmp_path / "diagnostics"
save_rgba(input_path, fake)
payload = run_compare(input_path, output_path, diagnostics_dir=diagnostics_dir, steps=20)
assert output_path.exists()
assert (diagnostics_dir / "compare-sheet.png").exists()
assert (diagnostics_dir / "compare.csv").exists()
assert len(payload["rows"]) == 3

13
tests/test_inference.py Normal file
View file

@ -0,0 +1,13 @@
from __future__ import annotations
from repixelizer.inference import infer_lattice
from repixelizer.synthetic import fake_pixelize, make_emblem
def test_infer_lattice_recovers_emblem_scale() -> None:
source = make_emblem(32, 32)
fake = fake_pixelize(source, upscale=12, phase_x=0.2, phase_y=0.35, blur_radius=0.6)
result = infer_lattice(fake)
assert result.target_width in range(28, 37)
assert result.target_height in range(28, 37)
assert result.confidence >= 0.0

29
tests/test_palette.py Normal file
View file

@ -0,0 +1,29 @@
from __future__ import annotations
from pathlib import Path
from repixelizer.palette import load_palette, quantize_rgba
from repixelizer.synthetic import make_emblem
def test_load_gpl_palette(tmp_path: Path) -> None:
palette_path = tmp_path / "palette.gpl"
palette_path.write_text(
"GIMP Palette\nName: Test\nColumns: 2\n255 0 0 Red\n0 255 0 Green\n",
encoding="utf-8",
)
palette = load_palette(palette_path)
assert palette == [(255, 0, 0), (0, 255, 0)]
def test_strict_quantization_stays_in_palette() -> None:
rgba = make_emblem(8, 8)
palette = [(255, 0, 0), (0, 255, 0), (255, 255, 255)]
result = quantize_rgba(rgba, mode="strict", palette=palette)
assert result is not None
unique = {
tuple((pixel[:3] * 255.0).round().astype(int))
for pixel in result.rgba.reshape(-1, 4)
if pixel[3] > 0.05
}
assert unique.issubset(set(palette))

56
tests/test_pipeline.py Normal file
View file

@ -0,0 +1,56 @@
from __future__ import annotations
from pathlib import Path
from repixelizer.baselines import naive_resize_baseline
from repixelizer.metrics import coherence_breakdown
from repixelizer.pipeline import run_pipeline
from repixelizer.synthetic import fake_pixelize, make_emblem, make_sprite
def test_pipeline_writes_output_and_diagnostics(tmp_path: Path) -> None:
source = make_emblem(32, 32)
fake = fake_pixelize(source, upscale=10, phase_x=0.15, phase_y=0.25, blur_radius=0.5)
input_path = tmp_path / "input.png"
output_path = tmp_path / "output.png"
diagnostics_dir = tmp_path / "diagnostics"
from repixelizer.io import save_rgba
save_rgba(input_path, fake)
result = run_pipeline(input_path, output_path, diagnostics_dir=diagnostics_dir, steps=24)
assert output_path.exists()
assert (diagnostics_dir / "run.json").exists()
assert result.output_rgba.shape[0] == result.inference.target_height
assert result.output_rgba.shape[1] == result.inference.target_width
def test_pipeline_beats_naive_on_coherence_for_synthetic_emblem(tmp_path: Path) -> None:
source = make_emblem(32, 32)
fake = fake_pixelize(source, upscale=12, phase_x=0.2, phase_y=0.35, blur_radius=0.65)
input_path = tmp_path / "input.png"
output_path = tmp_path / "output.png"
from repixelizer.io import save_rgba
save_rgba(input_path, fake)
result = run_pipeline(input_path, output_path, steps=32)
naive = naive_resize_baseline(fake, width=result.inference.target_width, height=result.inference.target_height)
optimized_score = coherence_breakdown(result.output_rgba)["coherence_score"]
naive_score = coherence_breakdown(naive)["coherence_score"]
assert optimized_score >= naive_score
def test_pipeline_preserves_transparency_for_sprite(tmp_path: Path) -> None:
source = make_sprite(24, 24)
fake = fake_pixelize(source, upscale=9, phase_x=0.1, phase_y=0.22, blur_radius=0.45)
input_path = tmp_path / "input.png"
output_path = tmp_path / "output.png"
from repixelizer.io import save_rgba
save_rgba(input_path, fake)
result = run_pipeline(input_path, output_path, steps=20)
alpha = result.output_rgba[..., 3]
assert alpha.min() < 0.05
assert alpha.max() > 0.9