What this app does
It removes the background from a photo so you're left with just the subject (a person, an object, an animal) on a transparent or custom background. You can use AI to do most of the work automatically, then clean up anything it missed using a set of manual tools.
You can also use it as a general image cutout tool: remove specific colors, fill in regions, paint over edges, and export the result in several formats.
How it works (in plain language)
Most image editors change the actual pixels of your photo when you edit. This one doesn't. Instead, it keeps your original image untouched at all times and builds a separate mask on top of it — think of the mask as a stencil that says which parts should be visible and which should be hidden.
When you erase, paint, or run the AI, you're modifying that stencil, not your photo. Your original is always there underneath, pixel-perfect. When you export, the original is combined with the stencil at full resolution to produce the final image.
This means you can edit as much as you want without losing image quality. Undo as many times as you like, try different things, throw it all away with Start over — your source photo never gets damaged.
🖱 Select
🖱 Select (press S) is the main "do stuff" tool. It works on both outlines and image layers. Hover over an outline to highlight it (outlines take priority over images), or hover over a visible part of an image layer to highlight that layer instead. Click to select, shift-click to toggle multiple outlines. When something is selected, an action bar appears at the bottom with Fill Region/Layer, Copy, Cut, Paste, Invert, Restore, Delete, and Deselect. These work on both outline regions and entire image layers. Hold Alt while hovering to reach under a nested outline. The standard Ctrl/⌘+X, Ctrl/⌘+C, and Ctrl/⌘+V shortcuts work from any tool.
Donuts and nested rings. When a tool traces a shape with a hole (like a ring), each ring is a separate outline. Hovering over one ring highlights only that ring — the other ring stays inactive. Click a single ring to select just it. To select both rings together (to Fill or Cut the donut shape with the hole preserved), click one ring then shift-click the other. The Fill/Cut operations honor the even-odd rule, so selecting both rings produces a real donut-with-hole result; selecting only the outer ring fills the whole area including the hole; selecting only the inner ring fills only the hole.
Transforming and recoloring layers and outlines. While the Select tool is active with something selected, a tab strip sits on top of the action bar with two tabs: 🎨 Color (left) and ◈ Transform (right). Clicking a tab expands its panel below the tabs — they're mutually exclusive, so expanding one collapses the other. Transform stays "always on" inside Select; its controls (Scale / Rotate / Flip / Reset / Center Image) just reveal when the tab is expanded.
In transform mode, click an image layer to select it for dragging, scaling, flipping, or rotating. Shift+click to select multiple image layers — all selected layers are highlighted. Inline controls (scale slider, flip H/V, rotate) appear in the top bar and operate on the primary (most recently clicked) layer. Click a selected layer again to deselect it, or click empty space (on the canvas, or in the empty area of the Layers panel) to deselect all.
Multi-select in the Layers panel works the same way: Ctrl/⌘+click rows to add or remove individual layers from the selection, or Shift+click a row to extend a range. Once multiple layers are selected — whether you picked them on the canvas, in the panel, or a mix of both — pressing Delete or Backspace removes them all in a single undoable step. Cmd/Ctrl+C, Cmd/Ctrl+X, and the Move tool also act on the full set. Press Escape to clear the selection.
Outlines are also interactive in transform mode: click-drag any outline to move it, click to select, shift-click to multi-select. Anchor points become visible and draggable. Inline controls offer scale, flip, and rotate for selected outlines.
Click the Transform button again (or press Escape, or switch tools) to disarm. Each operation pushes an undoable entry to history.
✋ Hand
✋ Hand (press H) lets you click-and-drag to move the canvas around. Hold Space or hold the middle mouse button and drag to pan temporarily from any tool — releasing returns to your previous tool. Both shortcuts also work mid-stroke: if you're painting and need to scroll, press the modifier, drag to pan, then release to keep painting.
👤 Remove Background
👤 Remove Background — Click this first if your photo has an obvious subject (a person, an animal, an object). The AI looks at your image, decides what the subject is, and removes everything else in a few seconds. The first time you use it, it has to download a small model file (~40MB). After that, it's fast.
🎨 Color
Color lives as a tab on top of the Select tool's action bar — the left-most of two tabs (Color and Transform). Select something (an image layer or an outlined region), then click the 🎨 Color tab to expand the Color panel. The Color tab gives you two one-click actions: 🪣 Paint Bucket (click a region on the canvas, like MS Paint) and 🌐 Fill Find (fires immediately on every pixel in the image matching Find). Set Fill Opacity to 0 to erase matched pixels instead of filling them — no separate Remove button.
The workflow, in order:
- Pick the Find color — click the swatch to open the custom color picker. The picker has a hue ring, an SV square, RGB sliders, a typeable hex field, a saved-color palette, and a built-in 💧 eyedropper (click it or press I). On Chrome / Edge the eyedropper lets you pick a color from anywhere on screen. On Safari / Firefox a circular magnifier appears the moment you click the eyedropper and follows your cursor anywhere — over the picker popover, the canvas, anywhere on the page — showing a zoomed pixel grid with a small square highlighting the exact pixel under sample (the OS cursor hides while you're sampling over the canvas). A small companion box appears in the top-left corner of the canvas showing the same area at normal zoom with a crosshair on the cursor — glance at it to keep track of where you are while the magnifier covers the work area. Click any pixel inside the canvas to commit the sample. Press Esc to cancel without picking, or Esc after the picker closes to revert any change you were dialing in.
- Pick the Fill color — same picker, same eyedropper. The Paint brush also uses the Fill color. The Fill picker also has a permanent grayscale slot in its second palette row — click it to put the active layer into grayscale-paint mode.
- Set Opacity — 100% replaces matched pixels with Fill. 0% erases them. Anything in between partially fills (blends Fill on top at that strength).
- Drag Tolerance — you'll see a live preview on the canvas of which pixels would be affected. Slide left and right freely; the preview is fully reversible until you commit.
- Drag Sensitivity to fine-tune — negative tightens the match (fewer stragglers), positive loosens it (catches pixels just outside Tolerance).
- Fire an action:
- 🪣 Paint Bucket — click the button, then click a spot on the canvas. The color at that clicked pixel floods outward and is replaced with Fill (at Opacity), stopping at pixels outside Tolerance. Best for cleaning up one region at a time (e.g., a sky behind a subject) without touching same-colored pixels elsewhere in the image.
- 🌐 Fill Find — fires immediately. Every pixel in the image matching Find (within Tolerance / Sensitivity) is replaced with Fill at Opacity. Best for solid-color backgrounds or recoloring one color everywhere it appears. No canvas interaction — the button itself is the action.
Controls in detail:
- Find — what color to look for. Used by 🌐 Fill Find. The 🪣 Paint Bucket ignores Find and seeds from the clicked pixel — state-of-the-art paint-bucket behavior.
- Fill — the color the actions paint with (and the color the Paint brush uses). Combined with Opacity.
- Opacity (0–100%) — how much of Fill to apply. 0% = erase matched pixels (transparent fill). 100% = fully replace with Fill. Intermediate values partially blend Fill on top of the original at that strength.
- Tolerance (0–100) — how strict the color match is. 0 = exact match only, 100 = nearly every color. Uses Oklab perceptual matching, so Tolerance feels consistent across red, blue, and green subjects.
- Sensitivity (−100…+100) — a plus/minus tweak on Tolerance. Use it to fine-tune when Tolerance alone is too coarse. Applies to both actions.
Edges are automatically anti-aliased — pixels near the Tolerance boundary get a smooth falloff instead of a hard cut, so JPEG compression halos and soft object edges come out clean instead of jagged.
Confirm or cancel the preview:
- Enter (or click the ▾ Color chevron to collapse the tab) — exits back to Select. If you have a live preview on the canvas, it's committed as one history entry before exiting, so nothing gets stuck without undo tracking.
- Esc — abandons the preview. Reverts the canvas to the state before you started touching sliders and exits to Select. Useful when you want to experiment with Tolerance/Sensitivity and back out cleanly.
🪄 Magic Wand
Press W or click the 🪄 Magic Wand button in the left sidebar's Draw group. (Customize via ⚙ Settings → Hotkeys if you want a different key.) The Wand selects pixels by color similarity and hands the result to the Select tool as an outline. Complementary to Magic Pen (which selects by anchor placement) and the Color tool (which edits pixels directly).
The workflow, in order:
- Click a color region on the canvas. The Wand samples the color at (and around) your click and selects every similar pixel — by default only pixels connected to the click point. A semi-transparent blue tint with animated marching ants shows the preview.
- Drag Tolerance — grow or shrink the selection live. 0 = exact match only, 100 = nearly every color.
- Use modifier keys on subsequent clicks —
Shift+click adds to the selection, Alt+click subtracts, Shift+Alt+click intersects. A plain click replaces the current selection.
- Refine with Sample size (Point / 3×3 / 5×5 averaged), Gap close (stops flood leaks through 1–2 px anti-aliased seams), Grow/Shrink (±10 px), and Feather (boundary smoothing).
- Press Enter to commit. The Wand converts the pixel selection to one or more outline polygons, switches to Select, and the action bar appears — Fill Region/Layer / Cut / Copy / Delete / Invert all work immediately on the new outline.
- Press Esc to discard the preview without creating an outline.
Controls in detail:
- Tolerance (0–100) — color-similarity threshold in Oklab perceptual space. Same metric the Color tool uses, so "Tolerance 30" feels the same across both tools.
- Sample size (Point / 3×3 / 5×5) — averages the seed color over an N×N window. Damps noise on JPEG / photographic input; use Point for flat-color graphics.
- Contig — Contiguous: on = only pixels connected to the click; off = every matching pixel in the image (multiple disjoint regions all land as one group).
- AA — Anti-alias: soft match band (partial α on edge pixels) vs hard threshold.
- Gap — Gap close radius. Raise when the flood leaks through a thin seam (classic case: letter "e" counter, where the inner ring is only 1–2 px from the outer).
- Grow — Expand (+) or contract (−) the selection by N pixels before commit.
- Feather — Gaussian blur on the scratch mask before threshold. Under outline output, this smooths the final polygon boundary (rounder corners). Note: it's not a true partial-α feather — the outline is still binary. For soft-edge selections, feather the outline's fill after commit using the Edges tab.
Guard rails: clicking on a fully-transparent pixel is a no-op (the Wand toasts "Click on a visible pixel"); a hidden or locked active layer blocks the Wand entirely. Tool-switch discards an uncommitted preview silently.
🍪 Cookie Cutter
Click the 🍪 Cookie Cutter button in the left sidebar's Draw group (or press K). The Cookie Cutter masks the active image layer through a chosen geometric shape — hexagons, circles, stars, hearts, donuts, polygons up to 12 sides, and many more — exactly the kind of "make a hex tile / make a circular avatar" workflow without leaving the editor.
The workflow, in order:
- Select the layer you want to cut. Cookie Cutter applies to the active image layer (the one you're editing).
- Click 🍪 Shape ▾ in the floatbar at the bottom and pick a shape from the searchable list. The shape is auto-fit to the layer's visible content (centered, sized to the shortest side / 2 — same math as a hex-tile cutter).
- A dashed preview appears on the canvas. Pick a different shape from the dropdown to swap previews instantly.
- Press Enter (or click ✓ Apply) to commit. Pixels outside the shape become transparent on that layer; the layer's bbox / contour highlight follow the new shape automatically. The cut is clean — no leftover outlines or selections.
- Or click ⬇ Export PNG to download a transparent PNG of just the shape — sized to the shape's tight bounding box, with the visible canvas clipped to the shape. Doesn't modify the layer; you can keep picking different shapes and exporting variants. This mirrors the standalone HexCutter tool's behavior.
- Press Escape (or click ✕ Cancel) to discard the preview without modifying the layer.
Reversible: the cut is destination-in alpha into maskCanvas — the original RGB pixels stay in the layer's image buffer, so the Restore brush can paint them back at any time. Ctrl+Z/⌘Z also undoes the entire cut in one step.
Combine with Transform: after cutting, switch to Select and use the Transform bar to scale, rotate, or flip the cookie-cut layer. Add a background layer underneath for an instant framed avatar / hex tile / heart sticker.
🤖 AI Editing Tools (foundation)
Four AI tools live in the left sidebar's AI group: 🤖 Smart Select (W), 🧽 AI Eraser (M), 🔍 AI Upscale (U), and 🎨 AI Generative Fill (J). In this build the buttons, sub-bars, and keybinds are wired but model adapters are not — clicking each tool opens its sub-bar with a placeholder message and a Cancel button. Per-tool model wiring lands in upcoming slices: Smart Select (SAM2) → Eraser (LaMa inpainting) → Upscale (Real-ESRGAN ×2 / ×4) → Generative Fill (remote provider; UI only).
The three local-AI tools (Smart Select, Eraser, Upscale) require WebGPU, available today in Chrome / Edge / Arc on desktop. Browsers without WebGPU (Safari at the moment) render those buttons disabled with an explanatory tooltip; Generative Fill stays enabled because its compute is remote. Each model is fetched once on first use (50–200 MB depending on the tool) and cached by the browser. The provider abstraction at js/ai/ is designed so swapping models, or wiring a remote API later, is a one-file change with no impact on tool code or your existing edits.
T Text
Click the T Text tab at the top of the bottom toolbar (it sits to the right of ◈ Transform and is always enabled — no selection or tool switch required). Expanding the tab flips the canvas cursor to an I-beam and opens the text controls: font family, size, color, Bold / Italic, and left / center / right alignment.
Two ways to start a text box (matches Figma / Photoshop):
- Click without dragging — drops a "point text" cursor that grows horizontally as you type. Use this for short labels, titles, single lines.
- Click and drag — draws a dashed box at the size you dragged. Releasing turns it into a fixed-width "paragraph text" box that wraps long lines and grows downward as you type. Use this for blocks of text you want bound to a specific width.
The workflow, in order:
- Click Text to open the tab. Pick the font / size / color / style you want for the next characters you type.
- Click or drag on the canvas as described above to place the box.
- Type. Inside the box, blue handles appear on the left and right edges — drag either handle to widen or narrow the box and the text re-flows live. Dragging the right handle of a point-text box inward converts it into a fixed-width wrapping box on the fly (no need to start over).
- Restyle parts of the text after typing. Highlight any range of characters and change font, size, color, Bold, or Italic — only the highlighted characters update, the rest of the text stays untouched. With nothing highlighted, the next character you type picks up the new style. Double-click inside the text box to select all of its text at once (handy for re-coloring or resizing the whole layer). Single-click still places the caret normally.
- Commit by clicking ✓ Confirm, pressing Enter or Esc, or clicking anywhere outside the text box — all four bake the styled text into the layer (named "Text: <first words>") and switch back to Select.
- Re-edit by double-clicking any existing text on the canvas — works from any tool (Select, Brush, etc.), not just Text. The Text tab opens, the edit box pre-fills with the original content, and every per-character style is preserved exactly. The double-click also pre-selects every character, so you can immediately retype to replace everything or pick a new color/size to restyle the whole layer in one move (Photoshop Type-tool parity). To re-edit without selecting all, click the text once with the Text tool — the caret lands at the end so you can keep typing.
- Transform the baked text by selecting the layer and using the ◈ Transform tab's Scale / Rotate / Flip controls — text layers scale and rotate like any image layer.
New line: press Shift+Enter inside the edit box to insert a new line. Plain Enter commits.
Empty layers are dropped: if you commit a fresh text layer without typing anything, it's removed instead of leaving an invisible placeholder. Undo is not needed.
Stays where you put it: new text layers are order-locked by default — clicking other layers won't promote them above your text in the stack. The position-number button on the text layer's row in the Layers panel shows it's locked; click it to unlock and let the layer flow with normal stack reordering.
Confirm and exit: while editing, pressing Enter or Esc, clicking ✓ Confirm, or clicking on empty canvas all do the same thing — commit the current text and switch back to Select. To start a fresh paragraph box right after committing, click-AND-drag (instead of just clicking) on empty canvas — the drag commits the old edit AND draws a new dashed paragraph rectangle, keeping you in Text mode.
Alignment — point vs paragraph: the two creation modes handle alignment differently, matching Figma / Photoshop behavior.
- Point text (created by clicking without dragging) has no fixed width — alignment shifts the glyphs around the click anchor: left grows the text rightward from the click, center centers the text on the click, right grows leftward and ends at the click. The dashed outline visibly moves with each alignment change because the text is repositioning around its anchor, not flowing inside a box.
- Paragraph text (created by clicking and dragging to draw a fixed-width box) keeps its box position and width on every alignment change — only the glyphs inside reflow to the chosen edge. To get the "alignment shifts text inside a fixed box" behavior, drag to create the text instead of clicking.
🎚 Color Correction (WIP) — Tone + Grade + Curves tabs
Color Correction lives as three tabs on the toolbar above the Select action bar: 🎚 Tone (Exposure / Contrast / Highlights / Shadows / Whites / Blacks), 🎨 Grade (Temp / Tint / Vibrance / Saturation / Hue / Clarity), and 📈 Curves (a master RGB tone curve in a floating editor popover). They sit on the right side of that bar, next to the existing 🎨 Color, ◈ Transform, and T Text tabs. Press V to toggle the Tone tab. Adjustments are non-destructive: the original pixels are preserved in imgCanvas and the adjustments re-bake every time you drag a slider, so you can re-drag any control any number of times without the baseline drifting.
The workflow, in order:
- Select one or more image layers you want to adjust (click in the Layers panel on the right, or on the canvas in Select mode; shift-click to add layers to the selection). Tone, Grade, Curves, and Edges tabs only enable when at least one image layer is selected.
- Click the 🎚 Tone, 🎨 Grade, or 📈 Curves tab on the toolbar (or press
V to toggle Tone). Tabs are grayed out in brush mode — exit to Select first.
- Drag any slider — the live preview updates against the original pixels. For Curves, the editor canvas opens in a floating popover above the canvas: click the curve to add a control point, drag a point to bend the curve, right-click a point (other than the endpoints) to remove it. Endpoints lock their x position but move freely on y.
- Switch tabs freely between Tone, Grade, and Curves — all three belong to the same color-correction session, so toggling between them does NOT commit history. Adjusting all three lands as one undo entry.
- Double-click a slider to reset that one control to zero. ↺ Reset Tone / ↺ Reset Grade / ↺ Reset Curve (footer) wipes that tab's controls only.
- Hold 👁 Before on any tab to compare against the unadjusted image; release to return.
- Click the active tab handle again (or open Color/Transform/Text) to commit. A single history entry is pushed so Ctrl+Z reverts the whole session.
Controls in detail:
- Exposure (stops, −5…+5) — overall brightness in linear light. +1 = twice as bright.
- Contrast — S-curve around linear mid-gray. Positive = more punch; negative = flatter.
- Highlights / Shadows — luminance-masked tonal compression. Negative Highlights pulls bright regions down; positive Shadows lifts dark regions.
- Whites / Blacks — endpoint stretch. Positive Whites extends the bright end; negative Blacks crushes shadows.
- Temp — color temperature: positive warms (more R, less B); negative cools.
- Tint — green/magenta balance: positive toward magenta, negative toward green.
- Vibrance — saturation curve that protects already-vivid colors and skin tones.
- Saturation — global color strength. −100 = grayscale.
- Hue — global hue rotation in degrees (−180…+180).
- Clarity — midtone local contrast. High-pass on the luminance channel. Adds texture punch.
- Curves (master RGB) — a tone curve mapping input to output in display-referred sRGB space. Use it for fine tonal shaping (S-curve for contrast, lifted blacks for a faded look, etc.). Monotonic-cubic interpolation prevents overshoot. Per-channel R/G/B curves are deferred to Phase 2.
Per-layer: each layer carries its own adjustment stack. Adjusting one layer doesn't affect the others. With multiple image layers selected (shift-click), every slider drag — and every curve edit — applies to every selected layer; the slider readout and the curve editor track the primary (last-clicked) layer. The stack is saved with the session — refresh the page and your adjustments come back. Adjustments bake into PNG export automatically.
Status: WIP badge is intentional. Tone, Grade, and a master RGB Curve are live. The full 6-color HSL matrix, per-channel R/G/B curves, the histogram strip, and the GPU shader path for smoother 4K drag are planned follow-ups — see FUTURE_FEATURES/COLOR_CORRECTION_PLAN.md.
🩹 Eraser
Paint to remove pixels. Press E or click the 🖌 Brushes button in the left sidebar and pick Eraser; the brush toolbar appears at the bottom of the canvas with size / hardness / flow sliders and Confirm/Cancel.
The Eraser penetrates all visible non-edit-locked layers — edit-lock a layer (✏️/🔒 in the Layers panel) to protect it from erasing.
Brush settings (shared with Restore / Edge Heal / Paint):
- Size — Brush diameter, in image pixels. Press
A / D to resize without leaving the canvas.
- Hardness — How sharp the brush edge is. 100% = a clean circle with binary 0/255 alpha (no anti-aliased fringe — required for shader-mask authoring). 0% = a soft cloud. Smoothstep falloff in between.
- Flow — How strong each stroke is. Lower values let you build up gradually with multiple passes.
Confirm and Cancel:
- ✓ Confirm (Enter) — Exits brush mode and switches to Select. All strokes stay as-is.
- ✕ Cancel (Esc) — Discards every stroke made since entering brush mode, on every layer affected. A toast appears;
Ctrl+Z restores everything.
↩︎ Restore
Paint to revert pixels to the original image. Press R or pick Restore from the brush toolbar. Brings back erased pixels AND wipes Paint / Edge Heal edits in the brushed area — useful for undoing local paint touch-ups without a full Ctrl+Z.
Brush settings (shared with Eraser / Edge Heal / Paint):
- Size — Brush diameter, in image pixels. Press
A / D to resize.
- Hardness — 100% = clean binary edge; 0% = soft cloud.
- Flow — Lower values build up gradually with multiple passes.
Confirm and Cancel:
- ✓ Confirm (Enter) — Exits brush mode and switches to Select.
- ✕ Cancel (Esc) — Discards every stroke made since entering brush mode.
Ctrl+Z restores them.
🪄 Edge Heal
Press X or pick Edge Heal from the brush toolbar. Paints outward using the color of the nearest visible object pixel — use this to smooth a jagged edge or grow an object outward by a pixel or two, without picking up the deleted background color.
Hardness and Flow don't apply, so both sliders are greyed out while Edge Heal is active. Only Size matters.
Brush settings:
- Size — Brush diameter, in image pixels. Press
A / D to resize.
Confirm and Cancel:
- ✓ Confirm (Enter) — Exits brush mode and switches to Select.
- ✕ Cancel (Esc) — Discards every stroke made since entering brush mode.
Ctrl+Z restores them.
🎨 Paint
Tap B for the last-used brush, or hold B to open the radial brush wheel and release on Paint. Paints with the Fill color from the Color panel — use this to fill in small holes the AI left behind. The Color panel auto-opens above the brush toolbar whenever you start brushing, so you can pick or change the brush color without leaving Paint.
Brush settings (shared with Eraser / Restore / Edge Heal):
- Size — Brush diameter, in image pixels. Press
A / D to resize.
- Hardness — 100% = clean binary edge (required for shader-mask authoring); 0% = soft cloud. Smoothstep falloff in between.
- Flow — Lower values build up gradually with multiple passes.
Confirm and Cancel:
- ✓ Confirm (Enter) — Exits brush mode and switches to Select.
- ✕ Cancel (Esc) — Discards every stroke made since entering brush mode, on every layer affected.
Ctrl+Z restores them.
✂ Edges (tab on the move toolbar)
The ✂ Edges tab sits on the floating move toolbar at the top of the canvas, right of Grade. It only does something visible after you've removed something — it tunes existing edges, it doesn't create them. Open it with at least one image layer selected (the tab is grayed out otherwise); if there are no edges to refine yet a toast guides you to run Remove Background, Color, or Eraser first.
Refine the edge shape — these sliders are live, non-destructive, and per-layer. Each selected image layer carries its own Feather / Contract / Threshold values; shift-click to multi-select and the slider drags apply to every selected layer in lockstep. The slider readout tracks the primary (last-clicked) layer.
- Feather (Fthr) — Softens (blurs) the edge. Useful for hair, fur, and natural transitions.
- Contract / Expand (C/E) — Shrinks the cutout inward (positive) or grows it outward (negative).
- Threshold (Thr) — Adjusts where the cutoff happens between visible and hidden.
- ↺ Reset — Restores Feather / C/E / Threshold to defaults (0 / 0 / 128) on every selected image layer in one undo step.
Clean up the edge — checkboxes for fixing common edge artifacts. Per-layer like the sliders: toggling a checkbox writes to every selected image layer. Decon's expensive recompute (multi-pass dilation, 1–2s on 24MP) only runs automatically for the active layer; non-active selected layers store the flag and recompute when they become active.
- Decon — When you remove a colored background (especially a strong one like green or pink), edge pixels often keep faint traces of that color. This option replaces those pixels with colors from inside your subject, eliminating the color bleed.
- Tighten — Shrinks the cutout by 1 pixel. Removes the outermost translucent edge ring.
- Sharp — Forces every pixel to be either fully visible or fully hidden. No anti-aliasing. Useful when you want crisp edges for graphics.
Background (collapsed by default)
Replace the (now transparent) background with a solid color or another image. Collapsed by default — click the section header on the right to expand.
⬇︎ Export
The ⬇︎ Export button in the top-right opens a dropdown where you pick the format and (for lossy formats) quality, then click Save image. Three formats:
- PNG — Highest quality, supports transparency. Larger file size. Use this for most cases.
- WebP — Smaller files than PNG, also supports transparency. Use this for the web.
- JPEG — Smallest files, but does NOT support transparency. The transparent area becomes whatever color you've set under Background (or white if Background is Transparent).
Tips
- Paste an image to start editing. A new tab is empty until you load something — every tool stays dimmed and clicking one prompts you to open an image. The fastest path in is ⌘V / Ctrl+V: a screenshot or copied image file from your OS clipboard becomes the new document instantly. You can also drag a file onto the splash, click Choose File…, or paste a layer copied from another tab. Loading any new image resets the active tool to 🖱 Select so you start from a known cursor every time; switching tabs preserves each tab's own tool.
- Use the document tabs at the top-left of the canvas to work on multiple separate documents at once. Click + to open a new blank tab (it appears immediately to the right of the most recent tab); click any tab to switch; hover a tab to reveal its × close button. Each tab keeps its own image, layers, history, outlines, and tool selection. Double-click a tab title to rename it — the new name auto-fills as the export filename when you open the Export panel (you can still edit it before saving). Copy / cut / paste work across tabs — copy in one, switch tabs, paste in another. Reloading the page (or reopening the browser later) closes every open tab into the History panel's recovery list and lands you on a fresh blank tab — click any recovery row to bring a tab back.
- Start with Remove Background for any image with an obvious subject. Clean up afterward with the other tools.
- Open the Color tab in Select's top bar and switch scope to Paint bucket for tricky areas the AI got wrong, like rocks or objects that look like background to it. Tolerance uses Oklab perceptual matching so the slider feels consistent across colors, and edges come out anti-aliased instead of jagged.
- If the Color tool leaves a faint halo, nudge Sens negative to tighten the match. If it's missing a few stragglers, nudge Sens positive. Sens applies to both 🪣 Paint Bucket and 🌐 Fill Find.
- Use the Edge Heal brush to fix jagged or eroded object outlines.
- The Magic Wand (W) lets you click a color region, drag Tolerance to grow/shrink live, Shift-click to add, Alt-click to subtract, Enter to commit as an outline.
- AI tools (
M Eraser, U Upscale, J Generative Fill) are foundation-only in this build — the buttons exist but model wiring lands in upcoming slices. The three local-AI tools require WebGPU (Chrome / Edge / Arc on desktop today; Safari is gated until it ships WebGPU). Each tool downloads its model once on first use (50–200 MB) and caches in the browser.
- Press
K for 🍪 Cookie Cutter, pick a shape (hexagon, circle, star, heart, donut, …), and press Enter to mask the active layer through it. Auto-fits to the layer's visible content. Restore brings cut pixels back; ⌘Z undoes the cut in one step.
- Click the T Text tab at the top of the bottom toolbar (always available, no hotkey) to place editable text on the canvas. Click for a point-text caret that grows as you type, or click-and-drag to draw a fixed-width box that wraps and grows downward. Inside the box, blue side handles let you resize the wrap width live. Highlight any characters and change font / size / color / Bold / Italic to restyle just those characters — the rest of the text is untouched. ✓ Confirm, Enter, or clicking outside the text box bakes the text and returns to Select. Double-click any existing text (from any tool) to re-edit with full per-character fidelity. Shift+Enter inserts a new line.
- Hold
Space or the middle mouse button to pan temporarily — releasing returns to your previous tool. Press H to switch to the Hand tool permanently.
- Press
A and D to shrink / grow the brush size quickly.
- Every slider is undoable. Drag any slider — brush size, hardness, flow, magic wand tolerance, color tolerance, text size, all 16 Color Adjust sliders — and ⌘Z / Ctrl+Z reverts that one slider tweak as a single step. Each release of a slider is its own undo entry, so you can step backward through individual adjustments the same way Lightroom and Camera Raw do. Discarding a Color Adjust session (closing the panel without committing, if a discard path exists) pushes one extra undo entry that restores everything to the session's start.
- The brush size slider reads 0–100 and reaches a much larger maximum than before — at 100 the brush can fill huge regions in one stroke. The slider is curved: the bottom half covers everyday small brushes so you can still dial in fine sizes by feel; the top half ramps fast up to the new max. Type any value (decimals allowed) into the box next to the slider.
- The brush flow slider now feels even across its whole range. Previously, only the very bottom of the slider made a visible difference; now flow=75, 50, 25 each produce a clearly weaker stroke than the one before.
- Set Hardness 100 when authoring shader masks — every brushstroke deposits exact 0 or 255 alpha (no anti-aliased fringe). Below 100, the brush uses a smoothstep falloff and is anti-aliased.
- Press
E for Eraser, R for Restore, X for Edge Heal, tap B for the last-used brush, or hold B to open the radial brush wheel — move the cursor toward the wedge you want and release to commit (no click needed). The center hub hosts a size slider; releasing with the cursor there makes no tool change. ⌘Z/Ctrl+Z to undo.
- While any brush is active, press Enter to confirm (exits to Select) or Esc to discard every stroke made since you entered brush mode.
Ctrl+Z restores discarded strokes.
- The Color tab (🎨 Color) auto-opens directly above the brush toolbar when you start brushing, so Find, Fill, Tolerance, Sensitivity, and Remove/Replace are visible without leaving your brush. The Paint brush reads the Fill swatch directly — change it here and the next stroke uses the new color. Toggling the Color panel doesn't switch tools — you stay in Paint / Eraser / Restore / Edge Heal. If you close the Color tab while still painting, it stays closed until you exit brush mode and re-enter.
- Every color swatch in the app — Find, Fill, Mask Overlay, Background, and Text — opens the same custom color picker. Click a swatch to expand a popover with a hue ring, an SV (saturation × brightness) square, RGB sliders, a typeable hex field, a saved-color palette (right-click to delete a swatch, click ⊕ to save the current color), and a built-in 💧 Eyedropper. Inside the picker, press I to start the eyedropper without clicking. On Chrome / Edge the eyedropper lets you pick a color from anywhere on screen using the system picker. On Safari / Firefox a circular 120 px magnifier (zoomed pixel grid, small square marking the center pixel, hex readout in a pill below) appears the instant you click the eyedropper, snaps to your cursor, and follows it anywhere — including back over the picker popover itself — the OS cursor hides while you're over the canvas, and the magnifier floats above all app chrome (sidebars, toolbars, panels) so it's never clipped. A 96 px companion box pinned to the top-left corner of the canvas shows the same area around the cursor at normal zoom (no magnification) with a crosshair on the cursor pixel — the orientation reference so you don't lose track of where you are while the magnifier covers the work area. Click any pixel inside the canvas to commit the sample, or press Esc to cancel. Drag the picker out of the way by clicking and holding any empty area inside the popover (the gap between sliders, footer padding) — while you hold and drag, the cursor turns into a closed hand. The picker remembers where you left it: close it and reopen any color swatch and it pops back at the dragged spot. Reloading the page resets it to the swatch you click. Click outside the picker to keep your color, or press Esc to revert and close.
- ✨ Studio tools are always available — use the Magic Pen tool (press
O) for precise manual selections with anchor points, and the Layers panel for multi-image composition.
- Use Invert on a selected outline to flip the selection — outline a person, hit Invert, then Delete to remove the background and keep the subject.
- The compact Transform bar at the top of the canvas has Scale, Rotate, Flip H/V, Reset, and Center Image controls. Click the ▾ chevron to collapse it to a tiny pill (click again to expand). You can disable auto-expand in ⚙ Settings → Preferences.
- Tiled storage (default ON in ⚙ Settings → Preferences) reduces per-stroke memory use on large images by roughly 100×, so large photos and long undo histories don't stutter the browser. If you ever see a visual or performance issue, turn it off and refresh — your work is preserved either way.
- Device RAM (in ⚙ Settings → Preferences → Memory) controls how long your undo history can grow. Tell SnipOut how much RAM your computer has — bigger values mean more undo steps. Default is 16 GB. The "History cap" hint right next to the input shows how many undo entries you'll get on the current image.
- Click ⬡ Shapes in the Outline tool bar to insert a perfect geometric shape — rectangles, circles, stars, arrows, hearts, and more. Search to find the one you want, then click to place its center (grid-snaps when Snap is on), move the mouse to size it, and click again to commit. Press Esc to cancel.
- Hold Alt while clicking to reach under a nested outline and select the one behind it.
- The Select tool can select image layers too — hover over a visible part of any layer to highlight it, click to select. Shift+click to multi-select images. Press Escape to deselect. The action bar is always visible when Select is active.
- Shift-click image layers to apply 🎚 Tone, 🎨 Grade, ✂ Edges, 🎨 Color, and Transform sliders to multiple layers at once. The slider readout tracks the primary (last-clicked) layer, but every dragged value writes to every selected layer. The five tabs only enable when at least one image layer is selected.
- The top toolbar remembers the last tab you opened. Open the 🎨 Color tab on a Select+image, switch to a brush — Color stays open. Switch back to Select with no selection — Color force-closes (you can't use it without a selection), but as soon as you re-select an image, Color auto-reopens. Same for ◈ Transform, 🎚 Tone, 🎨 Grade, 📈 Curves, 🎞 Develop, and ✂ Edges — whichever tab you opened most recently auto-reopens once its conditions (selection / image kind / not in brush mode) are met again. To stop the auto-reopen, click the open tab's handle to close it manually — that clears the memory until you open another tab.
- ⫼ Guides alignment lines are enabled by default; ⊞ Grid overlay is off by default. Toggle them with the corner buttons. Snap to Grid controls whether outlines snap to grid intersections.
- Canvas Size — click the dimensions readout next to the SnipOut logo (in the header) to reshape the document for a specific export target. Choose a preset (Instagram Square, 1080p, 4K, A4, etc.) or type custom W×H. Layers are not scaled or cropped — they stay at their pixel size and re-center in the new frame. Undo fully reverts the change.
- The ⛶ Fit ▾ dropdown in the Transform bar offers four ways to match the selected layer to the canvas: Fit (contain) — aspect preserved, fully visible; Fill (cover) — aspect preserved, canvas fully covered (edges may extend past); Stretch — non-uniform, may distort aspect ratio; Actual Size — reset scale to 100%. Rotation and flip are preserved except for Stretch, which bakes into pixels and resets transform. All four modes are undoable.
- The Eraser penetrates all visible non-edit-locked layers. Edit-lock a layer (✏️/🔒 in the Layers panel) to protect it from erasing.
- Selecting an image layer (click on canvas or panel) automatically brings it to the front so you can see what you're working on. Lock a layer's order (click its position number) to prevent this — order-locked layers stay pinned.
- Each image layer shows a bold green number indicating its position. Click the number to lock the order (turns red) — the layer stays pinned at that position when you drag other layers around it. Click again to unlock.
- The "All Layers" bar at the top of the Layers panel lets you toggle order lock, visibility, drag lock, and edit lock for every layer at once. Individual per-layer toggles still work independently afterward — each master button auto-updates only when all layers share the same state.
- Each image-layer row carries an inverted-pyramid icon stack: top row = order lock (numbered button), visibility 👁, drag lock ↔️/📌. Bottom row = chain 🔗/⛓️💥 and edit lock ✏️/🔒. The two locks have crisp, non-overlapping roles: drag lock blocks ONLY canvas drag (pixel edits and transforms still work). Edit lock blocks pixel edits, scale/flip/rotate, and delete (drag still works). They're independent — set neither, either, or both.
- Chain layers (🔗 / ⛓️💥) — click 🔗 on two or more image layers to lock them together: dragging, scaling, flipping, rotating, deleting, or reordering any one of them applies to every chained layer in lockstep, in a single undo step. Useful for keeping a paired base + mask aligned during edits, or for moving a subject across multiple stacked composites without breaking alignment. Click 🔗 again on a layer to unchain it (icon flips to ⛓️💥). The 🔗 in the "All Layers" master bar at the top of the panel chains / unchains every image layer at once. Per-layer locks still apply: a drag-locked peer stays put when the chain moves, an edit-locked peer refuses chain transforms, and the whole chain delete is refused if any peer is edit-locked.
- Per-layer Fill color + color-sync toggle (🎨🔗 / 🎨⛓️💥) — every image layer now remembers its own Fill color. Switch active layer and the Fill swatch in the Color tab updates to that layer's stored color. When two or more layers are chained together, a new 🎨🔗 button appears in the Color tab next to the Fill eyedropper. While it's ON, picking a color updates every chained layer's Fill in lockstep. Click it to break the link (icon flips to 🎨⛓️💥) and color picks only update the active layer — handy when you want one chained layer painted red and another blue. Auto-resets to ON only when a fresh chain forms; if you manually broke it, adding more layers to the chain leaves it broken.
- Paint strokes follow the chain. When you Paint on a chained layer, the same brush stroke also lands on every other chained layer in one go, with each layer using its own stored Fill color. Edit-locked or hidden chained layers are silently skipped. A single undo reverts the stroke on every layer at once. Eraser and Restore are unaffected — they keep their existing behavior of erasing/restoring through every visible unlocked layer regardless of chain.
- Export Pair. When 2 or more layers are chained together, the Export popover renames itself to Export pair and the save button becomes ⬇︎ Save pair. Confirming saves one PNG per chained layer, named
‹title›_‹layer name›.png. Each PNG is rendered with that layer's own transforms baked in (move / scale / flip / rotate), so the pair lands at matching dimensions and stays pixel-aligned — ready to drop straight into a Unity shader. Pair mode is always PNG (lossless); the format and quality controls are hidden so a JPEG can't accidentally break the alignment. Hidden and edit-locked chained layers still export — chain membership is what counts. If the chained layers don't have matching dimensions, the export refuses with a toast (resize the document or re-import the offending layer at the correct size).
- Grayscale "color" (🎚️) — the Fill / Find color swatches gain a grayscale option. Click the Fill (or Find) color swatch and a small 🎚️ Grayscale button pops up next to it, alongside the OS color picker. Pick a hex color in the OS picker as usual, OR click the 🎚️ button to put this layer in grayscale mode. In grayscale mode, every Paint stroke / Paint Bucket / Fill Find on this layer drains color from whatever's underneath instead of laying down the Fill color — like Photoshop's Sponge tool in Desaturate mode. Each pixel under the brush (or matching the flood / find) is pulled toward its grayscale equivalent (R = G = B = luma). Use it on a base sprite to grayscale-out the regions that will get tinted by the Unity shader at runtime. Per-layer: each layer carries its own grayscale flag, so switching active layer shows that layer's setting. In a chain: with color-sync on, clicking 🎚️ flips every chained layer's flag together; with color-sync off, only the active layer changes. During chained painting, each peer paints based on its own flag — so you can mark the base layer "grayscale" and the mask layer "color" and a single stroke does both jobs at once.
- Pre-export grayscale check. When you click ⬇︎ Save pair, SnipOut scans the bottom chained layer (the base) for non-grayscale pixels inside any chained mask zone. If it finds any, a dialog opens with three choices: Cancel backs out, Export anyway writes the files unmodified (you accept the wrong-hue risk in Unity), or Auto-flatten to luminance rewrites the offending base pixels to their grayscale equivalent in a single undo step and then exports. Convention: the lowest layer in the chain stack is treated as the base; everything above it is treated as a mask. The check is skipped on canvases larger than 4 megapixels.
- Click the 👁 eye toggle next to the "Outlines" divider in the Layers panel to temporarily hide all outlines when they're in the way.
- You can select multiple images at once in the file picker (or drag-and-drop several files). They're imported as separate layers in the order you selected them. If no document is open yet, the first image becomes the background and the rest become layers.
- Your session is auto-saved to IndexedDB every few seconds. Refreshing the page (or reopening the app later) lands you on a fresh blank tab — every tab you had open is closed into a recovery row at the top of the History panel (up to 20 most recent), exactly the same as clicking the SnipOut logo. Click a recovery row to restore that tab as a cold tab. The × on a recovery row permanently discards it. Both the logo click and a page refresh also clear your in-app Copy buffer, so the Paste button resets to disabled on the fresh tab.
- In the History tab, each row has a ⎘ copy button next to the pin. Clicking the row restores current state to that point (destructive — overwrites what's after); clicking ⎘ instead copies that entry's layer to the clipboard so you can paste it back in with Cmd/Ctrl+V as a new layer without losing any current work. Useful for side-by-side comparison or for cherry-picking an earlier mask without rewinding.
- The document area (artboard) is shown as a subtle floating sheet above a flat pasteboard. When the background is set to Transparent, the artboard shows a near-black checkerboard — transparent pixels inside your composite look like checker, while outside the artboard is a flat color. This tells you where the document edge actually is when dragging layers off the boundary.
- RAW camera files (CR2/CR3, NEF, ARW, DNG, RAF, ORF, RW2, PEF, RWL) are decoded on import and the underlying 16-bit linear sensor data is preserved on the layer. A 🎞 Develop tab appears next to Tone/Grade only when a RAW layer is selected — its WB Temp/Tint, Linear Exposure, and Highlight Recovery sliders operate on the sensor data before the 8-bit tone curve, so pushing Linear Exp +2 recovers shadow detail without posterizing (compare to the same gesture with Tone Exposure on a JPEG). Brush strokes (Paint / Restore / Edge Heal) layer on top of the develop pass, matching Lightroom and Capture One: large WB or exposure changes after painting will shift the surrounding image but leave brush pixels alone. Develop math is approximate (the embedded decoder doesn't expose camera color matrices), so colors aren't byte-for-byte Lightroom-accurate — relative slider feel is faithful, absolute calibration is not. The Develop tab is hidden on JPEG / PNG / WebP / GIF / BMP layers.
Technical details
For people who want to know how the internals work.
Architecture
Three-canvas pipeline at the source resolution:
imgCanvas — pristine source, never modified
imgClean — optional working RGB layer for tools that change colors (Paint Color, Edge Heal, Decontaminate)
maskCanvas — alpha channel encoding which pixels are kept
The visible composite is rebuilt on every change as (imgClean || imgCanvas) combined with a derived mask via destination-in. The derived mask is the raw maskCanvas passed through any active edge refinement and cleanup operations on every frame — refinement is non-destructive, the underlying mask is never modified.
Quality preservation
All operations work at full source resolution. The AI model resizes its input internally for inference, but the resulting matte is upscaled with high-quality smoothing back to the original size and used as alpha. Exports read the composite at the original resolution, not what's shown on screen.
Edge refinement blur
A pure-JavaScript separable box blur on the alpha channel. Two O(n) passes with a sliding-window sum, independent of radius — a 50px blur costs the same as a 5px blur. This replaced an earlier ctx.filter='blur()' approach that had a browser quirk where blurring a binary-alpha source could fail to produce a visible gradient. JS blur is bulletproof.
Flood fill
Stack-based scanline algorithm with edge-clamped color distance test. Operates on the pristine source colors so the test is deterministic regardless of prior edits. Sensitivity additively widens or shrinks the effective threshold; the visited region is hard-cut so there's never a hazy boundary.
Color decontamination
Multi-pass dilation. Each pass, partially-transparent pixels adjacent to fully-opaque pixels take the average color of their opaque 8-neighbors and are themselves marked as filled. Four passes cover most real-world fringe.
History
Snapshots both mask alpha and imgClean RGB. Uses a version counter to dedupe snapshots — entries that share an unchanged imgClean reuse one backing buffer by reference, so a long sequence of brush strokes that don't touch RGB only stores one shared RGB snapshot. This keeps memory bounded by the number of distinct RGB states, not the number of history entries.
AI model
Currently uses @imgly/background-removal v1.5.8 — an ISNet model running in the browser via ONNX-WASM. The library is MIT-licensed and the bundled model is Apache 2.0. The matte output is gamma-corrected (0.85) before becoming the mask alpha to crisp soft edges.