{
  "schemaVersion": 1,
  "contentVersion": "ca42e61ede0a24f789d7287a0001244ad22f4abf",
  "id": "docs/reference/colorimetry/range",
  "collection": "docs",
  "title": "Color Range",
  "description": "Limited (tv) and full (pc) range, how to recognize a range mix-up, and how to retag or convert range correctly in FFmpeg and the encoders.",
  "canonicalUrl": "https://encode.wiki/reference/colorimetry/range/",
  "apiUrl": "https://encode.wiki/api/v1/documents/docs/reference/colorimetry/range.json",
  "markdownUrl": "https://encode.wiki/api/v1/markdown/docs/reference/colorimetry/range.md",
  "status": "current",
  "tags": [
    "migrated"
  ],
  "license": "CC BY-SA 4.0",
  "dates": {
    "lastVerified": "2026-10-08T00:00:00.000Z"
  },
  "authors": [],
  "sources": [
    {
      "title": "ITU-T H.273 (07/2024) — VideoFullRangeFlag and quantization equations",
      "url": "https://www.itu.int/rec/T-REC-H.273-202407-I",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "ITU-R BT.709-6 — digital quantization levels",
      "url": "https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.709-6-201506-I%21%21PDF-E.pdf",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "FFmpeg filters documentation (scale, zscale, setparams, signalstats)",
      "url": "https://ffmpeg.org/ffmpeg-filters.html",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "VapourSynth R81 resize documentation (pixel range)",
      "url": "https://github.com/vapoursynth/vapoursynth/blob/R81/doc/functions/video/resize.rst",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "Matroska specification — Colour Range element",
      "url": "https://www.matroska.org/technical/elements.html",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    }
  ],
  "provenance": {
    "originUrl": "https://github.com/av1-community-contributors/codec-wiki/blob/37c3317fd058b23c71a87679bed5619a98f77752/docs/colorimetry/range.mdx",
    "originCommit": "37c3317fd058b23c71a87679bed5619a98f77752",
    "migratedAt": "2026-08-21T00:00:00.000Z",
    "modified": true,
    "originPath": "docs/colorimetry/range.mdx"
  },
  "headings": [
    {
      "depth": 2,
      "text": "Recognize a range mix-up",
      "anchor": "recognize-a-range-mix-up"
    },
    {
      "depth": 2,
      "text": "Check the tag and the samples",
      "anchor": "check-the-tag-and-the-samples"
    },
    {
      "depth": 2,
      "text": "Retag or convert",
      "anchor": "retag-or-convert"
    },
    {
      "depth": 2,
      "text": "Range in standalone encoders and containers",
      "anchor": "range-in-standalone-encoders-and-containers"
    }
  ],
  "sections": [
    {
      "id": "_preamble",
      "title": "Page introduction",
      "depth": 0,
      "canonicalUrl": "https://encode.wiki/reference/colorimetry/range/",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/reference/colorimetry/range/_preamble.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/reference/colorimetry/range/_preamble.md",
      "checksum": "63180fae22617e06fd41eca61f1830c6adef3b41922a49feb9d178c223c9a779",
      "bytes": 1249
    },
    {
      "id": "recognize-a-range-mix-up",
      "title": "Recognize a range mix-up",
      "depth": 2,
      "anchor": "recognize-a-range-mix-up",
      "canonicalUrl": "https://encode.wiki/reference/colorimetry/range/#recognize-a-range-mix-up",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/reference/colorimetry/range/recognize-a-range-mix-up.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/reference/colorimetry/range/recognize-a-range-mix-up.md",
      "checksum": "3b005c4cabedea45b794b795f1cb91aa0448c85e24abac6281e79e33c825557d",
      "bytes": 380
    },
    {
      "id": "check-the-tag-and-the-samples",
      "title": "Check the tag and the samples",
      "depth": 2,
      "anchor": "check-the-tag-and-the-samples",
      "canonicalUrl": "https://encode.wiki/reference/colorimetry/range/#check-the-tag-and-the-samples",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/reference/colorimetry/range/check-the-tag-and-the-samples.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/reference/colorimetry/range/check-the-tag-and-the-samples.md",
      "checksum": "59a95141237d106687b3599e706567788ca12c10dd3b31c3a5adf83dd6104bcf",
      "bytes": 707
    },
    {
      "id": "retag-or-convert",
      "title": "Retag or convert",
      "depth": 2,
      "anchor": "retag-or-convert",
      "canonicalUrl": "https://encode.wiki/reference/colorimetry/range/#retag-or-convert",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/reference/colorimetry/range/retag-or-convert.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/reference/colorimetry/range/retag-or-convert.md",
      "checksum": "c841514fa2bd779ca9b5bb5937ce30f9b9a4d53442ce8d972e20122aa0fa86b3",
      "bytes": 1948
    },
    {
      "id": "range-in-standalone-encoders-and-containers",
      "title": "Range in standalone encoders and containers",
      "depth": 2,
      "anchor": "range-in-standalone-encoders-and-containers",
      "canonicalUrl": "https://encode.wiki/reference/colorimetry/range/#range-in-standalone-encoders-and-containers",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/reference/colorimetry/range/range-in-standalone-encoders-and-containers.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/reference/colorimetry/range/range-in-standalone-encoders-and-containers.md",
      "checksum": "555ad21940f4eda69839267e0ac92bf6340b68703fb9a089d1f5def18640b4b5",
      "bytes": 573
    }
  ],
  "outboundReferences": [],
  "checksum": "af27e4ded0ff443419b02122be5d4b0194e72ede44c2468e296ebcf6ee6948a2",
  "contentFormat": "markdown",
  "markdown": "Range says which code values mean black and white. **Limited range** (also called tv, studio, broadcast or MPEG range) puts black at 16 and white at 235 in 8-bit video; **full range** (pc or JPEG range) uses 0–255. ffprobe reports it as `color_range=tv` or `color_range=pc`.\n\n| Code values | 8-bit limited | 10-bit limited | 8-bit full | 10-bit full |\n| --- | --- | --- | --- | --- |\n| Luma black–white | 16–235 | 64–940 | 0–255 | 0–1023 |\n| Chroma | 16–240 | 64–960 | 0–255 | 0–1023 |\n| Neutral chroma | 128 | 512 | 128 | 512 |\n\nDelivered video — Blu-ray, UHD Blu-ray including HDR, broadcast, streaming — is limited range almost without exception. Full range turns up in screen recordings, some phone and webcam footage, JPEG-derived video and RGB sources. Limited range exists for historical analog reasons; it costs very little precision at 10 bits, and following the convention avoids playback problems, so encode delivery copies as limited range unless you have a reason not to.\n\nValues below 16 or above 235 can legitimately appear in limited-range video (overshoot from cameras and filters). Players clip them on display, but encoders and filters normally keep them, so don't clamp a source just because it has them.\n\n## Recognize a range mix-up\n\n| Samples are | Player assumes | What you see |\n| --- | --- | --- |\n| Limited | Full | Washed out: black is gray, white is dull |\n| Full | Limited | Too contrasty: shadows and highlights crushed and clipped |\n\nBefore changing the file, rule out the player and display: GPU drivers and TVs have their own range settings that produce the same symptoms.\n\n## Check the tag and the samples\n\n```sh\nffprobe -v error -select_streams v:0 -show_entries stream=pix_fmt,color_range -of default=nw=1 input.mkv\n```\n\n`yuvj420p` (and the other `yuvj` formats) is FFmpeg's legacy way of saying full-range 8-bit; current FFmpeg still decodes full-range 8-bit H.264 and HEVC to it.\n\nTo see what the samples actually use, measure a scene that should contain black and white, such as credits:\n\n```sh\nffmpeg -ss 00:10:00 -i input.mkv -frames:v 100 -vf \"signalstats,metadata=mode=print:file=-\" -f null - | grep -E \"YMIN|YMAX\"\n```\n\n`YMIN` near 16 and `YMAX` near 235 means limited; values down to 0 and up to 255 mean full. A dim scene has neither, so a single frame proves nothing.\n\n## Retag or convert\n\n**The samples are right but the tag is wrong** (for example limited-range video tagged `pc`): retag with `setparams`, or fix the bitstream without re-encoding:\n\n```sh\nffmpeg -i input.mkv -vf setparams=range=tv -c:v libx264 -crf 18 output.mkv\nffmpeg -i input.mkv -c copy -bsf:v h264_metadata=video_full_range_flag=0 -color_range tv output.mkv\n```\n\n`hevc_metadata` has the same `video_full_range_flag` option; `av1_metadata` uses `color_range`. The bitstream filter doesn't change the container, and from a Matroska or MP4 input FFmpeg copies the old range value; with `-c copy`, `-color_range` sets only that container field, so the two agree again. For an existing Matroska file, `mkvpropedit output.mkv --edit track:v1 --set color-range=1` fixes it in place; remuxing with `mkvmerge` keeps the old value. If the input was 8-bit full range and decodes as `yuvj420p`, put `format=yuv420p` before `setparams`.\n\n**The samples need to change** (for example full-range phone footage for a limited-range delivery): convert with `scale` or `zscale`:\n\n```sh\nffmpeg -i full.mkv -vf scale=out_range=limited,format=yuv420p -c:v libx264 -crf 18 output.mkv\n```\n\nOn a full-range ramp this maps luma 0–255 to 16–235 and tags the output `tv`. The `format=yuv420p` is required for 8-bit full-range H.264/HEVC input, which decodes as `yuvj420p`: without it `scale` changes nothing, and `zscale=range=limited` converts the samples but leaves the output tagged `pc`. In VapourSynth, `core.resize.Spline36(clip, range_s=\"limited\")` does the same, using the clip's `_Range` property (0 limited, 1 full) as the input.\n\n> **Caution.**\n>\n> When re-encoding, don't rely on FFmpeg's `-color_range` output option to tag or to convert. In current FFmpeg it asks the filter graph for that range, so it converts the samples in some cases and does nothing in others (for example with `yuvj` input). Use `setparams` to tag and `scale`/`zscale` to convert.\n## Range in standalone encoders and containers\n\nY4M can carry a full-range flag (`XCOLORRANGE=FULL`), and FFmpeg writes it. x264 and aomenc read it; x265 4.3 and SvtAv1EncApp 4.2 ignore it and tag their output as limited. Pass the range to those two yourself: `--range full` for x265, `--color-range full` for SvtAv1EncApp.\n\nMatroska stores range in its own `Range` element with different numbers from H.273: 1 is broadcast (limited) and 2 is full. With `mkvmerge` that is `--color-range 0:1` for limited; the H.273 flag in the bitstream uses 0 for limited and 1 for full.\n"
}
