Upload an image to begin
or use a test image
Loading WASM...
For best results, use an image with good contrast and a subject that fills the frame.
Overview
Conway dithering converts an image into a one-bit Game of Life pattern. The resulting image is not merely styled to look like Conway's Game of Life — the pattern is actually produced by running the Life rules forward from an evolutionarily-optimized starting state. I developed this tool to create the cover of Dennett's Real Patterns in Science and Nature (MIT Press, 2026).
How It Works
The image is divided into overlapping tiles. For each tile, an evolutionary algorithm searches for a starting state that, after a fixed number of Game of Life steps, produces a pattern that approximates the target image. Candidates are mutated and evaluated over many generations, with the mutation rate decaying as the image converges.
Why It Works
Precursor Optimization
The algorithm evolves the precursor rather than the output directly, so the result is always a valid Game of Life state — not an approximation of one. The visual style is, thus, a natural consequence of the algorithm's operation.
Tile Decomposition
The use of overlapping tiles keeps each tile's search space small, while ensuring that adjacent regions remain visually coherent. Generations of the evolutionary algorithm are divided into sets called "iterations." After an iteration is complete (e.g., after 100 generations), the tiles are updated with information from the overlapping regions. Because each tile shares context with its neighbors, the final image is naturally seamless. Seaming is also mitigated by offsetting the tiles from iteration to iteration.
Density-Based Objective
Finally, scoring is done on a blurred version of both the evolved output and the target image. This shifts the objective from pixel-level matching — which would produce a hard-threshold result, turning bright regions solid white and dark regions solid black — to density matching, where the optimizer must produce the right proportion of live cells in each local area. The blur radius determines the spatial scale of this density constraint. The target is also rescaled to avoid pure black, since fully black — i.e., fully alive — regions would demand densities inconsistent with the rules of Life, which prevent overcrowding.
Output Controls
- Start / Pause / Resume
- Click to begin optimization. Click again to pause run. Click once more to resume run.
- Save Current
- Downloads the image currently displayed in the output panel.
- Save Best
- Downloads the image from the iteration with the lowest recorded loss. Enabled after the first cycle completes.
- M + Mouseover
- Hold M and move the mouse over the image to show a magnifying loupe.
History Controls
- Iterations
- Scrubs through snapshots. Snapshots are saved when loss drops more than 10% from the previous snapshot or every 32 iterations at most.
- GoL Steps
- Shows the evolution of each snapshot from precursor to output image in the GoL. The slider selects which GoL step is currently displayed. Useful for exploring how the pattern changes as it evolves forward in time.
- Save Current
- Downloads the currently displayed snapshot.
- Save Series
- Downloads a single image containing all GoL step counts (1 through N) for the selected iteration, laid out horizontally.
- M + Mouseover
- Hold M and move the mouse over the image to show a magnifying loupe.
Parameters
- Population
- Number of candidate precursors maintained per tile per iteration. More candidates explore the search space more broadly but increase computation per iteration.
- Tile Size
- Side length of the square region each tile covers in the output image. Fixed at run start. Smaller tiles reduce search space per tile and improve quality at the expense of speed.
- Tile Gens
- Number of generations the genetic algorithm runs per tile per iteration. More generations refine each tile further per pass but slow down iterations. Tiles are more refined each iteration, but share context information less often.
- Image Its
- Total number of iterations to run. Fixed at run start. More iterations allow the image to converge further, especially with a slow decay rate.
- GoL Steps
- Number of Game of Life steps applied to each precursor before scoring. Fixed at run start. More steps produce more Life-like patterns, while fewer steps makes it easier to approximate the target image.
- Mut. Rate
- Initial probability of flipping any given cell in a candidate precursor during mutation. Higher rates explore more aggressively early on; the rate decays over iterations.
- Decay λ
- Controls how quickly the mutation rate decays. Specifically, the half-life of the mutation rate in iterations. Smaller values decay faster, locking in structure sooner; larger values keep mutation active longer.
- Revert Best
- Number of consecutive bad cycles after which the precursor grid is reset to the best seen so far. Set to off (0) to disable. Prevents the algorithm from diverging too far from a known good solution; rapid resetting reduces exploration.
- Elitism
- Number of top candidates carried over unmutated to the next generation. Prevents the best solution from being lost to mutation; higher values reduce exploration.
- Loss Func.
- The function used to measure the difference between the blurred evolved output and the blurred target. Euclidean (L2) penalizes large errors heavily; Manhattan (L1) treats all errors equally; Huber is a blend of the two.