![stipple](https://cdn.slatesource.com/7/6/4/764d10fc-36f1-413d-887e-ebc849a01999.webp)

# stipple

- [Made in Slatesource](https://slatesource.com/@steph/stipple)
- By [Steph](https://slatesource.com/@steph)
- Created on Aug 5, 2026

## stipplestipple

A single-filesingle-file C librarylibrary for 1-bit1-bit ditheringdithering. FiveFive algorithmsalgorithms, no dependenciesdependencies, no allocationallocation you did not askask for, about 600600 lineslines. FourFour of those fivefive algorithmsalgorithms were writtenwritten by somebodysomebody otherother than the authorauthor. This pagepage is about them, becausebecause in a librarylibrary this smallsmall you are not dependingdepending on a projectproject. You are dependingdepending on fivefive peoplepeople.

![Gallery image 1](https://cdn.slatesource.com/b/7/4/b74413e3-8a6a-4851-a28b-97093cff93dc.webp)

The source. Generated greyscale: a ramp, a sphere and a hard bar, each stressing a different part of a kernel.

![Gallery image 2](https://cdn.slatesource.com/c/5/c/c5c18379-ac75-45f4-8715-99094990d030.webp)

Threshold. Twelve lines. Included so the others have something to be better than.

![Gallery image 3](https://cdn.slatesource.com/3/6/7/36702496-0534-4ea0-8438-7e4313333db7.webp)

Bayer 4x4. Ordered and tileable, which is why it is the only one that survives being applied per-tile.

![Gallery image 4](https://cdn.slatesource.com/1/f/9/1f94e0a5-d3cd-45bc-aded-415d599cf734.webp)

Floyd-Steinberg. Error pushed to four neighbours. The default, and the one most people mean.

![Gallery image 5](https://cdn.slatesource.com/e/3/b/e3b2761a-82e8-47a1-9ef5-ff42ed8afa48.webp)

Atkinson. Only three quarters of the error is distributed, which is why the highlights blow out like that.

## Those Are RealReal OutputsOutputs

EveryEvery imageimage aboveabove camecame out of the librarylibrary, runrun on the generatedgenerated sourcesource in the firstfirst tiletile. NothingNothing was retouchedretouched and nothingnothing was chosenchosen for flatteryflattery. The AtkinsonAtkinson samplesample losesloses detaildetail in the brightbright halfhalf and that is leftleft in, becausebecause the wholewhole reasonreason to shipship fivefive algorithmsalgorithms is that they failfail differentlydifferently and you needneed to seesee how beforebefore you pickpick oneone.

## RenRen OkabeOkabe, who wrotewrote the filefile that becamebecame this oneone

StartedStarted it as a 40 lineline thresholdthreshold functionfunction insideinside a GameGame BoyBoy emulatoremulator in 20172017, pulledpulled it out when a secondsecond projectproject neededneeded it, and has sincesince writtenwritten almostalmost nonenone of the algorithmsalgorithms in it. OwnsOwns the APIAPI, the single-headersingle-header buildbuild, and the decisiondecision that the librarylibrary nevernever allocatesallocates. ReviewsReviews everythingeverything. DescribesDescribes the rolerole as mostlymostly sayingsaying no.

## DilnozaDilnoza RakhimovaRakhimova

WroteWrote the Floyd-SteinbergFloyd-Steinberg implementationimplementation and then rewroterewrote it twicetwice. The secondsecond rewriterewrite removedremoved the serpentineserpentine optionoption afterafter demonstratingdemonstrating in a 900900 wordword issueissue commentcomment that it was producingproducing worseworse resultsresults than the plainplain scanscan for everyevery inputinput anyoneanyone couldcould produceproduce.

## MarcusMarcus FeldFeld

ContributedContributed AtkinsonAtkinson in 20192019 and the orderedordered BayerBayer matricesmatrices in 20202020. AlsoAlso wrotewrote the only documentationdocumentation anyoneanyone readsreads: a commentcomment blockblock aboveabove eacheach kernelkernel explainingexplaining what the algorithmalgorithm is for ratherrather than what it does.

## SofiaSofia AlmeidaAlmeida

FoundFound and fixedfixed the off-by-oneoff-by-one that misalignedmisaligned everyevery orderedordered ditherdither by oneone pixelpixel on imagesimages whosewhose widthwidth was not a multiplemultiple of fourfour. It had been therethere for threethree yearsyears and was visiblevisible in everyevery tiledtiled outputoutput, whichwhich is how it was finallyfinally spottedspotted.

## TobiTobi AdeyemiAdeyemi

PortedPorted the wholewhole librarylibrary to fixed-pointfixed-point arithmeticarithmetic so it runsruns on hardwarehardware withoutwithout an FPUFPU, and did it withoutwithout changingchanging a singlesingle outputoutput bytebyte on the floating-pointfloating-point pathpath. That constraintconstraint was self-imposedself-imposed and it tooktook ninenine monthsmonths.

People who wrote an algorithm here

5

Lines of C

617

Heap allocations

0

Algorithms

5

Years the ordered-dither off-by-one was live

3

> I wrote the first forty lines and the word no about four hundred times. Everything anyone actually uses this library for was written by somebody else.

## Why NamingNaming PeoplePeople MattersMatters HereHere

SixSix hundredhundred lineslines is smallsmall enoughenough that everyevery algorithmalgorithm has exactlyexactly oneone authorauthor and everyoneeveryone knowsknows who it is. When the fixed-pointfixed-point pathpath misbehavesmisbehaves on some embeddedembedded targettarget, the usefuluseful informationinformation is not that stipplestipple has a bugbug. It is that TobiTobi wrotewrote that pathpath, deliberatelydeliberately, underunder a constraintconstraint, and the issueissue shouldshould saysay so. CreditCredit and accountabilityaccountability are the samesame listlist readread in twotwo directionsdirections.

Getting it into your build

0%

Copy stipple.h into your source tree. That is the install

Define STIPPLE\_IMPLEMENTATION in exactly one translation unit before including it

C99 or newer. No build system, no package manager, nothing to configure

Define STIPPLE\_FIXED\_POINT if your target has no FPU

Pick an algorithm by looking at the samples above rather than by name

[Source and issue tracker](https://github.com/renokabe/stipple?utm_source=slatesource)