Files
rplace/plans/260417-1125-image-importer-enhancements/plan.md
T
tiennm99 75c1023554 feat(importer): phase 2 — overlay preview on main canvas
CanvasRenderer.setOverlay draws the palette-converted import preview on top
of committed + pending layers at (x, y) with a configurable alpha. Image
importer gains an "Overlay" toggle and opacity slider; the overlay
reactively follows resize/dither/origin changes and clears on panel close,
toggle-off, or image swap. Lets the user align the upload before spending
credits.
2026-04-17 11:45:16 +07:00

2.3 KiB

Image Importer Enhancements

Reference: WPlace-AutoBOT image-processor.js.

Goal

Grow the in-app Image Import panel into a full pre-placement pipeline: resize, transforms, tune, quantize with multiple dither algorithms, overlay-preview on canvas, then upload.

Principles

  • YAGNI/KISS — only add the features with clear UX value on our 2048x2048, 32-color canvas.
  • DRY — all pixel transforms live in src/lib/image-*.js and are reused by the CLI (scripts/image-to-colors.js).
  • Keep reactivity driven by $effect over a cached source RGBA buffer; each toggle re-runs the pipeline without re-decoding the file.
  • Never block manual drawing; uploader continues sharing the server-side rate limit.

Phases

# Phase Status Value
1 Resize controls Done Must-have — user explicitly asked
2 Overlay preview on canvas Done High — visualize alignment before spending credits
3 Transforms (flip / rotate) Todo Medium — quick fixes without re-editing source
4 More dithering algorithms Todo Medium — different looks per source
5 Color correction sliders Todo Medium — photos benefit most
6 Skip-white + paint-transparent toggles Todo Low — easy win, often useful for logos

Later / parked: multi-algorithm color distance (Lab/Oklab), Kuwahara smoothing, template save/load, repair mode. Revisit after Phase 6.

Dependencies

  • Phase 1 (resize) blocks Phase 2 (overlay needs final dimensions) and Phase 3 (transforms sit before or after resize, but the pipeline shape is set by Phase 1).
  • Phases 4, 5, 6 are independent of each other.

Shared pipeline shape (locked after Phase 1)

File → decode → srcRgba
            ↓  (reactive on: resize/transforms/color-correction/dither/skip-white)
        pipeline()
            ↓
        Int16Array paletteIndices
            ↓
        preview (palette → RGBA)
        + buildPixels(originX, originY, skipMatching) → upload

All steps operate on RGBA buffers so they compose. rgbaToPalette stays the final step.