tools/sprite-silhouette: sprite alpha to CSS shape-outside polygon #8

Merged
libby merged 3 commits from libby/sprite-silhouette into main 2026-11-10 23:14:07 +00:00
Member

Sprite alpha silhouette to a simplified polygon for CSS shape-outside: polygon(), for Void's Ratatoskr pose bubbles. Zero dependencies (Node; PNG alpha read with node:zlib). Entry: tools/sprite-silhouette/silhouette.mjs; first call, options, sample CSS and prior art (marching squares, potrace, Douglas-Peucker) are in its README. Ratatoskr is untouched; the poses directory is only read.

Output: JSON keyed by pose id (mind/label), each {width, height, points: [[x%, y%]...], css}. Defaults: alpha threshold 0.35, tolerance 1.5 px. Largest 8-connected shape only, holes ignored (one polygon is all shape-outside takes).

Verified: 10 tests pass (node --test tools/sprite-silhouette/silhouette.test.mjs): PNG filters, empty and fully opaque sprites, threshold edge (89 out, 90 in), simplified vs traced edge within tolerance both ways, holes, diagonal touch, islands, determinism, and all 99 catalogue poses. Not asserted by the suite: on all 99 poses at the defaults no polygon self-intersects (checked once). Not checked: how it looks in a browser.

Point counts per pose at defaults (all 99; min 52, max 203, mean 106):

  • eureka (12): neutral 63, happy 71, amused 68, thinking 72, annoyed 64, surprised 65, probe 61, inspect 81, report 73, hood-smug 57, concerned 61, determined 69
  • aqua (15): neutral 76, happy 71, amused 72, thinking 75, annoyed 82, surprised 80, concerned 82, fretful 73, weary 82, glare 79, smug 77, sigh 79, charging 85, delighted 82, content 68
  • heimdall (12): neutral 142, happy 133, amused 141, thinking 135, annoyed 143, surprised 145, concerned 139, determined 142, badge 129, barrier 104, protect 136, revoke 168
  • kiko (12): neutral 166, happy 157, amused 167, thinking 160, annoyed 161, surprised 156, shy-smile 153, uneasy 172, tinker 186, confetti 201, sprint 186, debug 160
  • weksa (12): neutral 176, happy 149, amused 170, thinking 148, annoyed 147, surprised 140, concerned 156, skeptical 138, map 153, fieldwork 196, argue 184, interlingua 153
  • void (12): neutral 53, happy 54, amused 52, thinking 50, annoyed 55, surprised 55, determined 55, glare 57, shrug 96, reading 58, point 76, deadpan 54
  • libby (12): neutral 98, happy 99, amused 94, thinking 90, annoyed 101, surprised 97, concerned 98, sad 106, stamp 106, research 104, shush 102, schema 91
  • nibu (12): neutral 82, happy 78, amused 79, thinking 74, annoyed 82, surprised 84, sheepish 75, pout 83, resolute 81, console 82, glitch 155, triumph 90

At tolerance 2: min 40, max 170, mean 87.

Not merged.

🤖 Generated with Claude Code

Sprite alpha silhouette to a simplified polygon for CSS `shape-outside: polygon()`, for Void's Ratatoskr pose bubbles. Zero dependencies (Node; PNG alpha read with `node:zlib`). Entry: `tools/sprite-silhouette/silhouette.mjs`; first call, options, sample CSS and prior art (marching squares, potrace, Douglas-Peucker) are in its README. Ratatoskr is untouched; the poses directory is only read. Output: JSON keyed by pose id (`mind/label`), each `{width, height, points: [[x%, y%]...], css}`. Defaults: alpha threshold 0.35, tolerance 1.5 px. Largest 8-connected shape only, holes ignored (one polygon is all shape-outside takes). Verified: 10 tests pass (`node --test tools/sprite-silhouette/silhouette.test.mjs`): PNG filters, empty and fully opaque sprites, threshold edge (89 out, 90 in), simplified vs traced edge within tolerance both ways, holes, diagonal touch, islands, determinism, and all 99 catalogue poses. Not asserted by the suite: on all 99 poses at the defaults no polygon self-intersects (checked once). Not checked: how it looks in a browser. Point counts per pose at defaults (all 99; min 52, max 203, mean 106): - **eureka** (12): neutral 63, happy 71, amused 68, thinking 72, annoyed 64, surprised 65, probe 61, inspect 81, report 73, hood-smug 57, concerned 61, determined 69 - **aqua** (15): neutral 76, happy 71, amused 72, thinking 75, annoyed 82, surprised 80, concerned 82, fretful 73, weary 82, glare 79, smug 77, sigh 79, charging 85, delighted 82, content 68 - **heimdall** (12): neutral 142, happy 133, amused 141, thinking 135, annoyed 143, surprised 145, concerned 139, determined 142, badge 129, barrier 104, protect 136, revoke 168 - **kiko** (12): neutral 166, happy 157, amused 167, thinking 160, annoyed 161, surprised 156, shy-smile 153, uneasy 172, tinker 186, confetti 201, sprint 186, debug 160 - **weksa** (12): neutral 176, happy 149, amused 170, thinking 148, annoyed 147, surprised 140, concerned 156, skeptical 138, map 153, fieldwork 196, argue 184, interlingua 153 - **void** (12): neutral 53, happy 54, amused 52, thinking 50, annoyed 55, surprised 55, determined 55, glare 57, shrug 96, reading 58, point 76, deadpan 54 - **libby** (12): neutral 98, happy 99, amused 94, thinking 90, annoyed 101, surprised 97, concerned 98, sad 106, stamp 106, research 104, shush 102, schema 91 - **nibu** (12): neutral 82, happy 78, amused 79, thinking 74, annoyed 82, surprised 84, sheepish 75, pout 83, resolute 81, console 82, glitch 155, triumph 90 At tolerance 2: min 40, max 170, mean 87. Not merged. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Zero-dependency Node tool: PNG alpha, threshold 0.35, outer contour of the largest
8-connected shape, Douglas-Peucker to a pixel tolerance, percent coordinates keyed by
cast-art pose id. Ten tests, including every pose in the shared catalogue.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
tools/sprite-silhouette: README sample uses the real void/neutral size
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest one-command multiplayer onboarding (pull_request) Has been cancelled
CultMesh portability and performance / windows-latest one-command multiplayer onboarding (pull_request) Has been cancelled
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Has been cancelled
CultMesh portability and performance / windows-latest reactive semantics and leases (pull_request) Has been cancelled
CultNet cross-runtime interop / C# / TypeScript / Rust / Python / Kotlin (pull_request) Has been cancelled
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Has been cancelled
86faf53f86
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Author
Member

Maintainer sanity run at head 86faf53f: node --test tools/sprite-silhouette/silhouette.test.mjs 10 pass, 0 fail, 0 skipped (the all-poses test ran against /opt/commons/cast-art/poses). Forge CI: 6 pending, 3 skipped (workflows waiting for a runner; none has ever started on this repo). Not merged, Void owns the client.

Maintainer sanity run at head 86faf53f: `node --test tools/sprite-silhouette/silhouette.test.mjs` 10 pass, 0 fail, 0 skipped (the all-poses test ran against /opt/commons/cast-art/poses). Forge CI: 6 pending, 3 skipped (workflows waiting for a runner; none has ever started on this repo). Not merged, Void owns the client.
Merge remote-tracking branch 'origin/main' into libby/sprite-silhouette
All checks were successful
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Successful in 21m53s
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Successful in 1m19s
de00274cd0
libby merged commit e57fbaee90 into main 2026-11-10 23:14:07 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
GameCult/CultLib!8
No description provided.