import type { BitReader, BitWriter } from '../bitreader'; /** * Build canonical Huffman code lengths from per-symbol frequencies, with * lengths capped at `maxBits`. Uses a textbook two-step: * * 1. Build a *standard* (uncapped) Huffman tree via min-heap merging. * This gives the optimal lengths if no cap were imposed. * 2. If any length exceeds `maxBits`, run zlib-style "bit-length * fix-up": iteratively shorten the deepest nodes and lengthen the * shallowest until every length fits and Kraft's inequality holds. * * Returns a `Uint8Array` of length `freq.length` where `lengths[s]` is the * number of bits assigned to symbol `s`, or 0 if `freq[s] === 0`. * * The earlier package-merge implementation was elegant on paper but * subtly miscomputed lengths for sparse distributions in a way that * violated Kraft's inequality (sum 2^-len > 1) — and that produced * decoder bitstreams the meta-Huffman tree couldn't parse. Standard * Huffman + length fix-up is what zlib, deflate, and libwebp use, and * it's known correct. */ export declare function buildCodeLengths(freq: Uint32Array | number[], maxBits?: unknown): Uint8Array; /** * Convert per-symbol lengths into the canonical code value for each symbol. * * Returns a `Uint32Array` of codes; bit ordering matches what VP8L expects: * bits are emitted high-to-low, which on the wire (LSB-first within byte) * means we *must* reverse before writing. */ export declare function lengthsToCodes(lengths: Uint8Array): Uint32Array; /** Reverse the low `bits` bits of `value`. Used to convert canonical codes to wire order. */ export declare function reverseBits(value: number, bits: number): number; /** * Write a Huffman tree to the bitstream using VP8L's "normal code" path — * which itself uses a tiny meta-Huffman code over the 19 code-length-codes. * * VP8L also has a "simple code" fast-path for trees with 1 or 2 non-zero * lengths; we use it when applicable since it's tiny on the wire. */ export declare function writeHuffmanTree(writer: BitWriter, lengths: Uint8Array): void; /** * Read a Huffman tree from `reader` for an alphabet of `numSymbols` symbols. * Mirrors `writeHuffmanTree` exactly. */ export declare function readHuffmanTree(reader: BitReader, numSymbols: number): HuffmanTree; /** * A built Huffman tree, ready to decode symbols from a bitstream. * * Storage is a single flat `Int32Array` holding a primary LUT followed * by zero or more secondary LUTs ("subtables") — the standard two-level * scheme used by every fast inflate decoder. Codes whose length fits in * the primary LUT (≤ 8 bits) decode in one peek + consume; longer codes * decode via a secondary LUT lookup with no tree walk. * * Entry encoding (`Int32` per slot): * - Non-negative entry → leaf: * bits 16..23 = code length (1..maxLen) * bits 0..15 = symbol (alphabet is ≤ 2328, fits in 16 bits) * - Negative entry → subtable pointer: * bits 0..23 = offset into `lut` of the subtable's first slot * bits 24..30 = subtable size in bits (so subtable has `1 << subBits` entries) * bit 31 = 1 (the sign bit, used as the discriminator) * * Subtable leaf entries store the *extra* code length beyond the primary * 8 bits in the same `bits 16..23` slot, so the consumer in `readSymbol` * adds 8 to that count when computing total bits to consume. */ export declare class HuffmanTree { buildFromLengths(lengths: Uint8Array | number[]): void; readSymbol(reader: BitReader): number; }