Bootstrap the repixelizer CLI project
This commit is contained in:
commit
aceefe46b2
24 changed files with 1398 additions and 0 deletions
18
tests/test_cli.py
Normal file
18
tests/test_cli.py
Normal 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
22
tests/test_compare.py
Normal 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
13
tests/test_inference.py
Normal 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
29
tests/test_palette.py
Normal 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
56
tests/test_pipeline.py
Normal 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
|
||||
Loading…
Reference in a new issue