Poisson image editing: a pasted moon takes on the light of a sunset sky.
A naive paste copies the source pixels and their background, leaving a hard seam. Poisson editing copies the source's gradients instead and solves for new pixels whose Laplacian matches them, with the border pinned to the target. Written as a correction to the source, this is Laplace's equation, and the correction (shown in the side panel) is a smooth colour membrane that relights the patch. Jacobi iteration and a multigrid V-cycle with red-black Gauss-Seidel solve the same equations side by side, and a chart plots both residuals against equal work. Mixed gradients keep whichever gradient is stronger, so a painting on rock keeps the rock's texture.
Try it. Drag the patch anywhere, and use the mouse wheel or the bracket keys to resize it. Pick a patch, switch between naive, seamless and mixed pasting, and between the Jacobi and multigrid solvers (switching restarts the solve so you can watch it converge). Stamp bakes the patch in and brings the next one.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a Poisson image editing (seamless cloning) demo with JavaScript and the HTML canvas element. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.
Start simple:
- Paint two images in code. A target: a sunset sky with an orange-to-purple gradient over a lake, 320 x 200. A source patch, 64 x 64: a grey cratered moon on a black square.
- Make a circular mask slightly larger than the moon. Let me drag the patch around the target.
- First show a naive paste: copy the source pixels inside the mask. The black square looks terrible, which is the point.
- Then blend: solve for new pixels f inside the mask such that 4 f(p) minus its four neighbours equals the same expression computed on the source, with the pixels just outside the mask fixed to the target. Solve each colour channel with Jacobi iteration, a few dozen sweeps per frame, starting from the naive paste, and draw the result every frame so I can watch colour creep in from the border.
- Clamp to 0..255 and draw the result scaled up with drawImage.
Once that works, make it beautiful:
- Show the correction (blended minus source) as its own small image: it should be a smooth colour wash.
- Plot the residual on a log scale per frame so I can see how slowly Jacobi converges.
- Add a 'mixed gradients' mode that keeps, for each pair of neighbouring pixels, whichever gradient is stronger, the source's or the target's, and try it with a painted symbol on a textured rock.
Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as a multigrid solver, a lasso tool to cut my own patches, or stamping several patches into one scene.