What this is
Clarity is a canvas image-filter library: 62 filters that each take an ImageData and return an ImageData, so they compose by chaining. They run as fragment shaders by default - an N-filter chain is N draw calls with no round-trip to the CPU between them - and every one of them has a CPU implementation behind it for where WebGL2 is missing.
This page is the playground for it. Pick a source, stack filters, drag to reorder, and read the code it generates. The chain lives in the URL, so anything you build here is a link:
Questions
- Do my images get uploaded anywhere?
- No. Every filter runs in your browser, on your machine. Nothing you drop on the page, and nothing from your webcam, is sent to a server - there is no server, only a static page.
- Does it need a GPU?
- No. Filters run as fragment shaders where WebGL2 is available, and every one of them has a CPU implementation behind it. The fallback is per stage rather than all-or-nothing, so one unsupported filter does not drop the whole chain.
- Can I use these filters in my own project?
- Yes - npm install @calrk/clarity. It is MIT licensed, has no dependencies, and needs no DOM: every filter takes an ImageData and returns an ImageData, so it runs in Node too.
- Can I share a chain I have built?
- Yes. The whole pipeline lives in the URL, so copying the address bar copies the exact stack, its filters, their settings and their order.
Every filter
All 62, by family, each linked to a chain that shows it working. This list and the palette above are built from the same catalogue in the library.
Process
- Bleed
- Blurs a single channel, so colour bleeds out of its edges.
- Bilateral
- Blurs flat areas while leaving edges sharp - denoising, skin smoothing, and the cartoon look.
- Blur
- Stack blur - a fast Gaussian approximation.
- ChromaKeyMakes transparency
- Makes one colour transparent, matching on hue rather than brightness - the green screen.
- Convolver
- Convolves a 3x3 kernel over the frame - sharpen, smooth, emboss, or edges by Sobel or Laplace.
- Desaturate
- Pulls colour towards grey, by an amount, keeping luminance.
- Dither
- Quantises to a few levels and hides the banding in a pattern - ordered, or error diffusion.
- DotCrawl
- The crawling dot pattern composite video leaves along colour edges.
- FeatherWants black & white
- Softens the edge of a binary mask without moving it - measured distance rather than blur, so it can spread or choke as well.
- GradientMap
- Recolours the frame by brightness through a named ramp - fire, ice, thermal - and can cycle it.
- Glow
- Blurs the image and blends the blur back over the original.
- Halftone
- Redraws the frame as a grid of dots on a flat ground, sized by how strong each cell is.
- HanoverBars
- Rotates the chroma of every other bar of lines, or darkens them.
- Histogram
- Draws the frame's tonal distribution across the bottom of it - the one filter that measures the picture rather than changing it.
- Invert
- Inverts colour. In dynamic mode it reflects within the image's own range.
- Levels
- Remaps the black point, white point and gamma - the everyday contrast control.
- Morphology
- Grows or shrinks light regions; open and close remove speckle without moving the edges that remain.
- Noise
- Adds random noise, optionally monochromatic.
- Pixelate
- Snaps the image to fixed-size blocks.
- Posteriser
- Quantises to a fixed number of colours via median cut.
- SkeletiserWants black & whiteMakes black & white
- Thins a shape down to the one-pixel lines running through the middle of it.
- Vignette
- Darkens towards the corners.
- hsvShifter
- Rotates hue and scales saturation/value.
Thresholders
- GradientThresholdMakes black & white
- Marks pixels whose neighbours differ by more than a threshold - edge detection by another route.
- MedianThreshold
- Quantises using median and quartile pixel values.
- ValueThresholdMakes black & white
- Two-tone threshold at a given value, or one derived from the image.
Salience
- EdgeDetector
- Highlights edges with a 3x3 kernel, or a fast two-sample difference.
- MotionDetectorNeeds motion
- Absolute difference between the current frame and one N frames back.
- ShotDetectorNeeds motion
- Marks the frame where a cut happened, by how much of the picture changed at once.
- SkinDetectorMakes black & white
- Thresholds YCbCr into a binary skin/not-skin mask.
Transform
- ChromaticAberration
- Displaces the R and G channels in opposite directions.
- DisplaceTwo inputsWants a normal map
- Moves every pixel by an offset read out of a second image - the irregular distortion a sine cannot make.
- FishEye
- Bows the image outward like a lens, or pinches it inward.
- Mirror
- Flips the image horizontally, vertically, or both.
- Rotator
- Rotates in 90 degree steps.
- Taper
- Squeezes one edge of the frame in - a flat trapezoid, or a plane receding away from you.
- Tiler
- Mirrors the image into four quadrants, so opposite edges match and the result tiles seamlessly.
- Translator
- Shifts the image by a percentage, wrapping at the edges.
- Wave
- Displaces pixels along a sine function.
Height Map
- ContourerWants a height map
- Bands a height map into discrete contour steps.
- NormalFlipWants a normal map
- Flips or swaps the X/Y axes of a normal map.
- NormalGeneratorWants a height map
- Derives a tangent-space normal map from a height map.
- NormalIntensityWants a normal map
- Strengthens or weakens the X/Y tilt of an existing normal map.
Starters
- CloudStarter
- Fills the frame with fractal gradient noise, in grey - fog, terrain, or a mask for anything else.
- CrackulateStarter
- Cracks a surface, in grey - recursive fracture with the T-junctions and dead ends a cell diagram cannot make.
- FillStarter
- Fills the frame with one flat colour.
- GradientStarter
- Fills the frame with a linear or radial grey ramp - the mask primitive for fading anything.
- WoodgrainStarter
- Fills the frame with growth rings and grain, in grey - timber out of an empty frame.
- ShapeStarter
- Draws one filled shape in grey - rectangle, circle, ellipse or regular polygon. The mask primitive for a region rather than a ramp.
- VoronoiStarter
- Fills the frame with cellular noise - blobs, cracked seams, or flat stone cells.
Dual Input
- AddTwo inputs
- Adds the second image to the first, clamping at white.
- SubtractTwo inputs
- Subtracts the second image from the first, clamping at black.
- DifferenceTwo inputs
- Absolute difference between two images - symmetric, and it keeps the range Subtract clamps away.
- BlendTwo inputsTakes a third input
- Weighted mix of two images. An optional third frame is a mask, mixing them per pixel rather than by one number.
- MaskTwo inputs
- Binary stencil - keeps the first image where the mask is light, blacks it out where the mask is dark.
- MultiplyTwo inputs
- Multiplies the two images together, channel by channel, keeping the first one's transparency.
- StamperTwo inputsTakes a third input
- Scatters copies of the second image over the frame - grass, flowers, stars. Wants a sprite with transparency, not a picture. An optional third frame is a probability map deciding where stamps land.
Misc
- Brickulate
- Overlays a brick/tile grid with bevelled grooves.
- DifferenceDetectorNeeds motion
- Compares each frame against the first one it saw.
- GhosterNeeds motion
- Onion-skins the last N frames together, weighted towards the newest.
- ScreenBurnNeeds motion
- Burns a fading ghost of the brightest thing that has been on screen.
- Puzzler
- Scrambles the image into shuffled tiles.
Clarity is built by Clark Lavery.
More about the project ·
Source on GitHub ·
@calrk/clarity on npm