atelier

Catalog / Technique

Image treatment

Use when dithering, screening, posterising, pixelating or recolouring an image on a page, as a look or as a state it arrives through. Covers the one idea under the treatments, the three ways to deliver one and when each, the resolution rule, moire, which treatments may rest on which images, and the no-go list.

Loads as
technique-image-treatment
Written for
An agent, to follow

Image treatment

Ordered dither, blue-noise dither, dot halftone and line halftone are one operation: compare the image’s luminance at a pixel with a threshold that depends only on the pixel’s position, and put ink where the luminance is below it. They differ only in the map of thresholds.

When to use

  • A picture arriving through a treatment that lifts: the look registers, then the picture is itself.
  • A decorative picture that stays treated, so that mismatched images read as one set.
  • A listing’s thumbnails, treated at rest and true on hover and focus, only if they are declared decorative.

Do not use it for:

  • Evidence. A screenshot’s colours are what it is evidence of; a treatment on it is transient only.
  • Small text under a 1-bit dither. The type is gone.
  • Every figure of a long page. One trick, once.
  • A hero with a headline over it. Type in the tint or the shade disappears into the picture.

Rules

  1. Choose the cell in CSS pixels, then snap it to whole device pixels. At 125 percent an 8 px tile came out as cells alternately one and two pixels wide, a plaid. Re-run when the ratio changes.
  2. The threshold map is the dial. Bayer from the bits of the coordinates (no bytes), blue noise as a tile (about 7 kB gzipped, because noise does not compress), a cosine bump for dots, a ramp for lines. One file; the map is a choice.
  3. Keep a halftone’s period at six device pixels or more and antialias the dots. Under that it moires against the pixel grid.
  4. A dither in CSS is the copy of the picture under a filter, with the map over it at half opacity. The average of the two, pivoted by a contrast of sixty, is the threshold test. The copy, not the picture: a filter on the picture’s parent reaches the caption, and wrapping the picture moves it.
  5. Colour the result with a table. An SVG feComponentTransfer maps black to the shade and white to the tint, the skin’s own colours. Blend layers do the same but have to sit outside the filtered box.
  6. A resting treatment only on a picture the page calls decorative. alt="" is how a page says a picture carries no information; the recipe checks it and refuses otherwise.
  7. Lift, never cut. End with a crossfade to the picture, and for the shader make the texture at the lid’s size so the last frame and the picture agree.
  8. Keep a lift at 300 ms or more and never loop. A level ramp or a dissolve over a large high-contrast image, run fast, is the nearest thing here to a flash.
  9. Error diffusion is build-time only. Each pixel depends on the ones before it, so it cannot run in a fragment shader and cannot animate.

Decisions

Question Choose Because
Which engine first? CSS (dither-lift) No context, no CORS, no image bytes, and it fails to the untouched picture
When the shader? For one sample a cell, whole round dots, and the pixel-by-pixel transitions Only a shader can do those
Bayer or blue noise by default? Bayer Free, and the recognisable look. Noise is quieter and costs 7 kB
sRGB or linear thresholding? sRGB Lighter, more mid-tone; it is what the CSS engine does anyway
Threshold-form or sampled dots in CSS? Threshold form The CSS engine can only make that one
Which transition? Fade in CSS; dissolve in the shader Develop re-rasters the box every frame; dissolve is the best still and thematically right
A treated state in the stylesheet, so it shows before script? No, on anything that is evidence If script never runs the picture stays treated
ASCII, CMYK rosettes, scanlines, CRT? No, on content pages Foreign colours, a costume on anything that never ran on a tube, and the costliest of the set

Tuning

Dial Start Range One end The other
Cell, CSS px (dither) 1.5 1 to 4 Grey; the pattern vanishes Chunky; reads as an old console
Period, CSS px (halftone) 6 4 to 14 Moire, mush A poster; the picture is hard to read
Angle 45 0 to 90 0 shows the grid as rows 15 or 75 look printed in colour
Levels 2 2 to 4 Hardest, least detail Keeps text legible, loses the bite
Bias 0 -0.2 to 0.2 Darker Lighter. A dark screenshot came out as ink at 0
Duration (ms) 700 300 to 1200 A flicker A wait
Hold (ms) 0 0 to 400 Lifts at once The treated state registers first

Ranges are from stills. Nothing has been tuned in motion.

Rest state

The untouched img, with no layer and no canvas. Under reduced motion the treatment is never shown: showing it and cutting to the picture is still a flash. A decorative picture with rest is the one case that stays treated. In print, the untouched picture: a resting dither beats against the printer’s own screen.

Cost

  • To build: the CSS engine small to medium (the snap, the table, Safari and Firefox); the shader medium, on the lid.
  • To run: the CSS engine is two filters and a blend on the browser’s own layers, no context, no image bytes; the noise tile is 7 kB. The shader is one lid per picture, with the lid’s costs.
  • To the reader: a picture they cannot read for the length of the lift. Keep it under about half a second on anything they came for.

Checklist

  • The budget check passes, with the noise tile’s price stated in the doc.
  • npm run check:browser: layers go on, hidden from readers, and nothing of them remains after the lift.
  • npm run check:browser: at a ratio of 1.5 the tile is a whole number of device pixels.
  • npm run check:browser: rest is refused on a picture with alt text.
  • Looked at on the editor image: type under the treatment is either legible or clearly meant to be gone.
  • Run once in Safari and once in Firefox before it is marked passed: the exact pixels of a contrast filter over a blended layer are not documented there.

Recipes

  • dither-lift: the CSS engine.
  • shader-lift: the shader, on the lid.

Sources

  • surma-ditherpunk: the treatments, blue noise, and linear light
  • wikipedia-ordered-dithering: the Bayer construction
  • peters-blue-noise-textures: void-and-cluster, as implemented here
  • demofox-interleaved-gradient-noise: the formula that stands in for a map
  • tudor-css-halftone: the pattern half of the CSS route
  • wikipedia-halftone: screens, angles, and why a resampled halftone moires