Skip to content

[#74] Economical-fidelity color default + painterly-grain detail level + postprocess perf#75

Merged
realproject7 merged 1 commit into
mainfrom
task/74-economical-fidelity
Jun 25, 2026
Merged

[#74] Economical-fidelity color default + painterly-grain detail level + postprocess perf#75
realproject7 merged 1 commit into
mainfrom
task/74-economical-fidelity

Conversation

@realproject7

Copy link
Copy Markdown
Owner

Fixes #74. Version 0.4.2 → 0.5.0.

What

Makes the default color engine produce faithful yet economical SVGs — keeping the deliberate detail an artist drew (dots, stipple, fine texture) while collapsing only anti-alias/compression fringes — and adds an on-demand max-grain mode for painterly art. Plus a large postprocess speedup that benefits every colour-rich output.

1. Detail-aware region merge (economical fidelity)

In the coverage path a small region merges into its nearest neighbour only when that neighbour is within a ΔE76 threshold (anti-alias / compression noise); a distinct-colour mark farther than it (a dot/stipple/texture drawn on purpose) is kept. One lever delivers both economy and fidelity — no separate node-reduction pass, stipple gate, or complexity estimator.

  • preprocess._merge_small_regions(noise_de) + quantize_coverage(region_noise_de=) + PreprocessOptions.coverage_region_noise_de (default 0.0 = legacy merge-everything; fully backward compatible — all other callers/tests unaffected).
  • pipeline coverage operating point becomes the validated faithful-economical default; COVERAGE_NOISE_DE maps the existing --detail dial to the threshold.

2. --detail high = painterly brush-grain

At --detail high the coverage path disables the pre-trace flatten and raises its path cap (_COVERAGE_MAX_PATHS_HIGH) so grain-rich output is kept rather than discarded to the baseline path. Lets textured art reach the reference target's grain density on demand (fidelity over economy). A misgated photo still explodes past the high cap and safely falls back.

3. Postprocess perf (every colour-rich output)

_consolidate ran an O(n²) pairwise ΔE scan and recomputed RGB→LAB on every comparison (~30 M calls / ~99 s on a grain-rich trace). Now: short-circuit to identity when palette_threshold <= 0 (the coverage path, where consolidation is a guaranteed no-op) + lru_cache on RGB→LAB. A max-fidelity textured convert: ~110 s → ~12 s, byte-identical output.

Results (vs reference target, 21-image illustration set)

  • Bytes 0.2–2.0× reference (was 8–13×); time 6–16 s (was up to 218 s); 14/21 ≥ 0.90 SSIM-to-reference; detail (dots/stipple/texture/outlines) visually preserved.
  • Heavily-textured outlier at --detail high: full grain density (≈ reference) in ~12 s.

Safety / no-regression

  • Default (normal) color output byte-identical where unchanged — corpus goldens green.
  • Flat/simple art unaffected (Priority EPIC: svgsmith — agent-native self-verifying raster→SVG vectorizer #1); gradients unaffected (smooth = all low-ΔE, gate never fires); photos protected by the coverage path-count fallback.
  • Full suite green except the known env-only test_version_is_single_sourced (editable-metadata artifact; passes in CI). ruff check src tests clean.
  • New tests: test_merge_small_regions_noise_de_keeps_distinct_marks, test_coverage_noise_de_dial_orders_detail_levels, test_palette_threshold_zero_merges_nothing.

dist built + twine check PASSED (svgsmith-0.5.0).

…l + postprocess perf

Detail-aware region merge: a small region merges into its nearest neighbour only
when that neighbour is within a ΔE76 threshold (anti-alias / compression noise);
a distinct-colour mark farther than it (a dot/stipple/texture drawn on purpose)
is KEPT. Collapses noise for economy/speed while preserving designer-detail.

- preprocess: _merge_small_regions(noise_de) + quantize_coverage(region_noise_de=)
  + PreprocessOptions.coverage_region_noise_de (default 0.0 = legacy, backward compat)
- pipeline: coverage operating point becomes the faithful-economical default;
  COVERAGE_NOISE_DE maps the --detail dial to the threshold. --detail high disables
  flatten + raises the coverage path cap so painterly brush-grain survives.
- postprocess: _consolidate short-circuits to identity when palette_threshold <= 0
  (coverage path = a no-op) and lru_cache on RGB->LAB; a grain-rich convert drops
  ~110s -> ~12s with byte-identical output.

Default color output now keeps deliberate detail and is economical (≈ reference-target
bytes vs the old 8-13x); flat/simple art unchanged (corpus goldens byte-identical).
Tests added for the noise_de gate, the detail->threshold ordering, and the
threshold<=0 identity. Version 0.4.2 -> 0.5.0.

Fixes #74

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@realproject7 realproject7 merged commit 86c7c57 into main Jun 25, 2026
4 checks passed
@realproject7 realproject7 deleted the task/74-economical-fidelity branch June 25, 2026 00:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Economical-fidelity color default (detail-aware merge) + painterly-grain detail level + postprocess perf

1 participant