Dither imagePro
Any image rendered dithered: Bayer 2, 4 and 8 and blue noise in a shader, Floyd-Steinberg, Atkinson and Sierra Lite in a worker, with ink and paper from your tokens and cells snapped to device pixels.
On this page
ProA portrait in four dither methods and three cell sizes. Hover or focus to see the original.
Installation
Usage
import { DitherImage } from "@/components/ui/chatcn/pro/dither-image"
<DitherImage src={image.url} alt={image.prompt} algorithm="atkinson" aspectRatio="4:5" reveal />The photo keeps its values in both themes: light areas take whichever of ink and paper is lighter. Set invert for a negative. Ordered methods update live as you change props; diffusion recomputes in a worker and caches the result, so switching themes only repaints.
Examples
Every method
ProOne photo through Bayer 2, 4 and 8, blue noise, Floyd-Steinberg, Atkinson and Sierra Lite, plus a three tone ordered dither.
States
Loading shows the paper, a missing file says what to do, and a host without CORS headers shows the plain photo instead of an error.
ProLoading, a missing file, four tones, a transparent paper, a negative, a muted ink and a reveal on hover.
Props
| Prop | Type | Notes |
|---|---|---|
src, alt | string | alt is required: it is the accessible name |
algorithm | "bayer-2" | "bayer-4" | "bayer-8" | "blue-noise" | "floyd-steinberg" | "atkinson" | "sierra-lite" | Default atkinson |
pixelSize | number | CSS px per cell, snapped to whole device pixels. Default 2 |
levels | number | Tones for ordered methods, 2 to 8. Default 2 |
ink, paper | string | Any CSS color or token. paper may be transparent |
contrast, brightness, threshold | number | Defaults 1.1, 0 and 0.5 |
invert | boolean | A negative |
reveal | boolean | Original on hover, keyboard focus, or press and hold on touch |
aspectRatio, width, height | Set the frame before the image loads, so nothing shifts | |
maxPixels | number | Default 1.5 MP. Lower it for many tiles |
renderer | "auto" | "webgl" | "2d" | Force a path |
onStatusChange | (status: "loading" | "ready" | "error") => void |
EffectImageFrame is exported too: the frame, real image, reveal and error state every image effect shares, for building your own.
Keyboard
| Key | Action |
|---|---|
Tab | With reveal, focus shows the original; leaving hides it |
Accessibility
- The canvas is
aria-hidden. The real content always exists: the<img>with youraltsits underneath and is what screen readers announce. - Under
forced-colors: activethe effect hides and the plain image shows with system colors. - Under
prefers-contrast: moreink and paper snap to the text and canvas tokens, with no mid tones.
Motion
- The first frame fades in over 200 ms. Reveal crossfades over 150 ms; nothing moves or scales.
- Under reduced motion only these short fades remain.