feat(tui): inpainting canvas — Mask state and PNG export #62

Merged
charles merged 1 commit from tui/inpaint-canvas-23 into main 2026-04-11 20:42:30 +00:00
Owner

Stacks on #61. Closes charles/loom#23.

Reusable Mask struct that drives the inpaint canvas overlay. Pixel-addressed grayscale buffer with cursor + brush state, paint(value) circle fill, move_cursor with edge clamping, adjust_brush clamped [1, 128], and to_png_bytes() returning an 8-bit PNG.

Tests (4 new, 74 total)

  • Circle paint produces the expected (~π·r²) pixel count
  • Cursor clamps at edges
  • PNG round-trip preserves the filled pixel count
  • Brush radius clamps at both ends

Out of scope

Full-screen overlay integration with image rendering happens in the glue PR that threads Box<dyn ImageRenderer> through AppCtx. Today the Mask struct is the part the overlay composes on top of.

Stacks on #61. Closes charles/loom#23. Reusable `Mask` struct that drives the inpaint canvas overlay. Pixel-addressed grayscale buffer with cursor + brush state, `paint(value)` circle fill, `move_cursor` with edge clamping, `adjust_brush` clamped `[1, 128]`, and `to_png_bytes()` returning an 8-bit PNG. ## Tests (4 new, 74 total) - Circle paint produces the expected (~π·r²) pixel count - Cursor clamps at edges - PNG round-trip preserves the filled pixel count - Brush radius clamps at both ends ## Out of scope Full-screen overlay integration with image rendering happens in the glue PR that threads `Box<dyn ImageRenderer>` through `AppCtx`. Today the `Mask` struct is the part the overlay composes on top of.
First half of the inpaint canvas overlay: a reusable Mask struct that
holds a pixel-addressed grayscale buffer, tracks cursor + brush radius,
and supports move_cursor, paint(value), clear, adjust_brush, and
to_png_bytes() export. Circle fill matches the expected ~π·r² pixel
count for a radius-8 stamp and survives a PNG round-trip.

The full-screen overlay that hooks this into AppCtx and exports the
mask path back into GenerateScreen.params.mask_image_path lands with
the image-renderer wiring in a later PR — the unit here is the mask
state machine that the overlay composes on top of.

Closes charles/loom#23

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
charles changed target branch from tui/generate-mode-tabs-22 to main 2026-04-11 20:42:25 +00:00
charles deleted branch tui/inpaint-canvas-23 2026-04-11 20:42:31 +00:00
Sign in to join this conversation.
No reviewers
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
charles/loom!62
No description provided.