Skip to content

Decoding Hashes ​

The decoder is the small half of the library (about 2.6 KB gzip) and the only part a browser needs to show placeholders. Its functions are exported from hazehash and from hazehash/decode, which are the same module. Importing them never pulls in the encoder.

ts
import { decode, getAspectRatio, getAverageColor, toBytes } from 'hazehash'

A hash is accepted as a base64url string or as the raw Uint8Array of its bytes. A hash that is not valid never hangs or crashes the decoder: the call either returns or throws a PlaceholderError. A truncated hash is valid and decodes with less detail.

Decoding to pixels ​

decode(hash, options?)

RgbaImage

Rebuilds the blurred preview as RGBA pixels. The result has the aspect ratio stored in the hash and the long side set by size, 32 pixels by default, so decoding a hash of a 1280×959 photo gives a 32×25 preview. The pixels are straight (non-premultiplied) sRGB, and a hash without alpha gives fully opaque pixels. It takes about 0.3 ms.

ts
import { decode } from 'hazehash'

const { width, height, data } = decode('Ed7UwRWKKv5znm6a7sC1tziHDNpMuCikxrYpIg')
// width: 32, height: 25, data: Uint8ClampedArray of 3200 bytes

The returned RgbaImage is { data: Uint8ClampedArray; width: number; height: number }, so it can be passed to new ImageData(data, width, height) as it is. To draw straight into a canvas, see Drawing to a Canvas.

hash ​

string | Uint8Array

The hash to decode.

options ​

DecodeOptions · optional

See Decoder options below.

Reading the aspect ratio ​

getAspectRatio(hash)

number

The width divided by the height that the hash stores, as a number such as 1.2968 for a 13:10 image. It reads only the header, so it is cheap enough to call on every render, and it is the number to use for aspect-ratio while the real image has not loaded. The ratio is stored with a resolution of about 9%, so for page layout use the real dimensions of the image when you have them.

ts
import { getAspectRatio } from 'hazehash'

getAspectRatio('Ed7UwRWKKv5znm6a7sC1tziHDNpMuCikxrYpIg') // 1.2968395546510096

Reading the average colour ​

getAverageColor(hash)

{ r: number; g: number; b: number; a: number }

The average colour of the image, read from the header alone. r, g and b are integers from 0 to 255 in sRGB, and a is the average opacity from 0 to 1, which is always 1 for a hash without alpha. Use it as the background-color of the box before the preview is drawn.

ts
import { getAverageColor } from 'hazehash'

getAverageColor('Ed7UwRWKKv5znm6a7sC1tziHDNpMuCikxrYpIg')
// { r: 152, g: 142, b: 126, a: 1 }

Converting a string to bytes ​

toBytes(base64url)

Uint8Array

Turns the base64url string of a hash into its bytes, the form for a binary column. The opposite function, toBase64Url(), comes from hazehash/encode. A string whose length is not valid throws InvalidLength, and one with a character outside the base64url alphabet throws InvalidCharacter.

ts
import { toBytes } from 'hazehash'

toBytes('Ed7UwRWKKv5znm6a7sC1tziHDNpMuCikxrYpIg').length // 28

Decoder options ​

size ​

number · default: 32

The long side of the decoded preview in pixels. The value is rounded and limited to 4–128, and the short side follows from the aspect ratio. A larger preview costs more time and shows nothing more, since the hash holds a few dozen coefficients, so the default is the right size for a blurred background.

dither ​

boolean · default: true

Applies a deterministic dither pattern while the preview is converted to 8-bit colour, which hides the banding that smooth gradients otherwise show. The pattern depends only on the pixel position, so the same hash always gives the same pixels. false gives plain rounding.

Example:

ts
const larger = decode(hash, { size: 64, dither: false })