Skip to content

ritmo-tools pixel: one-pixel outlines, bent grids, a shrink that keeps strokes - #179

Merged
SandroMaglione merged 1 commit into
mainfrom
tools/pixel-outline-grid
Nov 3, 2026
Merged

SandroMaglione merged 1 commit into
mainfrom
tools/pixel-outline-grid

Conversation

@SandroMaglione

Copy link
Copy Markdown
Member

Ideas taken from ToPixel (https://github.com/daisuqe/ToPixel), a one-file browser tool that turns upscaled pixel art back into 1 dot = 1 px. That repository has no license, so this PR takes the ideas only and rewrites the code to fit the fixer's pipeline. Its sample image was used for local evaluation only and is not committed.

What changes

  • Outlines (recipe outlines: "auto" | "on" | "off", --outlines, Outlines on the page; default "auto"). When the picture's dark strokes are about one cell wide, a stroke that a grid line split between two pixels goes back to one pixel, and followed lines keep off dark strokes. On top of ToPixel's rule there are three guards, each added after it broke the reference sprites in testing:

    • The outline colour comes from the gap in the brightness histogram. A fixed margin above the darkest pixels swept in dark fill shades.
    • A pixel only goes if the outline stays connected without it.
    • Two strokes meeting (a T or a corner) are left alone, and so are stroke ends.

    The report's grid.outlines says whether it ran.

  • Follow lines is now "off" | "straight" | "bend":

    • straight places every cut at once with dynamic programming: each cut on an edge, every gap near the cell size, and the cell count kept. Before, each cut was placed one after another.
    • bend places the cuts separately in each row and column of cells, using that band's edges plus its neighbours'. That fits a grid the generator warped. The page and the preview draw bent lines.
  • Keep outlines when shrinking now carries outlines over as strokes:

    • every new pixel a stroke passes through is marked;
    • the marks are thinned back to one pixel without breaking a stroke;
    • one-pixel steps become diagonals.

    A lone dark pixel still does not grow into a block.

Breaking: a recipe's follow is no longer a boolean. true becomes "straight", and false becomes "off" (or the field is left out). The changeset carries the fix.

Measured

References: synthetic outlined sprites with ground truth, scaled by non-whole factors, then blurred and noised, with strokes drawn off the grid, cells uneven, and grid lines bent. Six seeds per case, with each sprite's own palette, so the error comes from the grid alone.

case before (off / old follow) after
all artifacts combined 4.0% / 9.2% wrong 1.1% (bend)
thin strokes off the grid 5.6% / 4.1% 3.9% (bend), outline recall 76% → 84%
thick strokes off the grid 5.5% / 8.0% 4.9% (bend + outlines), 5.4% (outlines alone)
clean, uneven, mildly bent 0.0–0.3% unchanged
sine-warped grid, 0.45 of a cell 4–8 wrong pixels 0 (bend)

Shrinking 48 → 32 px, outlined sprites (8 seeds): the old shrink broke 12 strokes into 95 pieces; the new one keeps 11 (stair steps 25 → 11). A one-pixel ring shrunk from 16 to 11 px used to lose its sides; now it stays whole (this is a test).

Honest limits:

  • On a real AI picture (ToPixel's sample dragon) the default fix changes little; bend cleans a few muddy cells.
  • On thick or thin strokes, bend wins on four seeds of six and loses on two.
  • Outline thinning alone gives a small gain, because our "read the middle" sampling already rarely doubles outlines.
  • None of this fixes a wrongly detected cell size: a strongly bent grid still fails detection, at a low confidence that says so.

Verify

  • pnpm run check passes.
  • pnpm --dir website build passes.
  • New tests are in packages/tools/test/outline.test.ts.

🤖 Generated with Claude Code

…s strokes

After ToPixel (https://github.com/daisuqe/ToPixel):

- Outlines (recipe `outlines`, --outlines, on by "auto" when the dark
  strokes are about one cell wide): a stroke split between two pixels goes
  back to one, guarded so outlines, corners, and stroke ends never break;
  followed lines keep off dark strokes.
- Follow lines is "off" | "straight" | "bend": straight places every cut
  at once (dynamic programming) instead of one after another; bend places
  them in each row and column of cells, for warped grids.
- Keep outlines when shrinking carries strokes over, thins them without
  breaking, and turns one-pixel steps into diagonals.

Breaking: a recipe's `follow` is "off" | "straight" | "bend", not a boolean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@SandroMaglione
SandroMaglione merged commit e078c2a into main Nov 3, 2026
5 checks passed
@SandroMaglione
SandroMaglione deleted the tools/pixel-outline-grid branch November 3, 2026 04:45
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.

1 participant