ditherkit
@ditherkit/core

@ditherkit/core

Pure dithering algorithms and image utilities. No DOM, no framework.

@ditherkit/core is the algorithmic heart of the toolkit. It exports pure functions that operate on pixel buffers — no DOM, no framework, no runtime dependencies. Use it directly when you want full control, or reach for it when you're building on a stack that doesn't have a dedicated wrapper yet (Svelte, Vue, Cloudflare Workers, Node CLIs).

What's in the box

Every function mutates a Uint8ClampedArray of RGBA pixels in place. That's the same shape as ImageData.data in the browser and what Sharp hands you in Node, so the core slots into both worlds without conversion.

A typical pipeline

The algorithms assume grayscale input and a black/white (or color) palette. A normal call order looks like this:

import {
  applyBrightness,
  applyContrast,
  grayscale,
  floydSteinbergDither,
  type Color,
} from '@ditherkit/core'

const palette: Color[] = [
  { r: 0, g: 0, b: 0 },
  { r: 255, g: 255, b: 255 },
]

// `pixels` is a Uint8ClampedArray of RGBA. Get it from a canvas
// (`ctx.getImageData(...).data`) or from Sharp's raw buffer.

applyBrightness(pixels, 10)   // optional, [-100..100]
applyContrast(pixels, 20)     // optional, [-100..100]
grayscale(pixels)             // optimal for 2-colour palettes; omit for colour palettes
floydSteinbergDither(pixels, width, height, palette)

// `pixels` is now a 1-bit (or N-bit) dithered image in place.

Each step is in-place and allocates no new buffers, so the whole pipeline is O(pixels) time and O(1) extra memory per call.

When NOT to use @ditherkit/core directly

If you're in a plain React app, reach for @ditherkit/react. If you're on Next.js and want server-rendered and cached output, reach for @ditherkit/next. Those packages use @ditherkit/core internally and give you a component that handles the pixel plumbing and the Web Worker or Sharp glue for you.

Use @ditherkit/core directly when:

  • You're targeting a framework without a wrapper (Svelte, Vue, Solid).
  • You're in a build script and just need a .jpg.jpg transform.
  • You're at the edge (Cloudflare Workers) where Sharp isn't available.
  • You want to compose the algorithms into a larger pipeline of your own.

On this page