{
  "schemaVersion": 1,
  "contentVersion": "ca42e61ede0a24f789d7287a0001244ad22f4abf",
  "id": "docs/start-here/lossless",
  "collection": "docs",
  "title": "Lossless compression",
  "description": "How lossless compression works, from redundancy and entropy to run-length, Huffman, arithmetic and predictive coding, and how it is used in media codecs.",
  "canonicalUrl": "https://encode.wiki/start-here/lossless/",
  "apiUrl": "https://encode.wiki/api/v1/documents/docs/start-here/lossless.json",
  "markdownUrl": "https://encode.wiki/api/v1/markdown/docs/start-here/lossless.md",
  "status": "current",
  "tags": [
    "migrated"
  ],
  "license": "CC BY-SA 4.0",
  "dates": {
    "lastVerified": "2026-10-08T00:00:00.000Z"
  },
  "authors": [],
  "sources": [
    {
      "title": "NIST Dictionary of Algorithms and Data Structures — arithmetic coding",
      "url": "https://xlinux.nist.gov/dads/HTML/arithmeticCoding.html",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "NIST Dictionary of Algorithms and Data Structures — Huffman coding",
      "url": "https://xlinux.nist.gov/dads/HTML/huffmanCoding.html",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "RFC 9639 — Free Lossless Audio Codec (FLAC)",
      "url": "https://www.rfc-editor.org/rfc/rfc9639",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "RFC 9043 — FFV1 Video Coding Format",
      "url": "https://www.rfc-editor.org/rfc/rfc9043",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "W3C — Portable Network Graphics (PNG) Specification",
      "url": "https://www.w3.org/TR/png-3/",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    }
  ],
  "provenance": {
    "originUrl": "https://github.com/av1-community-contributors/codec-wiki/blob/37c3317fd058b23c71a87679bed5619a98f77752/docs/introduction/lossless.mdx",
    "originCommit": "37c3317fd058b23c71a87679bed5619a98f77752",
    "migratedAt": "2026-08-21T00:00:00.000Z",
    "modified": true,
    "originPath": "docs/introduction/lossless.mdx"
  },
  "headings": [
    {
      "depth": 2,
      "text": "Redundancy and entropy",
      "anchor": "redundancy-and-entropy"
    },
    {
      "depth": 2,
      "text": "Run-length encoding",
      "anchor": "run-length-encoding"
    },
    {
      "depth": 2,
      "text": "Huffman coding",
      "anchor": "huffman-coding"
    },
    {
      "depth": 2,
      "text": "Arithmetic coding",
      "anchor": "arithmetic-coding"
    },
    {
      "depth": 2,
      "text": "Prediction and residual coding",
      "anchor": "prediction-and-residual-coding"
    },
    {
      "depth": 2,
      "text": "Lossless in practice",
      "anchor": "lossless-in-practice"
    }
  ],
  "sections": [
    {
      "id": "_preamble",
      "title": "Page introduction",
      "depth": 0,
      "canonicalUrl": "https://encode.wiki/start-here/lossless/",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/start-here/lossless/_preamble.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/start-here/lossless/_preamble.md",
      "checksum": "50534723abdecfb6c18f3f7cec3fbda2381b6a69699ca14b4f4e84a83d1afad0",
      "bytes": 257
    },
    {
      "id": "redundancy-and-entropy",
      "title": "Redundancy and entropy",
      "depth": 2,
      "anchor": "redundancy-and-entropy",
      "canonicalUrl": "https://encode.wiki/start-here/lossless/#redundancy-and-entropy",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/start-here/lossless/redundancy-and-entropy.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/start-here/lossless/redundancy-and-entropy.md",
      "checksum": "3234abf02b72a0af4908474836c35fba7efbd24f6ac9e7947b815878942ecaa3",
      "bytes": 570
    },
    {
      "id": "run-length-encoding",
      "title": "Run-length encoding",
      "depth": 2,
      "anchor": "run-length-encoding",
      "canonicalUrl": "https://encode.wiki/start-here/lossless/#run-length-encoding",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/start-here/lossless/run-length-encoding.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/start-here/lossless/run-length-encoding.md",
      "checksum": "8bc74049b09fc6eb06370b3ced9616d0176d1ef5fe79d5295036736f17742fcc",
      "bytes": 253
    },
    {
      "id": "huffman-coding",
      "title": "Huffman coding",
      "depth": 2,
      "anchor": "huffman-coding",
      "canonicalUrl": "https://encode.wiki/start-here/lossless/#huffman-coding",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/start-here/lossless/huffman-coding.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/start-here/lossless/huffman-coding.md",
      "checksum": "6aa0f87550b836b5d4ee9aca9f02fd9ca1926911b2747a02502d52280b3b0c81",
      "bytes": 997
    },
    {
      "id": "arithmetic-coding",
      "title": "Arithmetic coding",
      "depth": 2,
      "anchor": "arithmetic-coding",
      "canonicalUrl": "https://encode.wiki/start-here/lossless/#arithmetic-coding",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/start-here/lossless/arithmetic-coding.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/start-here/lossless/arithmetic-coding.md",
      "checksum": "3aa1a6f13877c9b2e1d203e940073bfff28347cb021d031b41170c5ff347a454",
      "bytes": 1788
    },
    {
      "id": "prediction-and-residual-coding",
      "title": "Prediction and residual coding",
      "depth": 2,
      "anchor": "prediction-and-residual-coding",
      "canonicalUrl": "https://encode.wiki/start-here/lossless/#prediction-and-residual-coding",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/start-here/lossless/prediction-and-residual-coding.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/start-here/lossless/prediction-and-residual-coding.md",
      "checksum": "1465f1b45f58f5e86c8046865ce1d4b45ec2c8ab94f65808ce01b36cd353421b",
      "bytes": 866
    },
    {
      "id": "lossless-in-practice",
      "title": "Lossless in practice",
      "depth": 2,
      "anchor": "lossless-in-practice",
      "canonicalUrl": "https://encode.wiki/start-here/lossless/#lossless-in-practice",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/start-here/lossless/lossless-in-practice.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/start-here/lossless/lossless-in-practice.md",
      "checksum": "b8db2226e4c625c21cf74a3f97abdb0ccb498a00c681bf2cbdeeb332de90fd98",
      "bytes": 945
    }
  ],
  "outboundReferences": [
    "/codecs/audio/alac/",
    "/codecs/audio/flac/",
    "/codecs/audio/wavpack/",
    "/codecs/images/jxl/",
    "/codecs/images/png/",
    "/codecs/images/webp/",
    "/codecs/video/ffv1/",
    "/codecs/video/utvideo/",
    "/img/color-huffman-tree-svg.svg",
    "https://xlinux.nist.gov/dads/HTML/arithmeticCoding.html",
    "https://xlinux.nist.gov/dads/HTML/huffmanCoding.html"
  ],
  "checksum": "435cdd1d89194746ebe9f7a6f47b2c693fc0dfdbd7e57b70969d14b8d1cf64e2",
  "contentFormat": "markdown",
  "markdown": "Lossless compression makes data smaller in a way that can be reversed exactly: decoding gives back every original bit. It is used for archiving, for editing intermediates, for general file compression, and as the final stage inside every lossy media codec.\n\n## Redundancy and entropy\n\n**Redundancy** is the part of the data that is repetitive or predictable, and therefore carries no new information. **Entropy** measures how unpredictable the data is. Low entropy means high redundancy and good compressibility; random noise has high entropy and barely compresses at all. Lossless compression removes redundancy so that the encoded size approaches the entropy of the data.\n\nThat is also why lossless video and audio files stay large: real camera and microphone signals contain a lot of noise, which is unpredictable by nature.\n\n## Run-length encoding\n\nRun-length encoding (RLE) stores a run of identical values as one value and a count, so `AAAAABBBCC` becomes `5A3B2C`. It works well on long runs, such as flat-color graphics or digital silence, and does nothing for varied data.\n\n## Huffman coding\n\nHuffman coding gives frequent symbols short codes and rare symbols long ones. It builds a binary tree from the symbol probabilities; each symbol's code is the path from the root to its leaf, and no code is a prefix of another, so a decoder can read them back without separators.\n\nSuppose you log the state of a traffic light: green 50% of the time, red 40%, yellow 9%, and off for maintenance 1%. Four states fit in two bits each (`00`, `01`, `10`, `11`), an average of 2 bits per symbol. Huffman coding does better:\n\n| State    | Probability | Code  |\n| -------- | ----------- | ----- |\n| Green    | 50%         | `0`   |\n| Red      | 40%         | `11`  |\n| Yellow   | 9%          | `100` |\n| Off      | 1%          | `101` |\n\n![Traffic light Huffman tree](/img/color-huffman-tree-svg.svg)\n\nThe average code length is (0.5 × 1) + (0.4 × 2) + (0.09 × 3) + (0.01 × 3) = **1.6 bits per symbol**. ([NIST: Huffman coding](https://xlinux.nist.gov/dads/HTML/huffmanCoding.html))\n\n## Arithmetic coding\n\nHuffman codes must be a whole number of bits per symbol. Arithmetic coding removes that limit by representing a whole sequence as one number inside an interval that narrows with each symbol, in proportion to the symbol's probability. Real implementations work with finite-precision integers and emit bits as they go, but the idea is easiest to see with fractions. ([NIST: arithmetic coding](https://xlinux.nist.gov/dads/HTML/arithmeticCoding.html))\n\nGive each state a slice of `[0, 1)` matching its probability: green `[0, 0.5)`, red `[0.5, 0.9)`, yellow `[0.9, 0.99)`, off `[0.99, 1)`. For each symbol, with `width = high − low` of the current interval:\n\n```text\nnew_low  = low + width × symbol_low\nnew_high = low + width × symbol_high\n```\n\nEncoding **green, red, yellow, green**:\n\n| Symbol | Interval before | New interval |\n| ------ | --------------- | ------------ |\n| Green  | [0, 1)          | [0, 0.5)     |\n| Red    | [0, 0.5)        | [0.25, 0.45) |\n| Yellow | [0.25, 0.45)    | [0.43, 0.448) |\n| Green  | [0.43, 0.448)   | [0.43, 0.439) |\n\nAny number in the final interval identifies the sequence; 7/16 = 0.4375 (binary `0.0111`) is a short one. To decode, the decoder repeatedly finds which slice the number falls in and rescales: 0.4375 is green, rescaled to 0.875 is red, then 0.9375 is yellow, then about 0.4167 is green. It also needs to know when to stop, from a stored length or an end-of-message symbol.\n\nOver long sequences, arithmetic coding approaches the entropy of the source. For these probabilities that is −Σ p·log₂(p) ≈ **1.408 bits per symbol**, compared with Huffman's 1.6. Modern video codecs use adaptive arithmetic coders as their entropy-coding stage: CABAC in H.264 and HEVC, and a multi-symbol arithmetic coder in AV1.\n\n## Prediction and residual coding\n\nMedia samples are usually close to their neighbors, so a codec can predict each sample from previous ones and store only the difference (the **residual**). Residuals are small numbers clustered around zero, which entropy-code far better than the raw samples.\n\n- **FLAC** predicts each audio sample with a linear predictor (LPC) from previous samples and Rice-codes the residual.\n- **PNG** applies a per-row prediction filter (for example, \"subtract the pixel to the left\") and then compresses the result with DEFLATE.\n- **FFV1** predicts each pixel from its neighbors and codes the residual with a context-modelled range coder (or Golomb–Rice coding).\n\nGeneral-purpose compressors such as ZIP and zstd add **dictionary coding** (LZ77 and relatives): repeated byte sequences are replaced with references to an earlier occurrence.\n\n## Lossless in practice\n\n| Media  | Common lossless formats                                                                 |\n| ------ | --------------------------------------------------------------------------------------- |\n| Audio  | [FLAC](/codecs/audio/flac/), [WavPack](/codecs/audio/wavpack/), [ALAC](/codecs/audio/alac/) |\n| Video  | [FFV1](/codecs/video/ffv1/) for archiving, [UT Video](/codecs/video/utvideo/) for editing, x264/x265 lossless modes for small files |\n| Images | [PNG](/codecs/images/png/), lossless [WebP](/codecs/images/webp/), lossless [JPEG XL](/codecs/images/jxl/) |\n\nA lossless encode is only lossless if nothing changes before it. Converting 10-bit to 8-bit, 4:2:2 to 4:2:0, or RGB to YUV throws information away before the lossless encoder ever sees it. Keep the source's pixel format and sample format, and compare decoded output against the source (for example with FFmpeg's `framemd5` muxer) when it matters.\n"
}
