Repository navigation
pet: crisp half-block sprites (nearest sampling, hard shape edges) - #27
Conversation
387562b replaced Sprite's nearest-neighbour lookup with an alpha-weighted box filter, which smears avatar tiles at every scale except 1:1: a 96x96 pack drawn into a 40-cell tank averages neighbours into a blur. The terminal whale's cove was also rasterized with 4x4 (2x2 above 64 px) supersampling, so every shape edge became a fractional-alpha pixel that Sprite then blended toward the cell background, and the silhouette read as soft. - Sprite::sample takes the source pixel under the target pixel's centre. - The cove rasterizes one sample per pixel, so a shape edge is in or out. The cove's deliberate layer opacities (behind 0.68/0.9, front 0.82) keep their translucency; only the anti-aliased rim is gone. The five pet gallery snapshots change accordingly. Silhouettes lose the half pixel of rim that partial coverage used to paint, and the blended rim colours disappear (pet-cove colour runs: 3781 -> 2719 lines). No other snapshot moved. cargo test --locked: 787 passed; 0 failed (46 test binaries). cargo fmt --check clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
The pet looked blurred in the terminal. Upstream 387562b had replaced Sprite's nearest-neighbour lookup with an alpha-weighted box filter, which smears avatar tiles at every scale except 1:1. The whale cove was also rasterized with 4x4 supersampling (2x2 above 64 px), so every edge became a fractional-alpha pixel that Sprite then blended toward the background. Re-vendored from upstream 8f51c6bccadeb11278cda1e2481a116573e5d233 (codewhale-hq/codewhale-ratatui#27): - `Sprite::sample` takes the source pixel under the target pixel's centre. - `whale_motion/pixels.rs` rasterizes one sample per pixel. The cove's deliberate layer opacities keep their translucency; only the anti-aliased rim goes. Upstream, with this change: `cargo test --locked`, 787 passed, 0 failed (46 test binaries). The vendored crate goes to 0.1.2. It is the crates.io publish source, and it gained DotWhale after 0.1.1 was published, so the packaged codewhale-tui cannot compile against crates.io 0.1.1. Also changed: - crates/tui and pet/tui depend on 0.1.2, and both lockfiles are updated (cargo metadata --locked passes for the workspace and for pet/tui); - UPSTREAM.json records the upstream commit and the file hashes; - the vendored CHANGELOG has a 0.1.2 entry; - scripts/release/check-versions.sh allows 0.1.2; - the deconstruction roadmap names 0.1.2. Publishing codewhale-ratatui 0.1.2 to crates.io is a founder step and comes before the codewhale-tui publish. Evidence: cargo fmt --all -- --check is clean. The engine compile and the pet_watch tests are pending a local test build and hosted CI on #6957. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
"README matches the components" failed on #27 (run 38139243091): render-gallery reported six stale pet SVGs (pet.{dark,light}-truecolor- {1,2,3}.svg). The nearest-neighbour Sprite sampling and one-sample cove rasterization in 8f51c6b change the pixels those previews were rendered from. The same change made six README animations stale: subagents-dark, subagents-light, pet-dark, pet-light, pet-mode-dark and pet-mode-light. Regenerated with the repository's own tools from the actual buffers: - `cargo run --example gallery -- --svg target/readme-buffers`, then `tools/render-gallery.py ... --readme README.md`. README.md was unchanged. - The pet, pet_mode and subagents examples' `--frames` output, then `node tools/render-animation.cjs` (sharp 0.33.5 and ffmpeg). Evidence: these are the CI gallery steps run locally after regeneration: - render-gallery --check: "Verified 141 boards covering all 210 entries × 2 profiles". - check-animation: subagents dark/light, pet dark/light and pet-mode dark/light each "match all 200 current terminal-buffer frames". habitat-motion still matches 80 and showcase 128. Neither moved. - export-web-motion --check: "Verified 6 native tracks / 762 frames". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
There was a problem hiding this comment.
If your organization's extra usage balance is empty, an organization admin can add extra usage credits at claude.ai/admin-settings/usage. If its monthly spend limit was reached, an admin can raise it on the same page. If neither applies, contact Anthropic support.
Once extra usage is available, someone with write access to this repository can comment @claude review on this pull request to trigger a review.
There was a problem hiding this comment.
🟢 Approval recommended
The bounded sampling and rasterization changes are consistent with the intended crisp rendering, and the updated asset hashes match their GIF files.
0 open findings
What changed in this PR
Updates pet rendering to preserve crisp half-block edges when scaling.
Changes:
- Replaces box filtering with nearest-neighbor sprite sampling.
- Removes supersampling from cove rasterization.
- Refreshes pet preview assets and animation hashes.
| File | Description |
|---|---|
src/avatar_sprite.rs |
Uses nearest-neighbor sampling. |
src/whale_motion/pixels.rs |
Rasterizes one sample per pixel. |
assets/readme/pet.dark-truecolor-3.svg |
Updates the dark pet preview. |
assets/readme/subagents-light.gif.json |
Refreshes light animation hashes. |
assets/readme/subagents-dark.gif.json |
Refreshes dark animation hashes. |
assets/readme/pet-mode-light.gif.json |
Refreshes light pet-mode hashes. |
assets/readme/pet-mode-dark.gif.json |
Refreshes dark pet-mode hashes. |
assets/readme/pet-light.gif.json |
Refreshes light pet hashes. |
assets/readme/pet-dark.gif.json |
Refreshes dark pet hashes. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Summary
This fixes the half-block blur on the pet, one of the 0.10.2 pet bugs.
Two things caused the blur:
Sprite::samplebecame an alpha-weighted box filter, which smears avatar tiles at every scale except 1:1. A 96x96 pack drawn into a 40-cell tank averages neighbouring pixels.Spritethen blended toward the cell background.Changes:
Sprite::sampletakes the source pixel under the centre of the target pixel (nearest neighbour).whale_motion/pixels.rsrasterizes one sample per pixel, so a shape edge is either in or out. The cove's deliberate layer opacities stay translucent (behind 0.68/0.9, front 0.82); only the anti-aliased rim goes.The Codewhale engine vendors this change as
codewhale-ratatui0.1.2; see codewhale-hq/Codewhale#6957. That vendored copy is the crates.io publish source. Publishing 0.1.2 is a founder step.Evidence
cargo test --locked: 787 passed; 0 failed (46 test binaries).cargo fmt --check: clean.🤖 Generated with Claude Code
https://claude.ai/code/session_01BsXVvReYca2UxzimQtj7Mj
Generated by Claude Code