Classic clone brush. Pick a source point in a clean part of the image, then paint that source into a target area with a feathered brush. The source follows the cursor at a locked offset for the duration of each stroke, so you can repair along curved paths (galaxy arms, nebula filaments) while sampling a parallel stretch of similar structure. Useful for anything the one-click Blemish Blaster can't handle on its own: large irregular defects, star field continuations, satellite trail patches on textured background, and any time you want manual control over which pixels get used as the heal source.
Ctrl+left-click anywhere in the image sets the source point. A solid green X is drawn at that location so you can see what you've picked. The source persists until you Ctrl+click somewhere else or press Clear Source; it survives between strokes, mode changes, zoom and pan.
Each stroke captures the source–target offset at its first click — so the X marker you see while painting isn't the original Ctrl+click point, it's the live source position offset from your current cursor by that captured amount. This is the classical Photoshop clone-stamp behaviour: start the stroke where you want the fix to begin, and the source tracks along at the same relative offset.
Once a source is set, a plain left-click (no Ctrl) starts a stroke. Dragging continues it. Releasing ends it. A dotted green line links the brush to its live source position while the stroke is active, so you can always see where the next dab is being sampled from.
Dabs are placed at regular intervals along the drag path to keep the stroke smooth; the spacing is ¼ of the brush radius, so large brushes dab less often (fewer but bigger) and small brushes dab tightly along the path. Each dab's source position is computed from the stroke-wide offset — so if the source approaches the image edge mid-stroke, the dabs quietly skip over the out-of-bounds part rather than filling it with black.
The 90×90 preview to the right of the sliders shows the current mask at the live radius/feather/opacity values. Watching this while adjusting feather is the quickest way to understand what the brush will do before you click — the chip renders the exact mask that will be multiplied into the image.
Dismisses the current source point so Ctrl+click is needed again before the next stroke. Doesn't affect the painted result — only the source marker.
Off by default. When on, a statistical stretch is applied to the preview buffer only; the underlying image data (and the undo/redo state) is never modified by this control. Essential for working on linear data where a defect would otherwise be invisible against the background.
Both stretched and non-stretched display buffers are kept in sync during painting so toggling the checkbox is instant — no need to wait for a re-stretch of the whole image.
Toolbuttons for Zoom Out, Zoom In, Fit to Preview. Mouse wheel and trackpad zoom with the cursor as the anchor — small trackpad swipes fine, click-wheel detents coarse, hold Ctrl to zoom faster in either case. Range 0.05× to 4×. The preview auto-fits on first open; after that your zoom and pan state is preserved across all operations in the session.
Each complete stroke (down–drag–up) is one undo entry, regardless of how many dabs it contained. The ring holds up to 20 strokes. Ctrl+Z and Ctrl+Y undo/redo as usual (bound as actions on the dialog itself so they take priority when the dialog has focus).
Apply to Document commits the current working image back to the originating document as a single edit named “Clone Stamp” and closes the dialog. Mono originals are automatically collapsed back to a single plane; RGB sources stay RGB. Close discards everything. The dialog's window geometry is persisted per-user and restored on next open.
All processing on float32 [0, 1]. The dialog displays a 3-channel copy of the working image regardless of source depth; on Apply, mono originals are collapsed back to a single plane.
The brush is a circular disk with a feathered falloff ring at the
edge. With radius r and feather fraction
f ∈ [0, 1], the inner hard-disk radius is:
Everything inside rinner has weight 1;
between rinner and r the weight
falls off linearly to zero at the edge:
where d is the Euclidean distance from the brush
centre. At f = 0 the formula collapses to a
hard disk (the r·f denominator special-cases to a
step at d = r); at f = 1
it ramps linearly from the brush centre to the edge. The resulting
mask is cached by its (r, f) key as a NumPy array, so
subsequent dabs with the same parameters reuse the same buffer
without rebuilding it.
During a drag from p0 to
p1, dabs are placed at a fixed spacing
proportional to the brush radius:
then n dabs are linearly interpolated along the
segment. The ¼-radius spacing is the standard Photoshop
default — dense enough that the overlapping dab masks sum to a
flat stroke, sparse enough that huge brushes don't thrash the CPU.
When a stroke starts at target position
(tx(0), ty(0))
with source at (sx, sy), the
offset is captured and locked for the whole stroke:
Each subsequent dab at target position i samples
from:
which is the signature behaviour of a classical clone brush: as you drag the cursor, the sampled source traces a parallel path. Starting a new stroke captures a new offset based on wherever the stroke begins, so moving to a new target area doesn't drag the source along with you until you click to begin painting.
Per dab, the final per-pixel alpha combines mask weight and opacity, and the result is a straight linear blend:
applied in place on all three display channels. Source and target rectangles are clipped against the image bounds jointly: if either falls off the edge, the visible intersection is painted and the invisible part is skipped, so a brush that straddles the border still paints its in-bounds half without pulling in bogus zeros from off-image.
Snapshotting the entire image on every stroke is expensive and wasteful — most strokes touch a tiny fraction of the frame. The dialog partitions the image into 64×64 tiles and tracks which tiles each stroke has modified:
The result: a 20-pixel dab in a 6000×4000 frame costs one 64×64 patch to undo (16 KB), not the entire frame (288 MB). A long freehand stroke that traverses several tiles pays only for those tiles once each, regardless of how many dabs crossed them.
The dialog keeps three identical-shape float32 buffers in sync:
_image (authoritative), _display_raw (what
auto-stretch-off shows), and _display_stretched (what
auto-stretch-on shows). Each dab is applied in place to all three,
so toggling the auto-stretch checkbox swaps between them with no
latency.
During a drag, repainting the whole scene on every mouse-move event would starve the paint loop, so refresh is throttled to ~30 fps via a 33 ms single-shot timer: the first dab schedules a refresh, subsequent dabs within the window are coalesced into that pending refresh, and the preview catches up smoothly without flooding Qt's event queue.