Module

Puregrain.Kernel

Package
purescript-puregrain
Repository
roman-mkh/puregrain

Error-diffusion kernels: where each pixel's quantization error goes, and in what shares.

Use a ready-made kernel, or build your own from a list of offsets with fromOffsets, which checks it. The ready-made ones: floydSteinberg, atkinson, jarvisJudiceNinke, stucki, burkes, the Sierras sierra3, sierra2 and sierraLite, fan, shiauFan and shiauFan2; noDiffusion for none. Each one's table, its source and what it suits: docs/error-diffusion.md.

#Offset Source

type Offset = { dx :: Int, dy :: Int, weight :: Number }

One neighbour that gets a share of a pixel's error.

  • dx: columns to the right; negative to the left.
  • dy: rows down.
  • weight: the share of the error.

#Kernel Source

newtype Kernel

A checked list of neighbours. Build one with fromOffsets, or use a ready-made one. Opaque, so every kernel ditherImage gets is valid.

Instances

#fromOffsets Source

fromOffsets :: Array Offset -> Either String Kernel

Checks a list of offsets and makes it a kernel.

  • Array Offset: the neighbours and their shares.

Left says which offset breaks which rule (offsets counted from 0):

  • every offset must point to a pixel not yet processed, in row-by-row scan order: a later row (dy > 0), or the same row further right (dy == 0, dx > 0);
  • every weight must be a finite number (not NaN or infinite);
  • no two offsets may point to the same neighbour.

The weights usually add up to 1, but needn't: Atkinson's add up to 3/4 on purpose. An empty list is valid: it's noDiffusion.

-- half of the error to the right, half down
fromOffsets [ { dx: 1, dy: 0, weight: 0.5 }, { dx: 0, dy: 1, weight: 0.5 } ]

#offsets Source

offsets :: Kernel -> Array Offset

The kernel's offsets, as given to fromOffsets.

#floydSteinberg Source

floydSteinberg :: Kernel

Floyd–Steinberg (1976): 4 neighbours, the classic.

#atkinson Source

atkinson :: Kernel

Atkinson (Apple, 1980s): 6 neighbours over the next 2 rows, each getting 1/8, so only 3/4 of the error is passed on: crisper and higher in contrast, at the cost of detail in dark and light tones.

#jarvisJudiceNinke Source

jarvisJudiceNinke :: Kernel

Jarvis–Judice–Ninke (1976): 12 neighbours over the next 2 rows, for the smoothest texture, at about 2.5 times Floyd–Steinberg's cost.

#stucki Source

stucki :: Kernel

Stucki (Peter Stucki, IBM Zurich, 1981): 12 neighbours over the next 2 rows, like Jarvis–Judice–Ninke, with weights that give a clean, sharp result.

#burkes Source

burkes :: Kernel

Burkes (Daniel Burkes, 1988): Stucki without its last row, so 7 neighbours over the next row: a little less clean, at a lower cost.

#sierra3 Source

sierra3 :: Kernel

Sierra 3 (Frankie Sierra, 1989–1990; also "Sierra" or "three-row Sierra"): 10 neighbours over the next 2 rows, for results like Jarvis–Judice–Ninke's with fewer neighbours.

#sierra2 Source

sierra2 :: Kernel

Sierra 2 (Frankie Sierra, 1989–1990; also "two-row Sierra"): 7 neighbours over the next row, a faster Sierra 3.

#sierraLite Source

sierraLite :: Kernel

Sierra Lite (Frankie Sierra, 1989–1990; also "Filter Lite" or "Sierra-2-4A"): 3 neighbours, one fewer than Floyd–Steinberg, for similar results.

#fan Source

fan :: Kernel

Fan (Zhigang Fan, 1993): Floyd–Steinberg's 4 neighbours with one weight moved, its 1/16 from below-right to two columns left.

#shiauFan Source

shiauFan :: Kernel

Shiau–Fan (Jeng-Nan Shiau and Zhigang Fan, 1993): 4 neighbours, with weights in eighths, made to reduce the "worm" patterns of Floyd–Steinberg.

#shiauFan2 Source

shiauFan2 :: Kernel

Shiau–Fan 2 (Jeng-Nan Shiau and Zhigang Fan, 1993): the same aim with 5 neighbours, reaching three columns to the left.

#noDiffusion Source

noDiffusion :: Kernel

No neighbours: no error is passed on, so each pixel is quantized on its own. With Puregrain.Ordered, that's pure ordered dithering; with threshold or nearestLevel, plain rounding to a level.