diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 0000000..f28ec97 --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,291 @@ +# Copyright 2021-2024 The Khronos Group Inc. +# SPDX-License-Identifier: Apache-2.0 + +# GitHub CI file for vulkan spec and header generation +# See .gitlab-ci.yml for non-Actions comments and step dependencies. + +name: CI + +# Controls when the action will run. +on: + # Triggers the workflow on push or manual dispatch + push: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + # When a pull request is opened from a local branch or fork + pull_request: + +jobs: + license-check: + name: Verify repository license compliance + runs-on: ubuntu-latest + # We now refer to the container by its SHA instead of the name, to prevent + # caching problems when updating the image. + # container: khronosgroup/docker-images:asciidoctor-spec.20240726 + container: khronosgroup/docker-images@sha256:089687083ceb36483a3917389e4278718ab19c594099634f5dd80e22540c960f + + steps: + - uses: actions/checkout@v4 + - name: REUSE license checker + run: reuse lint + + terminology-check: + name: Run various checker scripts on the spec and XML sources + runs-on: ubuntu-latest + container: khronosgroup/docker-images@sha256:089687083ceb36483a3917389e4278718ab19c594099634f5dd80e22540c960f + + steps: + - uses: actions/checkout@v4 + - name: Internal self-test of the check_spec_links script + run: pytest test*.py + working-directory: scripts + - name: Generate a summary of problems for CI logs (if any) + run: | + mkdir -p gen/out/checks + scripts/check_spec_links.py --html=gen/out/checks/problems.html > /dev/null || true + make CHECK_XREFS= allchecks + + spec-toolchain: + name: Build a test spec and check against expectation, to make sure the spec toolchain works as expected + runs-on: ubuntu-latest + container: khronosgroup/docker-images@sha256:089687083ceb36483a3917389e4278718ab19c594099634f5dd80e22540c960f + + steps: + - uses: actions/checkout@v4 + - run: ./testBuild + + spec-core: + name: Build the core-only spec, to try and catch ifdef errors in extension markup + runs-on: ubuntu-latest + container: khronosgroup/docker-images@sha256:089687083ceb36483a3917389e4278718ab19c594099634f5dd80e22540c960f + + steps: + - uses: actions/checkout@v4 + - run: ./makeSpec -clean -spec core -genpath gencore QUIET= -j${nproc} -Otarget chunked html + + spec-generate: + name: Build the vulkan specification and generate any associated files (such as vulkan.h) + runs-on: ubuntu-latest + container: khronosgroup/docker-images@sha256:089687083ceb36483a3917389e4278718ab19c594099634f5dd80e22540c960f + + steps: + - uses: actions/checkout@v4 + - name: Build the actual spec (both chunked and single-page HTML), and other common targets + run: ./makeSpec -clean -spec all QUIET= -j${nproc} -Otarget manhtmlpages validusage styleguide registry chunked html + - name: Check consistency of internal xrefs and anchors in the output, now that an HTML output is available + run: make check-xrefs + - name: Build headers, for use by all later stages + run: make validate install test + working-directory: xml + - name: Package generated spec + # https://github.com/actions/upload-artifact#limitations + # upload-artifact would upload all of almost 10k files individually + # to GitHub, taking an inordinate amount of time. Tar it to upload + # just one large file: + run: tar -cvf spec-outputs.tar gen/ + - name: Archive generated spec + uses: actions/upload-artifact@v4 + with: + name: spec-outputs + path: spec-outputs.tar + + hpp-generate: + name: Generate the vulkan C++ header (vulkan.hpp) + runs-on: ubuntu-latest + needs: spec-generate + continue-on-error: true + + steps: + - uses: actions/checkout@v4 + # Generate the vulkan C++ header (vulkan.hpp) + # Failure (should be) allowed, for now + - name: Download generated spec + uses: actions/download-artifact@v4 + with: + name: spec-outputs + - name: Unpack generated spec + run: tar -xvf spec-outputs.tar + - run: | + SPEC_DIR="${PWD}" + # Unfortunately, asciidoctor-pdf gets pathname-specific errors + # building under the usual $GITHUB_WORKSPACE (/__w). As a workaround, + # generate the outputs in /tmp. + cd /tmp + rm -rf Vulkan-Hpp + git clone https://github.com/KhronosGroup/Vulkan-Hpp.git + cd Vulkan-Hpp + git submodule update --init --recursive -- tinyxml2 + rm -rf Vulkan-Docs + ln -s "${SPEC_DIR}" Vulkan-Docs + ##cp -r "${SPEC_DIR}" Vulkan-Docs + # Copy Vulkan C headers into subdir copy used by Vulkan-Hpp + ##cp -p ${SPEC_DIR}/include/vulkan/*.h Vulkan-Docs/include/vulkan/ + echo "Files in Vulkan-Docs:" + find Vulkan-Docs -type f + # cd /tmp/Vulkan-Hpp + cmake -H. -Bbuild + make -C build + cd build + ./VulkanHppGenerator -f "${SPEC_DIR}"/xml/vk.xml + cp /tmp/Vulkan-Hpp/vulkan/*.hpp ${SPEC_DIR}/gen/include/vulkan/ + - name: Upload generated hpp + uses: actions/upload-artifact@v4 + with: + name: hpp-outputs + path: gen/include/ + + ash-generate: + name: Generate Rust bindings (Ash crate) + runs-on: ubuntu-latest + needs: spec-generate + continue-on-error: true + env: + # Cached folder outside of git repo + CARGO_TARGET_DIR: ${{ github.workspace }}/ash-target + + steps: + - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + with: + repository: ash-rs/ash + path: ash + - uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + ash-target/ + key: ${{ runner.os }}-cargo-ash-generator-${{ hashFiles('**/Cargo.toml', '.github/workflows/CI.yml') }} + restore-keys: | + ${{ runner.os }}-cargo-ash-generator- + - name: Download generated spec + uses: actions/download-artifact@v4 + with: + name: spec-outputs + - name: Unpack generated spec + run: tar -xvf spec-outputs.tar + - name: Prepare environment + working-directory: ash + run: | + # Piece together minimal Vulkan-Headers - Ash only needs headers and vk.xml + rm -rf generator/Vulkan-Headers/* # Should already be empty, just in case + ln -s ${{ github.workspace }}/gen/include generator/Vulkan-Headers/ # Complete headers come from spec-generate + ln -s ${{ github.workspace }}/xml generator/Vulkan-Headers/registry # vk.xml sits in the root of this spec repo + + - name: Generate Ash crate + working-directory: ash + run: | + cargo run -p generator + cargo fmt --all + + - name: Package generated Ash crate + # https://github.com/actions/upload-artifact#limitations, see above + run: tar -cvf ash-outputs.tar ash/ + - name: Upload generated ash + uses: actions/upload-artifact@v4 + with: + name: ash-outputs + path: ash-outputs.tar + + # Run the CTS Vulkan framework tests, to make sure XML changes will not + # cause problems there. + cts-framework-tests: + name: Run Vulkan CTS framework tests to validate against XML changes + runs-on: ubuntu-latest + container: khronosgroup/docker-images@sha256:089687083ceb36483a3917389e4278718ab19c594099634f5dd80e22540c960f + continue-on-error: true + + steps: + - uses: actions/checkout@v4 + - name: Sparse/shallow clone of CTS GitHub repository to pull only relevant parts + run: | + git clone --sparse --depth 1 --single-branch --branch main https://github.com/KhronosGroup/VK-GL-CTS.git + cd VK-GL-CTS + # Add sparse checkout paths for required directories + git sparse-checkout add scripts external/vulkancts/framework external/vulkancts/scripts + # Link the spec project into CTS hierarchy, instead of cloning it + mkdir external/vulkan-docs + ln -s `cd .. ; pwd` external/vulkan-docs/src + - name: Run the Vulkan-specific tests (from scripts/check_build_sanity.py) # codespell:allow sanity + run: | + cd VK-GL-CTS + python3 external/vulkancts/scripts/gen_framework.py + python3 external/vulkancts/scripts/gen_framework_c.py + python3 external/vulkancts/scripts/gen_framework.py --api SC + python3 external/vulkancts/scripts/gen_framework_c.py --api SC + + h-compile: + name: Compile a simple test program that uses vulkan.h + runs-on: ubuntu-latest + needs: spec-generate + + steps: + - uses: actions/checkout@v4 + - name: Download generated files + uses: actions/download-artifact@v4 + with: + name: spec-outputs + - name: Unpack generated spec + run: tar -xvf spec-outputs.tar + # Compile a simple test program that uses vulkan.h + # The fake platform headers in tests/ allow compiling with all Vulkan + # platforms at once. + - run: | + gcc -c -std=c11 -Igen/include -Itests -Wall -Wextra -Werror tests/htest.c + clang -c -std=c11 -Igen/include -Itests -Wall -Wextra -Werror tests/htest.c + + hpp-compile: + name: Compile a simple test program that uses vulkan.hpp + runs-on: ubuntu-latest + needs: [spec-generate, hpp-generate] + continue-on-error: true + + steps: + - uses: actions/checkout@v4 + - name: Download generated spec + uses: actions/download-artifact@v4 + with: + name: spec-outputs + - name: Unpack generated spec + run: tar -xvf spec-outputs.tar + - name: Download generated hpp + uses: actions/download-artifact@v4 + with: + name: hpp-outputs + path: gen/include/ + # Compile a simple test program that uses vulkan.hpp + # Depends on spec-generate and hpp-generate + # Failure (should be) allowed, for now + - run: | + g++ -c -std=c++11 -Igen/include -IVulkan-Hpp -Wall -Wextra -Werror tests/hpptest.cpp + clang++ -c -std=c++11 -Igen/include -IVulkan-Hpp -Wall -Wextra -Werror tests/hpptest.cpp + + ash-compile: + name: Build-test Rust bindings (Ash crate) + runs-on: ubuntu-latest + needs: ash-generate + continue-on-error: true + + steps: + - name: Download generated files + uses: actions/download-artifact@v4 + with: + name: ash-outputs + - name: Unpack generated Ash crate + run: tar -xvf ash-outputs.tar + - uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + ash/target/ + key: ${{ runner.os }}-cargo-ash-compile-${{ hashFiles('**/Cargo.toml', '.github/workflows/CI.yml') }} + restore-keys: | + ${{ runner.os }}-cargo-ash-compile- + - name: Build-test ash crate + working-directory: ash + run: cargo clippy --all --all-targets diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..30cb022 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,263 @@ +# Copyright 2018-2024 The Khronos Group Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Gitlab CI file for vulkan spec and header generation + +# All stages use the same Docker image, so there are no prerequisites +# Refer to the container by its SHA instead of the name, to prevent +# caching problems when updating the image. +# image: khronosgroup/docker-images:asciidoctor-spec.20240727 +image: khronosgroup/docker-images@sha256:089687083ceb36483a3917389e4278718ab19c594099634f5dd80e22540c960f + +# Specify which gitlab runner to use +default: + tags: + - khrmedium + +# Verify repository license compliance +license-check: + stage: build + before_script: + # Nothing, all prerequisites are in the Docker image + script: + - reuse lint + allow_failure: false + +# Run various checker scripts on the spec and XML sources +# Separate from the generate step to set allow_failure: false +terminology_check: + stage: build + before_script: + # Nothing, all prerequisites are in the Docker image + script: + # Internal self-test of the check_spec_links script + - ( cd scripts && pytest test*.py ) + - mkdir -p gen/out/checks + # Generate a summary of problems for CI logs (if any) + # Override CHECK_XREFS to avoid building a redundant HTML target at this stage + - scripts/check_spec_links.py --html=gen/out/checks/problems.html > /dev/null || true + - make CHECK_XREFS= allchecks + allow_failure: false + +# Verify SPEC_VERSION = 1 for extension development branches +# This only runs on merge requests +spec_version_check: + stage: build + before_script: + # Nothing, all prerequisites are in the Docker image + script: + # Only run the test if CI_COMMIT_BRANCH is defined + - test -z "$CI_COMMIT_BRANCH" || scripts/testSpecVersion.py -branch $CI_COMMIT_BRANCH + allow_failure: false + +# Build a test spec and check against expectation, to make sure the spec toolchain works as expected +spec-toolchain: + stage: build + before_script: + # Nothing, all prerequisites are in the Docker image + script: + - ./testBuild + +# Build the vulkan specification and generate any associated files (such as vulkan.h) +spec-generate: + stage: build + before_script: + # Nothing, all prerequisites are in the Docker image + script: + - NODE_PATH="/usr/lib/node_modules" + - export NODE_PATH + # Build the core-only spec, to catch some incorrect ifdef errors + - ./makeSpec -clean -spec core -genpath gencore QUIET= -j${nproc} -Otarget html manhtmlpages + # Build the HTML/chunked spec and other common targets. + # The spec, refpages, and auxiliary documents are built first and the + # build log checked for asciidoctor warnings that cannot be made into + # fatal errors. + - ./makeSpec -clean -spec all QUIET= -j${nproc} -Otarget html manhtmlpages styleguide registry |& tee ERRS + - |+ + if fgrep -q 'WARNING: skipping reference to missing attribute:' ERRS + then + echo 'Found missing (undefined) asciidoctor attributes.' + echo 'These are probably from commonvalidity includes where attributes are not defined.' + echo 'If these are reported from building a refpage, edit the corresponding part of' + echo 'the specification source to fix the problem.' + echo '----' + fgrep -B 1 'WARNING: skipping reference to missing attribute:' ERRS + false + else + true + fi + # Build the rest of the targets, without cleaning the output directory + - ./makeSpec -spec all QUIET= -j${nproc} -Otarget chunked validusage + # Check consistency of internal xrefs and anchors in the HTML output + - make check-xrefs + # Build headers, for use by all later stages + - ( cd xml && make validate install test vtest ) + artifacts: + when: always + paths: + - src/ + - gen/ + - gencore/ + expire_in: 1 week + +# Build the vulkan sc specification and generate any associated files (such as vulkan_sc_core.h) +vksc-generate: + stage: build + before_script: + # Nothing, all prerequisites are in the Docker image + script: + - NODE_PATH="/usr/lib/node_modules" + - export NODE_PATH + - VULKAN_API="vulkansc" + - export VULKAN_API + # Build the actual spec (both chunked and single-page HTML), and other common targets + - ./makeSpec -clean -spec all -version sc1.0 -genpath genvksc QUIET= -j${nproc} -Otarget manhtmlpages validusage styleguide registry chunked html + # Check consistency of internal xrefs and anchors in the output, now + # that an HTML output is available + #- make check-xrefs + # Build headers, for use by all later stages + - ( cd xml && make GENERATED=../genvksc validate install test ) + artifacts: + when: always + paths: + - genvksc/ + expire_in: 1 week + allow_failure: true + + +# Generate the vulkan C++ header (vulkan.hpp) +hpp-generate: + stage: build + before_script: + - SPEC_DIR="${PWD}" + - cd /tmp + - rm -rf Vulkan-Hpp + - git clone https://github.com/KhronosGroup/Vulkan-Hpp.git + - cd Vulkan-Hpp + - git submodule update --init --recursive -- tinyxml2 + - rm -rf Vulkan-Docs + - cp -r "${SPEC_DIR}" Vulkan-Docs + # Copy Vulkan C headers into subdir copy used by Vulkan-Hpp + - cp -p ${SPEC_DIR}/include/vulkan/*.h Vulkan-Docs/include/vulkan/ + script: + - cd /tmp/Vulkan-Hpp + - cmake -H. -Bbuild + - make -C build + - cd build + - ./VulkanHppGenerator -f "${SPEC_DIR}"/xml/vk.xml + after_script: + - mkdir -p Vulkan-Hpp/vulkan/ + - cp /tmp/Vulkan-Hpp/vulkan/*.hpp Vulkan-Hpp/vulkan/ + artifacts: + paths: + - Vulkan-Hpp/vulkan/ + expire_in: 1 week + allow_failure: true + +# Regenerate Rust bindings (Ash crate) +ash-generate: + image: khronosgroup/docker-images@sha256:cf554c9cf5d0322e022f0be32efad9bff44ada4b32653bfdc8033cba22972fa2 + stage: build + needs: + - spec-generate # For the full include/ directory + cache: # Generator has lots of dependencies that take a while to download/compile + key: cargo-ash-generator + paths: + - cargo-cache + - ash-target + before_script: + - SPEC_DIR="${PWD}" + - rm -rf ash + - git clone https://github.com/ash-rs/ash + - pushd ash + # Piece together minimal Vulkan-Headers - Ash only needs headers and vk.xml + - rm -rf generator/Vulkan-Headers/* # Should already be empty, just in case + - ln -s ${SPEC_DIR}/gen/include generator/Vulkan-Headers/ # Complete headers come from spec-generate + - ln -s ${SPEC_DIR}/xml generator/Vulkan-Headers/registry # vk.xml sits in the root of this spec repo + # Move to root directory to be picked up by `cache` step + - export CARGO_HOME="${SPEC_DIR}/cargo-cache" + - export CARGO_TARGET_DIR="${SPEC_DIR}/ash-target" + script: + - cargo run -p generator + - cargo fmt --all + after_script: + # Make the folder a single level deep + - mv ash/ash ash-crate + - rm -rf ash/ + - mv ash-crate ash + artifacts: + paths: + - ash + expire_in: 1 week + allow_failure: true + +# Run the CTS Vulkan framework tests, to make sure XML changes will not +# cause problems there. +cts-framework-tests: + stage: build + before_script: + # Nothing, all prerequisites are in the Docker image + script: + # Clone the CTS GitHub repository. + # Use sparse / shallow clone since the repo is enormous and mostly not needed for these tests + - git clone --sparse --depth 1 --single-branch --branch main https://github.com/KhronosGroup/VK-GL-CTS.git + - cd VK-GL-CTS + # Add sparse checkout paths for required directories + - git sparse-checkout add scripts external/vulkancts/framework external/vulkancts/scripts + # Link the spec project into CTS hierarchy, instead of cloning it + - mkdir external/vulkan-docs + - ln -s `cd .. ; pwd` external/vulkan-docs/src + # Run the Vulkan-specific tests (from scripts/check_build_sanity.py) # codespell:allow sanity + - python3 external/vulkancts/scripts/gen_framework.py + - python3 external/vulkancts/scripts/gen_framework_c.py + - python3 external/vulkancts/scripts/gen_framework.py --api SC + - python3 external/vulkancts/scripts/gen_framework_c.py --api SC + allow_failure: true + +# Compile a simple test program that uses vulkan.h +# The fake platform headers in tests/ allow compiling with all Vulkan +# platforms at once. +h-compile: + stage: test + needs: + - spec-generate + before_script: + # Nothing, all prerequisites are in the Docker image + script: + - gcc -c -std=c11 -Igen/include -Itests -Wall -Wextra -Werror tests/htest.c + - clang -c -std=c11 -Igen/include -Itests -Wall -Wextra -Werror tests/htest.c + +# Compile a simple test program that uses vulkan.hpp +hpp-compile: + stage: test + needs: + - spec-generate + - hpp-generate + before_script: + # Nothing, all prerequisites are in the Docker image + script: + - g++ -c -std=c++11 -Igen/include -IVulkan-Hpp -Wall -Wextra -Werror tests/hpptest.cpp + - clang++ -c -std=c++11 -Igen/include -IVulkan-Hpp -Wall -Wextra -Werror tests/hpptest.cpp + allow_failure: true + +# Build-test Rust bindings (Ash crate) +ash-compile: + image: khronosgroup/docker-images@sha256:cf554c9cf5d0322e022f0be32efad9bff44ada4b32653bfdc8033cba22972fa2 + stage: test + needs: + - ash-generate + cache: + key: + files: + - ash/Cargo.toml + paths: + - cargo-cache + - ash-target + before_script: + - export CARGO_HOME="${SPEC_DIR}/cargo-cache" + - export CARGO_TARGET_DIR="${SPEC_DIR}/ash-target" + script: + - cd ash + # Build-test the ash crate + - cargo clippy --all --all-targets + allow_failure: true diff --git a/.reuse/dep5 b/.reuse/dep5 new file mode 100644 index 0000000..73a0fbf --- /dev/null +++ b/.reuse/dep5 @@ -0,0 +1,19 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: DataFormat +Source: https://github.com/KhronosGroup/DataFormat + +Files: images/*.svg config/*/docinfo-header.html +Copyright: 2015-2024 The Khronos Group Inc. +License: CC-BY-4.0 + +Files: katex/* +Copyright: 2013-2019 Khan Academy and other contributors +License: MIT + +Files: config/khronos.css +Copyright: 2013 Dan Allen +License: MIT + +Files: config/copyright-spec.adoc +Copyright: 2014-2024 The Khronos Group Inc +License: LicenseRef-KhronosSpecCopyright diff --git a/BUILD.adoc b/BUILD.adoc new file mode 100644 index 0000000..2b07893 --- /dev/null +++ b/BUILD.adoc @@ -0,0 +1,211 @@ +// Copyright 2014-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 + += Khronos^(TM) Data Format Specification Build Instructions and Notes +:toc2: +:toclevels: 2 + +ifdef::env-github[] +:note-caption: :information_source: +endif::[] + + +NEW == Building the Specification + +The build system relies on +link:http://www.methods.co.nz/asciidoc/index.html[asciidoc], which is +available as part of many Linux distributions. +The PDF build subsequently depends on +link:http://dblatex.sourceforge.net[dblatex]. + +All forms of the specification may be built with a simple `make` +or `make all` command, with an output into the `out` directory. + +Use `make pdf` to build just the PDF specification. + +Use `make html` to build the HTML version of the specification +without inline images, which are accessed from the `out` directory; +this is smaller than the `inlinehtml` version. + +Use `make inlinehtml` to create the HTML and then generate a version +with inlined images, allowing it to be transferred as a single +file; note that the HTML still relies on access to +link:http://www.mathjax.org[MathJax] and is therefore not completely +stand-alone. +This build option requires PERL. +Since the inline HTML file is very large, `make compressedinlinehtml` +produces a gzip-compressed version of the output. + +`make header` copies the header file into the `out/headers` directory. + +`make clean` removes the contents out `out` and temporary files. + + + +[[intro]] +== Introduction + +This README describes how to build the Data Format Specification and other +related targets. + +It documents how to set up your build environment, build steps and targets, +and contains some troubleshooting advice. + + +[[building]] +== Building the Spec + +First, clone the Khronos GitHub repository containing the Data Format +Specification to your local Linux, Windows, or Mac PC. +The repository is located at https://github.com/KhronosGroup/DataFormat/ . + +Next, install all the necessary build tools (see <> below). +If you are using the <>, +which we strongly recommend, two ways to build using the image are: + + $ # assuming a Linux docker host + $ scripts/runDocker + + $ # assuming a Linux podman host + $ scripts/runPodman + +executed from the specification repository root. + +`runDocker` runs the Docker image with the cloned repository mounted under +/spec and accesses it as a specified user (set to your own user and group +ID), so that it does not get filled with files owned by another user. +The script leaves you inside a bash shell in the running image. +Execute the commands: + + $ cd /spec + $ make clean html pdf + +to build HTML5 and PDF specification outputs for the Data Format 1.3 +Specification. + +There are many other ways of using the image, including inside a Continuous +Integration pipeline; locally with persistent Docker volume storage of the +repository; and so on. + +If you are not using our Docker image to build with, and you have a +<> with the entire +toolchain installed, you can just invoke the same `make` commands from the +repository root. + +[NOTE] +==== +You can modify the `runDocker` script to change the `docker` command-line +options, but it is important to always use the Docker image specified in +that script, so you have the latest version of the spec toolchain. +==== + +[NOTE] +==== + * The `pdf` target takes a long time to run. + The `html` target just generates the HTML output, which is often all + that is needed for spec bugfixes not involving extensions. +==== + +These targets generate output documents in the directory +specified by the Makefile variable `$(OUTDIR)` (by default, `out/`). + +Data Format Specification:: + * `html` -- Single-file HTML5 in `$(OUTDIR)/html/dataformat.html`, and KaTeX + dependency in $(OUTDIR)/katex + * `pdf` -- PDF in `$(OUTDIR)/pdf/dataformat.pdf` + + +=== Images Used in the Specification + +All images used in the specification are in the `images/` directory in the +SVG or PNG format. +We recommend using Inkscape to modify or create new images, due to problems +using SVG files created by some other tools; especially in the PDF builds. + + +[[styles]] +== Our Stylesheets + +We use an HTML stylesheet `config/khronos.css` derived from the +https://asciidoctor.org/docs/produce-custom-themes-using-asciidoctor-stylesheet-factory/[Asciidoctor +stylesheet factory] "`colony`" theme, with the default Arial font family +replaced by the sans-serif https://en.wikipedia.org/wiki/Noto_fonts[Noto +font family]. + + +[[depends]] +== Software Dependencies + +This section describes the software components used by the Data Format +specification toolchain. + + +[[depends-docker]] +=== Khronos-Provided Docker Image + +Khronos has published a Docker image containing a Debian Linux distribution +with the entire toolchain preinstalled. + +We will occasionally update this image if needed, and we recommend people +needing to build from this repository use the Docker image. + +Docker installation is beyond the scope of this document. +Refer to link:https://docs.docker.com/get-docker/[the Docker website] for +information about installing Docker on Linux, Windows, and MacOS X. + +Another way to execute the Docker image is using the open source podman +container tool. +See link:https://podman.io/get-started[the Podman website] for information +about installing podman on Linux, Windows, and MacOS X. + +The build image is *named* `khronosgroup/docker-images:asciidoctor-spec`. +However, due to local and CI caching problems when this image is updated on +dockerhub, we use the SHA256 of the latest image update, rather than the +image name. +The SHA256 can be determined from + + $ git grep -h sha256: .gitlab-ci.yml + +which will print a line like + + image: khronosgroup/docker-images@sha256:5e021da240f12121f064d2135e06320c021ac231c9ae8abbf6205b6130deb58b + +Everything following `image: ` is the to use. +The first time you try to run a container with this , as is done +by the `runDocker` and `runPodman` scripts described above under <>, the image will be pulled from Dockerhub and cached +locally on your machine. + +This image is used to build Specification output documents or other Makefile +targets. + +[NOTE] +==== +When we update the image on Dockerhub, it is to add new components or update +versions of components used in the specification toolchain. +To save space, you may want to periodically purge old images using `docker +images` and `docker rmi -f`. +==== + + +[[depends-nondocker]] +=== Non-Docker Build Environments + +We do not actively support building outside of our Docker image, but it is +straightforward to reproduce our toolchain in a Debian (or similar APT-based +Linux) distribution by executing the same steps as the +link:https://github.com/KhronosGroup/DockerContainers/blob/main/asciidoctor-spec.Dockerfile[Dockerfile] +used to build our Docker image. + +It should be possible to apply the same steps in a Windows Subsystem for +Linux (WSL2) environment on Windows 10, as well. + +[NOTE] +==== +While you do not have to use our Docker image, we cannot support every +possible build environment. +The Docker image is a straightforward way to build the specification in most +modern desktop environments, without needing to install and update the spec +toolchain yourself. +==== diff --git a/CODE_OF_CONDUCT.adoc b/CODE_OF_CONDUCT.adoc new file mode 100644 index 0000000..91d1024 --- /dev/null +++ b/CODE_OF_CONDUCT.adoc @@ -0,0 +1,10 @@ +// Copyright 2018-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 + += Code of Conduct + +A reminder that this repository is managed by the Khronos Group. +Interactions here should follow the +https://www.khronos.org/about/code-of-conduct[Khronos Code of Conduct], +which prohibits aggressive or derogatory language. Please keep the +discussion friendly and civil. diff --git a/CONTRIBUTING.adoc b/CONTRIBUTING.adoc new file mode 100644 index 0000000..1c5aa50 --- /dev/null +++ b/CONTRIBUTING.adoc @@ -0,0 +1,39 @@ +// Copyright 2020-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 + += Contributing + +Contributions to the DataFormat repository are welcome. + +Contributions may be in the form of Issues proposing a change, or Pull +Requests containing fixes for, or additions to: + + * Specification text and other documentation + * Specification scripting / build toolchains and related infrastructure + +Please keep contributions focused on solving a single issue or bug. + + +== Copyright Notice and License Template + +If you are adding a new file, it must be under one of the following +licenses: + + * Creative Commons Attribution 4.0 International, for specification text + (for example, link:dataformat.adoc[`dataformat.adoc]) + * Apache 2.0, for all other changes (for example, + link:scripts/runDocker[`runDocker`]) + +We use a short license in each file consisting of just the copyright +statement and the SPDX license identifier of the license applying to that +file, and link to the full license text from +link:LICENSE.adoc[`LICENSE.adoc`]. + + +== Contributor License Agreement + +When you propose a pull request, you must execute the +link:https://www.khronos.org/legal/Khronos_mixed_repository_CLA[Khronos +Mixed Repository Contributor License Agreement], to confirm you own your +work and are granting Khronos the necessary permissions to redistribute it +under our licenses. diff --git a/COPYING.adoc b/COPYING.adoc new file mode 100644 index 0000000..143cf6c --- /dev/null +++ b/COPYING.adoc @@ -0,0 +1,67 @@ +// Copyright 2020-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 + += COPYING File for the KhronosGroup/DataFormat Project + +== Licenses + +The DataFormat repository uses several licenses. + +* The source files (in asciidoctor and other formats) for the DataFormat + Specification and supporting documentation are licensed under the Creative + Commons Attribution 4.0 International License (SPDX license identifier + "`CC-BY-4.0`"). +* Header files, scripts, and other tooling used or generated as part of the + build process are typically licensed under the Apache License, Version 2.0 + (SPDX license identifier "`Apache-2.0`"). +* There are a few remaining files adopted from other open source projects, + such as a copy of the KaTeX distribution. + Such files continue under their original MIT licenses, or in a few cases, + like link:scripts/htmldiff/htmldiff[`scripts/htmldiff/htmldiff`], had no + license statement. + We have not added SPDX license identifiers to such externally originated + files. + +Users outside Khronos who create and post DataFormat Specifications, whether +modified or not, should use the CC-BY-4.0 license on the *output* documents +(HTML, PDF, etc.) they generate. +This is the default when building the Specification. + + +== Frequently Asked Questions + +Q: Why are the HTML and PDF Specifications posted on Khronos' website under +a license which is neither CC-BY nor Apache-2.0? + +A: The Specifications posted by Khronos in the DataFormat Registry are +licensed under the proprietary Khronos Specification License. +Only these Specifications are Ratified by the Khronos Board of Promoters, +and therefore they are the only Specifications covered by the Khronos +Intellectual Property Rights Policy. + + +Q: Does Khronos allow the creation and distribution of modified versions of +the Data Format Specification, such as translations to other languages? + +A: Yes. Such modified Specifications, since they are not created by Khronos, +should be placed under the CC-BY license. If you believe your modifications +are of general interest, consider contributing them back by making a pull +request (PR) in the KhronosGroup/DataFormat repository. + + +Q: Can I contribute changes to the Data Format Specification? + +A: Yes, by opening an Issue or Pull Request (PR) on the +link:https://github.com/KhronosGroup/DataFormat[DataFormat] GitHub project. +You must execute a click-through Contributor License Agreement, which brings +your changes under the umbrella of the Khronos IP policy. + + +Q: Can you change the license on your files so they are compatible with my +license? + +A: If you *require* GPL compatibility for use of Apache-2.0 licensed files +in our repository, please raise an issue identifying the files and the +reason for the request, and we will consider changing those specific files +to a dual Apache 2.0 - MIT license. + diff --git a/LICENSE.adoc b/LICENSE.adoc new file mode 100644 index 0000000..64df047 --- /dev/null +++ b/LICENSE.adoc @@ -0,0 +1,34 @@ +// Copyright 2020-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 + += LICENSE File for the KhronosGroup/Vulkan-Docs Project + +Files in this repository fall under one of these licenses: + + * SPDX license identifier: "`Apache-2.0 OR MIT`" + ** Apache License 2.0 OR MIT License + ** For scripts and XML which need to be usable in GPL-licensed projects. + + * SPDX license identifier: "`Apache-2.0`" + ** Apache License 2.0 + ** For other scripts + + * SPDX license identifier: "`CC-BY-4.0`" + ** Creative Commons Attribution 4.0 International + ** For specification source documents + + * SPDX license identifier: "`MIT`" + ** MIT License + ** For files copied from other MIT-licensed projects + + * SPDX license identifier: "`LicenseRef-MPLUS`" + ** M+ Font License + ** For fonts derived from the M+ Font Project + ** This license is open source, but not OSI approved + +Full license text of these licenses is available at: + + * Apache-2.0: https://opensource.org/licenses/Apache-2.0 + * MIT: https://opensource.org/licenses/MIT + * CC-BY-4.0: https://creativecommons.org/licenses/by/4.0/legalcode + * LicenseRef-MPLUS: https://osdn.net/softwaremap/trove_list.php?form_cat=370 diff --git a/Makefile b/Makefile index a929b28..289d21b 100644 --- a/Makefile +++ b/Makefile @@ -1,79 +1,198 @@ -# Copyright (c) 2014-2019 The Khronos Group Inc. -# Copyright notice at https://www.khronos.org/registry/speccopyright.html -all: compressedinlinehtml pdf header - -XMLLINT = --no-xmllint - -A2XOPTS = -a mathjax \ - --asciidoc-opts="-f config/mathjax-docbook.conf" \ - --xsltproc-opts="--param generate.consistent.ids 1" \ - $(XMLLINT) $(VERBOSE) --icons - -sources := df.txt \ - df-docinfo.xml \ - conversions.txt \ - conversionintro.txt \ - transferfunctions.txt \ - primaries.txt \ - colormodels.txt \ - quantization.txt \ - compformats.txt \ - compintro.txt \ - s3tc.txt \ - rgtc.txt \ - bptc.txt \ - etc1.txt \ - etc2.txt \ - astc.txt \ - pvrtc.txt \ - references.txt - -html_config := docbook-xsl/xhtml.xsl df-xhtml.css -html_config := $(addprefix config/,${html_config}) - -pdf_config := mathjax-docbook.conf docbook-xsl/pdf.xsl -pdf_config := $(addprefix config/,${pdf_config}) - -version := 1.3 -outbasename := out/dataformat.$(version) - -html: $(outbasename).html out/config/df-xhtml.css out/images/Khronos_Dec14.svg out/images/icons/note.png -inlinehtml: $(outbasename).inline.html -compressedinlinehtml: $(outbasename).inline.html.gz -pdf: $(outbasename).pdf -header: out/headers/khr_df.h - -$(outbasename).html: $(sources) $(html_config) | out - a2x $(A2XOPTS) -f xhtml df.txt -a svgpdf=svg -a a2xhtml=html -a docinfo --xsl-file=config/docbook-xsl/xhtml.xsl -a toc2 -a toclevels=2 -D out - ./simplifyhtmllinks.pl out/df.html out/df2.html - rm out/df.html - mv out/df2.html out/dataformat.1.3.html - -out/config/df-xhtml.css: config/df-xhtml.css | out out/config - cp $< $@ - -out/images/Khronos_Dec14.svg: images/Khronos_Dec14.svg | out/images - cp $< $@ - -out/images/icons/note.png: images/icons/note.png | out/images/icons - cp $< $@ - -out out/config out/headers out/images out/images/icons: - mkdir -p $@ - -$(outbasename).inline.html: $(outbasename).html inlinecss.pl inlineimages.pl - ./inlinecss.pl < out/dataformat.1.3.html | ./inlineimages.pl > $@ - -$(outbasename).inline.html.gz: $(outbasename).inline.html - gzip -9 -c < out/dataformat.1.3.inline.html > out/dataformat.1.3.inline.html.gz - -$(outbasename).pdf: $(sources) $(pdf_config) | out - asciidoc -d book -b docbook -a numbered -f config/mathjax-docbook.conf -a svgpdf=pdf -a a2x-format=pdf -a docinfo df.txt && \ - dblatex -b pdftex -p config/docbook-xsl/pdf.xsl -s dblatex/df.sty df.xml -o $@ - -out/headers/khr_df.h: headers/khr_df.h out/headers - cp $< $@ - -clean: - rm -f out/dataformat.1.3.pdf df.xml out/dataformat.1.3.html out/dataformat.1.3.inline.html out/dataformat.1.3.inline.html.gz - rm -rf out/config out/images out/headers +# Copyright 2024 The Khronos Group Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Khronos Data Format Specification Makefile + +# If a recipe fails, delete its target file. Without this cleanup, the leftover +# file from the failed recipe can falsely satisfy dependencies on subsequent +# runs of `make`. +.DELETE_ON_ERROR: + +# APITITLE can be set to extra text to append to the document title, +# normally used when building with extensions included. +APITITLE = + +# IMAGEOPTS is normally set to generate inline SVG images, but can be +# overridden to an empty string, since the inline option doesn't work +# well with our HTML diffs. +IMAGEOPTS = inline + +# The default 'all' target builds the following sub-targets: +# html - HTML5 single-page API specification +# pdf - PDF single-page API specification + +all: html pdf + +QUIET ?= @ +PYTHON ?= python3 +ASCIIDOC ?= asciidoctor +RUBY = ruby +NODEJS = node +PATCH = patch +RM = rm -f +RMRF = rm -rf +MKDIR = mkdir -p +CP = cp +ECHO = echo + +# Where the repo root is +ROOTDIR = $(CURDIR) +# Where the spec files are +SPECDIR = $(CURDIR) + +# Path to scripts used in generation +SCRIPTS = $(ROOTDIR)/scripts +# Path to configs and asciidoc extensions used in generation +CONFIGS = $(ROOTDIR)/config + +# Target directories for output files +# HTMLDIR - 'html' target +# PDFDIR - 'pdf' target +OUTDIR = $(CURDIR)/out +HTMLDIR = $(OUTDIR)/html +PDFDIR = $(OUTDIR)/pdf + +# PDF Equations are written to SVGs, this dictates the location to store those files (temporary) +PDFMATHDIR = $(OUTDIR)/equations_temp + +# Set VERBOSE to -v to see what asciidoc is doing. +VERBOSE = + +# asciidoc attributes to set (defaults are usually OK) +# NOTEOPTS sets options controlling which NOTEs are generated +# PATCHVERSION is the minor document release version +# ATTRIBOPTS sets the API revision and enables KaTeX generation +# EXTRAATTRIBS sets additional attributes, if passed to make +# ADOCMISCOPTS miscellaneous options controlling error behavior, etc. +# ADOCEXTS asciidoctor extensions to load +# ADOCOPTS options for asciidoc->HTML5 output + +NOTEOPTS = +PATCHVERSION = 1 +SPECREVISION = 1.3.$(PATCHVERSION) + +# Spell out ISO 8601 format as not all date commands support --rfc-3339 +SPECDATE = $(shell echo `date -u "+%Y-%m-%d %TZ"`) + +# Generate Asciidoc attributes for spec remark +# Could use `git log -1 --format="%cd"` to get branch commit date +# The dependency on HEAD is per the suggestion in +# http://neugierig.org/software/blog/2014/11/binary-revisions.html +SPECREMARK = from git branch: $(shell echo `git symbolic-ref --short HEAD 2> /dev/null || echo Git branch not available`) \ + commit: $(shell echo `git log -1 --format="%H" 2> /dev/null || echo Git commit not available`) + +# Some of the attributes used in building all spec documents: +# chapters - absolute path to chapter sources +# appendices - absolute path to appendix sources +# images - absolute path to images +ATTRIBOPTS = -a revnumber="$(SPECREVISION)" \ + -a revdate="$(SPECDATE)" \ + -a revremark="$(SPECREMARK)" \ + -a apititle="$(APITITLE)" \ + -a stem=latexmath \ + -a imageopts="$(IMAGEOPTS)" \ + -a config=$(ROOTDIR)/config \ + -a appendices=$(SPECDIR)/appendices \ + -a chapters=$(SPECDIR)/chapters \ + -a images=$(IMAGEPATH) \ + $(EXTRAATTRIBS) +ADOCMISCOPTS = --failure-level ERROR +# Non target-specific Asciidoctor extensions and options +ADOCEXTS = -r $(CONFIGS)/open_listing_block.rb +ADOCOPTS = -d book $(ADOCMISCOPTS) $(ATTRIBOPTS) $(NOTEOPTS) $(VERBOSE) $(ADOCEXTS) + +# HTML target-specific Asciidoctor extensions and options +ADOCHTMLEXTS = -r $(CONFIGS)/katex_replace.rb \ + -r $(CONFIGS)/loadable_html.rb + +# ADOCHTMLOPTS relies on the relative runtime path from the output HTML +# file to the katex scripts being set with KATEXDIR. This is overridden +# by some targets. +# KaTeX source is copied from KATEXSRCDIR in the repository to +# KATEXINSTDIR in the output directory. +# KATEXDIR is the relative path from a target to KATEXINSTDIR, since +# that is coded into CSS, and set separately for each HTML target. +# ADOCHTMLOPTS also relies on the absolute build-time path to the +# 'stylesdir' containing our custom CSS. +KATEXSRCDIR = $(ROOTDIR)/katex +KATEXINSTDIR = $(OUTDIR)/katex +ADOCHTMLOPTS = $(ADOCHTMLEXTS) -a katexpath=$(KATEXDIR) \ + -a stylesheet=khronos.css \ + -a stylesdir=$(ROOTDIR)/config \ + -a sectanchors + +# PDF target-specific Asciidoctor extensions and options +ADOCPDFEXTS = -r asciidoctor-pdf \ + -r asciidoctor-mathematical \ + -r $(CONFIGS)/asciidoctor-mathematical-ext.rb +ADOCPDFOPTS = $(ADOCPDFEXTS) -a mathematical-format=svg \ + -a imagesoutdir=$(PDFMATHDIR) \ + -a pdf-stylesdir=$(CONFIGS)/themes -a pdf-style=pdf + +.PHONY: directories + +# Images used by the specification. +# These are included in generated HTML now. +IMAGEPATH = $(SPECDIR)/images +SVGFILES = $(wildcard $(IMAGEPATH)/*.svg) + +# Top-level spec source file +SPECSRC = $(SPECDIR)/dataformat.adoc +# Static files making up sections of the specification. +SPECFILES = $(wildcard chapters/[A-Za-z]*.adoc appendices/[A-Za-z]*.adoc) + +# All non-format-specific dependencies +COMMONDOCS = $(SPECFILES) + +# Script to translate math at build time +TRANSLATEMATH = $(NODEJS) $(SCRIPTS)/translate_math.js $(KATEXSRCDIR)/katex.min.js + +# Install katex in KATEXINSTDIR ($(OUTDIR)/katex) to be shared by all +# HTML targets. +# We currently only need the css and fonts, but copy all of KATEXSRCDIR anyway. +$(KATEXINSTDIR): $(KATEXSRCDIR) + $(QUIET)$(MKDIR) $(KATEXINSTDIR) + $(QUIET)$(RMRF) $(KATEXINSTDIR) + $(QUIET)$(CP) -rf $(KATEXSRCDIR) $(KATEXINSTDIR) + +# Spec targets +# There is some complexity to try and avoid short virtual targets like 'html' +# causing specs to *always* be regenerated. + +html: $(HTMLDIR)/dataformat.html $(SPECSRC) $(COMMONDOCS) + +$(HTMLDIR)/dataformat.html: KATEXDIR = ../katex +$(HTMLDIR)/dataformat.html: $(SPECSRC) $(COMMONDOCS) $(KATEXINSTDIR) + $(QUIET)$(ASCIIDOC) -b html5 $(ADOCOPTS) $(ADOCHTMLOPTS) -o $@ $(SPECSRC) + $(QUIET)$(TRANSLATEMATH) $@ + +# PDF optimizer - usage $(OPTIMIZEPDF) in.pdf out.pdf +# OPTIMIZEPDFOPTS=--compress-pages is slightly better, but much slower +OPTIMIZEPDF = hexapdf optimize $(OPTIMIZEPDFOPTS) + +pdf: $(PDFDIR)/dataformat.pdf $(SPECSRC) $(COMMONDOCS) + +$(PDFDIR)/dataformat.pdf: $(SPECSRC) $(COMMONDOCS) + $(QUIET)$(MKDIR) $(PDFDIR) + $(QUIET)$(MKDIR) $(PDFMATHDIR) + $(QUIET)$(ASCIIDOC) -b pdf $(ADOCOPTS) $(ADOCPDFOPTS) -o $@ $(SPECSRC) + $(QUIET)$(OPTIMIZEPDF) $@ $@.out.pdf && mv $@.out.pdf $@ + $(QUIET)rm -rf $(PDFMATHDIR) + +# Clean generated and output files + +clean: clean_html clean_pdf clean_generated + +clean_html: + $(QUIET)$(RMRF) $(HTMLDIR) $(OUTDIR)/katex + $(QUIET)$(RM) $(OUTDIR)/dataformat.html + +clean_pdf: + $(QUIET)$(RMRF) $(PDFDIR) $(OUTDIR)/dataformat.pdf + +# Generated directories and files to remove +CLEAN_GEN_PATHS = \ + $(PDFMATHDIR) + +clean_generated: + $(QUIET)$(RMRF) $(CLEAN_GEN_PATHS) diff --git a/README.adoc b/README.adoc index e32e6ef..efa5ddb 100644 --- a/README.adoc +++ b/README.adoc @@ -1,13 +1,18 @@ -Khronos^(TM)^ Data Format Specification -======================================= +// Copyright 2014-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 -This repository contains source for the Khronos Data Format Specification. +ifdef::env-github[] +:note-caption: :information_source: +endif::[] + += Khronos^(TM)^ Data Format Specification The Khronos Data Format Specification describes a portable mechanism for describing a wide range of image/texture formats and other forms of data. It solely describes the format of what may be considered to be a single -"pixel" or a repeating group of pixels considered to be a "texture block". +"`pixel`" or a repeating group of pixels considered to be a "`texture +block`". A wide variety of incompatible mechanisms exist in the industry for describing formats that may be supported by an API. @@ -25,38 +30,71 @@ This specification also contains a detailed description of the in-memory representation of a number of compressed texture formats, and describes some common color spaces. -Building the Specification -========================== -The build system relies on -link:http://www.methods.co.nz/asciidoc/index.html[asciidoc], which is -available as part of many Linux distributions. -The PDF build subsequently depends on -link:http://dblatex.sourceforge.net[dblatex]. +== Repository Structure + +The link:https://github.com/KhronosGroup/DataFormat[DataFormat] repository, +and the equivalent internal Khronos tracking repository, contain sources for +the formal documentation of the Khronos Data Format Specification. +These include: + +[options="compact"] + * The Data Format Specification + * The `khr_df.h` C header file + * Related tools and scripts + +The repository hosts a public issue tracker, and outside developers can file +proposed changes (Pull Requests) against the Specification, subject to +approval by Khronos. + + +== External Contributions + +Khronos welcomes feedback in GitHub Issues, and proposed changes in GitHub +Pull Requests (PRs), but will not necessarily accept all such changes. + +Please keep your issues and pull requests focused on solving a single +problem. Broader feedback that tries to solve multiple problems, or touches +many parts of the Specification at once, is difficult for Khronos to review +in a timely fashion. + + +== Branch Structure + +The current Specification (Data Format 1.3) is maintained in the default +branch (currently `main`) of the repository. + + +== Directory Structure -All forms of the specification may be built with a simple "make" -or "make all" command, with an output into the "out" directory. +The directory structure is as follows: -Use "make pdf" to build just the PDF specification. +``` +README.adoc This file +BUILD.adoc Documents how to build the specifications +CONTRIBUTING.adoc Requirements for external contributions to the repository +COPYING.adoc Copyright and licensing information +CODE_OF_CONDUCT.adoc Code of Conduct +LICENSE.adoc Summary of licenses used by files in the repository +Makefile Makefile (see BUILD.adoc) +appendices/ Specification appendices +chapters/ Specification chapters +config/ Asciidoctor configuration, CSS, and index generator +images/ Images (figures, diagrams, icons) +out/ Default directory for the generated documents +scripts/ Helper scripts used in specification, header, and reference page generation +``` -Use "make html" to build the HTML version of the specification -without inline images, which are accessed from the "out" directory; -this is smaller than the "inlinehtml" version. -Use "make inlinehtml" to create the HTML and then generate a version -with inlined images, allowing it to be transferred as a single -file; note that the HTML still relies on access to -link:http://www.mathjax.org[MathJax] and is therefore not completely -stand-alone. -This build option requires PERL. -Since the inline HTML file is very large, "make compressedinlinehtml" -produces a gzip-compressed version of the output. +== Building the Specification and Reference Pages -"make header" copies the header file into the "out/headers" directory. +The document sources are marked up in Asciidoc format, and we use +`asciidoctor` and related toolchain components to generate output documents. +See link:BUILD.adoc[BUILD.adoc] for more information on installing the +toolchain and building the Specification. -"make clean" removes the contents out "out" and temporary files. -Default Branch Renaming -======================= +== Generating Headers and Related Files -The default branch of this repository was renamed from "master" to "main" on 2024-02-01. +The `khr_df.h` C header file defines structures and enums for specifying the +layout of images in memory. diff --git a/astc.txt b/chapters/astc.adoc similarity index 96% rename from astc.txt rename to chapters/astc.adoc index bbca306..ef77adc 100644 --- a/astc.txt +++ b/chapters/astc.adoc @@ -1,5 +1,6 @@ -// Copyright (c) 2014-2019 The Khronos Group Inc. -// Copyright notice at https://www.khronos.org/registry/speccopyright.html +// Copyright 2014-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 + [[ASTC]] == ASTC Compressed Texture Image Formats @@ -161,14 +162,14 @@ The two modes differ in various ways, as shown in <>. @@ -176,12 +177,12 @@ the decoding mode as shown in <>. [[astc_decoding_modes]] .ASTC decoding modes [options="header"] -|================ +|==== | Decode mode | LDR mode |  HDR mode | decode_float16 2+| Vector of FP16 values | decode_unorm8 | Vector of 8-bit unsigned normalized values |  invalid | decode_rgb9e5 2+|  Vector using a shared exponent format -|================ +|==== Using the decode_unorm8 decoding mode in HDR mode gives undefined results. @@ -236,7 +237,8 @@ The data specified per block are as follows: To decode one texel: -------------------- +[source] +---- (Optimization: If within known void-extent, immediately return single color) Find block containing texel @@ -258,7 +260,7 @@ Read color endpoint mode and endpoint data for selected partition Unquantize color endpoints Interpolate color endpoints using weight (or weights in dual-plane mode) Return interpolated color -------------------- +---- <<< @@ -276,7 +278,7 @@ For square and nearly-square blocks, this gives the bit rates in [[astc_footprint_2D]] .ASTC 2D footprint and bit rates [cols="1,1,1,1",width="50%"] -|====================== +|==== 2+^| *Footprint* .2+^.^| *Bit Rate* .2+^.^| *Increment* ^| *Width* ^| *Height* ^| 4 ^| 4 ^| 8.00 ^| 125% @@ -293,7 +295,7 @@ For square and nearly-square blocks, this gives the bit rates in ^| 10 ^| 10 ^| 1.28 ^| 120% ^| 12 ^| 10 ^| 1.07 ^| 120% ^| 12 ^| 12 ^| 0.89 ^| -|============= +|==== The ``Increment'' column indicates the ratio of bit rate against the next lower available rate. A consistent value in this column indicates an even @@ -308,7 +310,7 @@ For cubic and near-cubic blocks, this gives the bit rates in [[astc_footprint_3D]] .ASTC 3D footprint and bit rates [cols="1,1,1,1,1",width="60%"] -|====================== +|==== 3+^| *Block Footprint* .2+^.^| *Bit Rate* .2+^.^| *Increment* ^| *Width* ^| *Height* ^| *Depth* ^| 3 ^| 3 ^| 3 ^| 4.74 ^| 133% @@ -321,7 +323,7 @@ For cubic and near-cubic blocks, this gives the bit rates in ^| 6 ^| 5 ^| 5 ^| 0.85 ^| 120% ^| 6 ^| 6 ^| 5 ^| 0.71 ^| 120% ^| 6 ^| 6 ^| 6 ^| 0.59 ^| -|====================== +|==== The full profile supports only those block footprints listed in <> and <>. Other block sizes are not supported. @@ -338,26 +340,26 @@ Given an image which is _W_ {times} _H_ {times} _D_ pixels in size, with block s _w_ {times} _h_ {times} _d_, the size of the image in blocks is: [latexmath] -++++++++++++++++++++++ +++++ \begin{align*} \textrm{B}_\textrm{w} & = \left\lceil { W \over w } \right\rceil \\ \textrm{B}_\textrm{h} & = \left\lceil { H \over h } \right\rceil \\ \textrm{B}_\textrm{d} & = \left\lceil { D \over d } \right\rceil \end{align*} -++++++++++++++++++++++ +++++ For a 3D image built from 2D slices, each 2D slice is a single texel thick, so that for an image which is _W_ {times} _H_ {times} _D_ pixels in size, with block size _w_ {times} _h_, the size of the image in blocks is: [latexmath] -++++++++++++++++++++++ +++++ \begin{align*} \textrm{B}_\textrm{w} & = \left\lceil { W \over w } \right\rceil \\ \textrm{B}_\textrm{h} & = \left\lceil { H \over h } \right\rceil \\ \textrm{B}_\textrm{d} & = D \end{align*} -++++++++++++++++++++++ +++++ === Block Layout @@ -375,9 +377,9 @@ Each block has the same basic layout, shown in <>. [[astc-block-layout]] .ASTC block layout [width="97%",cols="1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"] -|==================== +|==== ^| ~127~ ^| ~126~ ^| ~125~ ^| ~124~ ^| ~123~ ^| ~122~ ^| ~121~ ^| ~120~ ^| ~119~ ^| ~118~ ^| ~117~ ^| ~116~ ^| ~115~ ^| ~114~ ^| ~113~ ^| ~112~ -12+|   Texel weight data (variable width) 4+|   Fill direction latexmath:[$\rightarrow$] +12+|   Texel weight data (variable width) 4+|   Fill direction latexmath:[\rightarrow] ^| ~111~ ^| ~110~ ^| ~109~ ^| ~108~ ^| ~107~ ^| ~106~ ^| ~105~ ^| ~104~ ^| ~103~ ^| ~102~ ^| ~101~ ^| ~100~ ^| ~99~ ^| ~98~ ^| ~97~ ^| ~96~ 16+|   Texel weight data ^| ~95~ ^| ~94~ ^| ~93~ ^| ~92~ ^| ~91~ ^| ~90~ ^| ~89~ ^| ~88~ ^| ~87~ ^| ~86~ ^| ~85~ ^| ~84~ ^| ~83~ ^| ~82~ ^| ~81~ ^| ~80~ @@ -387,12 +389,12 @@ Each block has the same basic layout, shown in <>. ^| ~63~ ^| ~62~ ^| ~61~ ^| ~60~ ^| ~59~ ^| ~58~ ^| ~57~ ^| ~56~ ^| ~55~ ^| ~54~ ^| ~53~ ^| ~52~ ^| ~51~ ^| ~50~ ^| ~49~ ^| ~48~ 5+| 6+|   More config data 5+| ^| ~47~ ^| ~46~ ^| ~45~ ^| ~44~ ^| ~43~ ^| ~42~ ^| ~41~ ^| ~40~ ^| ~39~ ^| ~38~ ^| ~37~ ^| ~36~ ^| ~35~ ^| ~34~ ^| ~33~ ^| ~32~ -8+|   latexmath:[$\leftarrow$] Fill direction 8+|   Color endpoint data +8+|   latexmath:[\leftarrow] Fill direction 8+|   Color endpoint data ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ 4+| 12+|   Extra configuration data ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 3+|   Extra 2+|   Part 11+|   Block mode -|==================== +|==== Since the size of the ``texel weight data'' field is variable, the positions shown for the ``more config data'' field and ``color endpoint @@ -412,12 +414,12 @@ in <> (only the bottom 32 bits are shown). [[astc-single-partition-layout]] .ASTC single-partition block layout [width="97%",cols="1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"] -|==================== +|==== ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ 15+|   Color endpoint data ^| CEM ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 3+|   CEM ^| 0 ^| 0 11+|   Block mode -|==================== +|==== CEM is the color endpoint mode field, which determines how the Color Endpoint Data is encoded. @@ -428,12 +430,12 @@ directly below the weight bits, as shown in <>. [[astc-multi-partition-layout]] .ASTC multi-partition block layout [width="97%",cols="1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"] -|==================== +|==== ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ 3+| 6+|   CEM 7+|   Partition index ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 3+|   Partition index 2+|   Part 11+|   Block mode -|==================== +|==== The Partition Index field specifies which partition layout to use. CEM is the first 6 bits of color endpoint mode information for the various @@ -469,7 +471,7 @@ and Bits. The details of this encoding can be found in [[astc-weight-range-encodings]] .ASTC weight range encodings [width="97%",cols="1,2,1,1,1,2,1,1,1"] -|==================== +|==== 1.2+^.^| *{rho}^2..0^* 4+^.^| *Low-precision range (_P_=0)* 4+^.^| *High-precision range (_P_=1)* ^.^| *Weight range* ^.^| *Trits* ^.^| *Quints* ^.^| *Bits* ^.^| *Weight range* ^.^| *Trits* ^.^| *Quints* ^.^| *Bits* ^| 000 4+^| Invalid 4+^| Invalid @@ -480,7 +482,7 @@ and Bits. The details of this encoding can be found in ^| 101 ^| 0..4 ^| ^| 1 ^| ^| 0..19 ^| ^| 1 ^| 2 ^| 110 ^| 0..5 ^| 1 ^| ^| 1 ^| 0..23 ^| 1 ^| ^| 3 ^| 111 ^| 0..7 ^| ^| ^| 3 ^| 0..31 ^| ^| ^| 5 -|==================== +|==== For 2D blocks, the Block Mode field is laid out as shown in <>. @@ -488,7 +490,7 @@ For 2D blocks, the Block Mode field is laid out as shown in [[astc-2d-block-mode-layout]] .ASTC 2D block mode layout, weight grid width and height [width="97%",cols="1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"] -|==================== +|==== ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 2+^| *W~width~* 2+^| *W~height~* 3+^| *Notes* ^| _D~P~_ ^| _P_ 2+^| _W_ 2+^| _H_ ^| {rho}^0^ ^| 0 ^| 0 ^| {rho}^2^ ^| {rho}^1^ 2+^| _W_+4 2+^| _H_+2 3+| ^| _D~P~_ ^| _P_ 2+^| _W_ 2+^| _H_ ^| {rho}^0^ ^| 0 ^| 1 ^| {rho}^2^ ^| {rho}^1^ 2+^| _W_+8 2+^| _H_+2 3+| @@ -503,7 +505,7 @@ For 2D blocks, the Block Mode field is laid out as shown in ^| x ^| x ^| 1 ^| 1 ^| 1 ^| 1 ^| 1 ^| 1 ^| 1 ^| 0 ^| 0 2+^| - 2+^| - 3+^| Void-extent ^| x ^| x ^| 1 ^| 1 ^| 1 ^| x ^| x ^| x ^| x ^| 0 ^| 0 2+^| - 2+^| - 3+^| Reserved* ^| x ^| x ^| x ^| x ^| x ^| x ^| x ^| 0 ^| 0 ^| 0 ^| 0 2+^| - 2+^| - 3+^| Reserved -|==================== +|==== Note that, due to the encoding of the {rho} field, as described in the previous page, bits {rho}^2^ and {rho}^1^ cannot both be zero, which disambiguates @@ -524,7 +526,7 @@ For 3D blocks, the Block Mode field is laid out as shown in <>. [[astc-color-endpoint-modes]] .ASTC color endpoint modes [cols="2,11,2",options="header",width="55%"] -|==================== +|==== ^| CEM |   Description ^| Class >| 0    |   LDR Luminance, direct ^| 0 >| 1    |   LDR Luminance, base+offset ^| 0 @@ -579,7 +581,7 @@ endpoints. They can be summarized as shown in <>. >| 13    |   LDR _RGBA_, base+offset ^| 3 >| 14    |   HDR _RGB_, direct + LDR Alpha ^| 3 >| 15    |   HDR _RGB_, direct + HDR Alpha ^| 3 -|==================== +|==== In multi-partition mode, the CEM field is of variable width, from 6 to 14 bits. The lowest 2 bits of the CEM field specify how the endpoint mode @@ -588,7 +590,7 @@ for each partition is calculated as shown in <> @@ -608,21 +610,21 @@ and <>. [[astc-multi-partition-color-endpoint-mode-layout]] .ASTC multi-partition color endpoint mode layout [cols="2,1,2,1,1,1,1,1,1,1,1,1",width="90%"] -|==================== +|==== ^| *Part* ^| ^| ^| ~n~ ^| ~m~ ^| ~l~ ^| ~k~ ^| ~j~ ^| ~i~ ^| ~h~ ^| ~g~ ^| ^| 2 ^| ... ^| Weight 2+^| M~1~ 6+| | ... ^| 3 ^| ... ^| Weight 2+^| M~2~ 2+^| M~1~ ^| M~0~ 3+| | ... ^| 4 ^| ... ^| Weight 2+^| M~3~ 2+^| M~2~ 2+^| M~1~ 2+^| M~0~ | ... -|==================== +|==== [[astc-multi-partition-color-endpoint-mode-layout-2]] .ASTC multi-partition color endpoint mode layout (2) [cols="2,1,1,1,1,1,1",width="60%"] -|==================== +|==== ^| *Part* ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| 2 2+^| M~0~ ^| C~1~ ^| C~0~ 2+^| CEM ^| 3 ^| M~0~ ^| C~2~ ^| C~1~ ^| C~0~ 2+^| CEM ^| 4 ^| C~3~ ^| C~2~ ^| C~1~ ^| C~0~ 2+^| CEM -|==================== +|==== In this view, each partition _i_ has two fields. C~_i_~ is the class selector bit, choosing between the two possible CEM classes (0 indicates the @@ -659,22 +661,22 @@ in one of the forms shown in <> and [[astc-range-forms]] .ASTC range forms [options="header",width="65%",cols="2,3,3"] -|==================== +|==== |   Value range |   MSB encoding |   LSB encoding -|   latexmath:[$0 \dots 2^n-1$] |   - |   _n_-bit value _m_ (_n_ {leq} 8) -|   latexmath:[$0 \dots (3 \times 2^n)-1$] |   Base-3 ``trit'' value _t_ |   _n_-bit value _m_ (_n_ {leq} 6) -|   latexmath:[$0 \dots (5 \times 2^n)-1$] |   Base-5 ``quint'' value _q_ |   _n_-bit value _m_ (_n_ {leq} 5) -|==================== +|   latexmath:[0 \dots 2^n-1] |   - |   _n_-bit value _m_ (_n_ {leq} 8) +|   latexmath:[0 \dots (3 \times 2^n)-1] |   Base-3 ``trit'' value _t_ |   _n_-bit value _m_ (_n_ {leq} 6) +|   latexmath:[0 \dots (5 \times 2^n)-1] |   Base-5 ``quint'' value _q_ |   _n_-bit value _m_ (_n_ {leq} 5) +|==== [[astc-range-encodings]] .ASTC encoding for different ranges [options="header",width="60%",cols="4,3,2,5"] -|==================== +|==== |   Value range |   Value |   Block |   Packed block size -|   latexmath:[$0 \dots 2^n-1$] |   _m_ |   1 |   _n_ -|   latexmath:[$0 \dots (3 \times 2^n)-1$] |   latexmath:[$t \times 2^n + m$] |   5 |   8 {plus} 5 {times} _n_ -|   latexmath:[$0 \dots (5 \times 2^n)-1$] |   latexmath:[$q \times 2^n + m$] |   3 |   7 {plus} 3 {times} _n_ -|==================== +|   latexmath:[0 \dots 2^n-1] |   _m_ |   1 |   _n_ +|   latexmath:[0 \dots (3 \times 2^n)-1] |   latexmath:[t \times 2^n + m] |   5 |   8 {plus} 5 {times} _n_ +|   latexmath:[0 \dots (5 \times 2^n)-1] |   latexmath:[q \times 2^n + m] |   3 |   7 {plus} 3 {times} _n_ +|==== Since 3^5^ is 243, it is possible to pack five trits into 8 bits (which has 256 possible values), so a trit can effectively be encoded as 1.6 bits. @@ -695,30 +697,31 @@ To decode the bits for value number _i_ in a sequence of bits _b_, both indexed from 0, perform the following: If the range is encoded as _n_ bits per value, then the value is bits -latexmath:[$b^{i\times n + n - 1 .. i \times n}$] -- a simple multiplexing operation. +latexmath:[b^{i\times n + n - 1 .. i \times n}] -- a simple multiplexing operation. If the range is encoded using a trit, then each block contains 5 values (v~0~ to v~4~), each of which contains a trit (t~0~ to t~4~) and a corresponding LSB value (m~0~ to m~4~). The first bit of the packed block is bit -latexmath:[$\left\lfloor {i\over 5} \right\rfloor \times (8 + 5 \times n)$]. The bits in the +latexmath:[\left\lfloor {i\over 5} \right\rfloor \times (8 + 5 \times n)]. The bits in the block are packed as shown in <> (in this example, _n_ is 4). [[astc-trit-based-packing]] .ASTC trit-based packing [width="80%"] -|=========================================== +|==== 4+^| ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ 4+^| ^| T^7^ 4+^| m~4~ ^| T^6^ ^| T^5^ 4+^| m~3~ ^| T^4^ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ -4+^| m~2~ ^| T^3^ ^| T^2^ 4+^| m~1~ ^| T^1^ ^| T^0^ 4+^| m~0~ ^| -|=========================================== +4+^| m~2~ ^| T^3^ ^| T^2^ 4+^| m~1~ ^| T^1^ ^| T^0^ 4+^| m~0~ +|==== <<< The five trits t~0~ to t~4~ are obtained by bit manipulations of the 8 bits T^7..0^ as follows: ------ +[source] +---- if T[4:2] = 111 C = { T[7:5], T[1:0] }; t4 = t3 = 2 else @@ -734,12 +737,12 @@ else if C[3:2] = 11 t2 = 2; t1 = 2; t0 = C[1:0] else t2 = C[4]; t1 = C[3:2]; t0 = { C[1], C[0]&~C[1] } ------ +---- If the range is encoded using a quint, then each block contains 3 values (v~0~ to v~2~), each of which contains a quint (q~0~ to q~2~) and a corresponding LSB value (m~0~ to m~2~). The first bit of the packed block is bit -latexmath:[$ \left\lfloor {i\over 3} \right\rfloor \times (7+3 \times n)$]. +latexmath:[ \left\lfloor {i\over 3} \right\rfloor \times (7+3 \times n)]. The bits in the block are packed as described in <> and <> (in this example, _n_ is 4). @@ -747,23 +750,24 @@ The bits in the block are packed as described in <> an [[astc-quint-based-packing]] .ASTC quint-based packing [width="20%"] -|=========== +|==== ^| ~18~ ^| ~17~ ^| ~16~ ^| Q^6^ ^| Q^5^ ^| m~2~ -|=========== +|==== [[astc-quint-based-packing-2]] .ASTC quint-based packing (2) [width="80%"] -|=========== +|==== ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 3+^| m~2~ ^| Q^4^ ^| Q^3^ 4+^| m~1~ ^| Q^2^ ^| Q^1^ ^| Q^0^ 4+^| m~0~ -|=========== +|==== The three quints q~0~ to q~2~ are obtained by bit manipulations of the 7 bits Q^6..0^ as follows: ------ +[source] +---- if Q[2:1] = 11 and Q[6:5] = 00 q2 = { Q[0], Q[4]&~Q[0], Q[3]&~Q[0] }; q1 = q0 = 4 else @@ -776,7 +780,7 @@ else q1 = 4; q0 = C[4:3] else q1 = C[4:3]; q0 = C[2:0] ------ +---- Both these procedures ensure a valid decoding for all 128 possible values (even though a few are duplicates). They can also be implemented @@ -814,7 +818,7 @@ range as described in <>. [[astc-color-unquantization-parameters]] .ASTC color unquantization parameters [cols="4,3,4,3,5,6,6,3,8",width="95%",options="header"] -|============ +|==== ^| Range ^| #Trits ^| #Quints ^| #Bits ^| Bit layout ^| ++A++ ^| ++B++ ^| ++C++ ^| ++D++ ^| 0..5 ^| 1 ^| ^| 1 ^| a ^| aaaaaaaaa ^| 000000000 ^| 204 ^| Trit value ^| 0..9 ^| ^| 1 ^| 1 ^| a ^| aaaaaaaaa ^| 000000000 ^| 113 ^| Quint value @@ -827,15 +831,16 @@ range as described in <>. ^| 0..95 ^| 1 ^| ^| 5 ^| edcba ^| aaaaaaaaa ^| edcb000ed ^| 11 ^| Trit value ^| 0..159 ^| ^| 1 ^| 5 ^| edcba ^| aaaaaaaaa ^| edcb0000e ^| 6 ^| Quint value ^| 0..191 ^| 1 ^| ^| 6 ^| fedcba ^| aaaaaaaaa ^| fedcb000f ^| 5 ^| Trit value -|============ +|==== These are then processed as follows: ------ +[source] +---- unq = D * C + B; unq = unq ^ A; unq = (A & 0x80) | (unq >> 2); ------ +---- Note that the multiply in the first line is nearly trivial as it only needs to multiply by 0, 1, 2, 3 or 4. @@ -859,7 +864,7 @@ The methods can be summarized as shown in <>. [[astc-ldr-color-endpoint-modes]] .ASTC LDR color endpoint modes [options="header",cols="2,3,11,1",width="55%"] -|============== +|==== ^| CEM ^| Range |   Description ^| _n_ >| 0   ^| LDR |   Luminance, direct ^| 2 >| 1   ^| LDR |   Luminance, base+offset ^| 2 @@ -877,7 +882,7 @@ The methods can be summarized as shown in <>. >| 13   ^| LDR |   _RGBA_, base+offset ^| 8 >| 14   ^| HDR |   _RGB_ + LDR Alpha ^| 8 >| 15   ^| HDR |   _RGB_ + HDR Alpha ^| 8 -|============== +|==== Mode 14 is special in that the alpha values are interpolated linearly, but the color components are interpolated logarithmically. This is the @@ -888,53 +893,60 @@ Decode the different LDR endpoint modes as follows: ==== Mode 0 LDR Luminance, direct ------ +[source] +---- e0=(v0,v0,v0,0xFF); e1=(v1,v1,v1,0xFF); ------ +---- ==== Mode 1 LDR Luminance, base+offset ------ +[source] +---- L0 = (v0>>2)|(v1&0xC0); L1=L0+(v1&0x3F); if (L1>0xFF) { L1=0xFF; } e0=(L0,L0,L0,0xFF); e1=(L1,L1,L1,0xFF); ------ +---- ==== Mode 4 LDR Luminance+Alpha,direct ------ +[source] +---- e0=(v0,v0,v0,v2); e1=(v1,v1,v1,v3); ------ +---- ==== Mode 5 LDR Luminance+Alpha, base+offset ------ +[source] +---- bit_transfer_signed(v1,v0); bit_transfer_signed(v3,v2); e0=(v0,v0,v0,v2); e1=(v0+v1,v0+v1,v0+v1,v2+v3); clamp_unorm8(e0); clamp_unorm8(e1); ------ +---- ==== Mode 6 LDR _RGB_, base+scale ------ +[source] +---- e0=(v0*v3>>8,v1*v3>>8,v2*v3>>8, 0xFF); e1=(v0,v1,v2,0xFF); ------ +---- ==== Mode 8 LDR _RGB_, Direct ------ +[source] +---- s0= v0+v2+v4; s1= v1+v3+v5; if (s1>=s0){e0=(v0,v2,v4,0xFF); e1=(v1,v3,v5,0xFF); } else { e0=blue_contract(v1,v3,v5,0xFF); e1=blue_contract(v0,v2,v4,0xFF); } ------ +---- ==== Mode 9 LDR _RGB_, base+offset ------ +[source] +---- bit_transfer_signed(v1,v0); bit_transfer_signed(v3,v2); bit_transfer_signed(v5,v4); @@ -944,28 +956,31 @@ else { e0=blue_contract(v0+v1,v2+v3,v4+v5,0xFF); e1=blue_contract(v0,v2,v4,0xFF); } clamp_unorm8(e0); clamp_unorm8(e1); ------ +---- ==== Mode 10 LDR _RGB_, base+scale plus two _A_ ------ +[source] +---- e0=(v0*v3>>8,v1*v3>>8,v2*v3>>8, v4); e1=(v0,v1,v2, v5); ------ +---- ==== Mode 12 LDR _RGBA_, direct ------ +[source] +---- s0= v0+v2+v4; s1= v1+v3+v5; if (s1>=s0){e0=(v0,v2,v4,v6); e1=(v1,v3,v5,v7); } else { e0=blue_contract(v1,v3,v5,v7); e1=blue_contract(v0,v2,v4,v6); } ------ +---- ==== Mode 13 LDR _RGBA_, base+offset ------ +[source] +---- bit_transfer_signed(v1,v0); bit_transfer_signed(v3,v2); bit_transfer_signed(v5,v4); @@ -975,7 +990,7 @@ if(v1+v3+v5>=0) { e0=(v0,v2,v4,v6); else { e0=blue_contract(v0+v1,v2+v3,v4+v5,v6+v7); e1=blue_contract(v0,v2,v4,v6); } clamp_unorm8(e0); clamp_unorm8(e1); ------ +---- The `bit_transfer_signed()` procedure transfers a bit from one value (_a_) to another (_b_). Initially, both _a_ and _b_ are in the range 0..255. @@ -983,7 +998,8 @@ After calling this procedure, _a_'s range becomes -32..31, and _b_ remains in the range 0..255. Note that, as is often the case, this is easier to express in hardware than in C: ------ +[source] +---- bit_transfer_signed(int& a, int& b) { b >>= 1; @@ -992,12 +1008,13 @@ bit_transfer_signed(int& a, int& b) a &= 0x3F; if( (a&0x20)!=0 ) a-=0x40; } ------ +---- The `blue_contract()` procedure is used to give additional precision to _RGB_ colors near gray: ------ +[source] +---- color blue_contract( int r, int g, int b, int a ) { color c; @@ -1007,12 +1024,13 @@ color blue_contract( int r, int g, int b, int a ) c.a = a; return c; } ------ +---- The `clamp_unorm8()` procedure is used to clamp a color into 8-bit unsigned normalized fixed-point range: ------ +[source] +---- void clamp_unorm8(color c) { if(c.r < 0) {c.r=0;} else if(c.r > 255) {c.r=255;} @@ -1020,7 +1038,7 @@ void clamp_unorm8(color c) if(c.b < 0) {c.b=0;} else if(c.b > 255) {c.b=255;} if(c.a < 0) {c.a=0;} else if(c.a > 255) {c.a=255;} } ------ +---- <<< @@ -1034,7 +1052,8 @@ pseudo-logarithmic representation. Mode 2 represents luminance-only data with a large range. It encodes using two values (v~0~, v~1~). The complete decoding procedure is as follows: ------ +[source] +---- if(v1 >= v0) { y0 = (v0 << 4); @@ -1048,7 +1067,7 @@ else // Construct RGBA result (0x780 is 1.0f) e0 = (y0, y0, y0, 0x780); e1 = (y1, y1, y1, 0x780); ------ +---- ==== HDR Endpoint Mode 3 @@ -1059,18 +1078,19 @@ bits for a base luminance value, together with an offset, into two values [[astc-hdr-mode-3-value-layout]] .ASTC HDR mode 3 value layout [width="60%",cols="2h,1,1,1,1,1,1,1,1"] -|===================== +|==== ^| *Value* ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ ^| v~0~ ^| M 7+^| L^6..0^ ^| v~1~ 4+^| X^3..0^ 4+^| d^3..0^ -|===================== +|==== The bit field marked as X allocates different bits to L or d depending on the value of the mode bit M. The complete decoding procedure is as follows: ------ +[source] +---- // Check mode bit and extract. if((v0&0x80) !=0) { @@ -1090,7 +1110,7 @@ if(y1 > 0xFFF) { y1 = 0xFFF; } // Construct RGBA result (0x780 is 1.0f) e0 = (y0, y0, y0, 0x780); e1 = (y1, y1, y1, 0x780); ------ +---- <<< @@ -1103,13 +1123,13 @@ mode bits into the four values (v~0~, v~1~, v~2~, v~3~), as shown in [[astc-hdr-mode-7-value-layout]] .ASTC HDR mode 7 value layout [width="50%",cols="3,1,1,1,1,1,1,1,1"] -|=================== +|==== ^| *Value* ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ ^|v~0~ 2+^|M^3..2^ 6+^| _R_^5..0^ ^|v~1~ ^|M^1^ ^|X^0^ ^|X^1^ 5+^| _G_^4..0^ ^|v~2~ ^|M^0^ ^|X^2^ ^|X^3^ 5+^| _B_^4..0^ ^|v~3~ ^|X^4^ ^|X^5^ ^|X^6^ 5+^| S^4..0^ -|=================== +|==== The mode bits M^0^ to M^3^ are a packed representation of an endpoint bit mode, together with the major component index. For modes 0 to 4, the @@ -1123,7 +1143,7 @@ extra bits X^0^ to X^6^, as shown in <>. [[astc-hdr-mode-7-endpoint-bit-mode]] .ASTC HDR mode 7 endpoint bit mode [width="85%",cols="2h,1,1,1,1,1,2,2,2,2,2,2,2"] -|=============== +|==== | 4+^| *Number of bits* | 7+^| *Destination of extra bits* ^| Mode ^| *_R_* ^| *_G_* ^| *_B_* ^| *S* | ^| *X^0^* ^| *X^1^* ^| *X^2^* ^| *X^3^* ^| *X^4^* ^| *X^5^* ^| *X^6^* ^| 0 ^| 11 ^| 5 ^| 5 ^| 7 ^| ^| _R_^9^ ^| _R_^8^ ^| _R_^7^ ^| _R_^10^ ^| _R_^6^ ^| S^6^ ^| S^5^ @@ -1132,7 +1152,7 @@ extra bits X^0^ to X^6^, as shown in <>. ^| 3 ^| 9 ^| 6 ^| 6 ^| 7 ^| ^| _R_^8^ ^| _G_^5^ ^| _R_^7^ ^| _B_^5^ ^| _R_^6^ ^| S^6^ ^| S^5^ ^| 4 ^| 8 ^| 7 ^| 7 ^| 6 ^| ^| _G_^6^ ^| _G_^5^ ^| _B_^6^ ^| _B_^5^ ^| _R_^6^ ^| _R_^7^ ^| S^5^ ^| 5 ^| 7 ^| 7 ^| 7 ^| 7 ^| ^| _G_^6^ ^| _G_^5^ ^| _B_^6^ ^| _B_^5^ ^| _R_^6^ ^| S^6^ ^| S^5^ -|=============== +|==== As noted before, this appears complex when expressed in C, but much easier to achieve in hardware: bit masking, extraction, shifting @@ -1142,7 +1162,8 @@ The complete decoding procedure is as follows: <<< ------ +[source] +---- // Extract mode bits and unpack to major component and mode. int majcomp; int mode; int modeval = ((v0&0xC0)>>6) | ((v1&0x80)>>5) | ((v2&0x80)>>4); @@ -1204,7 +1225,7 @@ e0.r = clamp( red - scale, 0, 0xFFF ); e0.g = clamp( green - scale, 0, 0xFFF ); e0.b = clamp( blue - scale, 0, 0xFFF ); e0.alpha = 0x780; ------ +---- ==== HDR Endpoint Mode 11 @@ -1216,7 +1237,7 @@ mode bits into the six values (v~0~, v~1~, v~2~, v~3~, v~4~, v~5~) as shown in [[astc-hdr-mode-11-value-layout]] .ASTC HDR mode 11 value layout [cols="3h,1,1,1,1,1,1,1,1",width="50%"] -|====================== +|==== ^| *Value* ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ ^| v~0~ 8+^| a^7..0^ ^| v~1~ ^|m~0~ ^|a^8^ 6+^| c^5..0^ @@ -1224,7 +1245,7 @@ mode bits into the six values (v~0~, v~1~, v~2~, v~3~, v~4~, v~5~) as shown in ^| v~3~ ^|m~2~ ^|X^1^ 6+^| b~1~^5..0^ ^| v~4~ ^|mj~0~ ^|X^2^ ^|X^4^ 5+^| d~0~^4..0^ ^| v~5~ ^|mj~1~ ^|X^3^ ^|X^5^ 5+^| d~1~^4..0^ -|====================== +|==== If the major component bits mj^1..0^ are both 1, then the _RGB_ values are specified directly by <>. @@ -1232,7 +1253,7 @@ are specified directly by <>. [[astc-hdr-mode-11-direct-value-layout]] .ASTC HDR mode 11 direct value layout [cols="3h,1,1,1,1,1,1,1,1",width="50%"] -|=================== +|==== ^| *Value* ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ ^| v~0~ 8+^| _R_~0~^11..4^ ^| v~1~ 8+^| _R_~1~^11..4^ @@ -1240,7 +1261,7 @@ are specified directly by <>. ^| v~3~ 8+^| _G_~1~^11..4^ ^| v~4~ ^| 1 7+^| _B_~0~^11..5^ ^| v~5~ ^| 1 7+^| _B_~1~^11..5^ -|=================== +|==== The mode bits m^2..0^ specify the bit allocation for the different values, and the destinations of the extra bits X^0^ to X^5^ as shown @@ -1249,7 +1270,7 @@ in <>. [[astc-hdr-mode-11-endpoint-bit-mode]] .ASTC HDR mode 11 endpoint bit mode [cols="2h,1,1,1,1,1,2,2,2,2,2,2",width="85%"] -|================= +|==== ^| 4+^| *Number of bits* | 6+^| *Destination of extra bits* ^| Mode ^| *a* ^| *b* ^| *c* ^| *d* ^| ^| *X^0^* ^| *X^1^* ^| *X^2^* ^| *X^3^* ^| *X^4^* ^| *X^5^* ^| 0 ^| 9 ^| 7 ^| 6 ^| 7 ^| ^| b~0~^6^ ^| b~1~^6^ ^| d~0~^6^ ^| d~1~^6^ ^| d~0~^5^ ^| d~1~^5^ @@ -1260,13 +1281,14 @@ in <>. ^| 5 ^| 11 ^| 6 ^| 7 ^| 6 ^| ^| a^9^ ^| a^10^ ^| c^7^ ^| c^6^ ^| d~0~^5^ ^| d~1~^5^ ^| 6 ^| 12 ^| 7 ^| 7 ^| 5 ^| ^| b~0~^6^ ^| b~1~^6^ ^| a^11^ ^| c^6^ ^| a^9^ ^| a^10^ ^| 7 ^| 12 ^| 6 ^| 7 ^| 6 ^| ^| a^9^ ^| a^10^ ^| a^11^ ^| c^6^ ^| d~0~^5^ ^| d~1~^5^ -|================= +|==== The complete decoding procedure is as follows: <<< ------ +[source] +---- // Find major component int majcomp = ((v4 & 0x80) >> 7) | ((v5 & 0x80) >> 6); @@ -1328,7 +1350,7 @@ e0.alpha = 0x780; if( majcomp == 1 ) { swap( e0.r, e0.g ); swap( e1.r, e1.g ); } else if( majcomp == 2 ) { swap( e0.r, e0.b ); swap( e1.r, e1.b ); } ------ +---- ==== HDR Endpoint Mode 14 @@ -1337,14 +1359,15 @@ v~2~, v~3~, v~4~, v~5~, v~6~, v~7~). First, the _RGB_ values are decoded from (v~0~..v~5~) using the method from Mode 11, then the alpha values are filled in from v~6~ and v~7~: ------ +[source] +---- // Decode RGB as for mode 11 (e0,e1) = decode_mode_11(v0,v1,v2,v3,v4,v5) // Now fill in the alphas e0.alpha = v6; e1.alpha = v7; ------ +---- Note that in this mode, the alpha values are interpreted (and interpolated) as 8-bit unsigned normalized values, as in the LDR modes. @@ -1363,15 +1386,16 @@ in <>. [[astc-hdr-mode-15-alpha-value-layout]] .ASTC HDR mode 15 alpha value layout [cols="h,1,1,1,1,1,1,1,1",width="75%"] -|==================== +|==== ^| *Value* ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ ^| v~6~ ^| _M_^0^ 7+^| A^6..0^ ^| v~7~ ^| _M_^1^ 7+^| B^6..0^ -|==================== +|==== The alpha values are decoded from v~6~ and v~7~ as follows: ------ +[source] +---- // Decode RGB as for mode 11 (e0,e1) = decode_mode_11(v0,v1,v2,v3,v4,v5) @@ -1399,7 +1423,7 @@ else v7 = clamp(v7, 0, 0xFFF); e0.alpha = v6; e1.alpha = v7; } ------ +---- Note that in this mode, the alpha values are interpreted (and interpolated) as 12-bit HDR values, and are interpolated as @@ -1442,11 +1466,11 @@ in <>. [[astc-weight-unquantization-values]] .ASTC weight unquantization values [cols="3,1,1,1,1,1",width="40%",options="header"] -|=========== +|==== ^| Range ^| 0 ^| 1 ^| 2 ^| 3 ^| 4 ^| 0..2 ^| 0 ^| 32 ^| 63 ^| - ^| - ^| 0..4 ^| 0 ^| 16 ^| 32 ^| 47 ^| 63 -|=========== +|==== For other values, we calculate the initial inputs to a bit manipulation procedure. These are denoted ++A++ (7 bits), ++B++ (7 bits), ++C++ (7 bits), @@ -1456,22 +1480,23 @@ and ++D++ (3 bits) and are decoded using the range as shown in [[astc-weight-unquantization-parameters]] .ASTC weight unquantization parameters [cols="4,3,4,3,5,6,6,3,8",width="95%",options="header"] -|============ +|==== ^| Range ^| #Trits ^| #Quints ^| #Bits ^| Bit layout ^| ++A++ ^| ++B++ ^| ++C++ ^| ++D++ ^| 0..5 ^| 1 ^| ^| 1 ^| a ^| aaaaaaa ^| 0000000 ^| 50 ^| Trit value ^| 0..9 ^| ^| 1 ^| 1 ^| a ^| aaaaaaa ^| 0000000 ^| 28 ^| Quint value ^| 0..11 ^| 1 ^| ^| 2 ^| ba ^| aaaaaaa ^| b000b0b ^| 23 ^| Trit value ^| 0..19 ^| ^| 1 ^| 2 ^| ba ^| aaaaaaa ^| b0000b0 ^| 13 ^| Quint value ^| 0..23 ^| 1 ^| ^| 3 ^| cba ^| aaaaaaa ^| cb000cb ^| 11 ^| Trit value -|=========== +|==== These are then processed as follows: ------ +[source] +---- unq = D * C + B; unq = unq ^ A; unq = (A & 0x20) | (unq >> 2); ------ +---- Note that the multiply in the first line is nearly trivial as it only needs to multiply by 0, 1, 2, 3 or 4. @@ -1479,9 +1504,10 @@ needs to multiply by 0, 1, 2, 3 or 4. As a final step, for all types of value, the range is expanded from 0..63 up to 0..64 as follows: ------ +[source] +---- if (unq > 32) { unq += 1; } ------ +---- This allows the implementation to use 64 as a divisor during interpolation, which is much easier than using 63. @@ -1502,24 +1528,25 @@ have values from 0 to one less than the block dimension in that axis. For each block dimension, we compute scale factors (_D~s~_, _D~t~_, _D~r~_): [latexmath] -+++++++++++++ +++++ \begin{align*} D_s = \left\lfloor {\left(1024 + \left\lfloor { \textrm{B}_\textrm{s} \over 2 }\right\rfloor\right) \over (\textrm{B}_\textrm{s}-1) } \right\rfloor \\ D_t = \left\lfloor {\left(1024 + \left\lfloor { \textrm{B}_\textrm{t} \over 2 }\right\rfloor\right) \over (\textrm{B}_\textrm{t}-1) } \right\rfloor \\ D_r = \left\lfloor {\left(1024 + \left\lfloor { \textrm{B}_\textrm{r} \over 2 }\right\rfloor\right) \over (\textrm{B}_\textrm{r}-1) } \right\rfloor \end{align*} -+++++++++++++ +++++ Since the block dimensions are constrained, these are easily looked up in a table. These scale factors are then used to scale the (b~s~, b~t~, b~r~) coordinates to a homogeneous coordinate (c~s~, c~t~, c~r~): ------ +[source] +---- cs = Ds * bs; ct = Dt * bt; cr = Dr * br; ------ +---- This homogeneous coordinate (c~s~, c~t~, c~r~) is then scaled again to give a coordinate (g~s~, g~t~, g~r~) in the weight-grid space. @@ -1527,11 +1554,12 @@ The weight-grid is of size (W~width~, W~height~, W~depth~), as specified in the block mode field (<> and <>): ------ +[source] +---- gs = (cs*(Wwidth-1)+32) >> 6; gt = (ct*(Wheight-1)+32) >> 6; gr = (cr*(Wdepth-1)+32) >> 6; ------ +---- The resulting coordinates may be in the range 0..176. These are interpreted as 4:4 unsigned fixed point numbers in the range 0.0 .. 11.0. @@ -1539,24 +1567,26 @@ as 4:4 unsigned fixed point numbers in the range 0.0 .. 11.0. If we label the integral parts of these (j~s~, j~t~, j~r~) and the fractional parts (f~s~, f~t~, f~r~), then: ------ +[source] +---- js = gs >> 4; fs = gs & 0x0F; jt = gt >> 4; ft = gt & 0x0F; jr = gr >> 4; fr = gr & 0x0F; ------ +---- These values are then used to interpolate between the stored weights. This process differs for 2D and 3D. For 2D, bilinear interpolation is used: ------ +[source] +---- v0 = js + jt*Wwidth; p00 = decode_weight(v0); p01 = decode_weight(v0 + 1); p10 = decode_weight(v0 + Wwidth); p11 = decode_weight(v0 + Wwidth + 1); ------ +---- The function `decode_weight(n)` decodes the _n_^th^ weight in the stored weight stream. @@ -1564,13 +1594,14 @@ The values p~00~ to p~11~ are the weights at the corner of the square in which the texel position resides. These are then weighted using the fractional position to produce the effective weight _i_ as follows: ------ +[source] +---- w11 = (fs*ft+8) >> 4; w10 = ft - w11; w01 = fs - w11; w00 = 16 - fs - ft + w11; i = (p00*w00 + p01*w01 + p10*w10 + p11*w11 + 8) >> 4; ------ +---- For 3D, simplex interpolation is used as it is cheaper than a naïve trilinear interpolation. First, we pick some parameters for the interpolation @@ -1580,7 +1611,7 @@ position as shown in <>. [[astc-simplex-interpolation-parameters]] .ASTC simplex interpolation parameters [options="header",width="90%",cols="1,1,1,2,2,1,1,1,1"] -|================== +|==== ^| _f~s~_ > _f~t~_ ^| _f~t~_ > _f~r~_ ^| _f~s~_ > _f~r~_ ^| _s_~1~ ^| _s_~2~ ^| _w_~0~ ^| _w_~1~ ^| _w_~2~ ^| _w_~3~ ^| True ^| True ^| _True_ ^| 1 ^| W~width~ ^| 16 - _f~s~_ ^| _f~s~_ - _f~t~_ ^| _f~t~_ - _f~r~_ ^| _f~r~_ ^| False ^| _True_ ^| True ^| W~width~ ^| 1 ^| 16 - _f~t~_ ^| _f~t~_ - _f~s~_ ^| _f~s~_ - _f~r~_ ^| _f~r~_ @@ -1588,19 +1619,20 @@ position as shown in <>. ^| True ^| _False_ ^| False ^| W~width~ {times} W~height~ ^| 1 ^| 16 - _f~r~_ ^| _f~r~_ - _f~s~_ ^| _f~s~_ - _f~t~_ ^| _f~t~_ ^| _False_ ^| True ^| False ^| W~width~ ^| W~width~ {times} W~height~ ^| 16 - _f~t~_ ^| _f~t~_ - _f~r~_ ^| _f~r~_ - _f~s~_ ^| _f~s~_ ^| False ^| False ^| _False_ ^| W~width~ {times} W~height~ ^| W~width~ ^| 16 - _f~r~_ ^| _f~r~_ - _f~t~_ ^| _f~t~_ - _f~s~_ ^| _f~s~_ -|================== +|==== Italicized test results are implied by the others. The effective weight _i_ is then calculated as: ------ +[source] +---- v0 = js + jt*Wwidth + jr*Wwidth*Wheight; p0 = decode_index(v0); p1 = decode_index(v0 + s1); p2 = decode_index(v0 + s1 + s2); p3 = decode_index(v0 + Wwidth*Wheight + Wwidth + 1); i = (p0*w0 + p1*w1 + p2*w2 + p3*w3 + 8) >> 4; ------ +---- <<< @@ -1616,22 +1648,25 @@ corresponding 8-bit endpoint components C~0~ and C~1~ as follows: If sRGB conversion is not enabled, or for the alpha channel in any case, C~0~ and C~1~ are first expanded to 16 bits by bit replication: ------ +[source] +---- C0 = (C0 << 8) | C0; C1 = (C1 << 8) | C1; ------ +---- If sRGB conversion is enabled, C~0~ and C~1~ for the _R_, _G_, and _B_ channels are expanded to 16 bits differently, as follows: ------ +[source] +---- C0 = (C0 << 8) | 0x80; C1 = (C1 << 8) | 0x80; ------ +---- C~0~ and C~1~ are then interpolated to produce a UNORM16 result C: ------ +[source] +---- C = floor( (C0*(64-i) + C1*i + 32)/64 ) ------ +---- If sRGB conversion is not enabled and the decoding mode is decode_float16, then if C = 65535 the final result is 1.0 (0x3C00); otherwise C is @@ -1646,7 +1681,8 @@ If sRGB conversion is not enabled and the decoding mode is decode_rgb9e5, then the final result is a combination of the (UNORM16) values of C for the three color components (_C~r~_, _C~g~_ and _C~b~_) computed as follows: ------ +[source] +---- int lz = clz17(Cr | Cg | Cb | 1); if (Cr == 65535) { Cr = 65536; lz = 0; } if (Cg == 65535) { Cg = 65536; lz = 0; } @@ -1657,7 +1693,7 @@ Cg = (Cg >> 8) & 0x1FF; Cb = (Cb >> 8) & 0x1FF; uint32_t exponent = 16 - lz; uint32_t texel = (exponent << 27) | (Cb << 18) | Cg << 9) | Cr; ------ +---- The ++clz17()++ function counts leading zeroes in a 17-bit value. @@ -1679,14 +1715,15 @@ are interpolated in the same way as LDR. The 16-bit value C is then decomposed into the top five bits, E, and the bottom 11 bits M, which are then processed and recombined with E to form the final value C~f~: ------ +[source] +---- C = floor( (C0*(64-i) + C1*i + 32)/64 ) E = (C & 0xF800) >> 11; M = C & 0x7FF; if (M < 512) { Mt = 3*M; } else if (M >= 1536) { Mt = 5*M - 2048; } else { Mt = 4*M - 512; } Cf = (E<<10) + (Mt>>3); ------ +---- This interpolation is a considerably closer approximation to a logarithmic space than simple 16-bit interpolation. @@ -1701,7 +1738,8 @@ If the decoding mode is decode_rgb9e5, then the final result is a combination fo the (IEEE FP16) values of C~f~ for the three color components (_C~r~_, _C~g~_ and _C~b~_) computed as follows: ------ +[source] +---- if( Cr > 0x7c00 ) Cr = 0; else if( Cr == 0x7c00 ) Cr = 0x7bff; if( Cg > 0x7c00 ) Cg = 0; else if( Cg == 0x7c00 ) Cg = 0x7bff; if( Cb > 0x7c00 ) Cb = 0; else if( Cb == 0x7c00 ) Cb = 0x7bff; @@ -1749,7 +1787,7 @@ Gm = (Gm >> gshift) & 0x1FF; Bm = (Bm >> bshift) & 0x1FF; uint32_t texel = (expo << 27) | (Bm << 18) | (Gm << 9) | (Rm << 0); ------ +---- <<< @@ -1769,13 +1807,13 @@ Component Selector (CCS) field as shown in <= d ) return 2; else return 3; } ------ +---- As has been observed before, the bit selections are much easier to express in hardware than in C. @@ -1860,7 +1899,8 @@ express in hardware than in C. The seed is expanded using a hash function `hash52()`, which is defined as follows: ------ +[source] +---- uint32_t hash52( uint32_t p ) { p ^= p >> 15; p -= p << 17; p += p << 7; p += p << 4; @@ -1868,7 +1908,7 @@ uint32_t hash52( uint32_t p ) p ^= p << 6; p ^= p >> 17; return p; } ------ +---- This assumes that all operations act on 32-bit values @@ -1878,7 +1918,8 @@ The size of the data used to represent color endpoints is not explicitly specified. Instead, it is determined from the block mode and number of partitions as follows: ------ +[source] +---- config_bits = 17; if(num_partitions>1) if(single_CEM) @@ -1899,7 +1940,7 @@ weight_bits = ceil(num_weights*8*trits_in_weight_range/5) + remaining_bits = 128 - config_bits - weight_bits; num_CEM_pairs = base_CEM_class+1 + count_bits(extra_CEM_bits); ------ +---- The CEM value range is then looked up from a table indexed by remaining bits and `num_CEM_pairs`. @@ -1910,7 +1951,8 @@ remaining bits. An equivalent iterative algorithm would be: ------ +[source] +---- num_CEM_values = num_CEM_pairs*2; for(range = each possible CEM range in descending order of size) @@ -1923,7 +1965,7 @@ for(range = each possible CEM range in descending order of size) break; } return range; ------ +---- In cases where this procedure results in unallocated bits, these bits are not read by the decoding process and can have any value. @@ -1945,7 +1987,7 @@ The layout of a 2D Void-Extent block is as shown in <>. [[astc-3d-void-extend-block-layout-overview]] .ASTC 3D void-extent block layout overview [cols="1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",width="97%"] -|================= +|==== ^| ~127~ ^| ~126~ ^| ~125~ ^| ~124~ ^| ~123~ ^| ~122~ ^| ~121~ ^| ~120~ ^| ~119~ ^| ~118~ ^| ~117~ ^| ~116~ ^| ~115~ ^| ~114~ ^| ~113~ ^| ~112~ 16+^| Block color _A_ component^15..0^ ^| ~111~ ^| ~110~ ^| ~109~ ^| ~108~ ^| ~107~ ^| ~106~ ^| ~105~ ^| ~104~ ^| ~103~ ^| ~102~ ^| ~101~ ^| ~100~ ^| ~99~ ^| ~98~ ^| ~97~ ^| ~96~ @@ -1986,7 +2028,7 @@ The layout of a 3D Void-Extent block is as shown in <>, anchor~3,2~ is <>, anchor~3,3~ is <>, and _part_ is encoded in the partition @@ -513,7 +514,7 @@ using <> with weights from the two-bit index row of [[bptcP2subset]] .Partition table for 2-subset BPTC, with the 4×4 block of values for each partition number [cols="5,5,5,5,1,5,5,5,5,1,5,5,5,5,1,5,5,5,5,1,5,5,5,5,1,5,5,5,5,1,5,5,5,5,1,5,5,5,5",width="97%"] -|================== +|==== 4+^| ~0~ 1.40+| 4+^| ~1~ 1.40+| 4+^| ~2~ 1.40+| 4+^| ~3~ 1.40+| 4+^| ~4~ 1.40+| 4+^| ~5~ 1.40+| 4+^| ~6~ 1.40+| 4+^| ~7~ ^| *_0_* ^| 0 ^| 1 ^| 1 ^| *_0_* ^| 0 ^| 0 ^| 1 ^| *_0_* ^| 1 ^| 1 ^| 1 ^| *_0_* ^| 0 ^| 0 ^| 1 ^| *_0_* ^| 0 ^| 0 ^| 0 ^| *_0_* ^| 0 ^| 1 ^| 1 ^| *_0_* ^| 0 ^| 0 ^| 1 ^| *_0_* ^| 0 ^| 0 ^| 0 ^| 0 ^| 0 ^| 1 ^| 1 ^| 0 ^| 0 ^| 0 ^| 1 ^| 0 ^| 1 ^| 1 ^| 1 ^| 0 ^| 0 ^| 1 ^| 1 ^| 0 ^| 0 ^| 0 ^| 1 ^| 0 ^| 1 ^| 1 ^| 1 ^| 0 ^| 0 ^| 1 ^| 1 ^| 0 ^| 0 ^| 0 ^| 1 @@ -561,12 +562,12 @@ using <> with weights from the two-bit index row of ^| 1 ^| 1 ^| 0 ^| 0 ^| 0 ^| 0 ^| 1 ^| 1 ^| 1 ^| 1 ^| 1 ^| 0 ^| 1 ^| 0 ^| 0 ^| 0 ^| 1 ^| 1 ^| 1 ^| 1 ^| 0 ^| 0 ^| 1 ^| 1 ^| 0 ^| 0 ^| 1 ^| 0 ^| 0 ^| 1 ^| 0 ^| 0 ^| 1 ^| 1 ^| 0 ^| 0 ^| 0 ^| 0 ^| 1 ^| 1 ^| 1 ^| 0 ^| 0 ^| 0 ^| 1 ^| 1 ^| 1 ^| 0 ^| 0 ^| 0 ^| 1 ^| 1 ^| 1 ^| 1 ^| 1 ^| 1 ^| 1 ^| 1 ^| 1 ^| 0 ^| 0 ^| 1 ^| 1 ^| 1 ^| 1 ^| 0 ^| 0 ^| *_1_* ^| 1 ^| 0 ^| 0 ^| *_1_* ^| 0 ^| 0 ^| 0 ^| *_1_* ^| 0 ^| 1 ^| 1 ^| *_1_* ^| 0 ^| 0 ^| 1 ^| *_1_* ^| 0 ^| 0 ^| 0 ^| 0 ^| 1 ^| 1 ^| 1 ^| 0 ^| 0 ^| 1 ^| 1 ^| *_1_* -|================== +|==== [[bptcP3subset]] .Partition table for 3-subset BPTC, with the 4×4 block of values for each partition number [cols="5,5,5,5,1,5,5,5,5,1,5,5,5,5,1,5,5,5,5,1,5,5,5,5,1,5,5,5,5,1,5,5,5,5,1,5,5,5,5",width="97%"] -|=============== +|==== 4+^| ~0~ 1.40+| 4+^| ~1~ 1.40+| 4+^| ~2~ 1.40+| 4+^| ~3~ 1.40+| 4+^| ~4~ 1.40+| 4+^| ~5~ 1.40+| 4+^| ~6~ 1.40+| 4+^| ~7~ ^| *_0_* ^| 0 ^| 1 ^| *_1_* ^| *_0_* ^| 0 ^| 0 ^| *_1_* ^| *_0_* ^| 0 ^| 0 ^| 0 ^| *_0_* ^| 2 ^| 2 ^| *_2_* ^| *_0_* ^| 0 ^| 0 ^| 0 ^| *_0_* ^| 0 ^| 1 ^| *_1_* ^| *_0_* ^| 0 ^| 2 ^| *_2_* ^| *_0_* ^| 0 ^| 1 ^| 1 ^| 0 ^| 0 ^| 1 ^| 1 ^| 0 ^| 0 ^| 1 ^| 1 ^| 2 ^| 0 ^| 0 ^| 1 ^| 0 ^| 0 ^| 2 ^| 2 ^| 0 ^| 0 ^| 0 ^| 0 ^| 0 ^| 0 ^| 1 ^| 1 ^| 0 ^| 0 ^| 2 ^| 2 ^| 0 ^| 0 ^| 1 ^| 1 @@ -614,12 +615,12 @@ using <> with weights from the two-bit index row of ^| 0 ^| *_1_* ^| 1 ^| 0 ^| 0 ^| 0 ^| 1 ^| 1 ^| 1 ^| 1 ^| 2 ^| 2 ^| 0 ^| 0 ^| 0 ^| 0 ^| 0 ^| 0 ^| 0 ^| 1 ^| 1 ^| 2 ^| 2 ^| 2 ^| 2 ^| 2 ^| 2 ^| 2 ^| 2 ^| 0 ^| 1 ^| 1 ^| 2 ^| 2 ^| 2 ^| 2 ^| 0 ^| 0 ^| *_1_* ^| 1 ^| *_1_* ^| 1 ^| 2 ^| 2 ^| 0 ^| 0 ^| 0 ^| 0 ^| 0 ^| 0 ^| 0 ^| 2 ^| 0 ^| 2 ^| 2 ^| 2 ^| 2 ^| 2 ^| 2 ^| 2 ^| *_2_* ^| 2 ^| 0 ^| 1 ^| 2 ^| 2 ^| 2 ^| *_2_* ^| 0 ^| 0 ^| 2 ^| *_2_* ^| 0 ^| 0 ^| 2 ^| *_2_* ^| 2 ^| *_1_* ^| 1 ^| *_2_* ^| 0 ^| 0 ^| 0 ^| *_1_* ^| *_1_* ^| 2 ^| 2 ^| *_2_* ^| 2 ^| 2 ^| 2 ^| *_2_* ^| 2 ^| 2 ^| 2 ^| 0 -|========== +|==== [[bptcA32index]] .BPTC anchor index values for the second subset of three-subset partitioning, by partition number [width="40%"] -|================ +|==== ^| ~0~ ^| ~1~ ^| ~2~ ^| ~3~ ^| ~4~ ^| ~5~ ^| ~6~ ^| ~7~ ^| 3 ^| 3 ^| 15 ^| 15 ^| 8 ^| 3 ^| 15 ^| 15 ^| ~8~ ^| ~9~ ^| ~10~ ^| ~11~ ^| ~12~ ^| ~13~ ^| ~14~ ^| ~15~ @@ -636,12 +637,12 @@ using <> with weights from the two-bit index row of ^| 3 ^| 15 ^| 5 ^| 5 ^| 5 ^| 8 ^| 5 ^| 10 ^| ~56~ ^| ~57~ ^| ~58~ ^| ~59~ ^| ~60~ ^| ~61~ ^| ~62~ ^| ~63~ ^| 5 ^| 10 ^| 8 ^| 13 ^| 15 ^| 12 ^| 3 ^| 3 -|================ +|==== [[bptcA33index]] .BPTC anchor index values for the third subset of three-subset partitioning, by partition number [width="40%"] -|=============== +|==== ^| ~0~ ^| ~1~ ^| ~2~ ^| ~3~ ^| ~4~ ^| ~5~ ^| ~6~ ^| ~7~ ^| 15 ^| 8 ^| 8 ^| 3 ^| 15 ^| 15 ^| 3 ^| 8 ^| ~8~ ^| ~9~ ^| ~10~ ^| ~11~ ^| ~12~ ^| ~13~ ^| ~14~ ^| ~15~ @@ -658,7 +659,7 @@ using <> with weights from the two-bit index row of ^| 15 ^| 3 ^| 15 ^| 15 ^| 15 ^| 15 ^| 15 ^| 15 ^| ~56~ ^| ~57~ ^| ~58~ ^| ~59~ ^| ~60~ ^| ~61~ ^| ~62~ ^| ~63~ ^| 15 ^| 15 ^| 15 ^| 15 ^| 3 ^| 15 ^| 15 ^| 8 -|=============== +|==== ifndef::a2xhtml[] @@ -672,7 +673,7 @@ endif::[] [[bptcA2index]] .BPTC anchor index values for the second subset of two-subset partitioning, by partition number [width="40%"] -|============== +|==== ^| ~0~ ^| ~1~ ^| ~2~ ^| ~3~ ^| ~4~ ^| ~5~ ^| ~6~ ^| ~7~ ^| 15 ^| 15 ^| 15 ^| 15 ^| 15 ^| 15 ^| 15 ^| 15 ^| ~8~ ^| ~9~ ^| ~10~ ^| ~11~ ^| ~12~ ^| ~13~ ^| ~14~ ^| ~15~ @@ -689,7 +690,7 @@ endif::[] ^| 6 ^| 2 ^| 6 ^| 8 ^| 15 ^| 15 ^| 2 ^| 2 ^| ~56~ ^| ~57~ ^| ~58~ ^| ~59~ ^| ~60~ ^| ~61~ ^| ~62~ ^| ~63~ ^| 15 ^| 15 ^| 15 ^| 15 ^| 15 ^| 2 ^| 2 ^| 15 -|============== +|==== ifndef::a2xhtml[] <<< @@ -710,14 +711,14 @@ given in <>. [[BPTCInterpolation]] .BPTC interpolation factors [cols="h,18*",width="85%"] -|========== +|==== .2+^.^| 2 2+^| Index 4+^| ~0~ 4+^| ~1~ 4+^| ~2~ 4+^| ~3~ 2+^| _Weight_ 4+^| 0 4+^| 21 4+^| 43 4+^| 64 .2+^.^| 3 2+^| Index 2+^| ~0~ 2+^| ~1~ 2+^| ~2~ 2+^| ~3~ 2+^| ~4~ 2+^| ~5~ 2+^| ~6~ 2+^| ~7~ 2+^| _Weight_ 2+^| 0 2+^| 9 2+^| 18 2+^| 27 2+^| 37 2+^| 46 2+^| 55 2+^| 64 .2+^.^| 4 2+^| Index ^| ~0~ ^| ~1~ ^| ~2~ ^| ~3~ ^| ~4~ ^| ~5~ ^| ~6~ ^| ~7~ ^| ~8~ ^| ~9~ ^| ~10~ ^| ~11~ ^| ~12~ ^| ~13~ ^| ~14~ ^| ~15~ 2+^| _Weight_ ^| 0 ^| 4 ^| 9 ^| 13 ^| 17 ^| 21 ^| 26 ^| 30 ^| 34 ^| 38 ^| 43 ^| 47 ^| 51 ^| 55 ^| 60 ^| 64 -|========== +|==== // Note: The interpolation formula is not explicitly present in the OpenGL Specification. // Since bit-exact interpolation is mandated by some implementations, the following formula is @@ -729,13 +730,13 @@ as an unsigned integer interpolation factor from <>: [[BPTCinterpolation]] .BPTC endpoint interpolation formula [latexmath] -++++++++++++++ +++++ \begin{align*} \mathit{interpolated\ value} & = ((64 - \mathit{weight}) \times \textit{E}_0 + \mathit{weight} \times \textit{E}_1 + 32) \gg 6 \end{align*} -++++++++++++++ +++++ -where latexmath:[$\gg$] performs a (truncating) bitwise right-shift, and +where latexmath:[\gg] performs a (truncating) bitwise right-shift, and _interpolated value_ is an (unsigned) integer in the range [0..255]. The interpolation results in an _RGBA_ color. If rotation bits are present, this interpolated color is remapped according to <>. @@ -743,15 +744,15 @@ this interpolated color is remapped according to <>. [[BPTCRotation]] .BPTC Rotation bits [cols="h,3",width="20%"] -|============ +|==== ^| 0 ^| no change ^| 1 ^| _swap_(_A_, _R_) ^| 2 ^| _swap_(_A_, _G_) ^| 3 ^| _swap_(_A_, _B_) -|============ +|==== These 8-bit values should be interpreted as _RGBA_ 8-bit normalized channels, -either linearly encoded (by multiplying by latexmath:[$1\over 255$]) or +either linearly encoded (by multiplying by latexmath:[1\over 255]) or with the <>. <<< @@ -783,7 +784,7 @@ number. Mode numbers not listed in <> [[table-bptcblockmodes]] .Endpoint and partition parameters for BPTC block modes [width="100%",cols="10%,15%,20%,20%,10%,1%,7%,10%,7%"] -|============== +|==== .2+^.^| *Mode number* .2+^.^| *Transformed endpoints* ^.^| *Partition bits (PB)* ^.^| *Endpoint bits (EPB)* ^.^| *Delta bits* 1.16+| ^.^| *Mode* ^.^| *Endpoint* ^.^| *Delta* ^| Bits per texel block 2+^| {_R_,_G_,_B_} bits per endpoint 3+^| Bits per texel block (total) ^| *0* ^| {check} ^| 5 ^| {10, 10, 10} ^| {5, 5, 5} ^| 2 ^| 30 ^| 45 @@ -800,7 +801,7 @@ number. Mode numbers not listed in <> ^| *7* ^| {check} ^| 0 ^| {11, 11, 11} ^| {9, 9, 9} ^| 5 ^| 33 ^| 27 ^| *11* ^| {check} ^| 0 ^| {12, 12, 12} ^| {8, 8, 8} ^| 5 ^| 36 ^| 24 ^| *15* ^| {check} ^| 0 ^| {16, 16, 16} ^| {4, 4, 4} ^| 5 ^| 48 ^| 12 -|============== +|==== The data for the compressed blocks is stored in a different manner for each mode. @@ -828,7 +829,7 @@ The partition number references the first half of <>. [[table-bptcblockformat]] .Block descriptions for BC6H block modes (LSB..MSB) [options="header",cols="3,13",width="85%"] -|=========================== +|==== ^| Mode Number ^| Block description ^.^| 0 ^.^| M^1..0^, _G_~2~^4^, _B_~2~^4^, _B_~3~^4^, _R_~0~^9..0^, _G_~0~^9..0^, _B_~0~^9..0^, _R_~1~^4..0^, _G_~3~^4^, _G_~2~^3..0^, _G_~1~^4..0^, _B_~3~^0^, _G_~3~^3..0^, _B_~1~^4..0^, _B_~3~^1^, _B_~2~^3..0^, @@ -869,7 +870,7 @@ The partition number references the first half of <>. _G_~0~^10..11^, _B_~1~^7..0^, _B_~0~^10..11^ ^.^| 15 ^.^| M^4..0^, _R_~0~^9..0^, _G_~0~^9..0^, _B_~0~^9..0^, _R_~1~^3..0^, _R_~0~^10..15^, _G_~1~^3..0^, _G_~0~^10..15^, _B_~1~^3..0^, _B_~0~^10..15^ -|========================== +|==== Indices are read in the same way as the BC7 formats including obeying the anchor values for index 0 and as needed by <>. @@ -884,7 +885,7 @@ In both cases, index bits are stored in y-major offset order by increasing little-endian bit number, with the bits for each index stored consecutively: [latexmath] -++++++++++++++ +++++ \begin{align*} {\textrm{Bit offset of IB}_{x,y}}^0 &= \begin{cases} 65, & 1\ \textrm{subset},\ x = y = 0 \\ @@ -894,12 +895,12 @@ little-endian bit number, with the bits for each index stored consecutively: 82 + 3 \times (x + 4\times y) - 2, & 2\ \textrm{subsets},\ \textrm{anchor}_2[\mathit{part}] < x + 4\times y \\ \end{cases} \\ \end{align*} -++++++++++++++ +++++ [[table-bptcbc6hbits]] .Interpretation of lower bits for BC6H block modes [width="85%", cols=">1,14*^1"] -|================ +|==== >| 14+^| *Mode* ^| *Bit* | *0* | *1* | *2* | *6* | *10* | *14* | *18* | *22* | *26* | *30* | *3* | *7* | *11* | *15* >| *0*   | M^0^: *0* | M^0^: *1* | M^0^: *0* | M^0^: *0* | M^0^: *0* | M^0^: *0* | M^0^: *0* | M^0^: *0* | M^0^: *0* | M^0^: *0* | M^0^: *1* | M^0^: *1* | M^0^: *1* | M^0^: *1* @@ -943,12 +944,12 @@ little-endian bit number, with the bits for each index stored consecutively: >| *38*   | _R_~1~^3^ | _R_~1~^3^ | _R_~1~^3^ | _R_~1~^3^ | _R_~1~^3^ | _R_~1~^3^ | _R_~1~^3^ | _R_~1~^3^ | _R_~1~^3^ | _R_~1~^3^ | _R_~1~^3^ | _R_~1~^3^ | _R_~1~^3^ | _R_~1~^3^ >| *39*   | _R_~1~^4^ | _R_~1~^4^ | _R_~1~^4^ | _R_~0~^10^ | _R_~0~^10^ | _R_~1~^4^ | _R_~1~^4^ | _R_~1~^4^ | _R_~1~^4^ | _R_~1~^4^ | _R_~1~^4^ | _R_~1~^4^ | _R_~1~^4^ | _R_~0~^15^ >| *40*   | _G_~3~^4^ | _R_~1~^5^ | _R_~0~^10^ | _G_~3~^4^ | _B_~2~^4^ | _G_~3~^4^ | _R_~1~^5^ | _G_~3~^4^ | _G_~3~^4^ | _R_~1~^5^ | _R_~1~^5^ | _R_~1~^5^ | _R_~1~^5^ | _R_~0~^14^ -|================ +|==== [[table-bptcbc6hbits2]] .Interpretation of upper bits for BC6H block modes [width="80%", cols=">1,14*^1"] -|================ +|==== >| 14+^| *Mode* ^| *Bit* | *0* | *1* | *2* | *6* | *10* | *14* | *18* | *22* | *26* | *30* | *3* | *7* | *11* | *15* >| *41*   | _G_~2~^0^ | _G_~2~^0^ | _G_~2~^0^ | _G_~2~^0^ | _G_~2~^0^ | _G_~2~^0^ | _G_~2~^0^ | _G_~2~^0^ | _G_~2~^0^ | _G_~2~^0^ | _R_~1~^6^ | _R_~1~^6^ | _R_~1~^6^ | _R_~0~^13^ @@ -992,7 +993,7 @@ little-endian bit number, with the bits for each index stored consecutively: >| *79*   | PB^2^ | PB^2^ | PB^2^ | PB^2^ | PB^2^ | PB^2^ | PB^2^ | PB^2^ | PB^2^ | PB^2^ | IB~3,0~^3^ | IB~3,0~^3^ | IB~3,0~^3^ | IB~3,0~^3^ >| *80*   | PB^3^ | PB^3^ | PB^3^ | PB^3^ | PB^3^ | PB^3^ | PB^3^ | PB^3^ | PB^3^ | PB^3^ | IB~0,1~^0^ | IB~0,1~^0^ | IB~0,1~^0^ | IB~0,1~^0^ >| *81*   | PB^4^ | PB^4^ | PB^4^ | PB^4^ | PB^4^ | PB^4^ | PB^4^ | PB^4^ | PB^4^ | PB^4^ | IB~0,1~^1^ | IB~0,1~^1^ | IB~0,1~^1^ | IB~0,1~^1^ -|================ +|==== [NOTE] ==== @@ -1023,7 +1024,7 @@ sign-extended if the format of the texture is signed or if the block mode has transformed endpoints. If the mode has transformed endpoints, the values from _E_~0~ are used as a base to offset all other endpoints, wrapped at the number of endpoint bits. -For example, _R_~1~ = (_R_~0~ {plus} _R_~1~) & latexmath:[$((1 \ll \mathrm{EPB})-1)$]. +For example, _R_~1~ = (_R_~0~ {plus} _R_~1~) & latexmath:[((1 \ll \mathrm{EPB})-1)]. [NOTE] ==== @@ -1051,7 +1052,8 @@ The following pseudocode assumes the computation uses sufficiently large intermediate values to avoid overflow. For the unsigned float format, we unquantize a value _x_ to _unq_ by: ------ +[source] +---- if (EPB >= 15) unq = x; else if (x == 0) @@ -1060,12 +1062,13 @@ else if (x == ((1 << EPB)-1)) unq = 0xFFFF; else unq = ((x << 15) + 0x4000) >> (EPB-1); ------ +---- The signed float unquantization is similar, but needs to worry about orienting the negative range: ------ +[source] +---- s = 0; if (EPB >= 16) { unq = x; @@ -1085,7 +1088,7 @@ if (EPB >= 16) { if (s) unq = -unq; } ------ +---- After the endpoints are unquantized, interpolation proceeds as in the fixed-point formats above using <>, including the interpolation @@ -1100,37 +1103,39 @@ represent [0.0..65504.0], where 65504.0 is the largest finite value representable in a half float. The bit pattern that represents 65504.0 is integer 0x7BFF, so the integer input range 0..0xFFFF can be mapped to this range by scaling the -interpolated integer i by latexmath:[$31\over 64$]: +interpolated integer i by latexmath:[31\over 64]: ------ +[source] +---- out = (i * 31) >> 6; ------ +---- For the signed format, the final unquantization step limits the range of the integer representation to the bit sequences which, when interpreted as -a 16-bit half float, represent the range [latexmath:[$-\infty$]..65504.0], -where latexmath:[$-\infty$] is represented in half float as the bit +a 16-bit half float, represent the range [latexmath:[-\infty]..65504.0], +where latexmath:[-\infty] is represented in half float as the bit pattern 0xFC00. The signed 16-bit integer range [-0x8000..0x7FFF] is remapped to this float representation by taking the absolute value of the interpolated -value i, scaling it by latexmath:[$31\over 32$], and restoring the sign bit: +value i, scaling it by latexmath:[31\over 32], and restoring the sign bit: ------ +[source] +---- out = i < 0 ? (((-i) * 31) >> 5) | 0x8000 : (i * 31) >> 5; ------ +---- The resultant bit pattern should be interpreted as a 16-bit half float. [NOTE] ==== -The ability to support latexmath:[$-\infty$] is considered ``accidental'' +The ability to support latexmath:[-\infty] is considered ``accidental'' due to the asymmetry of two's complement representation: in order to map integer 0x7FFF to 65504.0 and 0x0000 to 0.0, -0x7FFF maps to the largest finite negative value, -65504.0, represented as 0xFBFF. A two's complement signed integer can also represent -0x8000; it happens that the same unquantization formula maps 0x8000 to 0xFC00, -which is the half float bit pattern for latexmath:[$-\infty$]. +which is the half float bit pattern for latexmath:[-\infty]. Although decoders for BC6H should be bit-exact, encoders for this format -are encouraged to map latexmath:[$-\infty$] to -65504.0 (and to map -latexmath:[$\infty$] to 65504.0 and NaN values to 0.0) prior to encoding. +are encouraged to map latexmath:[-\infty] to -65504.0 (and to map +latexmath:[\infty] to 65504.0 and NaN values to 0.0) prior to encoding. ==== diff --git a/colormodels.txt b/chapters/colormodels.adoc similarity index 80% rename from colormodels.txt rename to chapters/colormodels.adoc index f764f9e..210eb6b 100644 --- a/colormodels.txt +++ b/chapters/colormodels.adoc @@ -1,5 +1,5 @@ -// Copyright (c) 2017 The Khronos Group Inc. -// Copyright notice at https://www.khronos.org/registry/speccopyright.html +// Copyright 2017-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 [[MODEL_CONVERSION]] == Color models @@ -41,17 +41,17 @@ In the broadcast standards which define these models: to refer to a continuous signal value in the range [0..1], mirroring the terminology in analog standards such as <> and <>. - For example, in these standards, the continuous encoding of latexmath:[$R'$] - is written latexmath:[$E_R'$]. + For example, in these standards, the continuous encoding of latexmath:[R'] + is written latexmath:[E_R']. <> and <> no longer use the _E_ convention, and refer to continuous values as, for example, _R′_ directly. For brevity, this specification does not use the _E_-prefix convention for model conversions, and all values can be assumed to be continuous. <> refers to the quantized digital version of - latexmath:[$E'_R$], latexmath:[$E'_G$] and latexmath:[$E'_B$] as - latexmath:[$E'_{R_D}$], latexmath:[$E'_{G_D}$] and latexmath:[$E'_{B_D}$]. + latexmath:[E'_R], latexmath:[E'_G] and latexmath:[E'_B] as + latexmath:[E'_{R_D}], latexmath:[E'_{G_D}] and latexmath:[E'_{B_D}]. In <> the quantized digital representation is instead - latexmath:[$D'_R$], latexmath:[$D'_G$] and latexmath:[$D'_B$], in + latexmath:[D'_R], latexmath:[D'_G] and latexmath:[D'_B], in <> and <> written as _DR′_, _DG′_ and _DB′_. * _Y′_ is a weighted sum of _R′_, _G′_ @@ -61,17 +61,17 @@ In the broadcast standards which define these models: Note that the ITU broadcast standards use ``luminance'' for _Y′_ despite some authorities reserving that term for a linear intensity representation. - Since this is a weighted sum of non-linear values, latexmath:[$Y'$] is + Since this is a weighted sum of non-linear values, latexmath:[Y'] is not mathematically equivalent to applying the non-linear transfer function to a weighted sum of linear _R_, _G_ and _B_ values: - latexmath:[$R^{\gamma}+G^{\gamma}+B^{\gamma} \neq (R + G + B)^{\gamma}$]. + latexmath:[R^{\gamma}+G^{\gamma}+B^{\gamma} \neq (R + G + B)^{\gamma}]. The prime symbol is often omitted so that _Y′_ is confusingly written _Y_. <> and <> refers to the continuous non-linear - ``luminance'' signal as latexmath:[$E'_Y$]; in <> and + ``luminance'' signal as latexmath:[E'_Y]; in <> and <> this value is just _Y′_. The quantized digital representation is written as simply _Y′_ - in <>, as latexmath:[$D'_Y$] in <>, and as + in <>, as latexmath:[D'_Y] in <>, and as _DY′_ in <> and <>. In this standard, _Y′_ refers to a continuous value. @@ -80,76 +80,76 @@ In the broadcast standards which define these models: * For the purposes of this section, we will refer to the weighting factor applied to _R′_ as _K~R~_ and the weighting factor applied to _B′_ as _K~B~_. The weighting factor of - _G′_ is therefore latexmath:[$1-K_R-K_B$]. Thus - latexmath:[$Y' = K_R \times R' + (1-K_R-K_B) \times G' + Kb \times B'$]. + _G′_ is therefore latexmath:[1-K_R-K_B]. Thus + latexmath:[Y' = K_R \times R' + (1-K_R-K_B) \times G' + Kb \times B']. Color differences are calculated from the non-linear _Y′_ and color components as: [latexmath] -++++++ +++++ \begin{align*} B'-Y' &= (1-K_B) \times B' - (1-K_R-K_B) \times G' - K_R \times R' \\ R'-Y' &= (1-K_R) \times R' - (1-K_R-K_B) \times G' - K_B \times B' \end{align*} -++++++ +++++ Note that, for _R′_, _G′_, _B′_ in the range [0..1]: [latexmath] -++++++ +++++ \begin{align*} (1-K_B) \geq B'-Y' \geq -(1-K_B) \\ (1-K_R) \geq R'-Y' \geq -(1-K_R) \end{align*} -++++++ +++++ -* latexmath:[$(B'-Y')$] scaled appropriately for incorporation into a PAL +* latexmath:[(B'-Y')] scaled appropriately for incorporation into a PAL sub-carrier signal is referred to in <> as _U_; note that the scale factor (0.493) is not the same as that used for digital encoding of this color difference. _U_ is colloquially used for other representations of this value. -* latexmath:[$(R'-Y')$] scaled appropriately for incorporation into a PAL +* latexmath:[(R'-Y')] scaled appropriately for incorporation into a PAL sub-carrier signal is referred to in <> as _V_; note that the scale factor (0.877) is not the same as that used for digital encoding of this color difference. _V_ is colloquially used for other representations of this value. -* latexmath:[$(B'-Y')$] scaled to the range [latexmath:[$-0.5..0.5$]] is +* latexmath:[(B'-Y')] scaled to the range [latexmath:[-0.5..0.5]] is referred to in <> and <> as - latexmath:[$E'_{C_B}$], and in <> and <> as - simply latexmath:[$C'_B$]. - In <> this value is referred to as latexmath:[$E'_\mathit{PB}$], + latexmath:[E'_{C_B}], and in <> and <> as + simply latexmath:[C'_B]. + In <> this value is referred to as latexmath:[E'_\mathit{PB}], and the analog signal is colloquially known as _P~B~_. - This standard uses the latexmath:[$C'_B$] terminology for brevity - and consistency with latexmath:[$Y'_CC'_\mathit{BC}C'_\mathit{RC}$]. + This standard uses the latexmath:[C'_B] terminology for brevity + and consistency with latexmath:[Y'_CC'_\mathit{BC}C'_\mathit{RC}]. It is common, especially in the name of a color model, to omit the prime symbol and write simply _C~B~_. -* latexmath:[$(R'-Y')$] scaled to the range [latexmath:[$-0.5..0.5$]] is +* latexmath:[(R'-Y')] scaled to the range [latexmath:[-0.5..0.5]] is referred to in <> and <> as - latexmath:[$E'_{C_R}$], and in <> and <> as - simply latexmath:[$C'_R$]. - In <> this value is referred to as latexmath:[$E'_\mathit{PR}$], + latexmath:[E'_{C_R}], and in <> and <> as + simply latexmath:[C'_R]. + In <> this value is referred to as latexmath:[E'_\mathit{PR}], and the analog signal is colloquially known as _P~R~_. - This standard uses the latexmath:[$C'_R$] terminology for brevity - and consistency with latexmath:[$Y'_CC'_\mathit{BC}C'_\mathit{RC}$]. + This standard uses the latexmath:[C'_R] terminology for brevity + and consistency with latexmath:[Y'_CC'_\mathit{BC}C'_\mathit{RC}]. It is common, especially in the name of a color model, to omit the prime symbol and write simply _C~R~_. -* latexmath:[$(B'-Y')$] scaled and quantized for digital representation is - known as simply latexmath:[$C'_B$] in <>, - latexmath:[$D'_\mathit{CB}$] in <> and latexmath:[$DC_B'$] +* latexmath:[(B'-Y')] scaled and quantized for digital representation is + known as simply latexmath:[C'_B] in <>, + latexmath:[D'_\mathit{CB}] in <> and latexmath:[DC_B'] in <> and <>. -* latexmath:[$(R'-Y')$] scaled and quantized for digital representation is - known as simply latexmath:[$C'_R$] in <>, - latexmath:[$D'_\mathit{CR}$] in <> and latexmath:[$DC_R'$] +* latexmath:[(R'-Y')] scaled and quantized for digital representation is + known as simply latexmath:[C'_R] in <>, + latexmath:[D'_\mathit{CR}] in <> and latexmath:[DC_R'] in <> and <>. * This section considers the color channels in continuous terms; - the terminology latexmath:[$DC_B'$] and latexmath:[$DC_R'$] is used + the terminology latexmath:[DC_B'] and latexmath:[DC_R'] is used in <>. Using this terminology, the following conversion formulae can be derived: [latexmath] -++++++ +++++ \begin{align*} Y' & = K_r \times R' + (1-K_R-K_B) \times G' + K_B \times B' \\ C'_B & = {(B' - Y')\over{2(1-K_B)}} \\ @@ -157,23 +157,23 @@ C'_B & = {(B' - Y')\over{2(1-K_B)}} \\ C'_R & = {(R' - Y')\over{2(1-K_R)}} \\ & = {R'\over{2}} - {{K_B \times B' + (1 - K_R - K_B) \times G'}\over{2(1-K_R)}} \end{align*} -++++++ +++++ <<< For the inverse conversion: [latexmath] -++++++ +++++ \begin{align*} R' & = Y' + 2(1-K_R)\times C'_R \\ B' & = Y' + 2(1-K_B)\times C'_B \end{align*} -++++++ +++++ The formula for _G′_ can be derived by substituting the formulae for _R′_ and _B′_ into the derivation of _Y′_: [latexmath] -++++++ +++++ \begin{align*} Y' = &\ K_R \times R' + (1-K_R-K_B) \times G' + K_B \times B' \\ = &\ K_R \times (Y'+2(1-K_R)\times C'_R) + \\ @@ -184,15 +184,15 @@ Y'\times(1-K_R-K_B) = &\ (1-K_R-K_B)\times G' + \\ &\ K_B\times 2(1-K_B)\times C'_B \\ G' = &\ Y' - {2(K_R(1-K_R)\times C'_R + K_B(1-K_B)\times C'_B)\over{1-K_R-K_B}} \end{align*} -++++++ +++++ The values chosen for _K~R~_ and _K~B~_ vary between standards. [NOTE] ==== -The required color model conversion between latexmath:[$Y'C_BC_R$] -and latexmath:[$R'G'B'$] can typically be deduced from other color +The required color model conversion between latexmath:[Y'C_BC_R] +and latexmath:[R'G'B'] can typically be deduced from other color space parameters: [options="header",cols="18%,18%,14%,18%,14%,18%"] @@ -239,17 +239,17 @@ defined in <> and using the <>: [latexmath] -++++++ +++++ \begin{align*} Y' & = 0.2126 \times R' + 0.7152 \times G' + 0.0722 \times B' \\ C'_B & = {(B' - Y')\over{1.8556}} \\ C'_R & = {(R' - Y')\over{1.5748}} \\ \end{align*} -++++++ +++++ Alternatively: [latexmath] -++++++ - $$\left(\begin{array}{c}Y' \\ +++++ +\left(\begin{array}{c}Y' \\ C'_B \\ C'_R\end{array}\right) = \left(\begin{array}{ccc}0.2126, & 0.7152, & 0.0722 \\ @@ -257,13 +257,13 @@ Alternatively: 0.5, & -{0.7152\over{1.5748}}, & -{0.0722\over{1.5748}}\end{array}\right) \left(\begin{array}{c}R'\\ G'\\ - B'\end{array}\right)$$ -++++++ + B'\end{array}\right) +++++ For the inverse conversion: [latexmath] -++++++ - $$\left(\begin{array}{c}R'\\ +++++ +\left(\begin{array}{c}R'\\ G'\\ B'\end{array}\right) = \left(\begin{array}{ccc}1, & 0, & 1.5748\\ @@ -271,8 +271,8 @@ For the inverse conversion: 1, & 1.8556, & 0\end{array}\right) \left(\begin{array}{c}Y'\\ C'_B\\ - C'_R\end{array}\right)$$ -++++++ + C'_R\end{array}\right) +++++ [[MODEL_BT601]] ==== BT.601 _Y′C~B~C~R~_ conversion @@ -285,17 +285,17 @@ defined in <> or <>: [latexmath] -++++++ +++++ \begin{align*} Y' & = 0.299 \times R' + 0.587 \times G' + 0.114 \times B' \\ C'_B & = {(B' - Y')\over{1.772}} \\ C'_R & = {(R' - Y')\over{1.402}} \\ \end{align*} -++++++ +++++ Alternatively: [latexmath] -++++++ - $$\left(\begin{array}{c}Y' \\ +++++ +\left(\begin{array}{c}Y' \\ C'_B \\ C'_R\end{array}\right) = \left(\begin{array}{ccc}0.299, & 0.587, & 0.114 \\ @@ -303,13 +303,13 @@ Alternatively: 0.5, & -{0.587\over{1.402}}, & -{0.114\over{1.402}}\end{array}\right) \left(\begin{array}{c}R'\\ G'\\ - B'\end{array}\right)$$ -++++++ + B'\end{array}\right) +++++ For the inverse conversion: [latexmath] -++++++ - $$\left(\begin{array}{c}R'\\ +++++ +\left(\begin{array}{c}R'\\ G'\\ B'\end{array}\right) = \left(\begin{array}{ccc}1, & 0, & 1.402\\ @@ -317,8 +317,8 @@ For the inverse conversion: 1, & 1.772, & 0\end{array}\right) \left(\begin{array}{c}Y'\\ C'_B\\ - C'_R\end{array}\right)$$ -++++++ + C'_R\end{array}\right) +++++ <<< [[MODEL_BT2020]] @@ -332,17 +332,17 @@ defined in <> and using the <>: [latexmath] -++++++ +++++ \begin{align*} Y' & = 0.2627 \times R' + 0.6780 \times G' + 0.0593 \times B' \\ C'_B & = {(B' - Y')\over{1.8814}} \\ C'_R & = {(R' - Y')\over{1.4746}} \\ \end{align*} -++++++ +++++ Alternatively: [latexmath] -++++++ - $$\left(\begin{array}{c}Y' \\ +++++ +\left(\begin{array}{c}Y' \\ C'_B \\ C'_R\end{array}\right) = \left(\begin{array}{ccc}0.2627, & 0.6780, & 0.0593 \\ @@ -350,13 +350,13 @@ Alternatively: 0.5, & -{0.6780\over{1.4746}}, & -{0.0593\over{1.4746}}\end{array}\right) \left(\begin{array}{c}R'\\ G'\\ - B'\end{array}\right)$$ -++++++ + B'\end{array}\right) +++++ For the inverse conversion: [latexmath] -++++++ - $$\left(\begin{array}{c}R'\\ +++++ +\left(\begin{array}{c}R'\\ G'\\ B'\end{array}\right) = \left(\begin{array}{ccc}1, & 0, & 1.4746\\ @@ -364,8 +364,8 @@ For the inverse conversion: 1, & 1.8814, & 0\end{array}\right) \left(\begin{array}{c}Y'\\ C'_B\\ - C'_R\end{array}\right)$$ -++++++ + C'_R\end{array}\right) +++++ [[MODEL_ST240]] ==== ST-240/SMPTE 240M _Y′C~B~C~R~_ conversion @@ -377,17 +377,17 @@ That is, for conversion using the <>: [latexmath] -++++++ +++++ \begin{align*} Y' & = 0.212 \times R' + 0.701 \times G' + 0.087 \times B' \\ C'_B & = {(B' - Y')\over{1.826}} \\ C'_R & = {(R' - Y')\over{1.576}} \\ \end{align*} -++++++ +++++ Alternatively: [latexmath] -++++++ - $$\left(\begin{array}{c}Y' \\ +++++ +\left(\begin{array}{c}Y' \\ C'_B \\ C'_R\end{array}\right) = \left(\begin{array}{ccc}0.212, & 0.701, & 0.087 \\ @@ -395,13 +395,13 @@ Alternatively: 0.5, & -{0.701\over{1.576}}, & -{0.087\over{1.576}}\end{array}\right) \left(\begin{array}{c}R'\\ G'\\ - B'\end{array}\right)$$ -++++++ + B'\end{array}\right) +++++ For the inverse conversion: [latexmath] -++++++ - $$\left(\begin{array}{c}R'\\ +++++ +\left(\begin{array}{c}R'\\ G'\\ B'\end{array}\right) = \left(\begin{array}{ccc}1, & 0, & 1.576\\ @@ -409,8 +409,8 @@ For the inverse conversion: 1, & 1.826, & 0\end{array}\right) \left(\begin{array}{c}Y'\\ C'_B\\ - C'_R\end{array}\right)$$ -++++++ + C'_R\end{array}\right) +++++ <<< [[MODEL_YCCBCCRC]] @@ -421,7 +421,7 @@ color representation as an alternative representation to _Y′C~B~C~R~_: [latexmath] -++++++ +++++ \begin{align*} Y'_C & = (0.2627R + 0.6780G + 0.0593B)' \\ C'_\mathit{BC} & = \begin{cases} @@ -431,25 +431,25 @@ C'_\mathit{RC} & = \begin{cases} {{R'-Y'_C}\over{1.7184}}, & -0.8592 \leq R'-Y'_C \leq 0 \\ {{R'-Y'_C}\over{0.9936}}, & 0 < R'-Y'_C \leq 0.4968\end{cases} \end{align*} -++++++ +++++ This terminology follow's BT.2020's convention of describing the -continuous values as latexmath:[$Y'_C$], latexmath:[$C'_\mathit{BC}$] and -latexmath:[$C'_\mathit{RC}$]; BT.2020 uses latexmath:[$\mathit{DY}'_C$], -latexmath:[$\mathit{DC}'_\mathit{BC}$] and -latexmath:[$\mathit{DC}'_\mathit{RC}$] to represent the +continuous values as latexmath:[Y'_C], latexmath:[C'_\mathit{BC}] and +latexmath:[C'_\mathit{RC}]; BT.2020 uses latexmath:[\mathit{DY}'_C], +latexmath:[\mathit{DC}'_\mathit{BC}] and +latexmath:[\mathit{DC}'_\mathit{RC}] to represent the quantized integer representations of the same values. -NOTE: latexmath:[$Y'_C$] is derived from applying a non-linear transfer -function to a combination of linear latexmath:[$\mathit{RGB}$] components +NOTE: latexmath:[Y'_C] is derived from applying a non-linear transfer +function to a combination of linear latexmath:[\mathit{RGB}] components and applying a non-linear transfer function to the result, but the -latexmath:[$C'_\mathit{BC}$] and latexmath:[$C'_\mathit{RC}$] color differences +latexmath:[C'_\mathit{BC}] and latexmath:[C'_\mathit{RC}] color differences still encode differences between non-linear values. The inverse transformation can be derived from the above: [latexmath] -++++++ +++++ \begin{align*} B' & = \begin{cases} Y'_C + 1.9404C'_\mathit{BC}, & C'_\mathit{BC} \leq 0 \\ @@ -459,7 +459,7 @@ R' & = \begin{cases} Y'_C + 0.9936C'_\mathit{RC}, & C'_\mathit{RC} > 0\end{cases}\\ G & = Y_C - 0.2627R - 0.0593B \end{align*} -++++++ +++++ NOTE: Performing these calculations requires conversion between a linear representation and a non-linear transfer function during @@ -474,7 +474,7 @@ color representation as an alternative representation to _Y′C~B~C~R~_: [latexmath] -++++++ +++++ \begin{align*} L & = {(1688R + 2146G + 262B)\over{4096}}\\ M & = {(683R + 2951G + 462B)\over{4096}}\\ @@ -492,7 +492,7 @@ I & = 0.5L' + 0.5M'\\ C_T & = {(6610L' - 13613M' + 7003S')\over{4096}}\\ C_P & = {(17933L' - 17390M' - 543S')\over{4096}} \end{align*} -++++++ +++++ Note that the suffix ~D~ indicates that PQ encoding is _display-referred_ and the suffix ~S~ indicates that HLG @@ -501,9 +501,11 @@ display and scene light respectively. To invert this, it can be observed that: +//@ To be checked - Jon + [latexmath] -++++++ - $$\left(\begin{array}{c}L' \\ +++++ +\left(\begin{array}{c}L' \\ M' \\ S' \end{array}\right) = 4096\times @@ -512,8 +514,8 @@ To invert this, it can be observed that: 17933, & -17390, & -543\end{array}\right)^{-1} \left(\begin{array}{c}I\\ C_T\\ - C_P\end{array}\right)$$ - $$\left(\begin{array}{c}L' \\ + C_P\end{array}\right) +\left(\begin{array}{c}L' \\ M' \\ S' \end{array}\right) = \left(\begin{array}{rrr}1, & 1112064/129174029, & 14342144/129174029 \\ @@ -521,8 +523,8 @@ To invert this, it can be observed that: 1, & 72341504/129174029, & -41416704/129174029\end{array}\right) \left(\begin{array}{c}I\\ C_T\\ - C_P\end{array}\right)$$ - $$\left(\begin{array}{c}L' \\ + C_P\end{array}\right) +\left(\begin{array}{c}L' \\ M' \\ S' \end{array}\right) \approx \left(\begin{array}{rrr}1, & 0.0086090370, & 0.1110296250 \\ @@ -530,10 +532,10 @@ To invert this, it can be observed that: 1, & 0.5600313357, & -0.3206271750\end{array}\right) \left(\begin{array}{c}I\\ C_T\\ - C_P\end{array}\right)$$ - $$\{L_D,M_D,S_D\} = \textrm{EOTF}_{\textrm{PQ}}(\{L',M',S'\})$$ - $$\{L_S,M_S,S_S\} = \textrm{OETF}_{\textrm{HLG}}^{-1}(\{L',M',S'\})$$ - $$\left(\begin{array}{c}R \\ + C_P\end{array}\right) +\{L_D,M_D,S_D\} = \textrm{EOTF}_{\textrm{PQ}}(\{L',M',S'\}) +\{L_S,M_S,S_S\} = \textrm{OETF}_{\textrm{HLG}}^{-1}(\{L',M',S'\}) +\left(\begin{array}{c}R \\ G \\ B\end{array}\right) = 4096\times @@ -542,8 +544,8 @@ To invert this, it can be observed that: 99, & 309, & 3688\end{array}\right)^{-1} \left(\begin{array}{c}L\\ M\\ - S\end{array}\right)$$ - $$\left(\begin{array}{c}R \\ + S\end{array}\right) +\left(\begin{array}{c}R \\ G \\ B \end{array}\right) = {4096\over 12801351680}\times \left(\begin{array}{rrr}10740530, & -7833490, & 218290 \\ @@ -551,8 +553,8 @@ To invert this, it can be observed that: -81102, & -309138, & 3515570\end{array}\right) \left(\begin{array}{c}L\\ M\\ - S\end{array}\right)$$ - $$\left(\begin{array}{c}R \\ + S\end{array}\right) +\left(\begin{array}{c}R \\ G \\ B \end{array}\right) \approx \left(\begin{array}{rrr}3.4366066943, & -2.5064521187, & 0.0698454243 \\ @@ -560,5 +562,5 @@ To invert this, it can be observed that: -0.0259498997, & -0.0989137147, & 1.1248636144\end{array}\right) \left(\begin{array}{c}L\\ M\\ - S\end{array}\right)$$ -++++++ + S\end{array}\right) +++++ diff --git a/chapters/compformats.adoc b/chapters/compformats.adoc new file mode 100644 index 0000000..645d97a --- /dev/null +++ b/chapters/compformats.adoc @@ -0,0 +1,18 @@ +// Copyright 2014-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 + +include::{chapters}/compintro.adoc[] + +include::{chapters}/s3tc.adoc[] + +include::{chapters}/rgtc.adoc[] + +include::{chapters}/bptc.adoc[] + +include::{chapters}/etc1.adoc[] + +include::{chapters}/etc2.adoc[] + +include::{chapters}/astc.adoc[] + +include::{chapters}/pvrtc.adoc[] diff --git a/compintro.txt b/chapters/compintro.adoc similarity index 97% rename from compintro.txt rename to chapters/compintro.adoc index 2a2ab8b..5d6e760 100644 --- a/compintro.txt +++ b/chapters/compintro.adoc @@ -1,3 +1,6 @@ +// Copyright 2014-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 + == Compressed Texture Image Formats For computer graphics, a number of texture compression schemes exist diff --git a/conversionintro.txt b/chapters/conversionintro.adoc similarity index 96% rename from conversionintro.txt rename to chapters/conversionintro.adoc index 6d89c64..774b649 100644 --- a/conversionintro.txt +++ b/chapters/conversionintro.adoc @@ -1,7 +1,8 @@ -// Copyright (c) 2019 The Khronos Group Inc. -// Copyright notice at https://www.khronos.org/registry/speccopyright.html +// Copyright 2019-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 == Introduction to color conversions + === Color space composition A ``color space'' determines the meaning of decoded numerical @@ -138,7 +139,7 @@ position in a different color space: [[conversionexample]] .Example sampling in one space and converting to a different space -image::images/colorconversion_accurate.{svgpdf}[width="{svgpdf@pdf:475pt:576}",align="center"] +image::{images}/colorconversion_accurate.svg[width="{svgpdf@pdf:475pt:576}",align="center"] In this diagram, non-linear luma _Y′_ channels are shown in black and white, color difference _C~B~_/_C~R~_ @@ -267,7 +268,7 @@ depicted in <>: [[approximateconversionexample]] .Example approximated sampling in one space and converting to a different space -image::images/colorconversion_approximate.{svgpdf}[width="{svgpdf@pdf:475pt:576}",align="center"] +image::{images}/colorconversion_approximate.svg[width="{svgpdf@pdf:475pt:576}",align="center"] A performance-optimized approximation to our example conversion may use the following steps: @@ -336,11 +337,11 @@ to be a simple <> (to using the ``<>'' OETF), since sRGB shares the BT.709 color primaries and is defined as a complementary <> intended to be combined with BT.709's OETF. -This interpretation imposes a latexmath:[$\gamma \approx$] 1.1 +This interpretation imposes a latexmath:[\gamma \approx] 1.1 OOTF. Matching the OOTF of a <>-<> system, -for which latexmath:[$\gamma \approx$] 1.2, implies using the +for which latexmath:[\gamma \approx] 1.2, implies using the <> EOTF to convert to linear light, then the <> EOTF^ -1^ to convert back to sRGB non-linear space. @@ -351,8 +352,8 @@ a linear OOTF, then the {_R′~sRGB~_, _G′~sRGB~_, _B′~sRGB~_} should be calculated as: [latexmath] -+++++ -$$\{\mathit{R}'_\mathit{sRGB},\mathit{G}'_\mathit{sRGB},\mathit{B}'_\mathit{sRGB}\} = +++++ +\{\mathit{R}'_\mathit{sRGB},\mathit{G}'_\mathit{sRGB},\mathit{B}'_\mathit{sRGB}\} = \textrm{EOTF}^{-1}_{sRGB}(\textrm{OETF}^{-1}_{\mathit{BT}.709} -(\{\mathit{R}'_{\mathit{BT}.709},\mathit{G}'_{\mathit{BT}.709},\mathit{B}'_{\mathit{BT}.709}\}))$$ -+++++ +(\{\mathit{R}'_{\mathit{BT}.709},\mathit{G}'_{\mathit{BT}.709},\mathit{B}'_{\mathit{BT}.709}\})) +++++ diff --git a/chapters/conversions.adoc b/chapters/conversions.adoc new file mode 100644 index 0000000..74895b3 --- /dev/null +++ b/chapters/conversions.adoc @@ -0,0 +1,12 @@ +// Copyright 2017-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 + +include::{chapters}/conversionintro.adoc[] + +include::{chapters}/transferfunctions.adoc[] + +include::{chapters}/primaries.adoc[] + +include::{chapters}/colormodels.adoc[] + +include::{chapters}/quantization.adoc[] diff --git a/df.txt b/chapters/df.adoc similarity index 94% rename from df.txt rename to chapters/df.adoc index 6c8d6ba..e65ba02 100644 --- a/df.txt +++ b/chapters/df.adoc @@ -1,10 +1,8 @@ -// Copyright (c) 2014-2019 The Khronos Group Inc. -// Copyright notice at https://www.khronos.org/registry/speccopyright.html -ifdef::a2xhtml[] -= Khronos Data Format Specification v1.3.1 = -endif::[] -[abstract] +// Copyright 2014-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 +[abstract] +-- This document describes a data format specification for non-opaque (user-visible) representations of user data to be used by, and shared between, Khronos standards. The intent of this specification is to @@ -16,25 +14,13 @@ allowing formats to be shared and compared. This document also acts as a reference for the memory layout of a number of common compressed texture formats, and describes conversion between a number of common color spaces. +-- -// Symbols... -:times: × -:plus: + -:check: ✓ -:alpha: α -:beta: β -:gamma: γ -:rho: ρ -:leq: ≤ -:geq: ≥ -:cdot: · -:asciidoc-numbered: +//@ ifndef::a2xhtml[] +//@ = Introduction +//@ endif::[] -ifndef::a2xhtml[] -= Introduction -endif::[] - -== Introduction == +== Introduction Many APIs operate on bulk data -- buffers, images, volumes, etc. -- each composed of many elements with a fixed and often simple representation. @@ -95,11 +81,11 @@ Later sections describe some of the common color space conversion operations and provide a description of the memory layout of a number of common texture compression formats. -ifndef::a2xhtml[] -= The Khronos Data Format Descriptor Block -endif::[] +//@ ifndef::a2xhtml[] +//@ = The Khronos Data Format Descriptor Block +//@ endif::[] -== Formats and texel access == +== Formats and texel access This document describes a standard layout for a data structure that can be used to define the representation of simple, portable, bulk data. Using such @@ -144,7 +130,7 @@ green channel in the next 6 bits, and red channel in the top 5 bits of a [[SimpleTexelBlock]] .A simple one-texel texel block -image::images/565pixels.{svgpdf}[width="{svgpdf@pdf:400pt:800}",align="center"] +image::{images}/565pixels.svg[width="{svgpdf@pdf:400pt:800}",align="center"] === 1-D texel addressing @@ -157,7 +143,8 @@ Taking the simplest case of an array in the C programming language as an example, a developer might define the following structure to represent a color texel: ------ +[source] +---- typedef struct _MyRGB { unsigned char red; unsigned char green; @@ -165,7 +152,7 @@ typedef struct _MyRGB { } MyRGB; MyRGB *myRGBarray = (MyRGB *) malloc(100 * sizeof(MyRGB)); ------ +---- To determine the location of, for example, the tenth element of ++myRGBarray++, the compiler needs to know the base address of @@ -179,22 +166,23 @@ of ++red++, ++green++ and ++blue++ due to padding; the difference in address between one ++MyRGB++ and the next can be described as the _pixel stride_ in bytes. -[[1DBytes]] +[[im-1DBytes]] .(Trivial) 1D address offsets for 1-byte elements, start of buffer -image::images/1DByteOffset.{svgpdf}[width="{svgpdf@pdf:290pt:450}",align="center"] +image::{images}/1DByteOffset.svg[width="{svgpdf@pdf:290pt:450}",align="center"] -[[1DWords]] +[[im-1DWords]] .1D address offsets for 2-byte elements, start of buffer -image::images/1DWordOffset.{svgpdf}[width="{svgpdf@pdf:290pt:450}",align="center"] +image::{images}/1DWordOffset.svg[width="{svgpdf@pdf:290pt:450}",align="center"] -[[1DRGB]] +[[im-1DRGB]] .1D address offsets for _R_,_G_,_B_ elements (padding in gray), start of buffer -image::images/1DRGBOffset.{svgpdf}[width="{svgpdf@pdf:460pt:720}",align="center"] +image::{images}/1DRGBOffset.svg[width="{svgpdf@pdf:460pt:720}",align="center"] An alternative representation is a ``structure of arrays'', distinct from the ``array of structures'' ++myRGBarray++: ------ +[source] +---- typedef struct _MyRGBSoA { unsigned char *red; unsigned char *green; @@ -205,7 +193,7 @@ MyRGBSoA myRGBSoA; myRGBSoA.red = (unsigned char *) malloc(100); myRGBSoA.green = (unsigned char *) malloc(100); myRGBSoA.blue = (unsigned char *) malloc(100); ------ +---- In this case, accessing a value requires the ++sizeof++ each channel element. @@ -235,33 +223,33 @@ In a simple 2-D representation, the row stride and the offset from the start of the storage can be described as follows: [latexmath] -++++++ +++++ \begin{align*} \textit{row stride}_\textit{pixels} &= \textit{width}_\textit{pixels} + \textit{padding}_\textit{pixels} \\ \textit{row stride}_\textit{bytes} &= \textit{width}_\textit{pixels} \times \textit{pixel stride}_\textit{bytes} + \textit{padding}_\textit{bytes} \\ \textit{offset}_\textit{pixels} &= x + (y \times \textit{rowstride}_\textit{pixels}) \\ \textit{address}_\textit{bytes} &= \textit{base} + (x \times \textit{pixel stride}_\textit{bytes}) + (y \times \textit{row stride}_\textit{bytes}) \end{align*} -++++++ +++++ -<<2DLinear>> shows example coordinate byte offsets for a 13{times}4 +<> shows example coordinate byte offsets for a 13{times}4 buffer, padding row stride to a multiple of four elements. -[[2DLinear]] +[[im-2DLinear]] .2D linear texel offsets from coordinates -image::images/2DLinearOffsets.{svgpdf}[width="{svgpdf@pdf:350pt:540}",align="center"] +image::{images}/2DLinearOffsets.svg[width="{svgpdf@pdf:350pt:540}",align="center"] -[[2DLinearMemoryOrder]] +[[im-2DLinearMemoryOrder]] .Order of byte storage in memory for coordinates in a linear 5{times}3 buffer, padded (italics) to 8{times}3 [cols="3,24*^",width="100%"] -|============================== +|==== ^| Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 ^| Coords | *0,0* | *1,0* | *2,0* | *3,0* | *4,0* | _5,0_ | _6,0_ | _7,0_ | *0,1* | *1,1* | *2,1* | *3,1* | *4,1* | _5,1_ | _6,1_ | _7,1_ | *0,2* | *1,2* | *2,2* | *3,2* | *4,2* | _5,2_ | _6,2_ | _7,2_ -|============================== +|==== -[[2DLinearRGB]] +[[im-2DLinearRGB]] .2D _R_,_G_,_B_ byte offsets (padding in gray) from coordinates for a 4{times}4 image -image::images/2DRGBOffsets.{svgpdf}[width="{svgpdf@pdf:350pt:540}",align="center"] +image::{images}/2DRGBOffsets.svg[width="{svgpdf@pdf:350pt:540}",align="center"] By convention, this ``linear'' layout is in _y_-major order (with the _x_ axis changing most quickly). @@ -276,9 +264,9 @@ _plane_ of data. In the same way that 1-D data can be described in structure-of-arrays form, two-dimensional data can also be implemented as multiple _planes_. -[[2DRGBplanes]] +[[im-2DRGBplanes]] .2D _R_,_G_,_B_ plane offsets from coordinates for 8{times}4 texels -image::images/2DRGBplanes.{svgpdf}[width="{svgpdf@pdf:250pt:400}",align="center"] +image::{images}/2DRGBplanes.svg[width="{svgpdf@pdf:250pt:400}",align="center"] In early graphics, planes often contributed individual bits to the pixel. This allowed pixels of less than a byte, reducing bandwidth and storage; @@ -336,7 +324,7 @@ were an independent, smaller image, and the order of tiles in memory may be as in the linear layout: [latexmath] -++++++ +++++ \begin{align*} \textit{If}\ a\ \%\ b &= a - \left(b\times\left\lfloor{a\over b}\right\rfloor\right), & \textit{texel offset} &= \left(x\ \%\ \textit{tw}\right) @@ -344,35 +332,38 @@ may be as in the linear layout: + \left\lfloor{x\over\textit{tw}}\right\rfloor\times\textit{th}\times\textit{tw} + \left\lfloor{y\over\textit{th}}\right\rfloor\times\textit{th}\times\textit{line stride} \end{align*} -++++++ +++++ This approach can be implemented efficiently in hardware, so long as the tile dimensions are powers of two, by interleaving some bits from the y-coordinate with the bits contributed by the x-coordinate. If ++twb++ = log~2~(_tw_) and ++thb++ = log~2~(_th_): ------ +[source] +---- pixelOffset = (x & ((1 << twb) - 1)) | ((y & ((1 << thb) - 1)) << twb) | ((x & ~((1 << twb) - 1)) << thb) | ((y & ~((1 << thb)-1)) * lineStride); ------ +---- For example, if a linear 16{times}12 image calculates a pixel offset relative to the start of the buffer as: ------ +[source] +---- pixelOffset = x | (y * 16); ------ +---- a 16{times}12 image comprised of 4{times}4 tiles may calculate the pixel offset relative to the start of the buffer as: ------ +[source] +---- pixelOffset = (x & 3) | ((y & 3) << 2) | ((x & ~3) << 2) | ((y & ~3) * 16); ------ +---- -[[2DTile4x4]] +[[im-2DTile4x4]] .4×4 tiled order texel offsets from coordinates (consecutive values linked in red to show the pattern) -image::images/2DTile4x4.{svgpdf}[width="{svgpdf@pdf:350pt:575}",align="center"] +image::{images}/2DTile4x4.svg[width="{svgpdf@pdf:350pt:575}",align="center"] Textures which have dimensions that are not a multiple of the tile size require padding. @@ -380,7 +371,7 @@ size require padding. <<< For so long as the size of a tile fits into an on-chip cache and can be filled efficiently by the memory subsystem, this approach has the -benefit that only one in latexmath:[$1\over n$] transitions between +benefit that only one in latexmath:[1\over n] transitions between vertically-adjacent lines requires accessing outside a tile of height _n_. The larger the tile, the greater the probability that vertically-adjacent @@ -395,11 +386,12 @@ some hardware implementations actually use a more complex layout in order to provide further locality of reference. One such scheme is Morton order: -[[2DMorton]] +[[im-2DMorton]] .Morton order texel offsets from coordinates (consecutive values linked in red) -image::images/2DMortonOffsets.{svgpdf}[width="{svgpdf@pdf:350pt:575}",align="center"] +image::{images}/2DMortonOffsets.svg[width="{svgpdf@pdf:350pt:575}",align="center"] ------ +[source] +---- uint32_t mortonOffset(uint32_t x, uint32_t y, uint32_t width, uint32_t height) { @@ -424,7 +416,7 @@ uint32_t mortonOffset(uint32_t x, uint32_t y, offset |= ((x | y) >> shift) << (shift * 2); return offset; } ------ +---- Note that this particular implementation assumes that the smaller of ++width++ and ++height++ is a power of two, and the larger is @@ -436,11 +428,12 @@ more efficient than this C code would imply. Another approach, with even more correlation between locality in _x_,_y_ space and memory offset, is Hilbert curve order: -[[2DHilbert]] +[[im-2DHilbert]] .Hilbert curve order texel offsets from coordinates (consecutive values linked in red) -image::images/2DHilbertOffsets.{svgpdf}[width="{svgpdf@pdf:350pt:575}",align="center"] +image::{images}/2DHilbertOffsets.svg[width="{svgpdf@pdf:350pt:575}",align="center"] ------ +[source] +---- uint32_t h(uint32_t size, uint32_t x, uint32_t y) { const uint32_t z = x ^ y; uint32_t offset = 0; @@ -469,7 +462,7 @@ uint32_t hilbertOffset(uint32_t x, uint32_t y, uint32_t width, uint32_t height) if (width < height) return (width * width) * (y / width) + h(width, y % width, x); else return (height * height) * (x / height) + h(height, x % height, y); } ------ +---- This code assumes that the smaller of ++width++ and ++height++ is a power of two, with the larger a multiple of the smaller. @@ -502,11 +495,11 @@ data in separate planes. In a linear layout, 3-dimensional textures can be accessed as: [latexmath] -++++++ +++++ \begin{align*} \textit{address}_\textit{bytes} &= \textit{base} + (x \times \textit{pixel stride}_\textit{bytes}) + (y \times \textit{row stride}_\textit{bytes}) + (z \times \textit{plane stride}_\textit{bytes}) \end{align*} -++++++ +++++ Here, the _plane stride_ is the offset between the start of one contiguous 2-D plane of data and the next. @@ -516,7 +509,8 @@ any additional padding. Again, non-linear approaches can be used to increase the correlation between storage address and coordinates. ------ +[source] +---- uint32_t tileOffset3D(uint32_t x, uint32_t y, uint32_t z, uint32_t twb, uint32_t thb, uint32_t tdb, uint32_t lineStride, uint32_t planeStride) { @@ -530,9 +524,10 @@ uint32_t tileOffset3D(uint32_t x, uint32_t y, uint32_t z, ((y & ~((1 << thb) - 1)) << tdb) * lineStride | ((z & ~((1 << tdb) - 1)) * planeStride); } ------ +---- ------ +[source] +---- uint32_t mortonOffset3D(uint32_t x, uint32_t y, uint32_t z, uint32_t width, uint32_t height, uint32_t depth) { const uint32_t max = width | height | depth; @@ -545,11 +540,12 @@ uint32_t mortonOffset3D(uint32_t x, uint32_t y, uint32_t z, } return offset; } ------ +---- There are multiple 3D variations on the Hilbert curve; one such is this: ------ +[source] +---- uint32_t hilbertOffset3D(uint32_t x, uint32_t y, uint32_t z, uint32_t size) { // "Harmonious" 3D Hilbert curve for cube of power-of-two edge "size": // http://herman.haverkort.net/recursive_tilings_and_space-filling_curves @@ -570,7 +566,7 @@ uint32_t hilbertOffset3D(uint32_t x, uint32_t y, uint32_t z, uint32_t size) { } return offset; } ------ +---- <<< === Downsampled channels @@ -593,17 +589,17 @@ space and bandwidth. In one common representation known colloquially as _YUV_ 4:2:2, each horizontal pair of _Y′_ values has a single _C~B~_ and _C~R~_ value shared for the pair. -For example, <<1DYCBCR_Y>> shows a 6-element 1-D buffer with one -_Y′_ value for each element, but as shown in <<1DYCBCR_CBCR>> +For example, <> shows a 6-element 1-D buffer with one +_Y′_ value for each element, but as shown in <> the _C~B~_ and _C~R~_ values are shared across pairs of elements. -[[1DYCBCR_Y]] +[[im-1DYCBCR_Y]] .1-D _Y′C~B~C~R~_ 4:2:2 buffer, texels associated with _Y′_ values -image::images/1DYCbCr_Y.{svgpdf}[width="{svgpdf@pdf:320pt:520}",align="center"] +image::{images}/1DYCbCr_Y.svg[width="{svgpdf@pdf:320pt:520}",align="center"] -[[1DYCBCR_CBCR]] +[[im-1DYCBCR_CBCR]] .1-D _Y′C~B~C~R~_ 4:2:2 buffer, texels associated with _C~B~_ and _C~R~_ values -image::images/1DYCbCr_CbCr.{svgpdf}[width="{svgpdf@pdf:320pt:520}",align="center"] +image::{images}/1DYCbCr_CbCr.svg[width="{svgpdf@pdf:320pt:520}",align="center"] In this case, we can say that the 2{times}1 coordinate region forms a _texel block_ which contains two _Y′_ values, one _C~B~_ value @@ -634,8 +630,8 @@ Our _Y′_ samples should fall naturally on our native coordinates. However, the _C~B~_ and _C~R~_ sample locations (which are typically at the same location as each other) could be considered as located coincident with one or other of the _Y′_ values as shown in -<<1DYCbCr_cosited>>, or could be defined as falling at the mid-point -between them as in <<1DYCbCr_midpoint>>. +<>, or could be defined as falling at the mid-point +between them as in <>. Different representations have chosen either of these alternatives -- in some cases, choosing a different option for each coordinate axis. The application can choose how to treat these sample locations: in @@ -643,13 +639,13 @@ some cases it may suffice to duplicate _C~B~_ and _C~R~_ across the pair of _Y′_ values, in others bilinear or bicubic filtering may be more appropriate. -[[1DYCbCr_cosited]] +[[im-1DYCbCr_cosited]] .1-D _Y′C~B~C~R~_ 4:2:2 buffer, _C~B~_ and _C~R~_ cosited with even _Y′_ values -image::images/1DYCbCr_cosited.{svgpdf}[width="{svgpdf@pdf:220pt:340}",align="center"] +image::{images}/1DYCbCr_cosited.svg[width="{svgpdf@pdf:220pt:340}",align="center"] -[[1DYCbCr_midpoint]] +[[im-1DYCbCr_midpoint]] .1-D _Y′C~B~C~R~_ 4:2:2 buffer, _C~B~_ and _C~R~_ midpoint between _Y′_ values -image::images/1DYCbCr_midpoint.{svgpdf}[width="{svgpdf@pdf:220pt:340}",align="center"] +image::{images}/1DYCbCr_midpoint.svg[width="{svgpdf@pdf:220pt:340}",align="center"] Traditional APIs have described the _C~B~_ and _C~R~_ as having 2{times}1 _downsampling_ in this format (there are half as many samples available @@ -666,14 +662,14 @@ streams. Because there are twice as many rows of _Y′_ data as there are _C~B~_ and _C~R~_ data, it is convenient to record the channels as -separate planes as shown in <<2DYCbCr420_traditional>> (with 2{times}2 +separate planes as shown in <> (with 2{times}2 texel blocks outlined in red); in addition, image compression schemes often work with the channels independently, which is amenable to planar storage. -[[2DYCbCr420_traditional]] +[[im-2DYCbCr420_traditional]] .2-D _Y′C~B~C~R~_ 4:2:0 planes, downsampled _C~B~_ and _C~R~_ at midpoint between _Y′_ values -image::images/2DYCbCr420_traditional.{svgpdf}[width="{svgpdf@pdf:310pt:480}",align="center"] +image::{images}/2DYCbCr420_traditional.svg[width="{svgpdf@pdf:310pt:480}",align="center"] In this case, the _C~B~_ and _C~R~_ planes are half the width and half the height of the _Y′_ plane, and also have half the line stride. @@ -681,13 +677,13 @@ Therefore if we store one byte per channel, the offsets for each plane in a linear representation can be calculated as: [latexmath] -++++++ +++++ \begin{align*} \textit{Y}'_\textit{address} &= \textit{Y}'_\textit{base} + x + (y \times \textit{row stride}_\textit{bytes}) \\ \textit{C}_\textit{B address} &= \textit{C}_\textit{B base} + \left\lfloor{x\over 2}\right\rfloor + \left(\left\lfloor{y\over 2}\right\rfloor\times {{\textit{row stride}_\textit{bytes}}\over 2}\right) \\ \textit{C}_\textit{R address} &= \textit{C}_\textit{R base} + \left\lfloor{x\over 2}\right\rfloor + \left(\left\lfloor{y\over 2}\right\rfloor\times {{\textit{row stride}_\textit{bytes}}\over 2}\right) \end{align*} -++++++ +++++ <<< A description based on downsampling factors is sufficient in the case of @@ -700,7 +696,7 @@ block, and two green values offset diagonally, as in <>. [[BayerOffsets]] .An 18{times}12 _^RG^_/_~GB~_ Bayer filter pattern (repeating pattern outlined in yellow) -image::images/Bayer18x12.{svgpdf}[width="{svgpdf@pdf:400pt:640}",align="center"] +image::{images}/Bayer18x12.svg[width="{svgpdf@pdf:400pt:640}",align="center"] A Bayer pattern can then be used to sample an image, as shown in <>, and this sampled version can later be used to @@ -714,13 +710,13 @@ this specification. [[SimpleBayerBlock]] .A Bayer-sampled image with a repeating 2{times}2 _^RG^_/_~GB~_ texel block (outlined in yellow) -image::images/Bayer.{svgpdf}[width="{svgpdf@pdf:95pt:170}",align="center"] +image::{images}/Bayer.svg[width="{svgpdf@pdf:95pt:170}",align="center"] In the Bayer representation, the red and blue channels can be considered to be downsampled by a factor of two in each dimension. The two green channels per 2{times}2 repeating block mean that the ``downsampling factor'' for the green channel is effectively -latexmath:[$\sqrt{2}$] in each direction. +latexmath:[\sqrt{2}] in each direction. <<< More complex layouts are not uncommon. @@ -728,12 +724,12 @@ For example, the X-Trans sample arrangement developed by Fujifilm for their digital camera range, shown in <>, consists of 6{times}6 texel blocks, with each sample, as in Bayer, corresponding to a single channel. In X-Trans, each block contains eight red, eight blue and twenty green -samples; red and blue are ``downsampled'' by latexmath:[$\sqrt{3\over 2}$] -and green is ``downsampled'' by latexmath:[$3\over\sqrt{5}$]. +samples; red and blue are ``downsampled'' by latexmath:[\sqrt{3\over 2}] +and green is ``downsampled'' by latexmath:[3\over\sqrt{5}]. [[XTrans]] .An 18{times}12 X-Trans image (repeating 6{times}6 pattern outlined in yellow) -image::images/X-Trans18x12.{svgpdf}[width="{svgpdf@pdf:400pt:640}",align="center"] +image::{images}/X-Trans18x12.svg[width="{svgpdf@pdf:400pt:640}",align="center"] Allowing for possible alternative orientations of the samples (such as whether the Bayer pattern starts with a row containing red or blue @@ -763,7 +759,7 @@ descriptor blocks. [[DescriptorAndDescriptorBlocks]] .Data format descriptor and descriptor blocks [width="75%",cols="1a"] -|============= +|==== ^|_Data format descriptor_ [width="100%",cols="1"] !============= @@ -771,7 +767,7 @@ descriptor blocks. ! _ Descriptor block 2_ !  : !============= -|============= +|==== The diversity of possible data makes a concise description that can support every possible format impractical. @@ -856,8 +852,8 @@ treated as a separate ``plane''. In linear layout, this can be represented by offsetting rows of _Y′_ data with odd _y_ coordinates by the row stride of the original _Y′_ plane; each new _Y′_ plane's stride is then -double that of the original _Y′_ plane, as in <<2DYCbCr420_KDFS>> -(c.f. <<2DYCbCr420_traditional>>). +double that of the original _Y′_ plane, as in <> +(c.f. <>). If the planes of a 6{times}4 _Y′C~B~C~R~_ 4:2:0 texture are stored consecutively in memory with no padding, which might be described in a traditional API as <>, the representation used by @@ -866,23 +862,23 @@ this specification would be that shown in <>. [[yuv420conventional]] .Plane descriptors of a 6{times}4 _Y′C~B~C~R~_-format buffer in a conventional API [cols="2,2,3,3",width="70%",options="header"] -|============================== +|==== ^| Plane ^| Byte offset ^| Byte stride ^| Downsample factor ^| _Y′_ ^| 0 ^| 6 ^| 1{times}1 ^| _C~B~_ ^| 24 ^| 3 ^| 2{times}2 ^| _C~R~_ ^| 30 ^| 3 ^| 2{times}2 -|============================== +|==== [[yuv420thisapi]] .Plane descriptors of a 6{times}4 _Y′C~B~C~R~_-format buffer using this standard [cols="4",width="60%",options="header"] -|============================== +|==== ^| Plane ^| Byte offset ^| Byte stride ^| Bytes per plane ^|_Y′_ plane 1 ^| 0 ^| 12 ^| 2 ^|_Y′_ plane 2 ^| 6 ^| 12 ^| 2 ^|_C~B~_ ^| 24 ^| 3 ^| 1 ^|_C~R~_ ^| 30 ^| 3 ^| 1 -|============================== +|==== NOTE: There is no expectation that an API must actually use this representation in accessing the data: it is simple for an API with @@ -926,9 +922,9 @@ This interpretation is not mandated to allow other reasons for encoding four-dimensional texels, although it is consistent with the fourth dimension representing ``time''. -[[2DYCbCr420_KDFS]] +[[im-2DYCbCr420_KDFS]] .2-D _Y′C~B~C~R~_ 4:2:0 planes, with separate even and odd _Y′_ planes -image::images/2DYCbCr420_KDFS.{svgpdf}[width="{svgpdf@pdf:310pt:480}",align="center"] +image::{images}/2DYCbCr420_KDFS.svg[width="{svgpdf@pdf:310pt:480}",align="center"] <<< === Bit pattern interpretation and _samples_ @@ -957,7 +953,7 @@ coordinate offset will always be 0,0,0,0. The descriptor block for a _Y′C~B~C~R~_ 4:2:0 layout is shown in <>. -<<2DYCbCr420Encoding>> shows this representation graphically: +<> shows this representation graphically: the three disjoint regions for each channels and the texel block covering them are shown on the left, represented in this specification as four planes of contiguous bytes. @@ -966,9 +962,9 @@ in top-to-bottom order); these _samples_ then describe the contributions from these logical bits, with geometric location of the sample at the right. -[[2DYCbCr420Encoding]] +[[im-2DYCbCr420Encoding]] ._Y′C~B~C~R~_ 4:2:0 described in six samples -image::images/2DYCbCrKDFSEncoding.{svgpdf}[width="{svgpdf@pdf:475pt:800}",align="center"] +image::{images}/2DYCbCrKDFSEncoding.svg[width="{svgpdf@pdf:475pt:800}",align="center"] <<< Consecutive samples with the same channel, location and flags may describe @@ -998,7 +994,7 @@ The descriptor block for this format is shown in [[RGB565BEEncoding]] ._RGB_ 565 big-endian encoding -image::images/RGB565BEKDFSEncoding.{svgpdf}[width="{svgpdf@pdf:490pt:850}",align="center"] +image::{images}/RGB565BEKDFSEncoding.svg[width="{svgpdf@pdf:490pt:850}",align="center"] In <>, bit 0 of the logical bit stream corresponds to bit 3 of the virtual sample that describes the green channel; therefore @@ -1021,7 +1017,7 @@ The precision to which sample coordinates are specified depends on the size of the texel block: coordinates in a 256{times}256 texel block can be specified only to integer-coordinate granularity, but offsets within a texel block that is only a single coordinate wide -are specified to the precision of latexmath:[$1\over 256$] of a +are specified to the precision of latexmath:[1\over 256] of a coordinate; this approach allows large texel blocks, half-texel offsets for representations such as _Y′C~B~C~R~_ 4:2:0, and precise fractional offsets for recording multisampled pattern locations. @@ -1176,7 +1172,8 @@ Additional information is required to access the image data: For example, if texels are laid out in memory in linear order: ------ +[source] +---- int numPlanes; char *planeBaseAddresses[8]; unsigned int strides[8][4]; @@ -1205,7 +1202,7 @@ decodeTexelGivenCoords(uint32_t *descriptor, float coords[4]) { // decodes the concatenated data according to the descriptor processTexel(descriptor, addresses, coords); } ------ +---- The ++processTexel++ function would typically operate on the coordinates having taken the remainder of dividing them by the texel block size. @@ -1345,7 +1342,8 @@ same channel at multiple locations. A _Y′C~B~C~R~_ buffer with downsampled chroma may have more luma samples than chroma, each at different locations. -== [[dataformatdescriptor]]Khronos Data Format Descriptor == +[[dataformatdescriptor]] +== Khronos Data Format Descriptor The data format descriptor consists of a contiguous area of memory, as shown in <>, divided into one or more @@ -1356,11 +1354,11 @@ The size of the data format descriptor varies according to its content. [[DataFormatDescriptorOverview]] .Data Format Descriptor layout [width="60%",cols="1,2"] -|===================================== +|==== >| *++uint32_t++*   ^|   *_totalSize_* >| _Descriptor block_   ^|   _First descriptor_ >| _Descriptor block_   ^|   _Second descriptor (optional) etc._ -|===================================== +|==== The *_totalSize_* field, measured in bytes, allows the full format descriptor to be copied without need for details of the descriptor to be interpreted. @@ -1404,20 +1402,21 @@ to provide their own means of identifying a data format descriptor if one is embedded in a multi-purpose byte stream. <<< -=== [[descriptorblock]]Descriptor block +[[descriptorblock]] +=== Descriptor block Each _descriptor block_ has the same prefix, shown in <>. [[DescriptorPrefix]] .Descriptor Block layout [cols="1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",width="97%"] -|==================== +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 15+^| *_descriptorType_* 17+^| *_vendorId_* 16+^| *_descriptorBlockSize_* 16+^| *_versionNumber_* 32+^| _Format-specific data_ -|==================== +|==== The *_vendorId_* is a 17-bit value uniquely assigned to organizations. If the organization has a 16-bit identifier assigned by the PCI SIG, @@ -1481,7 +1480,7 @@ format descriptor. [[DataFormatDescriptorHeaderExample]] .Data format descriptor header and descriptor block headers for two descriptor blocks [cols="1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",width="97%"] -|==================== +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize_* @@ -1493,9 +1492,10 @@ format descriptor. 15+^| *_descriptorType_* 17+^| *_vendorId_* 16+^| *_descriptorBlockSize_* 16+^| *_versionNumber_* 32+^| _Descriptor body_ -|==================== +|==== -== [[basicdescriptor]]Khronos Basic Data Format Descriptor Block == +[[basicdescriptor]] +== Khronos Basic Data Format Descriptor Block A _basic descriptor block_ (<>) is designed to encode common metadata associated with bulk data -- especially image or @@ -1518,7 +1518,7 @@ four _Y′_ samples and one sample each of _C~B~_ and _C~R~_. [[BasicDescriptorBlock]] .Basic Data Format Descriptor layout [cols="1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",width="97%"] -|==================== +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 15+^| *_descriptorType_* = 0 17+^| *_vendorId_* = 0 @@ -1529,7 +1529,7 @@ four _Y′_ samples and one sample each of _C~B~_ and _C~R~_. 8+^| *_bytesPlane7_* 8+^| *_bytesPlane6_* 8+^| *_bytesPlane5_* 8+^| *_bytesPlane4_* 32+^| _Sample information for the first sample_ 32+^| _Sample information for the second sample (optional), etc._ -|==================== +|==== The Basic Data Format Descriptor Block should be the first descriptor block in any data format descriptor of which it is a component. @@ -1544,12 +1544,12 @@ block fields: .Field location information for field *_xxx_* [cols="7,10,2"] -|================== +|==== ^| Word offset into basic descriptor block ^| *++KHR_DF_WORD_xxx++* ^| ... ^| Word offset into descriptor ^| *++KHR_DF_WORD_xxx++* {plus} 1 ^| ... ^| Start bit within word ^| *++KHR_DF_SHIFT_xxx++* ^| ... ^| Bit mask of value ^| *++KHR_DF_MASK_xxx++* ^| ... -|================== +|==== If the basic descriptor block is treated as a *++uint32_t++* array ++bdb[]++, field *_xxx_* can be accessed as follows: @@ -1563,24 +1563,24 @@ For example, *++KHR_DFDVAL++*(++bdb++, *++MODEL++*) returns the value: *++KHR_DF_MASK_MODEL++* & (++bdb++[*++KHR_DF_WORD_MODEL++*] >> *++KHR_DF_SHIFT_MODEL++*) <<< -=== *_vendorId_* === +=== *_vendorId_* The *_vendorId_* for the Basic Data Format Descriptor Block is 0, defined as *++KHR_DF_VENDORID_KHRONOS++* in the enum *++khr_df_vendorid_e++*. .Field location information for *_vendorId_* [cols="7,10,3"] -|================== +|==== ^| Word offset into basic descriptor block ^| *++KHR_DF_WORD_VENDORID++* ^| 0 ^| Word offset into descriptor ^| *++KHR_DF_WORD_VENDORID++* {plus} 1 ^| 1 ^| Start bit within word ^| *++KHR_DF_SHIFT_VENDORID++* ^| 0 ^| Bit mask of value ^| *++KHR_DF_MASK_VENDORID++* ^| 0x1FFFFU -|================== +|==== *++khr_df_vendorid_e++* *_vendorId_* = *++KHR_DF_MASK_VENDORID++* & + (++bdb++[*++KHR_DF_WORD_VENDORID++*] >> *++KHR_DF_SHIFT_VENDORID++*); -=== *_descriptorType_* === +=== *_descriptorType_* The *_descriptorType_* for the Basic Data Format Descriptor Block is 0, a value reserved in the enum of Khronos-specific descriptor types, @@ -1588,18 +1588,18 @@ a value reserved in the enum of Khronos-specific descriptor types, .Field location information for *_descriptorType_* [cols="7,10,3"] -|================== +|==== ^| Word offset into basic descriptor block ^| *++KHR_DF_WORD_DESCRIPTORTYPE++* ^| 0 ^| Word offset into descriptor ^| *++KHR_DF_WORD_DESCRIPTORTYPE++* {plus} 1 ^| 1 ^| Start bit within word ^| *++KHR_DF_SHIFT_DESCRIPTORTYPE++* ^| 17 ^| Bit mask of value ^| *++KHR_DF_MASK_DESCRIPTORTYPE++* ^| 0x7FFFU -|================== +|==== *++khr_df_descriptortype_e++* *_descriptorType_* = *++KHR_DF_MASK_DESCRIPTORTYPE++* & + (++bdb++[*++KHR_DF_WORD_DESCRIPTORTYPE++*] >> *++KHR_DF_SHIFT_DESCRIPTORTYPE++*); <<< -=== *_versionNumber_* === +=== *_versionNumber_* The *_versionNumber_* relating to the Basic Data Format Descriptor Block as described in this specification is 2. @@ -1613,17 +1613,17 @@ in later minor updates. .Field location information for *_versionNumber_* [cols="7,10,3"] -|================== +|==== ^| Word offset into basic descriptor block ^| *++KHR_DF_WORD_VERSIONNUMBER++* ^| 1 ^| Word offset into descriptor ^| *++KHR_DF_WORD_VERSIONNUMBER++* {plus} 1 ^| 2 ^| Start bit within word ^| *++KHR_DF_SHIFT_VERSIONNUMBER++* ^| 0 ^| Bit mask of value ^| *++KHR_DF_MASK_VERSIONNUMBER++* ^| 0xFFFFU -|================== +|==== *++uint32_t++* *_versionNumber_* = *++KHR_DF_MASK_VERSIONNUMBER++* & + (++bdb++[*++KHR_DF_WORD_VERSIONNUMBER++*] >> *++KHR_DF_SHIFT_VERSIONNUMBER++*); -=== *_descriptorBlockSize_* === +=== *_descriptorBlockSize_* The memory size of the Basic Data Format Descriptor Block depends on the number of samples contained within it. The memory requirements for this format @@ -1632,19 +1632,19 @@ is measured in bytes. .Field location information for *_descriptorBlockSize_* [cols="7,10,3"] -|================== +|==== ^| Word offset into basic descriptor block ^| *++KHR_DF_WORD_DESCRIPTORBLOCKSIZE++* ^| 1 ^| Word offset into descriptor ^| *++KHR_DF_WORD_DESCRIPTORBLOCKSIZE++* {plus} 1 ^| 2 ^| Start bit within word ^| *++KHR_DF_SHIFT_DESCRIPTORBLOCKSIZE++* ^| 16 ^| Bit mask of value ^| *++KHR_DF_MASK_DESCRIPTORBLOCKSIZE++* ^| 0xFFFFU -|================== +|==== *++uint32_t++* *_descriptorBlockSize_* = *++KHR_DF_MASK_DESCRIPTORBLOCKSIZE++* & + (++bdb++[*++KHR_DF_WORD_DESCRIPTORBLOCKSIZE++*] >> *++KHR_DF_SHIFT_DESCRIPTORBLOCKSIZE++*); <<< [[COLORMODEL]] -=== *_colorModel_* === +=== *_colorModel_* The *_colorModel_* determines the set of color (or other data) channels which may be encoded within the data, though there is no requirement that all @@ -1659,12 +1659,12 @@ and are represented as an unsigned 8-bit value. .Field location information for *_colorModel_* [cols="7,10,2"] -|================== +|==== ^| Word offset into basic descriptor block ^| *++KHR_DF_WORD_MODEL++* ^| 2 ^| Word offset into descriptor ^| *++KHR_DF_WORD_MODEL++* {plus} 1 ^| 3 ^| Start bit within word ^| *++KHR_DF_SHIFT_MODEL++* ^| 0 ^| Bit mask of value ^| *++KHR_DF_MASK_MODEL++* ^| 0xFF -|================== +|==== *++khr_df_model_e++* *_colorModel_* = *++KHR_DF_MASK_MODEL++* & + (++bdb++[*++KHR_DF_WORD_MODEL++*] >> *++KHR_DF_SHIFT_MODEL++*); @@ -1683,7 +1683,7 @@ obligated to represent alpha in any way in channel number 15. The value of each enumerant is shown in parentheses following the enumerant name. -==== *++KHR_DF_MODEL_UNSPECIFIED++* (= 0) ==== +==== *++KHR_DF_MODEL_UNSPECIFIED++* (= 0) When the data format is unknown or does not fall into a predefined category, utilities which perform automatic conversion based on an @@ -1708,7 +1708,7 @@ model, with an extension block describing the interpretation of each channel. <<< -==== *++KHR_DF_MODEL_RGBSDA++* (= 1) ==== +==== *++KHR_DF_MODEL_RGBSDA++* (= 1) This color model represents additive colors of three channels, nominally red, green and blue, supplemented by channels for @@ -1721,7 +1721,7 @@ data makes sense. [[RGBSDAChannels]] .Basic Data Format _RGBSDA_ channels [width="100%",options="header"] -|================================ +|==== ^| Channel number 2+|   Name |   Description ^| 0 2+|   *++KHR_DF_CHANNEL_RGBSDA_RED++* |   Red ^| 1 2+|   *++KHR_DF_CHANNEL_RGBSDA_GREEN++* |   Green @@ -1729,14 +1729,14 @@ data makes sense. ^| 13 2+|   *++KHR_DF_CHANNEL_RGBSDA_STENCIL++* |   Stencil ^| 14 2+|   *++KHR_DF_CHANNEL_RGBSDA_DEPTH++* |   Depth ^| 15 2+|   *++KHR_DF_CHANNEL_RGBSDA_ALPHA++* |   Alpha (opacity) -|================================ +|==== Portable representation of additive colors with more than three primaries requires an extension to describe the full color space of the channels present. There is no practical way to do this portably without taking significantly more space. -==== *++KHR_DF_MODEL_YUVSDA++* (= 2) ==== +==== *++KHR_DF_MODEL_YUVSDA++* (= 2) This color model represents color differences with three channels, nominally luma (_Y′_) and two color-difference chroma channels, @@ -1756,7 +1756,7 @@ a reason to do otherwise. [[YUVSDAChannels]] .Basic Data Format _YUVSDA_ channels [width="100%",options="header"] -|================================ +|==== ^| Channel number 2+|   Name |   Description ^| 0 2+|   *++KHR_DF_CHANNEL_YUVSDA_Y++* |   _Y_/_Y′_ (luma/luminance) ^| 1 2+|   *++KHR_DF_CHANNEL_YUVSDA_CB++* |   _C~B~_ (alias for _U_) @@ -1766,7 +1766,7 @@ a reason to do otherwise. ^| 13 2+|   *++KHR_DF_CHANNEL_YUVSDA_STENCIL++* |   Stencil ^| 14 2+|   *++KHR_DF_CHANNEL_YUVSDA_DEPTH++* |   Depth ^| 15 2+|   *++KHR_DF_CHANNEL_YUVSDA_ALPHA++* |   Alpha (opacity) -|================================ +|==== NOTE: Terminology for this color model is often abused. This model is based on the idea of creating a representation of monochrome light intensity as a @@ -1778,7 +1778,7 @@ derived, _Y′C~B~C~R~_ is more formally used to describe the representation of these color differences. See <> for more detail. <<< -==== *++KHR_DF_MODEL_YIQSDA++* (= 3) ==== +==== *++KHR_DF_MODEL_YIQSDA++* (= 3) This color model represents color differences with three channels, nominally luma (_Y_) and two color-difference chroma channels, _I_ and _Q_, @@ -1790,7 +1790,7 @@ _I_ and _Q_ are derived from _C~B~_ and _C~R~_ by a 33-degree rotation. [[YIQSDAChannels]] .Basic Data Format _YIQSDA_ channels [width="100%",options="header"] -|================================ +|==== ^| Channel number 2+|   Name |   Description ^| 0 2+|   *++KHR_DF_CHANNEL_YIQSDA_Y++* |   _Y_ (luma) ^| 1 2+|   *++KHR_DF_CHANNEL_YIQSDA_I++* |   _I_ (in-phase) @@ -1798,9 +1798,9 @@ _I_ and _Q_ are derived from _C~B~_ and _C~R~_ by a 33-degree rotation. ^| 13 2+|   *++KHR_DF_CHANNEL_YIQSDA_STENCIL++* |   Stencil ^| 14 2+|   *++KHR_DF_CHANNEL_YIQSDA_DEPTH++* |   Depth ^| 15 2+|   *++KHR_DF_CHANNEL_YIQSDA_ALPHA++* |   Alpha (opacity) -|================================ +|==== -==== *++KHR_DF_MODEL_LABSDA++* (= 4) ==== +==== *++KHR_DF_MODEL_LABSDA++* (= 4) This color model represents the ICC perceptually-uniform _L*a*b*_ color space, combined with the option of an alpha channel, as @@ -1809,7 +1809,7 @@ shown in <>. [[LABSDAChannels]] .Basic Data Format _LABSDA_ channels [width="100%",options="header"] -|================================ +|==== ^| Channel number 2+|   Name |   Description ^| 0 2+|   *++KHR_DF_CHANNEL_LABSDA_L++* |   _L_* (luma) ^| 1 2+|   *++KHR_DF_CHANNEL_LABSDA_A++* |   _a_* @@ -1817,9 +1817,9 @@ shown in <>. ^| 13 2+|   *++KHR_DF_CHANNEL_LABSDA_STENCIL++* |   Stencil ^| 14 2+|   *++KHR_DF_CHANNEL_LABSDA_DEPTH++* |   Depth ^| 15 2+|   *++KHR_DF_CHANNEL_LABSDA_ALPHA++* |   Alpha (opacity) -|================================ +|==== -==== *++KHR_DF_MODEL_CMYKA++* (= 5) ==== +==== *++KHR_DF_MODEL_CMYKA++* (= 5) This color model represents secondary (subtractive) colors and the combined key (black) channel, along with alpha, as shown in @@ -1828,17 +1828,17 @@ the combined key (black) channel, along with alpha, as shown in [[CMYKAChannels]] .Basic Data Format _CMYKA_ channels [width="100%",options="header"] -|================================ +|==== ^| Channel number 2+|   Name |   Description ^| 0 2+|   *++KHR_DF_CHANNEL_CMYKA_CYAN++* |   Cyan ^| 1 2+|   *++KHR_DF_CHANNEL_CMYKA_MAGENTA++* |   Magenta ^| 2 2+|   *++KHR_DF_CHANNEL_CMYKA_YELLOW++* |   Yellow ^| 3 2+|   *++KHR_DF_CHANNEL_CMYKA_KEY++* |   Key/Black ^| 15 2+|   *++KHR_DF_CHANNEL_CMYKA_ALPHA++* |   Alpha (opacity) -|================================ +|==== <<< -==== *++KHR_DF_MODEL_XYZW++* (= 6) ==== +==== *++KHR_DF_MODEL_XYZW++* (= 6) This ``color model'' represents channel data used for coordinate values, as shown in <> -- @@ -1851,15 +1851,15 @@ of the *_channelType_* field. [[XYZWChannels]] .Basic Data Format _XYZW_ channels [width="100%",options="header"] -|================================ +|==== ^| Channel number 2+|   Name |   Description ^| 0 2+|   *++KHR_DF_CHANNEL_XYZW_X++* |   _X_ ^| 1 2+|   *++KHR_DF_CHANNEL_XYZW_Y++* |   _Y_ ^| 2 2+|   *++KHR_DF_CHANNEL_XYZW_Z++* |   _Z_ ^| 3 2+|   *++KHR_DF_CHANNEL_XYZW_W++* |   _W_ -|================================ +|==== -==== *++KHR_DF_MODEL_HSVA_ANG++* (= 7) ==== +==== *++KHR_DF_MODEL_HSVA_ANG++* (= 7) This color model represents color differences with three channels, _value_ (luminance or luma), _saturation_ (distance from monochrome) @@ -1871,15 +1871,15 @@ wheel. [[HSVAAngChannels]] .Basic Data Format angular _HSVA_ channels [width="100%",options="header"] -|================================ +|==== ^| Channel number 2+|   Name |   Description ^| 0 2+|   *++KHR_DF_CHANNEL_HSVA_ANG_VALUE++* |   _V_ (value) ^| 1 2+|   *++KHR_DF_CHANNEL_HSVA_ANG_SATURATION++* |   _S_ (saturation) ^| 2 2+|   *++KHR_DF_CHANNEL_HSVA_ANG_HUE++* |   _H_ (hue) ^| 15 2+|   *++KHR_DF_CHANNEL_HSVA_ANG_ALPHA++* |   Alpha (opacity) -|================================ +|==== -==== *++KHR_DF_MODEL_HSLA_ANG++* (= 8) ==== +==== *++KHR_DF_MODEL_HSLA_ANG++* (= 8) This color model represents color differences with three channels, _lightness_ (maximum intensity), _saturation_ (distance from monochrome) @@ -1891,16 +1891,16 @@ wheel. [[HSLAAngChannels]] .Basic Data Format angular _HSLA_ channels [width="100%",options="header"] -|================================ +|==== ^| Channel number 2+|   Name |   Description ^| 0 2+|   *++KHR_DF_CHANNEL_HSLA_ANG_LIGHTNESS++* |   _L_ (lightness) ^| 1 2+|   *++KHR_DF_CHANNEL_HSLA_ANG_SATURATION++* |   _S_ (saturation) ^| 2 2+|   *++KHR_DF_CHANNEL_HSLA_ANG_HUE++* |   _H_ (hue) ^| 15 2+|   *++KHR_DF_CHANNEL_HSLA_ANG_ALPHA++* |   Alpha (opacity) -|================================ +|==== <<< -==== *++KHR_DF_MODEL_HSVA_HEX++* (= 9) ==== +==== *++KHR_DF_MODEL_HSVA_HEX++* (= 9) This color model represents color differences with three channels, _value_ (luminance or luma), _saturation_ (distance from monochrome) @@ -1912,15 +1912,15 @@ extremes on a color hexagon. [[HSVAHexChannels]] .Basic Data Format hexagonal _HSVA_ channels [width="100%",options="header"] -|================================ +|==== ^| Channel number 2+|   Name |   Description ^| 0 2+|   *++KHR_DF_CHANNEL_HSVA_HEX_VALUE++* |   _V_ (value) ^| 1 2+|   *++KHR_DF_CHANNEL_HSVA_HEX_SATURATION++* |   _S_ (saturation) ^| 2 2+|   *++KHR_DF_CHANNEL_HSVA_HEX_HUE++* |   _H_ (hue) ^| 15 2+|   *++KHR_DF_CHANNEL_HSVA_HEX_ALPHA++* |   Alpha (opacity) -|================================ +|==== -==== *++KHR_DF_MODEL_HSLA_HEX++* (= 10) ==== +==== *++KHR_DF_MODEL_HSLA_HEX++* (= 10) This color model represents color differences with three channels, _lightness_ (maximum intensity), _saturation_ (distance from monochrome) @@ -1932,15 +1932,15 @@ extremes on a color hexagon. [[HSLAHexChannels]] .Basic Data Format hexagonal _HSLA_ channels [width="100%",options="header"] -|================================ +|==== ^| Channel number 2+|   Name |   Description ^| 0 2+|   *++KHR_DF_CHANNEL_HSLA_HEX_LIGHTNESS++* |   _L_ (lightness) ^| 1 2+|   *++KHR_DF_CHANNEL_HSLA_HEX_SATURATION++* |   _S_ (saturation) ^| 2 2+|   *++KHR_DF_CHANNEL_HSLA_HEX_HUE++* |   _H_ (hue) ^| 15 2+|   *++KHR_DF_CHANNEL_HSLA_HEX_ALPHA++* |   Alpha (opacity) -|================================ +|==== -==== *++KHR_DF_MODEL_YCGCOA++* (= 11) ==== +==== *++KHR_DF_MODEL_YCGCOA++* (= 11) This color model represents low-cost approximate color differences with three channels, nominally luma (_Y_) and two color-difference chroma channels, @@ -1950,35 +1950,35 @@ supplemented by a channel for alpha, as shown in <>. [[YCoCgAChannels]] .Basic Data Format _YCoCgA_ channels [width="100%",options="header"] -|================================ +|==== ^| Channel number 2+|   Name |   Description ^| 0 2+|   *++KHR_DF_CHANNEL_YCGCOA_Y++* |   _Y_ ^| 1 2+|   *++KHR_DF_CHANNEL_YCGCOA_CG++* |   _Cg_ ^| 2 2+|   *++KHR_DF_CHANNEL_YCGCOA_CO++* |   _Co_ ^| 15 2+|   *++KHR_DF_CHANNEL_YCGCOA_ALPHA++* |   Alpha (opacity) -|================================ +|==== <<< -==== *++KHR_DF_MODEL_YCCBCCRC++* (= 12) ==== +==== *++KHR_DF_MODEL_YCCBCCRC++* (= 12) This color model represents the ``Constant luminance'' -latexmath:[$Y'_CC'_\mathit{BC}C'_\mathit{RC}$] color model defined as an +latexmath:[Y'_CC'_\mathit{BC}C'_\mathit{RC}] color model defined as an optional representation in ITU-T BT.2020 and described in <>. [[YCBCCRCChannels]] .Basic Data Format _Y′~C~C′~BC~C′~RC~_ channels [width="100%",options="header"] -|================================ +|==== ^| Channel number 2+|   Name |   Description -^| 0 2+|   *++KHR_DF_CHANNEL_YCCBCCRC_YC++* |   latexmath:[$Y'_C$] (luminance) -^| 1 2+|   *++KHR_DF_CHANNEL_YCCBCCRC_CBC++* |   latexmath:[$C'_\mathit{BC}$] -^| 2 2+|   *++KHR_DF_CHANNEL_YCCBCCRC_CRC++* |   latexmath:[$C'_\mathit{RC}$] +^| 0 2+|   *++KHR_DF_CHANNEL_YCCBCCRC_YC++* |   latexmath:[Y'_C] (luminance) +^| 1 2+|   *++KHR_DF_CHANNEL_YCCBCCRC_CBC++* |   latexmath:[C'_\mathit{BC}] +^| 2 2+|   *++KHR_DF_CHANNEL_YCCBCCRC_CRC++* |   latexmath:[C'_\mathit{RC}] ^| 13 2+|   *++KHR_DF_CHANNEL_YCCBCCRC_STENCIL++* |   Stencil ^| 14 2+|   *++KHR_DF_CHANNEL_YCCBCCRC_DEPTH++* |   Depth ^| 15 2+|   *++KHR_DF_CHANNEL_YCCBCCRC_ALPHA++* |   Alpha (opacity) -|================================ +|==== -==== *++KHR_DF_MODEL_ICTCP++* (= 13) ==== +==== *++KHR_DF_MODEL_ICTCP++* (= 13) This color model represents the ``Constant intensity _IC~T~C~P~_ color model'' defined as an optional @@ -1987,7 +1987,7 @@ representation in ITU-T BT.2100 and described in <>. [[ICTCPChannels]] .Basic Data Format _IC~T~C~P~_ channels [width="100%",options="header"] -|================================ +|==== ^| Channel number 2+|   Name |   Description ^| 0 2+|   *++KHR_DF_CHANNEL_ICTCP_I++* |   _I_ (intensity) ^| 1 2+|   *++KHR_DF_CHANNEL_ICTCP_CT++* |   _C~T~_ @@ -1995,10 +1995,10 @@ representation in ITU-T BT.2100 and described in <>. ^| 13 2+|   *++KHR_DF_CHANNEL_ICTCP_STENCIL++* |   Stencil ^| 14 2+|   *++KHR_DF_CHANNEL_ICTCP_DEPTH++* |   Depth ^| 15 2+|   *++KHR_DF_CHANNEL_ICTCP_ALPHA++* |   Alpha (opacity) -|================================ +|==== <<< -==== *++KHR_DF_MODEL_CIEXYZ++* (= 14) ==== +==== *++KHR_DF_MODEL_CIEXYZ++* (= 14) This color model represents channel data used to describe color coordinates in the <> coordinate @@ -2007,14 +2007,14 @@ space, as shown in <>. [[CIEXYZChannels]] .Basic Data Format CIE _XYZ_ channels [width="100%",options="header"] -|================================ +|==== ^| Channel number 2+|   Name |   Description ^| 0 2+|   *++KHR_DF_CHANNEL_CIEXYZ_X++* |   _X_ ^| 1 2+|   *++KHR_DF_CHANNEL_CIEXYZ_Y++* |   _Y_ ^| 2 2+|   *++KHR_DF_CHANNEL_CIEXYZ_Z++* |   _Z_ -|================================ +|==== -==== *++KHR_DF_MODEL_CIEXYY++* (= 15) ==== +==== *++KHR_DF_MODEL_CIEXYY++* (= 15) This color model represents channel data used to describe chromaticity coordinates in the <> coordinate @@ -2023,16 +2023,16 @@ space, as shown in <>. [[CIEXYYChannels]] .Basic Data Format CIE _xyY_ channels [width="100%",options="header"] -|================================ +|==== ^| Channel number 2+|   Name |   Description ^| 0 2+|   *++KHR_DF_CHANNEL_CIEXYZ_X++* |   _x_ ^| 1 2+|   *++KHR_DF_CHANNEL_CIEXYZ_YCHROMA++* |   _y_ ^| 2 2+|   *++KHR_DF_CHANNEL_CIEXYZ_YLUMA++* |   _Y_ -|================================ +|==== <<< [[CompressedFormatModels]] -=== *_colorModel_* for compressed formats === +=== *_colorModel_* for compressed formats A number of compressed formats are supported as part of *++khr_df_model_e++*. In general, these formats will have the texel block dimensions of the @@ -2068,7 +2068,7 @@ Example descriptors for compressed formats are provided after each model in this section. <<< -==== *++KHR_DF_MODEL_DXT1A++*/*++KHR_DF_MODEL_BC1A++* (= 128) ==== +==== *++KHR_DF_MODEL_DXT1A++*/*++KHR_DF_MODEL_BC1A++* (= 128) This model represents the DXT1 or BC1 format, described in <>. @@ -2088,7 +2088,7 @@ Enumerant names for these channel ids are listed in <>. [[bc1_channels]] .BC1A channel names [options="header"] -|==================== +|==== ^| Enumerant ^| Value ^| *++KHR_DF_CHANNEL_DXT1A_COLOR++* 1.2+^.^| 0 ^| *++KHR_DF_CHANNEL_BC1A_COLOR++* @@ -2096,13 +2096,13 @@ Enumerant names for these channel ids are listed in <>. ^| *++KHR_DF_CHANNEL_DXT1A_ALPHA++* ^| *++KHR_DF_CHANNEL_BC1A_ALPHAPRESENT++* ^| *++KHR_DF_CHANNEL_BC1A_ALPHA++* -|==================== +|==== <<< [[dxt1a_example_noalpha]] .Example DXT1A descriptor with no punch-through alpha [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -2119,12 +2119,12 @@ Enumerant names for these channel ids are listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== [[dxt1a_example_alpha]] .Example DXT1A descriptor with punch-through alpha [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -2141,10 +2141,10 @@ Enumerant names for these channel ids are listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== <<< -==== *++KHR_DF_MODEL_DXT2++*/*++3++*/*++KHR_DF_MODEL_BC2++* (= 129) ==== +==== *++KHR_DF_MODEL_DXT2++*/*++3++*/*++KHR_DF_MODEL_BC2++* (= 129) This model represents the DXT2/3 format, also known as BC2, and described in <>. @@ -2161,7 +2161,7 @@ Enumerant names for these channel ids are listed in <>. [[bc2_channels]] .BC2 channel names [options="header"] -|==================== +|==== ^| Enumerant ^| Value ^| *++KHR_DF_CHANNEL_DXT2_COLOR++* 1.3+^.^| 0 ^| *++KHR_DF_CHANNEL_DXT3_COLOR++* @@ -2169,7 +2169,7 @@ Enumerant names for these channel ids are listed in <>. ^| *++KHR_DF_CHANNEL_DXT2_ALPHA++* 1.3+^.^| 15 ^| *++KHR_DF_CHANNEL_DXT3_ALPHA++* ^| *++KHR_DF_CHANNEL_BC2_ALPHA++* -|==================== +|==== The alpha channel is 64 bits and at offset 0; the color channel is 64 bits and at offset 64. @@ -2179,7 +2179,7 @@ requires the whole texel block. .Example DXT2 descriptor (premultiplied alpha) [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 60 @@ -2202,12 +2202,12 @@ requires the whole texel block. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== <<< .Example DXT3 descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 60 @@ -2230,10 +2230,10 @@ requires the whole texel block. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== <<< -==== *++KHR_DF_MODEL_DXT4++*/*++5++*/*++KHR_DF_MODEL_BC3++* (= 130) ==== +==== *++KHR_DF_MODEL_DXT4++*/*++5++*/*++KHR_DF_MODEL_BC3++* (= 130) This model represents the DXT4/5 format, also known as BC3, and described in <>. @@ -2250,7 +2250,7 @@ Enumerant names for these channel ids are listed in <>. [[bc3_channels]] .BC3 channel names [options="header"] -|==================== +|==== ^| Enumerant ^| Value ^| *++KHR_DF_CHANNEL_DXT4_COLOR++* 1.3+^.^| 0 ^| *++KHR_DF_CHANNEL_DXT5_COLOR++* @@ -2258,7 +2258,7 @@ Enumerant names for these channel ids are listed in <>. ^| *++KHR_DF_CHANNEL_DXT4_ALPHA++* 1.3+^.^| 15 ^| *++KHR_DF_CHANNEL_DXT5_ALPHA++* ^| *++KHR_DF_CHANNEL_BC3_ALPHA++* -|==================== +|==== The alpha channel is 64 bits and at offset 0; the color channel is 64 bits and at offset 64. @@ -2268,7 +2268,7 @@ requires the whole texel block. .Example DXT4 descriptor (premultiplied alpha) [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 60 @@ -2291,12 +2291,12 @@ requires the whole texel block. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== <<< .Example DXT5 descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 60 @@ -2319,10 +2319,10 @@ requires the whole texel block. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== <<< -==== *++KHR_DF_MODEL_BC4++* (= 131) ==== +==== *++KHR_DF_MODEL_BC4++* (= 131) This model represents the Direct3D BC4 format for single-channel interpolated 8-bit data, as described in <>. @@ -2336,14 +2336,14 @@ The enumerant name for this channel id is listed in <>. [[bc4_channel]] .BC4 channel name [options="header"] -|==================== +|==== ^| Enumerant ^| Value ^| *++KHR_DF_CHANNEL_BC4_DATA++* ^| 0 -|==================== +|==== .Example BC4 unsigned descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -2360,11 +2360,11 @@ The enumerant name for this channel id is listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== .Example BC4 signed descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -2381,10 +2381,10 @@ The enumerant name for this channel id is listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* *++INT32_MIN++* 32+^| *_sampleUpper:_* *++INT32_MAX++* -|================================ +|==== <<< -==== *++KHR_DF_MODEL_BC5++* (= 132) ==== +==== *++KHR_DF_MODEL_BC5++* (= 132) This model represents the Direct3D BC5 format for dual-channel interpolated 8-bit data, as described in <>. @@ -2401,17 +2401,17 @@ Enumerant names for these channel ids are listed in <>. [[bc5_channels]] .BC5 channel names [options="header"] -|==================== +|==== ^| Enumerant ^| Value ^| *++KHR_DF_CHANNEL_BC5_RED++* 1.2+^.^| 0 ^| *++KHR_DF_CHANNEL_BC5_R++* ^| *++KHR_DF_CHANNEL_BC5_GREEN++* 1.2+^.^| 1 ^| *++KHR_DF_CHANNEL_BC5_G++* -|==================== +|==== .Example BC5 unsigned descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 60 @@ -2434,12 +2434,12 @@ Enumerant names for these channel ids are listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== <<< .Example BC5 signed descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 60 @@ -2462,7 +2462,7 @@ Enumerant names for these channel ids are listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* *++INT32_MIN++* 32+^| *_sampleUpper:_* *++INT32_MAX++* -|================================ +|==== <<< A legacy variant of this format known as ``ATI2n'' or ``3Dc'' swaps @@ -2470,7 +2470,7 @@ the location of the two channels, and can be encoded as follows: .Example ATI2n unsigned descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 60 @@ -2493,10 +2493,10 @@ the location of the two channels, and can be encoded as follows: 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== <<< -==== *++KHR_DF_MODEL_BC6H++* (= 133) ==== +==== *++KHR_DF_MODEL_BC6H++* (= 133) This model represents the Direct3D BC6H format for _RGB_ floating-point data, as described in <>. @@ -2511,16 +2511,16 @@ The enumerant names for this channel id are listed in <>. [[bc6h_channel]] .BC6H channel names [options="header"] -|==================== +|==== ^| Enumerant ^| Value ^| *++KHR_DF_CHANNEL_BC6H_COLOR++* 1.2+^.^| 0 ^| *++KHR_DF_CHANNEL_BC6H_DATA++* -|==================== +|==== [[example_bc6h]] .Example BC6H signed descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -2537,13 +2537,13 @@ The enumerant names for this channel id are listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0xBF800000U -- -1.0f 32+^| *_sampleUpper:_* 0x7F800000U -- 1.0f -|================================ +|==== <<< [[example_bc6hu]] .Example BC6H unsigned descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -2560,10 +2560,10 @@ The enumerant names for this channel id are listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0xBF800000U -- -1.0f 32+^| *_sampleUpper:_* 0x7F800000U -- 1.0f -|================================ +|==== <<< -==== *++KHR_DF_MODEL_BC7++* (= 134) ==== +==== *++KHR_DF_MODEL_BC7++* (= 134) This model represents the Direct3D BC7 format for _RGBA_ data, as described in <>. @@ -2578,16 +2578,16 @@ The enumerant names for this channel id are listed in <>. [[bc7_channel]] .BC7 channel names [options="header"] -|==================== +|==== ^| Enumerant ^| Value ^| *++KHR_DF_CHANNEL_BC7_COLOR++* 1.2+^.^| 0 ^| *++KHR_DF_CHANNEL_BC7_DATA++* -|==================== +|==== [[example_bc7]] .Example BC7 descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -2604,10 +2604,10 @@ The enumerant names for this channel id are listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== <<< -==== *++KHR_DF_MODEL_ETC1++* (= 160) ==== +==== *++KHR_DF_MODEL_ETC1++* (= 160) This model represents the original Ericsson Texture Compression format, described in <>, with a guarantee that the format does not rely @@ -2623,16 +2623,16 @@ The enumerant names for this channel id are listed in <>. [[etc1_channel]] .ETC1 channel names [options="header"] -|==================== +|==== ^| Enumerant ^| Value ^| *++KHR_DF_CHANNEL_ETC1_COLOR++* 1.2+^.^| 0 ^| *++KHR_DF_CHANNEL_ETC1_DATA++* -|==================== +|==== [[example_etc1]] .Example ETC1 descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -2649,10 +2649,10 @@ The enumerant names for this channel id are listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== <<< -==== *++KHR_DF_MODEL_ETC2++* (= 161) ==== +==== *++KHR_DF_MODEL_ETC2++* (= 161) This model represents the updated Ericsson Texture Compression format, ETC2, and also the related R11 EAC and RG11 EAC formats. @@ -2663,7 +2663,7 @@ The enumerant names for these channel ids are listed in <>. [[etc2_channels]] .ETC2 channel names [options="header"] -|==================== +|==== ^| Enumerant ^| Value ^| *++KHR_DF_CHANNEL_ETC2_RED++* 1.2+^.^| 0 ^| *++KHR_DF_CHANNEL_ETC2_R++* @@ -2672,7 +2672,7 @@ The enumerant names for these channel ids are listed in <>. ^| *++KHR_DF_CHANNEL_ETC2_COLOR++* ^| 2 ^| *++KHR_DF_CHANNEL_ETC2_ALPHA++* 1.2+^.^| 15 ^| *++KHR_DF_CHANNEL_ETC2_A++* -|==================== +|==== Channel ID 0 represents red, and is used for the R11 EAC format, as described in <>; the texel block size in this format @@ -2681,7 +2681,7 @@ is 8 bytes, represented as a single 64-bit sample. [[example_r11]] .Example R11 unsigned descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -2698,11 +2698,11 @@ is 8 bytes, represented as a single 64-bit sample. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== .Example R11 signed descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -2719,7 +2719,7 @@ is 8 bytes, represented as a single 64-bit sample. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* *++INT32_MIN++* 32+^| *_sampleUpper:_* *++INT32_MAX++* -|================================ +|==== <<< Channel ID 1 represents green; the presence of samples for both red @@ -2729,7 +2729,7 @@ and green, in that order, indicates the RG11 EAC format as described in [[example_rg11]] .Example RG11 unsigned descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 60 @@ -2752,11 +2752,11 @@ and green, in that order, indicates the RG11 EAC format as described in 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== .Example RG11 signed descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 60 @@ -2779,7 +2779,7 @@ and green, in that order, indicates the RG11 EAC format as described in 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* *++INT32_MIN++* 32+^| *_sampleUpper:_* *++INT32_MAX++* -|================================ +|==== <<< Channel ID 2 represents _RGB_ combined content, for the ETC2 format as described in @@ -2789,7 +2789,7 @@ A single sample of ID 2 indicates RGB2 with no alpha, occupying 8 bytes. [[example_etc2]] .Example ETC2 descriptor (with no alpha) [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -2806,7 +2806,7 @@ A single sample of ID 2 indicates RGB2 with no alpha, occupying 8 bytes. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== <<< Channel ID 15 indicates the presence of alpha. @@ -2817,7 +2817,7 @@ co-sited, ``punch through'' alpha is supported as described in [[example_etc2_punchthrough]] .Example ETC2 descriptor with punchthrough alpha [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 60 @@ -2840,7 +2840,7 @@ co-sited, ``punch through'' alpha is supported as described in 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== <<< Finally, if the texel block size is 16 bytes and the alpha channel appears in the @@ -2850,7 +2850,7 @@ alpha is supported, as described in <>. [[example_etc2_alpha]] .Example ETC2 descriptor with separate alpha [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 60 @@ -2873,10 +2873,10 @@ alpha is supported, as described in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== <<< -==== *++KHR_DF_MODEL_ASTC++* (= 162) ==== +==== *++KHR_DF_MODEL_ASTC++* (= 162) This model represents Adaptive Scalable Texture Compression as a single channel in a texel block of 16 bytes. ASTC HDR (high dynamic range) and @@ -2899,17 +2899,17 @@ The enumerant name for this channel id is listed in <>. [[astc_channels]] .ASTC channel name [options="header"] -|==================== +|==== ^| Enumerant ^| Value ^| *++KHR_DF_CHANNEL_ASTC_DATA++* ^| 0 -|==================== +|==== <<< [[example_astc_ldr]] .Example 4{times}4 ASTC LDR descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -2926,12 +2926,12 @@ The enumerant name for this channel id is listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== [[example_astc_hdr]] .Example 8{times}5 ASTC HDR descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -2948,10 +2948,10 @@ The enumerant name for this channel id is listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0xBF800000U -- -1.0f 32+^| *_sampleUpper:_* 0x7F800000U -- 1.0f -|================================ +|==== <<< -==== *++KHR_DF_MODEL_ETC1S++* (= 163) ==== +==== *++KHR_DF_MODEL_ETC1S++* (= 163) This model represents a subset of the original Ericsson Texture Compression format, described in <>, which is restricted @@ -2967,16 +2967,16 @@ The enumerant names for this channel id are listed in <>. [[etc1s_channel]] .ETC1S channel names [options="header"] -|==================== +|==== ^| Enumerant ^| Value ^| *++KHR_DF_CHANNEL_ETC1S_COLOR++* 1.2+^.^| 0 ^| *++KHR_DF_CHANNEL_ETC1S_DATA++* -|==================== +|==== [[example_etc1s]] .Example ETC1S descriptor [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -2993,10 +2993,10 @@ The enumerant names for this channel id are listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== <<< -==== *++KHR_DF_MODEL_PVRTC++* (= 164) ==== +==== *++KHR_DF_MODEL_PVRTC++* (= 164) This model represents the first generation of PowerVR Texture Compression as a single channel in a texel block of 8 bytes. 4-bit-per-pixel mode @@ -3010,17 +3010,17 @@ The enumerant names for this channel id are listed in <>. [[pvrtc_channel]] .PVRTC channel names [options="header"] -|==================== +|==== ^| Enumerant ^| Value ^| *++KHR_DF_CHANNEL_PVRTC_COLOR++* 1.2+^.^| 0 ^| *++KHR_DF_CHANNEL_PVRTC_DATA++* -|==================== +|==== <<< [[example_pvrtc4bpp]] .Example PVRTC 4bpp descriptor [options="header"] -|================================ +|==== 32+^| ~++uint32_t++ bit~ ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -3037,12 +3037,12 @@ The enumerant names for this channel id are listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== [[example_pvrtc2bpp]] .Example PVRTC 2bpp descriptor [options="header"] -|================================ +|==== 32+^| ~++uint32_t++ bit~ ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -3059,10 +3059,10 @@ The enumerant names for this channel id are listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== <<< -==== *++KHR_DF_MODEL_PVRTC2++* (= 165) ==== +==== *++KHR_DF_MODEL_PVRTC2++* (= 165) This model represents the second generation of PowerVR Texture Compression as a single channel in a texel block of 8 bytes. 4-bit-per-pixel mode @@ -3076,17 +3076,17 @@ The enumerant names for this channel id are listed in <>. [[pvrtc2_channel]] .PVRTC2 channel names [options="header"] -|==================== +|==== ^| Enumerant ^| Value ^| *++KHR_DF_CHANNEL_PVRTC2_COLOR++* 1.2+^.^| 0 ^| *++KHR_DF_CHANNEL_PVRTC2_DATA++* -|==================== +|==== <<< [[example_pvrtc24bpp]] .Example PVRTC2 4bpp descriptor [options="header"] -|================================ +|==== 32+^| ~++uint32_t++ bit~ ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -3103,12 +3103,12 @@ The enumerant names for this channel id are listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== [[example_pvrtc22bpp]] .Example PVRTC2 2bpp descriptor [options="header"] -|================================ +|==== 32+^| ~++uint32_t++ bit~ ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -3125,10 +3125,10 @@ The enumerant names for this channel id are listed in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* *++UINT32_MAX++* -|================================ +|==== <<< -=== *_colorPrimaries_* === +=== *_colorPrimaries_* It is not sufficient to define a buffer as containing, for example, additive primaries. Additional information is required to define @@ -3142,17 +3142,17 @@ More information about color primaries is provided in <>. .Field location information for *_colorPrimaries_* [cols="7,10,2"] -|================== +|==== ^| Word offset into basic descriptor block ^| *++KHR_DF_WORD_PRIMARIES++* ^| 2 ^| Word offset into descriptor ^| *++KHR_DF_WORD_PRIMARIES++* {plus} 1 ^| 3 ^| Start bit within word ^| *++KHR_DF_SHIFT_PRIMARIES++* ^| 8 ^| Bit mask of value ^| *++KHR_DF_MASK_PRIMARIES++* ^| 0xFF -|================== +|==== *++khr_df_primaries_e++* *_colorPrimaries_* = *++KHR_DF_MASK_PRIMARIES++* & + (++bdb++[*++KHR_DF_WORD_PRIMARIES++*] >> *++KHR_DF_SHIFT_PRIMARIES++*); -==== *++KHR_DF_PRIMARIES_UNSPECIFIED++* (= 0) ==== +==== *++KHR_DF_PRIMARIES_UNSPECIFIED++* (= 0) This ``set of primaries'' identifies a data representation whose color representation is unknown or which does not fit into this list of @@ -3165,7 +3165,7 @@ indicate that samples represent ``red'', ``green'' and ``blue'', but should mark the primaries here as ``unspecified'' and provide a detailed description in an extension block. -==== *++KHR_DF_PRIMARIES_BT709++* (= 1) ==== +==== *++KHR_DF_PRIMARIES_BT709++* (= 1) This value represents the Color Primaries defined by the <> and described in <>, @@ -3184,7 +3184,7 @@ a sensible default set of color primaries for common rendering operations. *++KHR_DF_PRIMARIES_SRGB++* is provided as a synonym for *++KHR_DF_PRIMARIES_BT709++*. -==== *++KHR_DF_PRIMARIES_BT601_EBU++* (= 2) ==== +==== *++KHR_DF_PRIMARIES_BT601_EBU++* (= 2) This value represents the Color Primaries defined in the <> for standard-definition television, @@ -3192,7 +3192,7 @@ particularly for 625-line signals, and described in <>. Conversion to and from BT.601 _Y′C~B~C~R~_ (_YUV_) typically uses the color conversion matrix defined in the BT.601 specification and described in <>. -==== *++KHR_DF_PRIMARIES_BT601_SMPTE++* (= 3) ==== +==== *++KHR_DF_PRIMARIES_BT601_SMPTE++* (= 3) This value represents the Color Primaries defined in the <> for standard-definition television, @@ -3200,7 +3200,7 @@ particularly for 525-line signals, and described in <>. Conversion to and from BT.601 _Y′C~B~C~R~_ (_YUV_) typically uses the color conversion matrix defined in the BT.601 specification and described in <>. -==== *++KHR_DF_PRIMARIES_BT2020++* (= 4) ==== +==== *++KHR_DF_PRIMARIES_BT2020++* (= 4) This value represents the Color Primaries defined in the <> for ultra-high-definition television @@ -3208,47 +3208,47 @@ and described in <>. Conversion to and from BT.2020 _Y′C (_YUV_ uses the color conversion matrix defined in the BT.2020 specification and described in <>. -==== *++KHR_DF_PRIMARIES_CIEXYZ++* (= 5) ==== +==== *++KHR_DF_PRIMARIES_CIEXYZ++* (= 5) This value represents the theoretical Color Primaries defined by the International Color Consortium for the <> linear color space. -==== *++KHR_DF_PRIMARIES_ACES++* (= 6) ==== +==== *++KHR_DF_PRIMARIES_ACES++* (= 6) This value represents the Color Primaries defined for the <> and described in <>. -==== *++KHR_DF_PRIMARIES_ACESCC++* (= 7) ==== +==== *++KHR_DF_PRIMARIES_ACESCC++* (= 7) This value represents the Color Primaries defined for the <> compositor and described in <>. -==== *++KHR_DF_PRIMARIES_NTSC1953++* (= 8) ==== +==== *++KHR_DF_PRIMARIES_NTSC1953++* (= 8) This value represents the Color Primaries defined for the NTSC 1953 color television transmission standard and described in <>. -==== *++KHR_DF_PRIMARIES_PAL525++* (= 9) ==== +==== *++KHR_DF_PRIMARIES_PAL525++* (= 9) This value represents the Color Primaries defined for 525-line PAL signals, described in <>. -==== *++KHR_DF_PRIMARIES_DISPLAYP3++* (= 10) ==== +==== *++KHR_DF_PRIMARIES_DISPLAYP3++* (= 10) This value represents the Color Primaries defined for the Display P3 color space, described in <>. -==== *++KHR_DF_PRIMARIES_ADOBERGB++* (= 11) ==== +==== *++KHR_DF_PRIMARIES_ADOBERGB++* (= 11) This value represents the Color Primaries defined in <>, described in <>. <<< -=== *_transferFunction_* === +=== *_transferFunction_* Many color representations contain a non-linear _transfer function_ which maps between a linear (intensity-based) representation and @@ -3284,12 +3284,12 @@ intermediate values to which the transfer function should apply. .Field location information for *_transferFunction_* [cols="4,5,2"] -|================== +|==== ^| Word offset into basic descriptor block ^| *++KHR_DF_WORD_TRANSFER++* ^| 2 ^| Word offset into descriptor ^| *++KHR_DF_WORD_TRANSFER++* {plus} 1 ^| 3 ^| Start bit within word ^| *++KHR_DF_SHIFT_TRANSFER++* ^| 16 ^| Bit mask of value ^| *++KHR_DF_MASK_TRANSFER++* ^| 0xFF -|================== +|==== *++khr_df_transfer_e++* *_transferFunction_* = *++KHR_DF_MASK_TRANSFER++* & + (++bdb++[*++KHR_DF_WORD_TRANSFER++*] >> *++KHR_DF_SHIFT_TRANSFER++*); @@ -3297,14 +3297,14 @@ intermediate values to which the transfer function should apply. The enumerant value for each of the following transfer functions is shown in parentheses alongside the title. -==== *++KHR_DF_TRANSFER_UNSPECIFIED++* (= 0) ==== +==== *++KHR_DF_TRANSFER_UNSPECIFIED++* (= 0) This value should be used when the transfer function is unknown, or specified only in an extension block, precluding conversion of color spaces and correct filtering of the data values using only the information in the basic descriptor block. -==== *++KHR_DF_TRANSFER_LINEAR++* (= 1) ==== +==== *++KHR_DF_TRANSFER_LINEAR++* (= 1) This value represents a linear transfer function: for color data, there is a linear relationship between numerical pixel values and @@ -3312,22 +3312,22 @@ the intensity of additive colors. This transfer function allows for blending and filtering operations to be applied directly to the data values. -==== *++KHR_DF_TRANSFER_SRGB++* (= 2) ==== +==== *++KHR_DF_TRANSFER_SRGB++* (= 2) This value represents the non-linear transfer function defined in the <> for mapping between numerical pixel values and displayed light intensity, as described in <>. [width="60%",cols="^8,^2,^3"] -|========== +|==== | Mapping from linear intensity to encoding | EOTF^ -1^ | <> | Mapping from encoding to linear intensity | EOTF | <> -|========== +|==== Encoded values outside the range 0..1 use the extended formulae for EOTF and EOTF^-1^ described in <>. -==== *++KHR_DF_TRANSFER_ITU++* (= 3) ==== +==== *++KHR_DF_TRANSFER_ITU++* (= 3) This value represents the non-linear transfer function defined by the ITU and used in the BT.601, BT.709 and BT.2020 specifications @@ -3335,12 +3335,12 @@ for mapping between represented scene light intensity and numerical pixel values, as described in <>. [width="60%",cols="^8,^2,^3"] -|========== +|==== | Mapping from linear intensity to encoding | OETF | <> | Mapping from encoding to linear intensity | OETF^ -1^ | <> -|========== +|==== -==== *++KHR_DF_TRANSFER_NTSC++* (= 4) ==== +==== *++KHR_DF_TRANSFER_NTSC++* (= 4) This value represents the non-linear transfer function defined by the original NTSC television broadcast specification for mapping @@ -3348,15 +3348,15 @@ between represented scene light intensity or display light intensity and numerical pixel values, as described in <>. [width="60%",cols="^8,^4"] -|========== +|==== | Mapping from linear intensity to encoding | EOTF^ -1^ / OETF | Mapping from encoding to linear intensity | EOTF / OETF^ -1^ -|========== +|==== NOTE: More recent formulations of this transfer functions, such as that defined in SMPTE 170M-2004, use the ``ITU'' formulation described above. -==== *++KHR_DF_TRANSFER_SLOG++* (= 5) ==== +==== *++KHR_DF_TRANSFER_SLOG++* (= 5) This value represents a nonlinear Transfer Function between linear scene light intensity and nonlinear pixel values, used by some @@ -3364,12 +3364,12 @@ Sony video cameras to represent an increased dynamic range, and is described in <>. [width="60%",cols="^8,^2"] -|========== +|==== | Mapping from linear intensity to encoding | OETF | Mapping from encoding to linear intensity | OETF^ -1^ -|========== +|==== -==== *++KHR_DF_TRANSFER_SLOG2++* (= 6) ==== +==== *++KHR_DF_TRANSFER_SLOG2++* (= 6) This value represents a nonlinear Transfer Function between linear scene light intensity and nonlinear pixel values, used by some @@ -3377,25 +3377,25 @@ Sony video cameras to represent a further increased dynamic range, and is described in <>. [width="60%",cols="^8,^2"] -|========== +|==== | Mapping from linear intensity to encoding | OETF | Mapping from encoding to linear intensity | OETF^ -1^ -|========== +|==== -==== *++KHR_DF_TRANSFER_BT1886++* (= 7) ==== +==== *++KHR_DF_TRANSFER_BT1886++* (= 7) -This value represents the nonlinear latexmath:[$\gamma = 2.4$] +This value represents the nonlinear latexmath:[\gamma = 2.4] EOTF between encoded pixel values and linear image intensity defined in <> and described in <>. [width="70%",cols="^8,^2,^5"] -|========== -| Mapping from linear intensity to encoding | EOTF^ -1^ | latexmath:[$\{R',G',B'\} = \{R,G,B\}^{2.4}$] -| Mapping from encoding to linear intensity | EOTF | latexmath:[$\{R,G,B\} = \{R',G',B'\}^{1\over{2.4}}$] -|========== +|==== +| Mapping from linear intensity to encoding | EOTF^ -1^ | latexmath:[\{R',G',B'\} = \{R,G,B\}^{2.4}] +| Mapping from encoding to linear intensity | EOTF | latexmath:[\{R,G,B\} = \{R',G',B'\}^{1\over{2.4}}] +|==== <<< -==== *++KHR_DF_TRANSFER_HLG_OETF++* (= 8) ==== +==== *++KHR_DF_TRANSFER_HLG_OETF++* (= 8) This value represents the Hybrid Log Gamma OETF between linear scene light intensity and nonlinear pixel values, defined by the @@ -3403,12 +3403,12 @@ ITU in BT.2100 for high dynamic range television, and described in <>. [width="60%",cols="^8,^2,^3"] -|========== +|==== | Mapping from linear intensity to encoding | OETF | <> | Mapping from encoding to linear intensity | OETF^ -1^ | <> -|========== +|==== -==== *++KHR_DF_TRANSFER_HLG_EOTF++* (= 9) ==== +==== *++KHR_DF_TRANSFER_HLG_EOTF++* (= 9) This value represents the Hybrid Log Gamma EOTF between nonlinear pixel values and linear image light intensity, defined by the ITU @@ -3416,12 +3416,12 @@ in BT.2100 for high dynamic range television, and described in <>. [width="60%",cols="^8,^2,^3"] -|========== +|==== | Mapping from linear intensity to encoding | EOTF^ -1^ | <> | Mapping from encoding to linear intensity | EOTF | <> -|========== +|==== -==== *++KHR_DF_TRANSFER_PQ_EOTF++* (= 10) ==== +==== *++KHR_DF_TRANSFER_PQ_EOTF++* (= 10) This value represents the Perceptual Quantization EOTF between nonlinear pixel values and linear image light intensity, defined @@ -3429,12 +3429,12 @@ by the ITU in BT.2100 for high dynamic range television, and described in <>. [width="60%",cols="^8,^2,^3"] -|========== +|==== | Mapping from linear intensity to encoding | EOTF^ -1^ | <> | Mapping from encoding to linear intensity | EOTF | <> -|========== +|==== -==== *++KHR_DF_TRANSFER_PQ_OETF++* (= 11) ==== +==== *++KHR_DF_TRANSFER_PQ_OETF++* (= 11) This value represents the Perceptual Quantization OETF between linear scene light intensity and nonlinear pixel values, defined @@ -3442,61 +3442,61 @@ by the ITU in BT.2100 for high dynamic range television, and described in <>. [width="60%",cols="^8,^2,^3"] -|========== +|==== | Mapping from linear intensity to encoding | OETF | <> | Mapping from encoding to linear intensity | OETF^ -1^ | <> -|========== +|==== -==== *++KHR_DF_TRANSFER_DCIP3++* (= 12) ==== +==== *++KHR_DF_TRANSFER_DCIP3++* (= 12) This value represents the transfer function between nonlinear pixel values and linear image light intensity defined in DCI P3 and described in <>. [width="60%",cols="^8,^2"] -|========== +|==== | Mapping from linear intensity to encoding | EOTF^ -1^ | Mapping from encoding to linear intensity | EOTF -|========== +|==== <<< -==== *++KHR_DF_TRANSFER_PAL_OETF++* (= 13) ==== +==== *++KHR_DF_TRANSFER_PAL_OETF++* (= 13) This value represents the OETF between linear scene light intensity and nonlinear pixel values for legacy PAL systems described in <>. [width="60%",cols="^8,^2"] -|========== +|==== | Mapping from linear intensity to encoding | OETF | Mapping from encoding to linear intensity | OETF^ -1^ -|========== +|==== -==== *++KHR_DF_TRANSFER_PAL625_EOTF++* (= 14) ==== +==== *++KHR_DF_TRANSFER_PAL625_EOTF++* (= 14) This value represents the EOTF between nonlinear pixel values and linear image light intensity for legacy 625-line PAL systems described in <>. [width="60%",cols="^8,^2"] -|========== +|==== | Mapping from linear intensity to encoding | EOTF^ -1^ | Mapping from encoding to linear intensity | EOTF -|========== +|==== -==== *++KHR_DF_TRANSFER_ST240++* (= 15) ==== +==== *++KHR_DF_TRANSFER_ST240++* (= 15) This value represents the transfer function between linear scene light intensity and nonlinear pixel values associated with the legacy ST-240 (SMPTE240M) standard, described in <>. [width="60%",cols="^8,^4"] -|========== +|==== | Mapping from linear intensity to encoding | EOTF^ -1^ / OETF | Mapping from encoding to linear intensity | EOTF / OETF^ -1^ -|========== +|==== -==== *++KHR_DF_TRANSFER_ACESCC++* (= 16) ==== +==== *++KHR_DF_TRANSFER_ACESCC++* (= 16) This value represents the nonlinear transfer function between linear scene light intensity and nonlinear pixel values used in @@ -3505,12 +3505,12 @@ for use within Color Grading Systems, S-2014-003, defined in <>. This is described in <>. [width="60%",cols="^8,^2"] -|========== +|==== | Mapping from linear intensity to encoding | OETF | Mapping from encoding to linear intensity | OETF^ -1^ -|========== +|==== -==== *++KHR_DF_TRANSFER_ACESCCT++* (= 17) ==== +==== *++KHR_DF_TRANSFER_ACESCCT++* (= 17) This value represents the nonlinear transfer function between linear scene light intensity and nonlinear pixel values used in @@ -3519,18 +3519,18 @@ system for use within Color Grading Systems, S-2016-001, defined in <>. This is described in <>. [width="60%",cols="^8,^2"] -|========== +|==== | Mapping from linear intensity to encoding | OETF | Mapping from encoding to linear intensity | OETF^ -1^ -|========== +|==== -==== *++KHR_DF_TRANSFER_ADOBERGB++* (= 18) ==== +==== *++KHR_DF_TRANSFER_ADOBERGB++* (= 18) This value represents the transfer function defined in the Adobe RGB (1998) specification and described in <>. <<< -=== *_flags_* === +=== *_flags_* The format supports some configuration options in the form of boolean flags; these are described in the enumeration @@ -3538,17 +3538,17 @@ boolean flags; these are described in the enumeration .Field location information for *_flags_* [cols="7,10,2"] -|================== +|==== ^| Word offset into basic descriptor block ^| *++KHR_DF_WORD_FLAGS++* ^| 2 ^| Word offset into descriptor ^| *++KHR_DF_WORD_FLAGS++* {plus} 1 ^| 3 ^| Start bit within word ^| *++KHR_DF_SHIFT_FLAGS++* ^| 24 ^| Bit mask of value ^| *++KHR_DF_MASK_FLAGS++* ^| 0xFF -|================== +|==== *++khr_df_flags_e++* *_flags_* = *++KHR_DF_MASK_FLAGS++* & (++bdb++[*++KHR_DF_WORD_FLAGS++*] >> *++KHR_DF_SHIFT_FLAGS++*); -==== *++KHR_DF_FLAG_ALPHA_PREMULTIPLIED++* (= 1) ==== +==== *++KHR_DF_FLAG_ALPHA_PREMULTIPLIED++* (= 1) If the *++KHR_DF_FLAG_ALPHA_PREMULTIPLIED++* bit is set, any color information in the data should be interpreted as having been @@ -3563,7 +3563,7 @@ This flag has no effect if there is no alpha channel in the format. <<< -=== *_texelBlockDimension[0..3]_* === +=== *_texelBlockDimension[0..3]_* The *_texelBlockDimension_* fields define an integer bound on the range of coordinates covered by the repeating block described by the samples; @@ -3597,12 +3597,12 @@ values would therefore be: [[YUV420Basic]] .Example Basic Data Format *_texelBlockDimension_* values for _Y′C~B~C~R~_ 4:2:0 [width="40%",cols="5,1"] -|================================ +|==== ^| *_texelBlockDimension0_* ^| 1 ^| *_texelBlockDimension1_* ^| 1 ^| *_texelBlockDimension2_* ^| 0 ^| *_texelBlockDimension3_* ^| 0 -|================================ +|==== In the descriptor block examples in this specification, block dimensions larger than 1 (encoded as 0) are shown as the value to be stored in the @@ -3611,7 +3611,7 @@ for clarity. .Field location information for *_texelBlockDimension[0..3]_* [cols="7,10,2"] -|================== +|==== ^| Word offset into basic descriptor block ^| *++KHR_DF_WORD_TEXELBLOCKDIMENSION[0..3]++* ^| 3 ^| Word offset into descriptor ^| *++KHR_DF_WORD_TEXELBLOCKDIMENSION[0..3]++* {plus} 1 ^| 4 1.4+^.^| Start bit within word ^| *++KHR_DF_SHIFT_TEXELBLOCKDIMENSION0++* ^| 0 @@ -3619,7 +3619,7 @@ for clarity. ^| *++KHR_DF_SHIFT_TEXELBLOCKDIMENSION2++* ^| 16 ^| *++KHR_DF_SHIFT_TEXELBLOCKDIMENSION3++* ^| 24 ^| Bit mask of value ^| *++KHR_DF_MASK_TEXELBLOCKDIMENSION[0..3]++* ^| 0xFF -|================== +|==== *++uint32_t++* *_texelBlockDimension0_* = *++KHR_DF_MASK_TEXELBLOCKDIMENSION0++* & + (++bdb++[*++KHR_DF_WORD_TEXELBLOCKDIMENSION0++*] >> *++KHR_DF_SHIFT_TEXELBLOCKDIMENSION0++*); @@ -3634,7 +3634,7 @@ for clarity. (++bdb++[*++KHR_DF_WORD_TEXELBLOCKDIMENSION3++*] >> *++KHR_DF_SHIFT_TEXELBLOCKDIMENSION3++*); <<< -=== *_bytesPlane[0..7]_* === +=== *_bytesPlane[0..7]_* The Basic Data Format Descriptor divides the image into a number of planes, each consisting of an integer number of consecutive bytes. @@ -3679,7 +3679,7 @@ no *_bytesPlane_* value is zero, 8 planes are considered to exist. .Field location information for *_bytesPlane[0..7]_* [cols="7,10,2"] -|================== +|==== 1.2+^.^| Word offset into basic descriptor block ^| *++KHR_DF_WORD_BYTESPLANE[0..3]++* ^| 4 ^| *++KHR_DF_WORD_BYTESPLANE[4..7]++* ^| 5 1.2+^.^| Word offset into descriptor ^| *++KHR_DF_WORD_BYTESPLANE[0..3]++* {plus} 1 ^| 5 @@ -3693,7 +3693,7 @@ no *_bytesPlane_* value is zero, 8 planes are considered to exist. ^| *++KHR_DF_SHIFT_BYTESPLANE6++* ^| 16 ^| *++KHR_DF_SHIFT_BYTESPLANE7++* ^| 24 ^| Bit mask of value ^| *++KHR_DF_MASK_BYTESPLANE[0..7]++* ^| 0xFF -|================== +|==== *++uint32_t++* *_bytesPlane[0..7]_* = *++KHR_DF_MASK_BYTESPLANE[0..7]++* & + (++bdb++[*++KHR_DF_WORD_BYTESPLANE[0..7]++*] >> *++KHR_DF_SHIFT_BYTESPLANE[0..7]++*); @@ -3705,7 +3705,8 @@ The scheme for encoding paletted formats as of version 1.3 is described in <>. <<< -=== [[sample]]Sample information === +[[sample]] +=== Sample information The layout and position of the information within each plane is determined by a number of _samples_, each consisting of a single @@ -3715,25 +3716,25 @@ the texel block, as shown in <>. [[SampleOverview]] .Basic Data Format Descriptor Sample Information [width="98%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ ^| *_F_* ^| *_S_* ^| *_E_* ^| *_L_* 4+^| *_channelType_* 8+^| *_bitLength_* 16+^| *_bitOffset_* 8+^| *_samplePosition3_* 8+^| *_samplePosition2_* 8+^| *_samplePosition1_* 8+^| *_samplePosition0_* 32+^| *_sampleLower_* 32+^| *_sampleUpper_* -|================================ +|==== Bits *_F_*, *_S_*, *_E_* and *_L_* are abbreviations for the following qualifier flags: [cols="1,5,1",width="65%"] -|================================ +|==== ^| *_F_* ^| *++KHR_DF_SAMPLE_DATATYPE_FLOAT++* ^| 0x80 ^| *_S_* ^| *++KHR_DF_SAMPLE_DATATYPE_SIGNED++* ^| 0x40 ^| *_E_* ^| *++KHR_DF_SAMPLE_DATATYPE_EXPONENT++* ^| 0x20 ^| *_L_* ^| *++KHR_DF_SAMPLE_DATATYPE_LINEAR++* ^| 0x10 -|================================ +|==== The sample information begins at word *++KHR_DF_WORD_SAMPLESTART++* = 6, offset from the start of the basic descriptor block. @@ -3794,11 +3795,11 @@ sample fields: .Field location information for sample field *_xxx_* [cols="7,10,2"] -|================== +|==== ^| Word offset relative to start of sample ^| *++KHR_DF_SAMPLEWORD_xxx++* {plus} 1 ^| ... ^| Start bit within word ^| *++KHR_DF_SAMPLESHIFT_xxx++* ^| ... ^| Bit mask of value ^| *++KHR_DF_SAMPLEMASK_xxx++* ^| ... -|================== +|==== If the basic descriptor block is treated as a *++uint32_t++* array ++bdb[]++, sample field *_xxx_* can be accessed as follows: @@ -3817,7 +3818,7 @@ For example, *++KHR_DFDSVAL++*(++bdb++, 2, *++CHANNELID++*) returns the value: {plus} *++KHR_DF_SAMPLEWORD_CHANNELID++*] >> *++KHR_DF_SAMPLESHIFT_CHANNELID++*) <<< -=== Sample *_bitOffset_* === +=== Sample *_bitOffset_* The *_bitOffset_* field describes the offset of the least significant bit of this sample from the least significant bit of the least @@ -3834,17 +3835,17 @@ This mechanism notably supports values that are zero-extended. .Field location information for sample *_bitOffset_* [cols="7,10,2"] -|================== +|==== ^| Word offset relative to start of sample ^| *++KHR_DF_SAMPLEWORD_BITOFFSET++* ^| 0 ^| Start bit within word ^| *++KHR_DF_SAMPLESHIFT_BITOFFSET++* ^| 0 ^| Bit mask of value ^| *++KHR_DF_SAMPLEMASK_BITOFFSET++* ^| 0xFFFFU -|================== +|==== *++uint32_t++* *_bitoffset_* = *++KHR_DF_SAMPLEMASK_BITOFFSET++* & + ((++bdb++[*++KHR_DF_WORD_SAMPLESTART++* {plus} (_sample_ {times} *++KHR_DF_WORD_SAMPLEWORDS++*) + {plus} *++KHR_DF_SAMPLEWORD_BITOFFSET++*]) >> *++KHR_DF_SAMPLESHIFT_BITOFFSET++*); -=== Sample *_bitLength_* === +=== Sample *_bitLength_* The *_bitLength_* field describes the number of consecutive bits from the concatenated bit stream that contribute to the sample. This field @@ -3877,18 +3878,18 @@ represented number (without the -1 offset) in parentheses for clarity. .Field location information for sample *_bitLength_* [cols="7,10,2"] -|================== +|==== ^| Word offset relative to start of sample ^| *++KHR_DF_SAMPLEWORD_BITLENGTH++* ^| 0 ^| Start bit within word ^| *++KHR_DF_SAMPLESHIFT_BITLENGTH++* ^| 16 ^| Bit mask of value ^| *++KHR_DF_SAMPLEMASK_BITLENGTH++* ^| 0xFF -|================== +|==== *++uint32_t++* *_bitLength_* = *++KHR_DF_SAMPLEMASK_BITLENGTH++* & + ((++bdb++[*++KHR_DF_WORD_SAMPLESTART++* {plus} (_sample_ {times} *++KHR_DF_WORD_SAMPLEWORDS++*) + {plus} *++KHR_DF_SAMPLEWORD_BITLENGTH++*]) >> *++KHR_DF_SAMPLESHIFT_BITLENGTH++*); <<< -=== Sample *_channelType_* and qualifiers === +=== Sample *_channelType_* and qualifiers The *_channelType_* field is an unsigned 8-bit quantity. @@ -3901,11 +3902,11 @@ for each model. .Field location information for sample *_channelType_* [cols="7,10,2"] -|================== +|==== ^| Word offset relative to start of sample ^| *++KHR_DF_SAMPLEWORD_CHANNELID++* ^| 0 ^| Start bit within word ^| *++KHR_DF_SAMPLESHIFT_CHANNELID++* ^| 24 ^| Bit mask of value ^| *++KHR_DF_SAMPLEMASK_CHANNELID++* ^| 0xF -|================== +|==== *++khr_df_model_channels_e++* *_channelType_* = *++KHR_DF_SAMPLEMASK_CHANNELID++* & + ((++bdb++[*++KHR_DF_WORD_SAMPLESTART++* {plus} (_sample_ {times} *++KHR_DF_WORD_SAMPLEWORDS++*) + @@ -3916,11 +3917,11 @@ The top four bits of the *_channelType_* are described by the .Field location information for sample *_qualifiers_* [cols="7,10,2"] -|================== +|==== ^| Word offset relative to start of sample ^| *++KHR_DF_SAMPLEWORD_QUALIFIERS++* ^| 0 ^| Start bit within word ^| *++KHR_DF_SAMPLESHIFT_QUALIFIERS++* ^| 24 ^| Bit mask of value ^| *++KHR_DF_SAMPLEMASK_QUALIFIERS++* ^| 0xF0 -|================== +|==== *++khr_df_sample_datatype_qualifiers_e++* *_qualifiers_* = *++KHR_DF_SAMPLEMASK_QUALIFIERS++* & + ((++bdb++[*++KHR_DF_WORD_SAMPLESTART++* {plus} (_sample_ {times} *++KHR_DF_WORD_SAMPLEWORDS++*) + @@ -3955,7 +3956,7 @@ For samples in which the *++KHR_DF_SAMPLE_DATATYPE_EXPONENT++* bit is not set: * If the *++KHR_DF_SAMPLE_DATATYPE_FLOAT++* bit, shown as *_F_* in <>, is set, the sample holds floating point data in a conventional format of 10, 11 or 16 bits, as described in <>, - or of 32, or 64 bits as described in <>. + or of 32, or 64 bits as described in <>. Unless a genuine unsigned format is intended, *++KHR_DF_SAMPLE_DATATYPE_SIGNED++* (bit *_S_*) should also be set. Less common floating point representations can be generated with @@ -3989,13 +3990,13 @@ channel, as shown in <>. [[exponentqualifiers]] .Qualifier interpretation when *++KHR_DF_SAMPLE_DATATYPE_EXPONENT++* = 1 [cols="^1,^1,^1,4,^5", width="50%"] -|=========== +|==== | *_E_* | *_L_* | *_F_* |  *Interpretation* | *Formula* -| 1 | 0 | 0 |  Exponent | latexmath:[$\mathit{base\ value}\times 2^\mathit{modifier}$] -| 1 | 0 | 1 |  Multiplier | latexmath:[$\mathit{base\ value}\times\mathit{modifier}$] -| 1 | 1 | 0 |  Divisor | latexmath:[$\mathit{base\ value}\over\mathit{modifier}$] -| 1 | 1 | 1 |  Power | latexmath:[$\mathit{base\ value}^\mathit{modifier}$] -|=========== +| 1 | 0 | 0 |  Exponent | latexmath:[\mathit{base\ value}\times 2^\mathit{modifier}] +| 1 | 0 | 1 |  Multiplier | latexmath:[\mathit{base\ value}\times\mathit{modifier}] +| 1 | 1 | 0 |  Divisor | latexmath:[\mathit{base\ value}\over\mathit{modifier}] +| 1 | 1 | 1 |  Power | latexmath:[\mathit{base\ value}^\mathit{modifier}] +|==== For samples in which the *++KHR_DF_SAMPLE_DATATYPE_EXPONENT++* bit is set: @@ -4048,7 +4049,7 @@ to be represented in fixed-point terms, and the values may be signed depending on whether the *_S_* bit is set. <<< -=== *_samplePosition[0..3]_* === +=== *_samplePosition[0..3]_* The sample has an associated location within the 4-dimensional space of the texel block. @@ -4057,14 +4058,14 @@ of the texel block, represented as an 8-bit unsigned integer quantity. .Field location information for sample *_samplePosition[0..3]_* [cols="7,10,2"] -|================== +|==== ^| Word offset relative to start of sample ^| *++KHR_DF_SAMPLEWORD_SAMPLEPOSITION[0..3]++* ^| 1 1.4+^.^| Start bit within word ^| *++KHR_DF_SAMPLESHIFT_SAMPLEPOSITION0++* ^| 0 ^| *++KHR_DF_SAMPLESHIFT_SAMPLEPOSITION1++* ^| 8 ^| *++KHR_DF_SAMPLESHIFT_SAMPLEPOSITION2++* ^| 16 ^| *++KHR_DF_SAMPLESHIFT_SAMPLEPOSITION3++* ^| 24 ^| Bit mask of value ^| *++KHR_DF_SAMPLEMASK_SAMPLEPOSITION[0..3]++* ^| 0xF -|================== +|==== *++khr_df_model_channels_e++* *_samplePosition0_* = *++KHR_DF_SAMPLEMASK_SAMPLEPOSITION0++* & + ((++bdb++[*++KHR_DF_WORD_SAMPLESTART++* {plus} (_sample_ {times} *++KHR_DF_WORD_SAMPLEWORDS++*) + @@ -4088,31 +4089,31 @@ corresponding *_texelBlockDimension_* value as follows: ifdef::a2xhtml[] // N.B. HTML math output doesn't support bold italics [latexmath] -++++++ +++++ \begin{align*} n &= \left\lceil\textrm{log}_2(\textbf{texelBlockDimension} + 1)\right\rceil \\ \textit{coordinateOffset} &= \textbf{samplePosition} \times 2^{n - 8} \end{align*} -++++++ +++++ endif::[] ifndef::a2xhtml[] [latexmath] -++++++ +++++ \begin{align*} n &= \left\lceil\textrm{log}_2(\textbf{\textit{texelBlockDimension}} + 1)\right\rceil \\ \textit{coordinateOffset} &= \textbf{\textit{samplePosition}} \times 2^{n - 8} \end{align*} -++++++ +++++ endif::[] For example, if *_texelBlockDimension0_* is 1 (indicating a texel block width of two units) *_samplePosition0_* is described in units of -latexmath:[${2\over 256} = {1\over 128}$]. +latexmath:[{2\over 256} = {1\over 128}]. That is, a *_samplePosition0_* of 128 would encode an offset of ``1.0'' and a *_samplePosition0_* of 64 would encode an offset of ``0.5''. If *_texelBlockDimension0_* is 5 (indicating a texel block width of six units), *_samplePosition0_* is described in units of -latexmath:[${8\over 256} = {1\over 32}$]. +latexmath:[{8\over 256} = {1\over 32}]. That is, a *_samplePosition0_* of 64 would encode an offset of ``2.0'' and a *_samplePosition0_* of 24 would encode an offset of ``0.75''. @@ -4141,7 +4142,7 @@ This change does not affect the representation of single-coordinate texel blocks; that is, a *_samplePosition_* of ``0'' still represents ``0.0''. <<< -=== *_sampleLower_* and *_sampleUpper_* === +=== *_sampleLower_* and *_sampleUpper_* The *_sampleLower_* and *_sampleUpper_* fields are used to define the mapping between the numerical value stored in the format and the @@ -4165,23 +4166,23 @@ range (which corresponds to an encoding of 0.5 in numerical terms). ifdef::a2xhtml[] // N.B. HTML math output doesn't support bold italics [latexmath] -++++++ +++++ \begin{align*} \textit{out}_\textit{unsigned} &= \left({{\textit{value} - \textbf{sampleLower}}\over{\textbf{sampleUpper} - \textbf{sampleLower}}}\right) \\ \textit{out}_\textit{signed} &= \left({{\textit{value} - \textbf{sampleLower}}\over{\textbf{sampleUpper} - \textbf{sampleLower}}} - 0.5\right) \times 2 \\ \textit{out}_\textit{color difference} &= \left({{\textit{value} - \textbf{sampleLower}}\over{\textbf{sampleUpper} - \textbf{sampleLower}}} - 0.5\right) \end{align*} -++++++ +++++ endif::[] ifndef::a2xhtml[] [latexmath] -++++++ +++++ \begin{align*} \textit{out}_\textit{unsigned} &= \left({{\textit{value} - \textbf{\textit{sampleLower}}}\over{\textbf{\textit{sampleUpper}} - \textbf{\textit{sampleLower}}}}\right) \\ \textit{out}_\textit{signed} &= \left({{\textit{value} - \textbf{\textit{sampleLower}}}\over{\textbf{\textit{sampleUpper}} - \textbf{\textit{sampleLower}}}} - 0.5\right) \times 2 \\ \textit{out}_\textit{color difference} &= \left({{\textit{value} - \textbf{\textit{sampleLower}}}\over{\textbf{\textit{sampleUpper}} - \textbf{\textit{sampleLower}}}} - 0.5\right) \end{align*} -++++++ +++++ endif::[] For example, the BT.709 television broadcast standard dictates that @@ -4416,7 +4417,8 @@ In the interests of portability, the following summary (which assumes that bitfields are encoded starting at bit 0) is therefore provided for information, but is not canonical: ------ +[source] +---- typedef struct _DFDSampleType { uint32_t bitOffset: 16; uint32_t bitLength: 8; @@ -4450,9 +4452,9 @@ typedef struct _BasicDataFormatDescriptor { uint32_t bytesPlane7: 8; DFDSampleType samples[]; } BasicDataFormatDescriptor; ------ +---- -== Extension for more complex formats == +== Extension for more complex formats Some formats will require more channels than can be described in the Basic Format Descriptor, or may have more specific color requirements. For example, @@ -4524,7 +4526,7 @@ form of allocation while reading texel values. [[DepthExtensionExample]] .Example of a depth buffer with an extension to indicate a virtual allocation [width="97%"] -|============= +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 56 -- total size of the two blocks plus one 32-bit value @@ -4548,7 +4550,7 @@ form of allocation while reading texel values. 16+^| *_descriptorBlockSize:_* 8 + (4 {times} 1) = 12 16+^| *_versionNumber:_* 0 32+^| ~Data specific to the extension follows~ 32+^| 1 -- buffer is ``virtual'' -|============= +|==== It is possible for a vendor to use the extension block to store peripheral information required to access the image -- plane base addresses, stride, etc. @@ -4581,7 +4583,7 @@ describes additional planes. [[AdditionalPlanes]] .Additional planes descriptor block [width="97%"] -|============= +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 15+^| *_descriptorType:_* 0x6001 17+^| *_vendorId:_* 0 @@ -4589,7 +4591,7 @@ describes additional planes. 32+^| *_bytesPlane0_* 32+^| *_bytesPlane1_* _(optional)_ 32+^| _(etc.)_ -|============= +|==== If this descriptor block is present, the *_bytesPlane[0..7]_* fields of the basic descriptor block are ignored, and the number of bytes for plane @@ -4618,7 +4620,7 @@ cannot represent the format without extension. The basic descriptor block allows texel blocks of up to four non-trivial dimensions, and with a texel block size of up to 256 coordinate units, -with sample positions described in precision up to latexmath:[$1\over 256$] +with sample positions described in precision up to latexmath:[1\over 256] of a coordinate. Under rare circumstances, this may provide insufficient flexibility. An extension descriptor block, with *_vendorId_* = *++KHR_DF_VENDORID_KHRONOS++* @@ -4634,7 +4636,7 @@ users of the layout being described. [[AdditionalDimensions]] .Additional dimensions descriptor block [width="97%"] -|============= +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 15+^| *_descriptorType:_* 0x6002 17+^| *_vendorId:_* 0 @@ -4645,7 +4647,7 @@ users of the layout being described. 16+^| *++uint16_t++* *_sample0Pos0_* 16+^| *++uint16_t++* *_sample0Pos0Divisor_* 16+^| *++uint16_t++* *_sample0Pos1_* 16+^| *++uint16_t++* *_sample0Pos1Divisor_* 32+^| _(etc.)_ -|============= +|==== The fields *_texelBlockDimension[0..n]_* describe the size in coordinate units of the texel block in the corresponding dimension; as with the @@ -4656,7 +4658,7 @@ are ignored. For each sample, the *_samplePos_* and *_samplePosDivisor_* fields store a numerator and denominator pair for the coordinate -latexmath:[$\textit{offset} = {\textit{numerator}\over\textit{denominator}}$] +latexmath:[\textit{offset} = {\textit{numerator}\over\textit{denominator}}] for each dimension, with all dimensions for a sample described before describing the next sample. *_samplePos_* and *_samplePosDivisor_* should be minimized, leaving an @@ -4681,9 +4683,9 @@ This descriptor block should be used only if the Khronos Basic Descriptor Block is the first descriptor block in the data format descriptor, and cannot represent the format without extension. -== Frequently Asked Questions == +== Frequently Asked Questions -=== Why have a binary format rather than a human-readable one? === +=== Why have a binary format rather than a human-readable one? While it is not expected that every new container will have a unique data descriptor or that analysis of the data format descriptor will be @@ -4694,12 +4696,12 @@ a large number of format descriptors to be stored, and to be amenable to hardware interpretation or processing in shaders. These goals preclude a text-based representation such as an XML schema. -=== Why not use an existing representation such as those on FourCC.org? === +=== Why not use an existing representation such as those on FourCC.org? Formats in FourCC.org do not describe in detail sufficient information for many APIs, and are sometimes inconsistent. -=== Why have a descriptive format? === +=== Why have a descriptive format? Enumerations are fast and easy to process, but are limited in that any software can only be aware of the enumeration values in place when it @@ -4710,7 +4712,7 @@ for more flexible software which can support a wide range of formats without needing each to be listed, and simplifies the programming of conditional behavior based on format properties. -=== Why describe this standard within Khronos? === +=== Why describe this standard within Khronos? Khronos supports multiple standards that have a range of internal data representations. There is no requirement that this standard be used @@ -4719,7 +4721,7 @@ Khronos standards may use this specification as part of a consistent approach to inter-standard operation. <<< -=== Why should I use this descriptor if I don't need most of the fields? === +=== Why should I use this descriptor if I don't need most of the fields? While a library may not use all the data provided in the data format descriptor that is described within this standard, it is common for @@ -4740,7 +4742,7 @@ software outside the proprietary library and for reducing the effort needed to provide a complete, unambiguous and accurate description of a format in human-readable terms. -=== Why not expand each field out to be integer for ease of decoding? === +=== Why not expand each field out to be integer for ease of decoding? There is a trade-off between size and decoding effort. It is assumed that data which occupies the same 32-bit word may need to be tested @@ -4750,7 +4752,7 @@ it is intended that most data can be extracted with low-cost operations, typically being byte-aligned (other than sample flags) and with the natural alignment applied to multi-byte quantities. -=== Can this descriptor be used for text content? === +=== Can this descriptor be used for text content? For simple ASCII content, there is no reason that plain text could not be described in some way, and this may be useful for image formats that contain @@ -4764,13 +4766,13 @@ for this standard. :valign: center [[fpformats]] -== Floating-point formats == +== Floating-point formats Some common floating-point numeric representations are defined in -<>. Additional floating point formats are defined in this +<>. Additional floating point formats are defined in this section. -[[16bitfp]] +[[im-16bitfp]] === 16-bit floating-point numbers A 16-bit floating-point number has a 1-bit sign (_S_), a 5-bit @@ -4779,8 +4781,8 @@ The value _V_ of a 16-bit floating-point number is determined by the following: [latexmath] -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -\[ +++++ +\begin{aligned} V = \begin{cases} (-1)^S \times 0.0, & E = 0, M = 0 \\ @@ -4791,20 +4793,20 @@ V = (-1)^S \times \mathit{Inf}, & E = 31, M = 0 \\ \mathit{NaN}, & E = 31, M \neq 0 \end{cases} -\] -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +\end{aligned} +++++ If the floating-point number is interpreted as an unsigned 16-bit integer _N_, then [latexmath] -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - $$S = \left\lfloor { { N \bmod 65536 } \over 32768 } \right\rfloor$$ - $$E = \left\lfloor { { N \bmod 32768 } \over 1024 } \right\rfloor$$ - $$M = N \bmod 1024.$$ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++ +S = \left\lfloor { { N \bmod 65536 } \over 32768 } \right\rfloor \\ +E = \left\lfloor { { N \bmod 32768 } \over 1024 } \right\rfloor \\ +M = N \bmod 1024. +++++ -[[11bitfp]] +[[im-11bitfp]] === Unsigned 11-bit floating-point numbers An unsigned 11-bit floating-point number has no sign bit, a 5-bit exponent @@ -4813,8 +4815,8 @@ The value _V_ of an unsigned 11-bit floating-point number is determined by the following: [latexmath] -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -\[ +++++ +\begin{aligned} V = \begin{cases} 0.0, & E = 0, M = 0 \\ @@ -4824,19 +4826,19 @@ V = \mathit{Inf}, & E = 31, M = 0 \\ \mathit{NaN}, & E = 31, M \neq 0 \end{cases} -\] -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +\end{aligned} +++++ If the floating-point number is interpreted as an unsigned 11-bit integer _N_, then [latexmath] -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - $$E = \left\lfloor { N \over 64 } \right\rfloor$$ - $$M = N \bmod 64.$$ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++ +E = \left\lfloor { N \over 64 } \right\rfloor \\ +M = N \bmod 64. +++++ -[[10bitfp]] +[[im-10bitfp]] === Unsigned 10-bit floating-point numbers An unsigned 10-bit floating-point number has no sign bit, a 5-bit @@ -4845,8 +4847,8 @@ The value _V_ of an unsigned 10-bit floating-point number is determined by the following: [latexmath] -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -\[ +++++ +\begin{aligned} V = \begin{cases} 0.0, & E = 0, M = 0 \\ @@ -4856,17 +4858,17 @@ V = \mathit{Inf}, & E = 31, M = 0 \\ \mathit{NaN}, & E = 31, M \neq 0 \end{cases} -\] -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +\end{aligned} +++++ If the floating-point number is interpreted as an unsigned 10-bit integer _N_, then [latexmath] -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - $$E = \left\lfloor { N \over 32 } \right\rfloor$$ - $$M = N \bmod 32.$$ -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++ +E = \left\lfloor { N \over 32 } \right\rfloor \\ +M = N \bmod 32. +++++ [[customfp]] === Non-standard floating point formats @@ -4878,7 +4880,7 @@ data, as follows. Note that non-standard floating point formats do not use the *++KHR_DF_SAMPLE_DATATYPE_FLOAT++* bit. An example of use of the 16-bit floating point format described in -<<16bitfp>> but described in terms of a custom floating point format +<> but described in terms of a custom floating point format is provided in <>. Note that this is provided for example only, and this particular format would be better described using the standard 16-bit floating @@ -4909,7 +4911,7 @@ For example, the shared exponent formats shown in therefore the *_sampleUpper_* values for the 9-bit mantissas are 256 -- this being the mantissa value for 1.0 when the exponent is set to 0. -For the 16-bit signed floating point format described in <<16bitfp>>, +For the 16-bit signed floating point format described in <>, *_sampleUpper_* should be set to 1024, indicating the implicit ``1'' bit which is above the 10 bits representable in the mantissa. *_sampleLower_* should be 0 in this case, since the mantissa uses a sign-magnitude @@ -4956,7 +4958,7 @@ exponent's *_sampleUpper_* value and with a mantissa of non-0 are interpreted as representing not-a-number (_NaN_). Note that these interpretations are compatible with the -corresponding numerical representations in <>. +corresponding numerical representations in <>. ==== Conversion formulae @@ -4965,8 +4967,8 @@ exponent value of _E_, a format with an implicit ``1'' bit can be converted from its representation to a real value as follows: [latexmath] -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -\[ +++++ +\begin{aligned} V = \begin{cases} (-1)^S \times 0.0, & E = 0, M = 0 \\ @@ -4976,16 +4978,16 @@ V = (-1)^S \times \mathit{Inf}, & E > E_\mathit{sampleUpper}, M = 0 \\ \mathit{NaN}, & E > E_\mathit{sampleUpper}, M \neq 0. \end{cases} -\] -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +\end{aligned} +++++ If there is no implicit ``1'' bit (that is, the *_sampleUpper_* value of the mantissa is representable in the number of bits assigned to the mantissa), the value can be converted to a real value as follows: [latexmath] -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -\[ +++++ +\begin{aligned} V = \begin{cases} (-1)^S \times 2^{E-E_{\mathit{sampleUower}}} \times { \left( { M \over M_\mathit{sampleUpper} } \right) }, @@ -4993,8 +4995,8 @@ V = (-1)^S \times \mathit{Inf}, & E > E_\mathit{sampleUpper}, M = 0 \\ \mathit{NaN}, & E > E_\mathit{sampleUpper}, M \neq 0. \end{cases} -\] -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +\end{aligned} +++++ A descriptor block for a format without an implicit ``1'' (and with the added complication of having the same exponent bits shared across multiple @@ -5003,26 +5005,26 @@ in <>. In the case of this particular example, the a equations simplify to: [latexmath] -+++++++++++++++++++ - $$red = \mathit{red}_\mathrm{shared}\times 2^{(\mathit{exp}_\mathrm{shared}-B-N)}$$ - $$green = \mathit{green}_\mathrm{shared}\times 2^{(\mathit{exp}_\mathrm{shared}-B-N)}$$ - $$blue = \mathit{blue}_\mathrm{shared}\times 2^{(\mathit{exp}_\mathrm{shared}-B-N)}$$ -+++++++++++++++++++ +++++ +red = \mathit{red}_\mathrm{shared}\times 2^{(\mathit{exp}_\mathrm{shared}-B-N)} \\ +green = \mathit{green}_\mathrm{shared}\times 2^{(\mathit{exp}_\mathrm{shared}-B-N)} \\ +blue = \mathit{blue}_\mathrm{shared}\times 2^{(\mathit{exp}_\mathrm{shared}-B-N)} +++++ Where: [latexmath] -+++++++++++++++++++ - $$N = 9 \textrm{ (= number of mantissa bits per component)}$$ - $$B = 15 \textrm{ (= exponent bias)}$$ -+++++++++++++++++++ +++++ +N = 9 \textrm{ (= number of mantissa bits per component)} \\ +B = 15 \textrm{ (= exponent bias)} +++++ Note that in general conversion from a real number _to_ any representation may require rounding, truncation and special value management rules which are beyond the scope of a data format specification and may be documented in APIs which generate these formats. -== Example format descriptors == +== Example format descriptors NOTE: Example data format descriptors for compressed formats can be found under the *_colorModel_* field in <>. @@ -5030,7 +5032,7 @@ be found under the *_colorModel_* field in <>. [[exampledescriptor_565]] .565 _RGB_ packed 16-bit format as written to memory by a little-endian architecture [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 76 @@ -5059,14 +5061,14 @@ be found under the *_colorModel_* field in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* 31 -|================================ +|==== <<< [[exampledescriptor_cosited]] .Four co-sited 8-bit sRGB channels, assuming premultiplied alpha [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 92 @@ -5101,14 +5103,14 @@ be found under the *_colorModel_* field in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* 255 -|================================ +|==== <<< [[exampledescriptor_mono8bit]] .A single 8-bit monochrome channel [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -5125,7 +5127,7 @@ be found under the *_colorModel_* field in <>. 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* 255 -|================================ +|==== [[exampledescriptor_1bpp]] ifdef::a2xhtml[] .A single 1-bit monochrome channel, as an 8×1 texel block to allow byte-alignment @@ -5134,7 +5136,7 @@ ifndef::a2xhtml[] .A single 1-bit monochrome channel, as an 8×1 texel block to allow byte-alignment, part 1 of 2 endif::[] [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 156 @@ -5158,13 +5160,13 @@ endif::[] 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* 1 ifndef::a2xhtml[] -|================================ +|==== <<< .A single 1-bit monochrome channel, as an 8×1 texel block to allow byte-alignment, part 2 of 2 [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ endif::[] @@ -5204,14 +5206,14 @@ endif::[] 8+^| 0 8+^| 0 8+^| 0 8+^| 0xE0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* 1 -|================================ +|==== <<< [[exampledescriptor_bayer]] .2×2 Bayer pattern: four 8-bit distributed sRGB channels, spread across two lines (as two planes) [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 92 @@ -5246,14 +5248,14 @@ endif::[] 8+^| 0 8+^| 0 8+^| 0x80 (_y_ = ``1'') 8+^| 0x80 (_x_ = ``1'') 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* 255 -|================================ +|==== <<< [[exampledescriptor_simplepalette]] .Simple paletted format: 8-bit index to 240 entries of 4-bit _R_, _G_, _B_ channels [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 92 @@ -5288,12 +5290,12 @@ endif::[] 8+^| 0 8+^| 0 8+^| 0 8+^| 0 (palette id) 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* 15 -|================================ +|==== [[exampledescriptor_LUT]] .Paletted color look-up table format: three 8-bit indices into separate 256-entry 10-bit channels [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 124 @@ -5340,12 +5342,12 @@ endif::[] 8+^| 0 8+^| 0 8+^| 0 8+^| 2 (*++BLUE++* palette) 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* 1023 -|================================ +|==== [[exampledescriptor_ycbcr]] ._Y′C~B~C~R~_ 4:2:0: BT.709 reduced-range data, with _C~B~_ and _C~R~_ aligned to the midpoint of the _Y′_ samples [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 124 @@ -5392,12 +5394,12 @@ endif::[] 8+^| 0 8+^| 0 8+^| 0x40 (_y_ = ``0.5'') 8+^| 0x40 (_x_ = ``0.5'') 32+^| *_sampleLower:_* 16 32+^| *_sampleUpper:_* 240 -|================================ +|==== [[exampledescriptor_bigendian]] .565 _RGB_ packed 16-bit format as written to memory by a big-endian architecture [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 92 @@ -5432,12 +5434,12 @@ endif::[] 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* 31 -|================================ +|==== [[exampledescriptor_r9g9b9e5]] .R9G9B9E5 shared-exponent format [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 124 @@ -5484,12 +5486,12 @@ endif::[] 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* 15 -- exponent bias -|================================ +|==== [[exampledescriptor_AcornTint]] .Acorn 256-color format (2 bits each independent _RGB_, 2 bits shared tint) [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 108 @@ -5530,7 +5532,7 @@ endif::[] 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* 3 -|================================ +|==== ifdef::a2xhtml[] .V210 format (full-range _Y′C~B~C~R~_) @@ -5540,7 +5542,7 @@ ifndef::a2xhtml[] .V210 format (full-range _Y′C~B~C~R~_) part 1 of 2 endif::[] [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 220 @@ -5582,11 +5584,11 @@ endif::[] 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* 1023 ifndef::a2xhtml[] -|================================ +|==== .V210 format (full-range _Y′C~B~C~R~_) part 2 of 2 [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ endif::[] @@ -5632,12 +5634,12 @@ endif::[] 8+^| 0 8+^| 0 8+^| 0 8+^| 0xA0 (_x_ = ``5.0'') 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* 1023 -|================================ +|==== [[exampledescriptor_intensity]] .Intensity-alpha format showing aliased samples [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 92 @@ -5672,12 +5674,12 @@ endif::[] 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0 32+^| *_sampleUpper:_* 255 -|================================ +|==== [[exampledescriptor_48bit]] .A 48-bit signed middle-endian red channel: three co-sited 16-bit little-endian words, high word first [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 76 @@ -5706,12 +5708,12 @@ endif::[] 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0xFFFF8000U -- top 16 bits of 0x800000000000, sign-extended 32+^| *_sampleUpper:_* 0x00007FFFU -- top 16 bits of 0x7FFFFFFFFFFF -|================================ +|==== [[exampledescriptor_float16explicit]] .A single 16-bit floating-point red value, described explicitly (example only!) [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 76 @@ -5740,12 +5742,12 @@ endif::[] 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 15 -- bias 32+^| *_sampleUpper:_* 30 -- support for infinities because 30 < 2^*bitLength*^ - 1 -|================================ +|==== [[exampledescriptor_float16implicit]] .A single 16-bit floating-point red value, described normally [width="97%"] -|================================ +|==== 32+^| *~++uint32_t++ bit~* ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 32+^| *_totalSize:_* 44 @@ -5762,27 +5764,27 @@ endif::[] 8+^| 0 8+^| 0 8+^| 0 8+^| 0 32+^| *_sampleLower:_* 0xBF800000U -- IEEE 754 floating-point representation for -1.0f 32+^| *_sampleUpper:_* 0x3F800000U -- IEEE 754 floating-point representation for 1.0f -|================================ +|==== -ifndef::a2xhtml[] -= Color conversions -endif::[] +//@ ifndef::a2xhtml[] +//@ = Color conversions +//@ endif::[] -include::conversions.txt[] +include::{chapters}/conversions.adoc[] -ifndef::a2xhtml[] -= Compressed Texture Formats -endif::[] +//@ ifndef::a2xhtml[] +//@ = Compressed Texture Formats +//@ endif::[] -include::compformats.txt[] +include::{chapters}/compformats.adoc[] -ifndef::a2xhtml[] -= References and contributors -endif::[] +//@ ifndef::a2xhtml[] +//@ = References and contributors +//@ endif::[] -include::references.txt[] +include::{chapters}/references.adoc[] -== Contributors == +== Contributors Frank Brill diff --git a/etc1.txt b/chapters/etc1.adoc similarity index 95% rename from etc1.txt rename to chapters/etc1.adoc index 5503a18..ce6ba60 100644 --- a/etc1.txt +++ b/chapters/etc1.adoc @@ -1,5 +1,6 @@ -// Copyright (c) 2014-2019 The Khronos Group Inc. -// Copyright notice at https://www.khronos.org/registry/speccopyright.html +// Copyright 2014-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 + [[ETC1]] == ETC1 Compressed Texture Image Formats @@ -36,7 +37,7 @@ _d_~3~ _h_~3~ _l_~3~ _p_~3~ _d_~4~ _h_~4~ _l_~4~ _p_~4~. [[ETC18x8]] .Pixel layout for an 8×8 texture using four ETC1 compressed blocks -image::images/ETCletter8x8.{svgpdf}[width="{svgpdf@pdf:218pt:327}",align="center"] +image::{images}/ETCletter8x8.svg[width="{svgpdf@pdf:218pt:327}",align="center"] Note how pixel _a_~2~ in the second block is adjacent to pixel _m_~1~ in the first block. @@ -51,18 +52,18 @@ _q_~7~ at the highest. The 64 bits specifying the block are then represented by the following 64 bit integer: [latexmath] -++++++ +++++ \begin{align*} \mathit{int64bit} & = 256\times (256\times (256\times (256\times (256\times (256\times (256\times q_0+q_1)+q_2)+q_3)+q_4)+q_5)+q_6)+q_7 \end{align*} -++++++ +++++ Each 64-bit word contains information about a 4{times}4 pixel block as shown in <>. [[ETC1layout]] .Pixel layout for an ETC1 compressed block -image::images/ETCletterdirections.{svgpdf}[width="{svgpdf@pdf:115pt:173}",align="center"] +image::{images}/ETCletterdirections.svg[width="{svgpdf@pdf:115pt:173}",align="center"] There are two modes in ETC1: the `individual' mode and the `differential' mode. Which mode is @@ -82,7 +83,7 @@ endif::[] ifndef::a2xhtml[] [width="55%",cols="16*1"] endif::[] -|==================== +|==== 16+^| [[ETC1individual]]*a) Bit layout in bits 63 through 32 if _diff bit_ = 0* ^| ~63~ ^| ~62~ ^| ~61~ ^| ~60~ ^| ~59~ ^| ~58~ ^| ~57~ ^| ~56~ ^| ~55~ ^| ~54~ ^| ~53~ ^| ~52~ ^| ~51~ ^| ~50~ ^| ~49~ ^| ~48~ 4+^| Base color 1 @@ -156,7 +157,7 @@ _bit_ 16+^| *Less significant pixel index bits* ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ ^| _p_^0^ ^| _o_^0^ ^| _n_^0^ ^| _m_^0^ ^| _l_^0^ ^| _k_^0^ ^| _j_^0^ ^| _i_^0^ ^| _h_^0^ ^| _g_^0^ ^| _f_^0^ ^| _e_^0^ ^| _d_^0^ ^| _c_^0^ ^| _b_^0^ ^| _a_^0^ -|==================== +|==== <<< In both modes, the 4{times}4 block is divided into @@ -170,11 +171,11 @@ of each other, as shown in <>. [[ETC12x4]] .Two 2{times}4-pixel ETC1 subblocks side-by-side -image::images/ETC2x4.{svgpdf}[width="{svgpdf@pdf:142pt:213}",align="center"] +image::{images}/ETC2x4.svg[width="{svgpdf@pdf:142pt:213}",align="center"] [[ETC14x2]] .Two 4{times}2-pixel ETC1 subblocks on top of each other -image::images/ETC4x2.{svgpdf}[width="{svgpdf@pdf:142pt:213}",align="center"] +image::{images}/ETC4x2.svg[width="{svgpdf@pdf:142pt:213}",align="center"] In both individual and differential mode, a _base color_ for each subblock is stored, but the way they are stored is different in @@ -198,12 +199,12 @@ In summary, the _base colors_ for the subblocks in the individual mode are: [latexmath] -++++++ +++++ \begin{align*} \mathit{base\ color_{subblock1}} & = \mathit{extend\_4to8bits}(\mathit{R}, \mathit{G}, \mathit{B}) \\ \mathit{base\ color_{subblock2}} & = \mathit{extend\_4to8bits}(\mathit{R}_2, \mathit{G}_2, \mathit{B}_2) \end{align*} -++++++ +++++ In the `differential' mode (_diff bit_ = 1), the _base color_ for subblock 1 is derived from the five-bit codewords _R_, @@ -233,12 +234,12 @@ In summary, the _base colors_ for the subblocks in the differential mode are: [latexmath] -++++++ +++++ \begin{align*} \mathit{base\ color_{subblock1}} & = \mathit{extend\_5to8bits}(\mathit{R}, \mathit{G}, \mathit{B}) \\ \mathit{base\ color_{subblock2}} & = \mathit{extend\_5to8bits}(\mathit{R}+\mathit{R}_\mathrm{d}, \mathit{G}+\mathit{G}_\mathrm{d}, \mathit{B}+\mathit{B}_\mathrm{d}) \end{align*} -++++++ +++++ Note that these additions are not allowed to under- or overflow (go below zero or above 31). (The compression scheme can easily @@ -281,7 +282,7 @@ clamped to [0..255], resulting in the color [[ETC1modifiersets]] .Intensity modifier sets for ETC1 compressed textures [cols="2,1,1,1,1",width="48%"] -|============== +|==== ^| *_Table codeword_* 4+^.^| *Modifier table* ^| 0 >| -8   >| -2   >| 2   >| 8   ^| 1 >| -17   >| -5   >| 5   >| 17   @@ -291,19 +292,19 @@ clamped to [0..255], resulting in the color ^| 5 >| -80   >| -24   >| 24   >| 80   ^| 6 >| -106   >| -33   >| 33   >| 106   ^| 7 >| -183   >| -47   >| 47   >| 183   -|============== +|==== [[ETC1modifiermapping]] .Mapping from pixel index values to modifier values for ETC1 compressed textures [cols="1,1,3",width="50%"] -|============ +|==== 2+^| *_Pixel index_ value* .2+^.^| *Resulting modifier value* ^| *MSB* ^| *LSB* ^| 1 ^| 1 |   -b (large negative value) ^| 1 ^| 0 |   -a (small negative value) ^| 0 ^| 0 |   {plus}a (small positive value) ^| 0 ^| 1 |   {plus}b (large positive value) -|============ +|==== [NOTE] ==== diff --git a/etc2.txt b/chapters/etc2.adoc similarity index 95% rename from etc2.txt rename to chapters/etc2.adoc index 711ed96..9a276a4 100644 --- a/etc2.txt +++ b/chapters/etc2.adoc @@ -1,5 +1,6 @@ -// Copyright (c) 2014-2019 The Khronos Group Inc. -// Copyright notice at https://www.khronos.org/registry/speccopyright.html +// Copyright 2014-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 + [[ETC2]] == ETC2 Compressed Texture Image Formats @@ -98,7 +99,7 @@ _d_~3~ _h_~3~ _l_~3~ _p_~3~ _d_~4~ _h_~4~ _l_~4~ _p_~4~. [[ETC28x8]] .Pixel layout for an 8×8 texture using four ETC2 compressed blocks -image::images/ETCletter8x8.{svgpdf}[width="{svgpdf@pdf:218pt:327}",align="center"] +image::{images}/ETCletter8x8.svg[width="{svgpdf@pdf:218pt:327}",align="center"] Note how pixel _a_~3~ in the third block is adjacent to pixel _d_~1~ in the first block. @@ -122,11 +123,11 @@ _q_~0~ is located at the lowest memory address and _q_~7~ at the highest. The 64 bits specifying the block are then represented by the following 64 bit integer: [latexmath] -++++++ +++++ \begin{align*} \mathit{int64bit} & = 256\times (256\times (256\times (256\times (256\times (256\times (256\times q_0+q_1)+q_2)+q_3)+q_4)+q_5)+q_6)+q_7 \end{align*} -++++++ +++++ The number of bits that represent a 4{times}4 texel block is 128 bits if the format is RGBA ETC2 with a linear or sRGB transfer function. In @@ -140,12 +141,12 @@ This is split into two 64-bit integers, one used for color channel decompression and one for alpha channel decompression: [latexmath] -++++++ +++++ \begin{align*} \mathit{int64bit_{Alpha}} & = 256\times (256\times (256\times (256\times (256\times (256\times (256\times q_0+q_1)+q_2)+q_3)+q_4)+q_5)+q_6)+q_7 \\ \mathit{int64bit_{Color}} & = 256\times (256\times (256\times (256\times (256\times (256\times (256\times q_8+q_9)+q_{10})+q_{11})+q_{12})+q_{13})+q_{14})+q_{15} \end{align*} -++++++ +++++ <<< @@ -158,12 +159,12 @@ a three-channel 4{times}4 pixel block as shown in [[Figure-etc2-pixellayout]] .Pixel layout for an ETC2 compressed block -image::images/ETCletterdirections.{svgpdf}[width="{svgpdf@pdf:115pt:173}",align="center"] +image::{images}/ETCletterdirections.svg[width="{svgpdf@pdf:115pt:173}",align="center"] [[Table-etc2-dataformat]] .Texel Data format for ETC2 compressed texture formats [cols="1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",width="97%"] -|==================== +|==== 32+| [[ETC2ModeSelection]]  *a) Location of bits for mode selection* ^| ~63~ ^| ~62~ ^| ~61~ ^| ~60~ ^| ~59~ ^| ~58~ ^| ~57~ ^| ~56~ ^| ~55~ ^| ~54~ ^| ~53~ ^| ~52~ ^| ~51~ ^| ~50~ ^| ~49~ ^| ~48~ ^| ~47~ ^| ~46~ ^| ~45~ ^| ~44~ ^| ~43~ ^| ~42~ ^| ~41~ ^| ~40~ ^| ~39~ ^| ~38~ ^| ~37~ ^| ~36~ ^| ~35~ ^| ~34~ ^| ~33~ ^| ~32~ 5+^| _R_ 3+^| _R_~d~ 5+^| _G_ 3+^| _G_~d~ 5+^| _B_ 3+^| _B_~d~ 6+^| ...... ^| _D_ ^| . @@ -187,7 +188,7 @@ image::images/ETCletterdirections.{svgpdf}[width="{svgpdf@pdf:115pt:173}",align= ^| . 6+^| _R_ ^| _G_^6^ ^| . 6+^| _G_^5..0^ ^| _B_^5^ 3+^| ... 2+^| _B_^4..3^ ^| . 3+^| _B_^2..0^ 5+^| _R_~h~^5..1^ ^| 1 ^| _R~h~_^0^ ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 7+^| _G_~h~ 6+^| _B_~h~ 6+^| _R_~v~ 7+^| _G_~v~ 6+^| _B_~v~ -|==================== +|==== <<< @@ -226,11 +227,11 @@ they are stored is different in the two modes: [[Table-etc2-sidebyside]] .Two 2{times}4-pixel ETC2 subblocks side-by-side -image::images/ETC2x4.{svgpdf}[width="{svgpdf@pdf:142pt:213}",align="center"] +image::{images}/ETC2x4.svg[width="{svgpdf@pdf:142pt:213}",align="center"] [[Table-etc2-ontop]] .Two 4{times}2-pixel ETC2 subblocks on top of each other -image::images/ETC4x2.{svgpdf}[width="{svgpdf@pdf:142pt:213}",align="center"] +image::{images}/ETC4x2.svg[width="{svgpdf@pdf:142pt:213}",align="center"] In the `individual' mode, following the layout shown in <> of <>, the @@ -248,12 +249,12 @@ instead. In summary, the _base colors_ for the subblocks in the individual mode are: [latexmath] -++++++ +++++ \begin{align*} \mathit{base\ color_{subblock1}} & = \mathit{extend4to8bits}(\mathit{R}, \mathit{G}, \mathit{B}) \\ \mathit{base\ color_{subblock2}} & = \mathit{extend4to8bits}(\mathit{R}_2, \mathit{G}_2, \mathit{B}_2) \end{align*} -++++++ +++++ <<< @@ -286,12 +287,12 @@ In summary, the _base colors_ for the subblocks in the `differential' mode are: [latexmath] -++++++ +++++ \begin{align*} \mathit{base\ color_{subblock1}} & = \mathit{extend5to8bits}(\mathit{R}, \mathit{G}, \mathit{B}) \\ \mathit{base\ color_{subblock2}} & = \mathit{extend5to8bits}(\mathit{R}+\mathit{R}_\mathrm{d}, \mathit{G}+\mathit{G}_\mathrm{d}, \mathit{B}+\mathit{B}_\mathrm{d}) \end{align*} -++++++ +++++ Note that these additions will not under- or overflow, or one of the alternative decompression modes would have been chosen instead of the @@ -312,7 +313,7 @@ textures and can therefore be hardcoded into the decompression unit. [[Table-etc2-modifiers]] .ETC2 intensity modifier sets for `individual' and `differential' modes [cols="2,1,1,1,1",width="45%"] -|============== +|==== ^| *_Table codeword_* 4+^.^| Modifier table ^| 0 >| -8   >| -2   >| 2   >| 8   ^| 1 >| -17   >| -5   >| 5   >| 17   @@ -322,19 +323,19 @@ textures and can therefore be hardcoded into the decompression unit. ^| 5 >| -80   >| -24   >| 24   >| 80   ^| 6 >| -106   >| -33   >| 33   >| 106   ^| 7 >| -183   >| -47   >| 47   >| 183   -|============== +|==== [[Table-etc2-pixelindices]] .Mapping from pixel index values to modifier values for RGB ETC2 compressed textures [cols="1,1,3",width="50%"] -|============ +|==== 2+^.^| *_Pixel index_ value* .2+^.^| *Resulting _modifier_ value* ^| *MSB* ^| *LSB* ^| 1 ^| 1 |   -b (large negative value) ^| 1 ^| 0 |   -a (small negative value) ^| 0 ^| 0 |   {plus}a (small positive value) ^| 0 ^| 1 |   {plus}b (large positive value) -|============ +|==== Next, we identify which _modifier_ value to use from the modifier table using the two _pixel index_ bits. The _pixel index_ bits are unique for @@ -370,7 +371,7 @@ channels are modified by clamping to the range [0..255]. [[Figure-etc2-individual]] .ETC2 `individual' mode -image::images/ETC1Ind.{svgpdf}[width="{svgpdf@pdf:190.5pt:382.5}",align="center"] +image::{images}/ETC1Ind.svg[width="{svgpdf@pdf:190.5pt:382.5}",align="center"] In this example, one _base color_ is encoded as the 4-bit triple (4, 11, 9), which is expanded by _extend4to8bits_ to @@ -379,13 +380,13 @@ Modifier table 4 [-60, -18, 18, 60] is selected for this subblock giving the following _paint colors_: [options="header",width="25%",cols="2,1,1,1"] -|===== +|==== ^| Modifier ^| _R_ ^| _G_ ^| _B_ ^| -60   >| 8   >| 127   >| 93   ^| -18   >| 58   >| 169   >| 135   ^| 18   >| 86   >| 205   >| 171   ^| 60   >| 128   >| 247   >| 213   -|===== +|==== The other _base color_ is encoded as the 4-bit triple (14, 3, 8), which is expanded by _extend4to8bits_ to @@ -394,13 +395,13 @@ Modifier table 0 [-8, -2, 2, 8] is selected for this subblock, giving the following _paint colors_ for the subblock: [options="header",width="25%",cols="2,1,1,1"] -|===== +|==== ^| Modifier ^| _R_ ^| _G_ ^| _B_ ^| -8 >| 230   >| 43   >| 128   ^| -2 >| 236   >| 49   >| 134   ^| 2 >| 240   >| 53   >| 138   ^| 8 >| 246   >| 59   >| 144   -|===== +|==== In this example, none of the _paint colors_ are modified by the process of clipping the channels to the range [0..255]. @@ -426,7 +427,7 @@ modified by clamping to [0..255]. [[Figure-etc2-differential]] .ETC2 `differential' mode -image::images/ETC1Diff.{svgpdf}[width="{svgpdf@pdf:190.5pt:382.5}",align="center"] +image::{images}/ETC1Diff.svg[width="{svgpdf@pdf:190.5pt:382.5}",align="center"] Here the first subblock's _base color_ is encoded as the 5-bit triple (29, 26, 8), and expanded by _extend5to8bits_ to @@ -454,13 +455,13 @@ In this example, modifier table 2 [-29, -9, 9, 29] is applied to subblock 1's _base color_ of (239, 214, 66): [options="header",width="25%",cols="2,1,1,1"] -|===== +|==== ^| Modifier ^| _R_ ^| _G_ ^| _B_ ^| -29 >| 210   >| 185   >| 37   ^| -9 >| 230   >| 205   >| 57   ^| 9 >| 248   >| 223   >| 75   ^| 29 >| 268   >| 243   >| 95   -|===== +|==== The last row is clamped to (255, 243, 95), so subblock 1's _paint colors_ are not colinear in this example. @@ -469,13 +470,13 @@ Similarly, modifier table 3 [-42, -13, 13, 42] is applied to the _base color_ of subblock 2, (206, 189, 90): [options="header",width="25%",cols="2,1,1,1"] -|===== +|==== ^| Modifier ^| _R_ ^| _G_ ^| _B_ ^| -42 >| 164   >| 147   >| 48   ^| -13 >| 193   >| 176   >| 77   ^| 13 >| 219   >| 202   >| 103   ^| 42 >| 248   >| 231   >| 132   -|===== +|==== ==== @@ -490,24 +491,24 @@ are not stored sequentially, but in the layout shown in colors are constructed as follows: [latexmath] -++++++ +++++ \begin{align*} \mathit{base\ color\ 1} & = \mathit{extend4to8bits}(\: (\mathit{R}^{3..2} \ll 2)\: | \: \mathit{R}^{1..0}, \: \mathit{G}, \: \mathit{B}) \\ \mathit{base\ color\ 2} & = \mathit{extend4to8bits}(\mathit{R}_2, \: \mathit{G}_2, \: \mathit{B}_2) \end{align*} -++++++ +++++ -Here, latexmath:[$\ll$] denotes bit-wise left shift and latexmath:[$|$] +Here, latexmath:[\ll] denotes bit-wise left shift and latexmath:[|] denotes bit-wise OR. In the `H' mode, the two colors are constructed as follows: [latexmath] -++++++ +++++ \begin{align*} \mathit{base\ color\ 1} & = \mathit{extend4to8bits}(\mathit{R}, \: (\mathit{G}^{3..1} \ll 1) \: | \: \mathit{G}^0, \: (\mathit{B}^3 \ll 3) \: | \: \mathit{B}^{2..0}) \\ \mathit{base\ color\ 2} & = \mathit{extend4to8bits}(\mathit{R}_2, \: \mathit{G}_2, \: \mathit{B}_2) \end{align*} -++++++ +++++ Both the `T' and `H' modes have four _paint colors_ which are the colors that will be used in the decompressed block, but they are @@ -519,7 +520,7 @@ determined, which will be used to modify the luminance of one of the _base colors_. This is done by combining the values _d~a~_ and _d~b~_ shown in <> of <> by -(_d~a~_ latexmath:[$\ll$] 1) | _d~b~_, +(_d~a~_ latexmath:[\ll] 1) | _d~b~_, and then using this value as an index into the small look-up table shown in <>. For example, if _d~a~_ is 10 binary and _d~b~_ is 1 binary, the _distance index_ @@ -531,7 +532,7 @@ the `distance' _d_ subtracted. [[Table-etc2-distancetable]] .Distance table for ETC2 `T' and `H' modes [options="header",width="25%"] -|================ +|==== ^.^| Distance index ^.^| Distance _d_ ^| 0 ^| 3 ^| 1 ^| 6 @@ -541,19 +542,19 @@ the `distance' _d_ subtracted. ^| 5 ^| 32 ^| 6 ^| 41 ^| 7 ^| 64 -|================ +|==== In summary, to determine the four _paint colors_ for a `T' block: [latexmath] -+++++++++++ +++++ \begin{align*} \mathit{paint\ color\ 0} & = \mathit{base\ color\ 1} \\ \mathit{paint\ color\ 1} & = \mathit{base\ color\ 2 + (d, d, d)} \\ \mathit{paint\ color\ 2} & = \mathit{base\ color\ 2} \\ \mathit{paint\ color\ 3} & = \mathit{base\ color\ 2 - (d, d, d)} \end{align*} -+++++++++++ +++++ In both cases, the value of each channel is clamped to within [0..255]. @@ -571,7 +572,7 @@ channels are modified by clamping to [0..255]. [[Figure-etc2-T]] .ETC2 `T' mode -image::images/ETC2T.{svgpdf}[width="{svgpdf@pdf:190.5pt:382.5}",align="center"] +image::{images}/ETC2T.svg[width="{svgpdf@pdf:190.5pt:382.5}",align="center"] In this example, the first _base color_ is defined as the triple of 4-bit _RGB_ values (13, 1, 8), which is expanded by _extend4to8bits_ to @@ -600,21 +601,21 @@ is slightly more complex. In order to construct the three-bit index into the distance table shown in <>, _d~a~_ and _d~b~_ shown in <> of <> are used as the most significant bit and middle bit, respectively, but the least -significant bit is computed as (_base color 1_ value latexmath:[$\geq$] _base color 2_ +significant bit is computed as (_base color 1_ value latexmath:[\geq] _base color 2_ value), the `value' of a color for the comparison being equal to -(_R_ latexmath:[$\ll$] 16) {plus} (_G_ latexmath:[$\ll$] 8) +_ B_. +(_R_ latexmath:[\ll] 16) {plus} (_G_ latexmath:[\ll] 8) +_ B_. Once the `distance' _d_ has been determined for an `H' block, the four _paint colors_ will be: [latexmath] -+++++++++++ +++++ \begin{align*} \mathit{paint\ color\ 0} & = \mathit{base\ color\ 1 + (d, d, d)} \\ \mathit{paint\ color\ 1} & = \mathit{base\ color\ 1 - (d, d, d)} \\ \mathit{paint\ color\ 2} & = \mathit{base\ color\ 2 + (d, d, d)} \\ \mathit{paint\ color\ 3} & = \mathit{base\ color\ 2 - (d, d, d)} \end{align*} -+++++++++++ +++++ Again, all color components are clamped to within [0..255]. @@ -632,7 +633,7 @@ to the range [0..255]. [[Figure-etc2-H]] .ETC2 `H' mode -image::images/ETC2H.{svgpdf}[width="{svgpdf@pdf:190.5pt:382.5}",align="center"] +image::{images}/ETC2H.svg[width="{svgpdf@pdf:190.5pt:382.5}",align="center"] In this example, the first _base color_ is defined as the triple of 4-bit _RGB_ values (13, 1, 8), as in the `T mode' case above. @@ -650,14 +651,14 @@ must be greater than _base color 2_), corresponding to a distance _d_ of 32. This leads to the following _paint colors_: [width="50%",cols="2,1,1,1,2,1,1,1"] -|===== +|==== .2+^.^| *_Paint color_ id* 3+^| *_Base color_* ^| *Distance* 3+^| *_Paint color_* ^| *_R_* ^| *_G_* ^| *_B_* ^| *_d_* ^| *_R_* ^| *_G_* ^| *_B_* ^| 0 .2+>.^| 221 .2+>.^| 17 .2+>.^| 136 ^| {plus}32 >| 253   >| 49   >| 168   ^| 1 ^| -32 >| 189   >| -15   >| 104   ^| 2 .2+>.^| 68 .2+>.^| 204 .2+>.^| 221 ^| {plus}32 >| 100   >| 236   >| 253   ^| 3 ^| -32 >| 36   >| 172   >| 189   -|===== +|==== The _G_ channel of _paint color 1_ is clamped to 0, giving (189, 0, 104). This stops _paint color_ 1 being @@ -698,13 +699,13 @@ With three _base colors_ in _RGB_:888 format, the color of each pixel can then be determined as: [latexmath] -++++++++++++ +++++ \begin{align*} \mathit{R}(x,y) & = {x\times (\mathit{R}_\mathrm{h}-\mathit{R})\over 4.0} + {y\times (\mathit{R}_\mathrm{v}-\mathit{R})\over 4.0} + \mathit{R} \\ \mathit{G}(x,y) & = {x\times (\mathit{G}_\mathrm{h}-\mathit{G})\over 4.0} + {y\times (\mathit{G}_\mathrm{v}-\mathit{G})\over 4.0} + \mathit{G} \\ \mathit{B}(x,y) & = {x\times (\mathit{B}_\mathrm{h}-\mathit{B})\over 4.0} + {y\times (\mathit{B}_\mathrm{v}-\mathit{B})\over 4.0} + \mathit{B} \end{align*} -++++++++++++ +++++ where _x_ and _y_ are values from 0 to 3 corresponding to the pixels coordinates within the block, _x_ being in the @@ -717,16 +718,16 @@ integer if there is a tie) and then clamped to a value between 0 and 255. Note that this is equivalent to [latexmath] -++++++++++++++ +++++ \begin{align*} \mathit{R}(x,y) & = \mathit{clamp255}((x\times (\mathit{R}_\mathrm{h}-\mathit{R}) + y\times (\mathit{R}_\mathrm{v}-\mathit{R}) + 4\times \mathit{R} + 2) \gg 2) \\ \mathit{G}(x,y) & = \mathit{clamp255}((x\times (\mathit{G}_\mathrm{h}-\mathit{G}) + y\times (\mathit{G}_\mathrm{v}-\mathit{G}) + 4\times \mathit{G} + 2) \gg 2) \\ \mathit{B}(x,y) & = \mathit{clamp255}((x\times (\mathit{B}_\mathrm{h}-\mathit{B}) + y\times (\mathit{B}_\mathrm{v}-\mathit{B}) + 4\times \mathit{B} + 2) \gg 2) \end{align*} -++++++++++++++ +++++ where _clamp255_({cdot}) clamps the value to a number in the range -[0..255] and where latexmath:[$\gg$] performs bit-wise right shift. +[0..255] and where latexmath:[\gg] performs bit-wise right shift. This specification gives the output for each compression mode in 8-bit integer colors between 0 and 255, and these values all need to be @@ -740,7 +741,7 @@ values are shown as small diamonds. [[Figure-etc2-planar]] .ETC2 `planar' mode -image::images/ETC2P.{svgpdf}[width="{svgpdf@pdf:190.5pt:382.5}",align="center"] +image::{images}/ETC2P.svg[width="{svgpdf@pdf:190.5pt:382.5}",align="center"] In this example, the origin (_R_,_ G_,_ B_) is encoded as the 6-7-6-bit value (12, 64, 62), which is expanded to (48, 129, 251). @@ -755,7 +756,7 @@ The `horizontal' (interpolated by _x_) _base color_ The resulting texel colors are then: [options="header",width="25%",cols="1,1,1,1,1"] -|===== +|==== ^| _x_ ^| _y_ ^| _R_ ^| _G_ ^| _B_ ^| 0 ^| 0 >| 48   >| 129   >| 251   ^| 1 ^| 0 >| 87   >| 99   >| 226   @@ -773,7 +774,7 @@ The resulting texel colors are then: ^| 1 ^| 3 >| 172   >| 171   >| 174   ^| 2 ^| 3 >| 211   >| 142   >| 149   ^| 3 ^| 3 >| 250   >| 112   >| 124   -|===== +|==== ==== @@ -807,7 +808,7 @@ endif::[] ifndef::a2xhtml[] [width="60%"] endif::[] -|============= +|==== 16+|   *a) Bit layout in bits 63 through 48* ^| ~63~ ^| ~62~ ^| ~61~ ^| ~60~ ^| ~59~ ^| ~58~ ^| ~57~ ^| ~56~ ^| ~55~ ^| ~54~ ^| ~53~ ^| ~52~ ^| ~51~ ^| ~50~ ^| ~49~ ^| ~48~ 8+^| _base codeword_ 4+^| _multiplier_ 4+^| _table index_ @@ -820,7 +821,7 @@ endif::[] ^| _f_~{alpha}~^1^ ^| _f_~{alpha}~^0^ ^| _g_~{alpha}~^2^ ^| _g_~{alpha}~^1^ ^| _g_~{alpha}~^0^ ^| _h_~{alpha}~^2^ ^| _h_~{alpha}~^1^ ^| _h_~{alpha}~^0^ ^| _i_~{alpha}~^2^ ^| _i_~{alpha}~^1^ ^| _i_~{alpha}~^0^ ^| _j_~{alpha}~^2^ ^| _j_~{alpha}~^1^ ^| _j_~{alpha}~^0^ ^| _k_~{alpha}~^2^ ^| _k_~{alpha}~^1^ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ ^| _k_~{alpha}~^0^ ^| _l_~{alpha}~^2^ ^| _l_~{alpha}~^1^ ^| _l_~{alpha}~^0^ ^| _m_~{alpha}~^2^ ^| _m_~{alpha}~^1^ ^| _m_~{alpha}~^0^ ^| _n_~{alpha}~^2^ ^| _n_~{alpha}~^1^ ^| _n_~{alpha}~^0^ ^| _o_~{alpha}~^2^ ^| _o_~{alpha}~^1^ ^| _o_~{alpha}~^0^ ^| _p_~{alpha}~^2^ ^| _p_~{alpha}~^1^ ^| _p_~{alpha}~^0^ -|============= +|==== The 64-bits in _int64bit~Alpha~_ used to decompress the alpha channel are laid out as shown in <>. The information @@ -846,11 +847,11 @@ calculated the following way: [[Equation-etc2eac-eqn-base]] .ETC2 base [latexmath] -++++++ +++++ \begin{align*} \mathit{clamp255}(\mathit{base\ codeword} + \mathit{modifier}\times \mathit{multiplier}) \end{align*} -++++++ +++++ where _clamp255_({cdot}) maps values outside the range [0..255] to 0.0 or 255.0. @@ -868,7 +869,7 @@ one of 16 pre-determined `modifier tables', shown in [[Table-etc2eac-modifiers]] .Intensity modifier sets for RGBA ETC2 alpha component [cols="20%,10%,10%,10%,10%,10%,10%,10%,10%",width="60%",options="header"] -|================= +|==== ^| _Table index_ 8+^| Modifier table >| 0   >| -3   >| -6   >| -9   >| -15   >| 2   >| 5   >| 8   >| 14   >| 1   >| -3   >| -7   >| -10   >| -13   >| 2   >| 6   >| 9   >| 12   @@ -886,7 +887,7 @@ one of 16 pre-determined `modifier tables', shown in >| 13   >| -1   >| -2   >| -3   >| -10   >| 0   >| 1   >| 2   >| 9   >| 14   >| -4   >| -6   >| -8   >| -9   >| 3   >| 5   >| 7   >| 8   >| 15   >| -3   >| -5   >| -7   >| -9   >| 2   >| 4   >| 6   >| 8   -|================= +|==== For example, a _table index_ of 13 (1101 binary) means that we should use table [-1, -2 -3, -10, 0, 1, 2, 9]. @@ -958,11 +959,11 @@ the highest. The red component of the 4{times}4 block is then represented by the following 64-bit integer: [latexmath] -++++++ +++++ \begin{align*} \mathit{int64bit} & = 256\times (256\times (256\times (256\times (256\times (256\times (256\times q_0+q_1)+q_2)+q_3)+q_4)+q_5)+q_6)+q_7 \end{align*} -++++++ +++++ This 64-bit word contains information about a single-channel 4{times}4 pixel block as shown in <>. The 64-bit word @@ -978,11 +979,11 @@ The decoded value is calculated as: [[Equation-r11eac-eqn-start]] .Unsigned R11 EAC start [latexmath] -++++++ +++++ \begin{align*} \mathit{clamp1}\left((\mathit{base\ codeword}+0.5)\times \frac{1}{255.875} + \mathit{modifier}\times\mathit{multiplier}\times\frac{1}{255.875}\right) \end{align*} -+++++++ +++++ where _clamp1_({cdot}) maps values outside the range [0.0, 1.0] to 0.0 or 1.0. @@ -997,24 +998,24 @@ To get a value between 0 and 2047 we must multiply <> by 2047.0: [latexmath] -+++++++ +++++ \begin{align*} \mathit{clamp2}\left((\mathit{base\ codeword}+0.5)\times \frac{2047.0}{255.875} + \mathit{modifier}\times\mathit{multiplier}\times\frac{2047.0}{255.875}\right) \end{align*} -+++++++ +++++ where _clamp2_({cdot}) clamps to the range [0.0, 2047.0]. -Since latexmath:[$2047.0 \over 255.875$] is exactly 8.0, the above equation can be written as +Since latexmath:[2047.0 \over 255.875] is exactly 8.0, the above equation can be written as [[Equation-r11eac-eqn-simple]] .Unsigned R11 EAC simple [latexmath] -+++++++ +++++ \begin{align*} \mathit{clamp2}(\mathit{base\ codeword}\times 8 + 4 + \mathit{modifier} \times \mathit{multiplier} \times 8) \end{align*} -+++++++ +++++ The _base codeword_ is stored in the first 8 bits as shown in <> part (a). Bits 63..56 in each block @@ -1071,36 +1072,36 @@ This value should in turn be multiplied by 8 by left-shifting it three steps: We now add this to the base value and get 828 - 160 = 668. After clamping we still get 668 = 01010011100b. This is our 11-bit output value, which represents the -value latexmath:[${668 \over 2047} = 0.32633121 \ldots$] +value latexmath:[{668 \over 2047} = 0.32633121 \ldots] If the _multiplier_ value is zero (i.e., the _multiplier_ bits 55..52 are -all zero), we should set the _multiplier_ to latexmath:[$1.0\over 8.0$]. +all zero), we should set the _multiplier_ to latexmath:[1.0\over 8.0]. <> can then be simplified to [[Equation-r11eac-eqn-simpler]] .Unsigned R11 EAC simpler [latexmath] -++++++ +++++ \begin{align*} \mathit{clamp2}(\mathit{base\ codeword}\times 8 + 4 + \mathit{modifier}) \end{align*} -+++++++ +++++ As an example, assume a _base codeword_ of 103, a _table index_ of 13, a _pixel index_ of 3 and a _multiplier_ value of 0. We treat the _base codeword_ the same way, getting 828 = 103{times}8{plus}4. The _modifier_ is still -10. -But the _multiplier_ should now be latexmath:[$1 \over 8$], which +But the _multiplier_ should now be latexmath:[1 \over 8], which means that third term becomes -latexmath:[$-10\times \left({1\over 8}\right)\times 8 = -10$]. +latexmath:[-10\times \left({1\over 8}\right)\times 8 = -10]. The sum therefore becomes 828-10 = 818. After clamping we still get 818 = 01100110010b, and this is our 11-bit output value, and it represents -latexmath:[${818 \over 2047} = 0.39960918 \ldots$] +latexmath:[{818 \over 2047} = 0.39960918 \ldots] Some OpenGL ES implementations may find it convenient to use 16-bit values for further processing. In this case, the 11-bit value should be extended using bit replication. An 11-bit value _x_ is extended to 16 -bits through latexmath:[$(x\ll 5) + (x \gg 6)$]. For example, the value +bits through latexmath:[(x\ll 5) + (x \gg 6)]. For example, the value 668 = 01010011100b should be extended to 0101001110001010b = 21386. @@ -1113,10 +1114,10 @@ than 11 bits. Note that the method does not have the same reconstruction levels as the alpha part in the RGBA ETC2 format. For instance, for a _base codeword_ of 255 and a _table value_ of 0, the alpha part of the -RGBA ETC2 format will represent a value of latexmath:[${(255+0)\over 255.0} = 1.0$] +RGBA ETC2 format will represent a value of latexmath:[{(255+0)\over 255.0} = 1.0] exactly. In R11 EAC the same _base codeword_ and _table value_ will -instead represent latexmath:[${(255.5+0)\over 255.875} = 0.99853444 \ldots$] +instead represent latexmath:[{(255.5+0)\over 255.875} = 0.99853444 \ldots] That said, it is still possible to decode the alpha part of the RGBA ETC2-format using R11 EAC hardware. This is done by truncating the 11-bit number to 8 bits. @@ -1126,7 +1127,7 @@ becomes the 8-bit value 11111111b = 255 which is exactly the correct value according to RGBA ETC2. Clamping has to be done to [0, 255] after truncation for RGBA ETC2 decoding. Care must also be taken to handle the case when the _multiplier_ value is -zero. In the 11-bit version, this means multiplying by latexmath:[$1 \over 8$], but in +zero. In the 11-bit version, this means multiplying by latexmath:[1 \over 8], but in the 8-bit version, it really means multiplication by 0. Thus, the decoder will have to know if it is an RGBA ETC2 texture or an R11 EAC texture to decode @@ -1134,7 +1135,7 @@ correctly, but the hardware can be 100% shared. <<< As stated above, a _base codeword_ of 255 and a _table value_ of 0 will -represent a value of latexmath:[${(255.5+0) \over 255.875} = 0.99853444 \ldots$], and this +represent a value of latexmath:[{(255.5+0) \over 255.875} = 0.99853444 \ldots], and this does not reach 1.0 even though 255 is the highest possible _base codeword_. However, it is still possible to reach a pixel value of 1.0 since a _modifier_ other than 0 can be used. @@ -1144,38 +1145,38 @@ As an example, assume we choose the _base codeword_ 255, a _multiplier_ of 1 and <>, [latexmath] -++++++ +++++ \begin{align*} \mathit{clamp1}\left((\mathit{base\ codeword}+0.5)\times \frac{1}{255.875} + \mathit{table\ value} \times \mathit{multiplier} \times \frac{1}{255.875}\right) \end{align*} -++++++ +++++ we get [latexmath] -++++++ +++++ \begin{align*} \mathit{clamp1}\left((255+0.5)\times \frac{1}{255.875} + \left[ \begin{array}{cccccccc} -3 & -5 & -7 &-9 & 2 & 4 & 6 & 8 \end{array}\right] \times \frac{1}{255.875}\right) \end{align*} -++++++ +++++ which equals [latexmath] -++++++ +++++ \begin{align*} \mathit{clamp1}\left(\left[ \begin{array}{cccccccc} 0.987 & 0.979 & 0.971 & 0.963 & 1.00 & 1.01 & 1.02 & 1.03 \end{array}\right]\right) \end{align*} -++++++ +++++ or after clamping [latexmath] -++++++ +++++ \begin{align*} \left[ \begin{array}{cccccccc} 0.987 & 0.979 & 0.971 & 0.963 & 1.00 & 1.00 & 1.00 & 1.00\end{array}\right] \end{align*} -++++++ +++++ which shows that several values can be 1.0, even though the base value does not reach 1.0. The same reasoning goes for 0.0. @@ -1193,12 +1194,12 @@ The 128 bits specifying the block are then represented by the following two 64 bit integers: [latexmath] -++++++ +++++ \begin{align*} \mathit{int64bit}_0 & = 256\times (256\times (256\times (256\times (256\times (256\times (256\times q_0+q_1)+q_2)+q_3)+q_4)+q_5)+q_6)+q_7 \\ \mathit{int64bit}_1 & = 256\times (256\times (256\times (256\times (256\times (256\times (256\times p_0+p_1)+p_2)+p_3)+p_4)+p_5)+p_6)+p_7 \end{align*} -++++++ +++++ The 64-bit word _int64bit_~0~ contains information about the red component of a two-channel 4{times}4 pixel block as shown in @@ -1218,11 +1219,11 @@ The red component of the 4{times}4 block is then represented by the following 64 bit integer: [latexmath] -+++++ +++++ \begin{align*} \mathit{int64bit} & = 256\times(256\times(256\times(256\times(256\times(256\times(256\times q_0+q_1)+q_2)+q_3)+q_4)+q_5)+q_6)+q_7 \end{align*} -+++++ +++++ This 64-bit word contains information about a single-channel 4{times}4 pixel block as shown in <>. @@ -1238,11 +1239,11 @@ The decoded value is calculated as [[Equation-signedr11eac-eqn-start]] .Signed R11 EAC start [latexmath] -+++++ +++++ \begin{align*} \mathit{clamp1}\left(\mathit{base\ codeword}\times \frac{1}{127.875} + \mathit{modifier}\times \mathit{multiplier}\times \frac{1}{127.875}\right) \end{align*} -+++++ +++++ where _clamp1_({cdot}) maps values outside the range [-1.0, 1.0] to -1.0 or 1.0. @@ -1257,23 +1258,23 @@ To get a value between -1023 and 1023 we must multiply <> by 1023.0: [latexmath] -+++++ +++++ \begin{align*} \mathit{clamp2}\left(\mathit{base\ codeword}\times \frac{1023.0}{127.875} + \mathit{modifier}\times \mathit{multiplier}\times \frac{1023.0}{127.875}\right) \end{align*} -+++++ +++++ where _clamp2_({cdot}) clamps to the range [-1023.0, 1023.0]. Since -latexmath:[$1023.0\over 127.875$] is exactly 8, the above formula can be written as: +latexmath:[1023.0\over 127.875] is exactly 8, the above formula can be written as: [[Equation-signedr11eac-eqn-simple]] .Signed R11 EAC simple [latexmath] -+++++ +++++ \begin{align*} \mathit{clamp2}(\mathit{base\ codeword}\times 8 + \mathit{modifier}\times \mathit{multiplier} \times 8) \end{align*} -+++++ +++++ The _base codeword_ is stored in the first 8 bits as shown in <> part (a). It is a two's-complement value @@ -1322,37 +1323,37 @@ This value should in turn be multiplied by 8 by left-shifting it three steps: We now add this to the base value and get 480-160 = 320. After clamping we still get 320 = 00101000000b. This is our 11-bit output value, which represents the value -latexmath:[${320\over 1023} = 0.31280547\ldots$]. +latexmath:[{320\over 1023} = 0.31280547\ldots]. If the _multiplier_ value is zero (i.e., the _multiplier_ bits 55..52 are -all zero), we should set the _multiplier_ to latexmath:[$1.0 \over 8.0$]. +all zero), we should set the _multiplier_ to latexmath:[1.0 \over 8.0]. <> can then be simplified to: [[Equation-signedr11eac-eqn-simpler]] .Signed R11 EAC simpler [latexmath] -+++++ +++++ \begin{align*} \mathit{clamp2}(\mathit{base\ codeword} \times 8 + \mathit{modifier}) \end{align*} -+++++ +++++ As an example, assume a _base codeword_ of 65, a _table index_ of 13, a _pixel index_ of 3 and a _multiplier_ value of 0. We treat the _base codeword_ the same way, getting 480 = 60{times}8. The _modifier_ is still -10. -But the _multiplier_ should now be latexmath:[$1 \over 8$], which means -that third term becomes latexmath:[$-10\times\left({1 \over 8}\right)\times 8 = -10$]. +But the _multiplier_ should now be latexmath:[1 \over 8], which means +that third term becomes latexmath:[-10\times\left({1 \over 8}\right)\times 8 = -10]. The sum therefore becomes 480-10 = 470. Clamping does not affect the value since it is already in the range [-1023, 1023], and the 11-bit output value is therefore 470 = 00111010110b. -This represents latexmath:[${470\over 1023} = 0.45943304 \dots$] +This represents latexmath:[{470\over 1023} = 0.45943304 \dots] Some OpenGL ES implementations may find it convenient to use two's-complement 16-bit values for further processing. In this case, a positive 11-bit value should be extended using bit replication on all the bits except the sign bit. An 11-bit value x is extended to 16 bits through -(_x_ latexmath:[$\ll$] 5) {plus} (_x_ latexmath:[$\gg$] 5). +(_x_ latexmath:[\ll] 5) {plus} (_x_ latexmath:[\gg] 5). Since the sign bit is zero for a positive value, no addition logic is needed for the bit replication in this case. For example, the value 470 = 00111010110b in the above example should be @@ -1360,7 +1361,8 @@ expanded to 0011101011001110b = 15054. A negative 11-bit value must first be made positive before bit replication, and then made negative again: ------ +[source] +---- if (result11bit >= 0) { result16bit = (result11bit << 5) + (result11bit >> 5); } else { @@ -1368,7 +1370,7 @@ if (result11bit >= 0) { result16bit = (result11bit << 5) + (result11bit >> 5); result16bit = -result16bit; } ------ +---- Simply bit replicating a negative number without first making it positive will not give a correct result. @@ -1381,7 +1383,7 @@ the other hand, an implementation is not allowed to truncate the Note that it is not possible to specify a base value of 1.0 or -1.0. The largest possible _base codeword_ is {plus}127, which represents -latexmath:[${127 \over 127.875} = 0.993\ldots$]. +latexmath:[{127 \over 127.875} = 0.993\ldots]. However, it is still possible to reach a pixel value of 1.0 or -1.0, since the base value is modified by the table before the pixel value is calculated. Indeed, half of the _modifiers_ will often produce a value of 1.0. As an example, @@ -1391,38 +1393,38 @@ the _multiplier_ is one. Starting with <>, [latexmath] -++++++ +++++ \begin{align*} \mathit{base\ codeword}\times \frac{1}{127.875} + \mathit{modifier}\times \mathit{multiplier}\times \frac{1}{127.875} \end{align*} -++++++ +++++ we get [latexmath] -++++++ +++++ \begin{align*} \frac{127}{127.875} + \left[\begin{array}{cccccccc} -3 & -5 & -7 & -9 & 2 & 4 & 6 & 8 \end{array}\right] \times \frac{1}{127.875} \end{align*} -++++++ +++++ which equals [latexmath] -++++++ +++++ \begin{align*} \left[ \begin{array}{cccccccc} 0.970 & 0.954 & 0.938 & 0.923 & 1.01 & 1.02 & 1.04 &1.06\end{array}\right] \end{align*} -++++++ +++++ or after clamping [latexmath] -++++++ +++++ \begin{align*} \left[ \begin{array}{cccccccc} 0.970 & 0.954 & 0.938 & 0.923 & 1.00 & 1.00 & 1.00 & 1.00 \end{array}\right] \end{align*} -++++++ +++++ This shows that it is indeed possible to arrive at the value 1.0. The same reasoning goes for -1.0. @@ -1447,12 +1449,12 @@ where byte _q_~0~ is located at the lowest memory address and _p_~7~ at the high two 64 bit integers: [latexmath] -++++++ +++++ \begin{align*} \mathit{int64bit}_0 & = 256\times (256\times (256\times (256\times (256\times (256\times (256\times q_0+q_1)+q_2)+q_3)+q_4)+q_5)+q_6)+q_7 \\ \mathit{int64bit}_1 & = 256\times (256\times (256\times (256\times (256\times (256\times (256\times p_0+p_1)+p_2)+p_3)+p_4)+p_5)+p_6)+p_7 \end{align*} -++++++ +++++ The 64-bit word _int64bit_~0~ contains information about the red component of a two-channel 4{times}4 pixel block as shown in @@ -1476,7 +1478,7 @@ determining the mode used in a given block. [[Table-etc2punch-dataformat]] .Texel Data format for punchthrough alpha ETC2 compressed texture formats [cols="1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",width="97%"] -|==================== +|==== 32+|   *a) Location of bits for mode selection* ^| ~63~ ^| ~62~ ^| ~61~ ^| ~60~ ^| ~59~ ^| ~58~ ^| ~57~ ^| ~56~ ^| ~55~ ^| ~54~ ^| ~53~ ^| ~52~ ^| ~51~ ^| ~50~ ^| ~49~ ^| ~48~ ^| ~47~ ^| ~46~ ^| ~45~ ^| ~44~ ^| ~43~ ^| ~42~ ^| ~41~ ^| ~40~ ^| ~39~ ^| ~38~ ^| ~37~ ^| ~36~ ^| ~35~ ^| ~34~ ^| ~33~ ^| ~32~ 5+^| _R_ 3+^| _R_~d~ 5+^| _G_ 3+^| _G_~d~ 5+^| _B_ 3+^| _B_~d~ 6+^| ...... ^| _Op_ ^| . @@ -1497,7 +1499,7 @@ determining the mode used in a given block. ^| . 6+^| _R_ ^| _G_^6^ ^| . 6+^| _G_^5..0^ ^| _B_^5^ 3+^| ... 2+^| _B_^4..3^ ^| . 3+^| _B_^2..0^ 5+^| _R_~h~^5..1^ ^| 1 ^| _R_~h~^0^ ^| ~31~ ^| ~30~ ^| ~29~ ^| ~28~ ^| ~27~ ^| ~26~ ^| ~25~ ^| ~24~ ^| ~23~ ^| ~22~ ^| ~21~ ^| ~20~ ^| ~19~ ^| ~18~ ^| ~17~ ^| ~16~ ^| ~15~ ^| ~14~ ^| ~13~ ^| ~12~ ^| ~11~ ^| ~10~ ^| ~9~ ^| ~8~ ^| ~7~ ^| ~6~ ^| ~5~ ^| ~4~ ^| ~3~ ^| ~2~ ^| ~1~ ^| ~0~ 7+^| _G_~h~ 6+^| _B_~h~ 6+^| _R_~v~ 7+^| _G_~v~ 6+^| _B_~v~ -|==================== +|==== To determine the mode, the three 5-bit values _R_, _G_ and _B_, and the three 3-bit values _R_~d~, _G_~d~ and _B_~d~ are examined. @@ -1551,12 +1553,12 @@ In summary, the _base colors_ for the subblocks in the differential mode are: [latexmath] -++++++ +++++ \begin{align*} \mathit{base\ color_{subblock1}} & = \mathit{extend5to8bits}(\mathit{R}, \mathit{G}, \mathit{B}) \\ \mathit{base\ color_{subblock2}} & = \mathit{extend5to8bits}(\mathit{R}+\mathit{R}_\mathrm{d}, \mathit{G}+\mathit{G}_\mathrm{d}, \mathit{B}+\mathit{B}_\mathrm{d}) \end{align*} -++++++ +++++ Note that these additions will not under- or overflow, or one of the alternative decompression modes would have been chosen instead of the @@ -1565,7 +1567,7 @@ alternative decompression modes would have been chosen instead of the [[Table-etc2punch-modifiers-a]] .ETC2 intensity modifier sets for the `differential' if `opaque' (_Op_) is set [cols="3,1,1,1,1",options="header",width="40%"] -|======== +|==== ^| _Table codeword_ 4+^| Modifier table ^| 0 >| -8   >| -2   >| 2   >| 8   ^| 1 >| -17   >| -5   >| 5   >| 17   @@ -1575,12 +1577,12 @@ alternative decompression modes would have been chosen instead of the ^| 5 >| -80   >|-24   >| 24   >| 80   ^| 6 >| -106   >|-33   >| 33   >|106   ^| 7 >| -183   >|-47   >| 47   >|183   -|======== +|==== [[Table-etc2punch-modifiers-b]] .ETC2 intensity modifier sets for the `differential' if `opaque' (_Op_) is unset [cols="3,1,1,1,1",options="header",width="40%"] -|======== +|==== ^| _Table codeword_ 4+^| Modifier table ^| 0 >| -8   >| 0   >| 0   >| 8   ^| 1 >| -17   >| 0   >| 0   >| 17   @@ -1590,7 +1592,7 @@ alternative decompression modes would have been chosen instead of the ^| 5 >| -80   >| 0   >| 0   >| 80   ^| 6 >| -106   >| 0   >| 0   >| 106   ^| 7 >| -183   >| 0   >| 0   >| 183   -|======== +|==== After obtaining the _base color_, a table is chosen using the _table codewords_: For subblock 1, _table codeword 1_ is used (bits 39..37), and @@ -1635,26 +1637,26 @@ color (255, 37, 45). [[Table-etc2punch-pixelindices-a]] .ETC2 mapping from pixel index values to modifier values when `opaque' bit is set [cols="1,1,3",width="50%"] -|============ +|==== 2+^| *_Pixel index_ value* .2+^.^| *Resulting _modifier_ value* ^| *msb* ^| *lsb* ^| 1 ^| 1 |   -b (large negative value) ^| 1 ^| 0 |   -a (small negative value) ^| 0 ^| 0 |   {plus}a (small positive value) ^| 0 ^| 1 |   {plus}b (large positive value) -|============ +|==== [[Table-etc2punch-pixelindices-b]] .ETC2 mapping from pixel index values to modifier values when `opaque' bit is unset [cols="1,1,3",width="50%"] -|============ +|==== 2+^| *_Pixel index_ value* .2+^.^| *Resulting _modifier_ value* ^| *msb* ^| *lsb* ^| 1 ^| 1 |   -b (large negative value) ^| 1 ^| 0 |   0 (zero) ^| 0 ^| 0 |   0 (zero) ^| 0 ^| 1 |   {plus}b (large positive value) -|============ +|==== The alpha component is decoded using the `opaque'-bit, which is positioned in bit 33 (see @@ -1665,7 +1667,8 @@ if MSB==1 and LSB==0, the alpha value will be zero, otherwise it will be 255. Finally, if the alpha value equals 0, the red, green and blue components will also be zero. ------ +[source] +---- if (opaque == 0 && MSB == 1 && LSB == 0) { red = 0; green = 0; @@ -1674,7 +1677,7 @@ if (opaque == 0 && MSB == 1 && LSB == 0) { } else { alpha = 255; } ------ +---- Hence _paint color 2_ will equal _RGBA_ = (0, 0, 0, 0) if opaque = 0. @@ -1690,22 +1693,22 @@ stored sequentially, but in the layout shown in To clarify, in the `T' mode, the two colors are constructed as follows: [latexmath] -++++++ +++++ \begin{align*} \mathit{base\ color\ 1} & = \mathit{extend4to8bits}(\: (\mathit{R}^{3..2} \ll 2)\: | \: \mathit{R}^{1..0}, \: \mathit{G}, \: \mathit{B}) \\ \mathit{base\ color\ 2} & = \mathit{extend4to8bits}(\mathit{R}_2, \: \mathit{G}_2, \: \mathit{B}_2) \end{align*} -++++++ +++++ In the `H' mode, the two colors are constructed as follows: [latexmath] -++++++ +++++ \begin{align*} \mathit{base\ color\ 1} & = \mathit{extend4to8bits}(\mathit{R}, \: (\mathit{G}^{3..1} \ll 1) \: | \: \mathit{G}^0, \: (\mathit{B}^3 \ll 3) \: | \: \mathit{B}^{2..0}) \\ \mathit{base\ color\ 2} & = \mathit{extend4to8bits}(\mathit{R}_2, \: \mathit{G}_2, \: \mathit{B}_2) \end{align*} -++++++ +++++ The function _extend4to8bits_({cdot}) just replicates the four bits twice. This is equivalent to multiplying by 17. As an example, @@ -1719,7 +1722,7 @@ color_. To obtain the other _paint colors_, a `distance' is first determined, which will be used to modify the luminance of one of the _base colors_. This is done by combining the values _d~a~_ and _d~b~_ shown in <> part (c) by -(_d~a~_ latexmath:[$\ll$] 1) | _d~b~_, and +(_d~a~_ latexmath:[\ll] 1) | _d~b~_, and then using this value as an index into the small look-up table shown in <>. For example, if _d~a~_ is 10 binary and _d~b~_ is 1 binary, the index is 101 binary and the selected distance _d_ @@ -1729,21 +1732,22 @@ second _base color_ with the `distance' _d_ subtracted. In summary, to determine the four _paint colors_ for a `T' block: [latexmath] -++++++ +++++ \begin{align*} \mathit{paint\ color\ 0} & = \mathit{base\ color\ 1} \\ \mathit{paint\ color\ 1} & = \mathit{base\ color\ 2 + (d, d, d)} \\ \mathit{paint\ color\ 2} & = \mathit{base\ color\ 2} \\ \mathit{paint\ color\ 3} & = \mathit{base\ color\ 2 - (d, d, d)} \end{align*} -++++++ +++++ In both cases, the value of each channel is clamped to within [0..255]. Just as for the differential mode, the _RGB_ channels are set to zero if alpha is zero, and the alpha component is calculated the same way: ------ +[source] +---- if (opaque == 0 && MSB == 1 && LSB == 0) { red = 0; green = 0; @@ -1752,33 +1756,34 @@ if (opaque == 0 && MSB == 1 && LSB == 0) { } else { alpha = 255; } ------ +---- A `distance' value is computed for the `H' mode as well, but doing so is slightly more complex. In order to construct the three-bit index into the distance table shown in <>, _d~a~_ and _d~b~_ shown in <> part (d) are used as the most significant bit and middle bit, respectively, but the -least significant bit is computed as (_base color 1_ value latexmath:[$\geq$] +least significant bit is computed as (_base color 1_ value latexmath:[\geq] _base color 2_ value), the `value' of a color for the comparison being equal to -(_R_ latexmath:[$\ll$] 16) {plus} (_G_ latexmath:[$\ll$] 8)_ {plus} B_. +(_R_ latexmath:[\ll] 16) {plus} (_G_ latexmath:[\ll] 8)_ {plus} B_. Once the `distance' _d_ has been determined for an `H' block, the four _paint colors_ will be: [latexmath] -++++++ +++++ \begin{align*} \mathit{paint\ color\ 0} & = \mathit{base\ color\ 1 + (d, d, d)} \\ \mathit{paint\ color\ 1} & = \mathit{base\ color\ 1 - (d, d, d)} \\ \mathit{paint\ color\ 2} & = \mathit{base\ color\ 2 + (d, d, d)} \\ \mathit{paint\ color\ 3} & = \mathit{base\ color\ 2 - (d, d, d)} \end{align*} -++++++ +++++ Yet again, _RGB_ is zeroed if alpha is 0 and the alpha component is determined the same way: ------ +[source] +---- if (opaque == 0 && MSB == 1 && LSB == 0) { red = 0; green = 0; @@ -1787,7 +1792,7 @@ if (opaque == 0 && MSB == 1 && LSB == 0) { } else { alpha = 255; } ------ +---- Hence _paint color 2_ will have _R_ =_ G _=_ B _= alpha = 0 if opaque = 0. @@ -1827,14 +1832,14 @@ With three _base colors_ in _RGB_:888 format, the color of each pixel can then be determined as: [latexmath] -++++++ +++++ \begin{align*} \mathit{R}(x,y) & = {x\times (\mathit{R}_\mathrm{h}-\mathit{R})\over 4.0} + {y\times (\mathit{R}_\mathrm{v}-\mathit{R})\over 4.0} + \mathit{R} \\ \mathit{G}(x,y) & = {x\times (\mathit{G}_\mathrm{h}-\mathit{G})\over 4.0} + {y\times (\mathit{G}_\mathrm{v}-\mathit{G})\over 4.0} + \mathit{G} \\ \mathit{B}(x,y) & = {x\times (\mathit{B}_\mathrm{h}-\mathit{B})\over 4.0} + {y\times (\mathit{B}_\mathrm{v}-\mathit{B})\over 4.0} + \mathit{B} \\ A(x,y) & = 255 \end{align*} -++++++ +++++ where _x_ and _y_ are values from 0 to 3 corresponding to the pixels coordinates within the block, _x_ being in the _u_ direction and _y_ in the @@ -1846,14 +1851,14 @@ integer if there is a tie) and then clamped to a value between 0 and 255. Note that this is equivalent to [latexmath] -+++++++++++++++ +++++ \begin{align*} \mathit{R}(x,y) & = \mathit{clamp255}((x\times (\mathit{R}_\mathrm{h}-\mathit{R}) + y\times (\mathit{R}_\mathrm{v}-\mathit{R}) + 4\times \mathit{R} + 2) \gg 2) \\ \mathit{G}(x,y) & = \mathit{clamp255}((x\times (\mathit{G}_\mathrm{h}-\mathit{G}) + y\times (\mathit{G}_\mathrm{v}-\mathit{G}) + 4\times \mathit{G} + 2) \gg 2) \\ \mathit{B}(x,y) & = \mathit{clamp255}((x\times (\mathit{B}_\mathrm{h}-\mathit{B}) + y\times (\mathit{B}_\mathrm{v}-\mathit{B}) + 4\times \mathit{B} + 2) \gg 2) \\ A(x,y) & = 255 \end{align*} -+++++++++++++++ +++++ where _clamp255_({cdot}) clamps the value to a number in the range [0..255]. diff --git a/primaries.txt b/chapters/primaries.adoc similarity index 84% rename from primaries.txt rename to chapters/primaries.adoc index baf0145..8356001 100644 --- a/primaries.txt +++ b/chapters/primaries.adoc @@ -1,5 +1,5 @@ -// Copyright (c) 2017 The Khronos Group Inc. -// Copyright notice at https://www.khronos.org/registry/speccopyright.html +// Copyright 2017-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 [[PRIMARY_CONVERSION]] == Color primaries @@ -24,12 +24,12 @@ linear luminance. _xyY_ is related to _XYZ_ via the following formulae: [latexmath] -++++++ +++++ \begin{align*} x & = {X\over{X + Y + Z}} &&&y & = {Y\over{X + Y + Z}} &&&z & = {Z\over{X + Y + Z}} = 1 - x - y\\ &&X & = {Y\over{y}}x &&&Z & = {Y\over{y}}(1-x-y) \end{align*} -++++++ +++++ This is relevant because, although the brightness of the display in a color space definition is typically undefined, the *white point* is known: @@ -41,8 +41,8 @@ primaries. NOTE: Many color standards use the CIE D65 standard illuminant as a white point. D65 is intended to represent average daylight, and has a color temperature of approximately 6500K. In <> terms, this -white point is defined in ITU standards as latexmath:[$x=0.3127,\ y=0.3290$], -but elsewhere given as latexmath:[$x=0.312713,\ y=0.329016$]. +white point is defined in ITU standards as latexmath:[x=0.3127,\ y=0.3290], +but elsewhere given as latexmath:[x=0.312713,\ y=0.329016]. Different coordinates will affect the conversion matrices given below. The definition of the D65 white point is complicated by the constants in Planck's Law (which is a component in calculating the white point from @@ -50,25 +50,25 @@ the color temperature) having been revised since D65 was standardized, such that the standard formula for calculating CIE coordinates from the color temperature do not agree with the D65 standard. The actual color temperature of D65 is nearer to -latexmath:[$6500\times {1.4388\over 1.438} \approx 6503.6\textrm{K}$]. +latexmath:[6500\times {1.4388\over 1.438} \approx 6503.6\textrm{K}]. Assuming an arbitrary white luminance (_Y_ value) of 1.0, it is possible to express the following identity for the _X_, _Y_ and _Z_ coordinates of each color channel _R_, _G_ and _B_, and of the white point _W_: [latexmath] -++++++ +++++ \begin{align*} W_X &= R_X + G_X + B_X &W_Y &= R_Y + G_Y + B_Y = 1.0 &W_Z &= R_Z + G_Z + B_Z \end{align*} -++++++ +++++ -The identities latexmath:[$X = Y{x\over{y}}$] and -latexmath:[$Z = Y{{(1-x-y)}\over{y}}$] can be used to +The identities latexmath:[X = Y{x\over{y}}] and +latexmath:[Z = Y{{(1-x-y)}\over{y}}] can be used to re-express the above terms in the _xyY_ space: [latexmath] -++++++ +++++ \begin{align*} R_Y\left({R_x\over{R_y}}\right) + G_Y\left({G_x\over{G_y}}\right) + @@ -82,12 +82,12 @@ B_Y\left({1-B_x-B_y\over{B_y}}\right) & = W_Y\left({1-W_x-W_y\over{W_y}}\right) = {1-W_x-W_y\over{W_y}} \end{align*} -++++++ +++++ This equation for _W~Z~_ can be simplified to: [latexmath] -++++++ +++++ \begin{align*} R_Y\left({1-R_x\over{R_y}}-1\right) + G_Y\left({1-G_x\over{G_y}}-1\right) + @@ -95,87 +95,87 @@ B_Y\left({1-B_x\over{B_y}}-1\right) & = W_Y\left({1-W_x\over{W_y}}-1\right) = {1-W_x\over{W_y}}-1 \end{align*} -++++++ +++++ -Since latexmath:[$R_Y + G_Y + B_Y = W_Y = 1$], this further +Since latexmath:[R_Y + G_Y + B_Y = W_Y = 1], this further simplifies to: [latexmath] -++++++ +++++ \begin{align*} R_Y\left({1-R_x\over{R_y}}\right) + G_Y\left({1-G_x\over{G_y}}\right) + B_Y\left({1-B_x\over{B_y}}\right) & = {1-W_x\over{W_y}} \end{align*} -++++++ +++++ -The latexmath:[$R_Y+G_Y+B_Y$] term for _W~Y~_ can be multiplied by -latexmath:[$R_x\over{R_y}$] and subtracted from the equation for _W~X~_: +The latexmath:[R_Y+G_Y+B_Y] term for _W~Y~_ can be multiplied by +latexmath:[R_x\over{R_y}] and subtracted from the equation for _W~X~_: [latexmath] -++++++ -$$ G_Y\left({G_x\over{G_y}}-{R_x\over{R_y}}\right) + - B_Y\left({B_x\over{B_y}}-{R_x\over{R_y}}\right) = - {W_x\over{W_y}}-{R_x\over{R_y}}$$ -++++++ +++++ +G_Y\left({G_x\over{G_y}}-{R_x\over{R_y}}\right) + +B_Y\left({B_x\over{B_y}}-{R_x\over{R_y}}\right) = +{W_x\over{W_y}}-{R_x\over{R_y}} +++++ -Similarly, the latexmath:[$R_Y+G_Y+B_Y$] term can be multiplied by -latexmath:[$1-R_x\over{R_y}$] and subtracted from the simplified +Similarly, the latexmath:[R_Y+G_Y+B_Y] term can be multiplied by +latexmath:[1-R_x\over{R_y}] and subtracted from the simplified _W~Z~_ line: [latexmath] -++++++ -$$ G_Y\left({1-G_x\over{G_y}}-{1-R_x\over{R_y}}\right) + - B_Y\left({1-B_x\over{B_y}}-{1-R_x\over{R_y}}\right) = - {1-W_x\over{W_y}}-{1-R_x\over{R_y}}$$ -++++++ +++++ +G_Y\left({1-G_x\over{G_y}}-{1-R_x\over{R_y}}\right) + +B_Y\left({1-B_x\over{B_y}}-{1-R_x\over{R_y}}\right) = +{1-W_x\over{W_y}}-{1-R_x\over{R_y}} +++++ Finally, the _G~Y~_ term can be eliminated by multiplying the former of these -two equations by latexmath:[${1-G_x\over{G_y}}-{1-R_x\over{R_y}}$] and subtracting it -from the latter multiplied by latexmath:[${G_x\over{G_y}}-{R_x\over{R_y}}$], giving: +two equations by latexmath:[{1-G_x\over{G_y}}-{1-R_x\over{R_y}}] and subtracting it +from the latter multiplied by latexmath:[{G_x\over{G_y}}-{R_x\over{R_y}}], giving: [latexmath] -++++++ -$$ B_Y\left(\left({1-B_x\over{B_y}}-{1-R_x\over{R_y}}\right) - \left({G_x\over{G_y}}-{R_x\over{R_y}}\right) - - \left({B_x\over{B_y}}-{R_x\over{R_y}}\right) - \left({1-G_x\over{G_y}}-{1-R_x\over{R_y}}\right)\right)$$ -$$ = \left({1-W_x\over{W_y}}-{1-R_x\over{R_y}}\right) - \left({G_x\over{G_y}}-{R_x\over{R_y}}\right) - - \left({W_x\over{W_y}}-{R_x\over{R_y}}\right) - \left({1-G_x\over{G_y}}-{1-R_x\over{R_y}}\right)$$ -++++++ +++++ +B_Y\left(\left({1-B_x\over{B_y}}-{1-R_x\over{R_y}}\right) +\left({G_x\over{G_y}}-{R_x\over{R_y}}\right) - +\left({B_x\over{B_y}}-{R_x\over{R_y}}\right) +\left({1-G_x\over{G_y}}-{1-R_x\over{R_y}}\right)\right) \\ += \left({1-W_x\over{W_y}}-{1-R_x\over{R_y}}\right) +\left({G_x\over{G_y}}-{R_x\over{R_y}}\right) - +\left({W_x\over{W_y}}-{R_x\over{R_y}}\right) +\left({1-G_x\over{G_y}}-{1-R_x\over{R_y}}\right) +++++ Thus: [latexmath] -++++++ -$$ B_Y = {{\left({1-W_x\over{W_y}}-{1-R_x\over{R_y}}\right) - \left({G_x\over{G_y}}-{R_x\over{R_y}}\right) - - \left({W_x\over{W_y}}-{R_x\over{R_y}}\right) - \left({1-G_x\over{G_y}}-{1-R_x\over{R_y}}\right)} - \over{\left({1-B_x\over{B_y}}-{1-R_x\over{R_y}}\right) - \left({G_x\over{G_y}}-{R_x\over{R_y}}\right) - - \left({B_x\over{B_y}}-{R_x\over{R_y}}\right) - \left({1-G_x\over{G_y}}-{1-R_x\over{R_y}}\right)}}$$ -++++++ +++++ +B_Y = {{\left({1-W_x\over{W_y}}-{1-R_x\over{R_y}}\right) +\left({G_x\over{G_y}}-{R_x\over{R_y}}\right) - +\left({W_x\over{W_y}}-{R_x\over{R_y}}\right) +\left({1-G_x\over{G_y}}-{1-R_x\over{R_y}}\right)} +\over{\left({1-B_x\over{B_y}}-{1-R_x\over{R_y}}\right) +\left({G_x\over{G_y}}-{R_x\over{R_y}}\right) - +\left({B_x\over{B_y}}-{R_x\over{R_y}}\right) +\left({1-G_x\over{G_y}}-{1-R_x\over{R_y}}\right)}} +++++ This allows _G~Y~_ to be calculated by rearranging an earlier equation: [latexmath] -++++++ -$$ G_Y = - {{W_x\over{W_y}}-{R_x\over{R_y}} - -B_Y\left({B_x\over{B_y}}-{R_x\over{R_y}}\right) - \over{{G_x\over{G_y}}-{R_x\over{R_y}}}}$$ -++++++ +++++ +G_Y = +{{W_x\over{W_y}}-{R_x\over{R_y}} +-B_Y\left({B_x\over{B_y}}-{R_x\over{R_y}}\right) +\over{{G_x\over{G_y}}-{R_x\over{R_y}}}} +++++ And finally: [latexmath] -++++++ -$$ R_Y = 1 - G_Y - B_Y $$ -++++++ +++++ +R_Y = 1 - G_Y - B_Y +++++ These relative magnitudes allow the definition of vectors representing the color primaries in the _XYZ_ space, which in turn @@ -187,8 +187,8 @@ but sufficient to allow transformation to another set of color primaries. The transform from the defined color primaries to _XYZ_ space is: [latexmath] -++++++ -$$ \left(\begin{array}{c}X\\ +++++ +\left(\begin{array}{c}X\\ Y\\ Z\end{array}\right) = \left(\begin{array}{ccc}R_X, & G_X, & B_X \\ @@ -202,14 +202,14 @@ R_Y, & G_Y, & B_Y \\ {R_Y\over{R_y}}(1-R_x-R_y), & {G_Y\over{G_y}}(1-G_x-G_y), & {B_Y\over{B_y}}(1-B_x-B_y) \end{array}\right)\left(\begin{array}{c}R\\ G\\ -B\end{array}\right)$$ -++++++ +B\end{array}\right) +++++ The transform from _XYZ_ space to the defined color primaries is therefore: [latexmath] -++++++ -$$ \left(\begin{array}{c}R\\ +++++ +\left(\begin{array}{c}R\\ G\\ B\end{array}\right) = \left(\begin{array}{ccc}R_X, & G_X, & B_X \\ @@ -223,14 +223,14 @@ R_Y, & G_Y, & B_Y \\ {R_Y\over{R_y}}(1-R_x-R_y), & {G_Y\over{G_y}}(1-G_x-G_y), & {B_Y\over{B_y}}(1-B_x-B_y) \end{array}\right)^{-1}\left(\begin{array}{c}X\\ Y\\ -Z\end{array}\right)$$ -++++++ +Z\end{array}\right) +++++ NOTE: These transforms assume that the black point for the color space -is at latexmath:[$(X, Y, Z) = (0, 0, 0)$]. If the black point is non-zero, +is at latexmath:[(X, Y, Z) = (0, 0, 0)]. If the black point is non-zero, these transforms require a translational component. In some color spaces the black point has the same color as the white point, in which case it is also -possible to adjust the latexmath:[$(R, G, B)$] values outside the matrix. +possible to adjust the latexmath:[(R, G, B)] values outside the matrix. [NOTE] ==== @@ -326,14 +326,14 @@ descriptor for such a pixel. <> (HDTV) defines the following chromaticity coordinates: [latexmath] -++++++ +++++ \begin{align*} R_x &= 0.640 & R_y &= 0.330 \\ G_x &= 0.300 & G_y &= 0.600 \\ B_x &= 0.150 & B_y &= 0.060 \\ W_x &= 0.3127 & W_y &= 0.3290\ (\textrm{D}65) \end{align*} -++++++ +++++ These chromaticity coordinates are also shared by <> and <>. @@ -341,8 +341,8 @@ Therefore to convert from linear color values defined in terms of BT.709 color primaries to _XYZ_ space the formulae in <> result in the following matrix: [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{ccc} @@ -351,15 +351,15 @@ Z\end{array}\right) \approx 0.019331, & 0.119195, & 0.950532\end{array}\right) \left(\begin{array}{c} R_{709} \\ G_{709} \\ -B_{709}\end{array}\right)$$ -++++++ +B_{709}\end{array}\right) +++++ The inverse transformation, from the _XYZ_ space to a color defined in terms of BT.709 color primaries, is: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{709} \\ +++++ +\left(\begin{array}{c} R_{709} \\ G_{709} \\ B_{709}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -369,13 +369,12 @@ B_{709}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{709} \\ +++++ +\left(\begin{array}{c} R_{709} \\ G_{709} \\ B_{709}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -385,8 +384,7 @@ B_{709}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] NOTE: <> lists a slightly different version of this matrix, @@ -401,24 +399,24 @@ the <> standard for NTSC). The following chromaticity coordinates are defined for 625-line ``EBU'' systems: [latexmath] -++++++ +++++ \begin{align*} R_x &= 0.640 & R_y &= 0.330 \\ G_x &= 0.290 & G_y &= 0.600 \\ B_x &= 0.150 & B_y &= 0.060 \\ W_x &= 0.3127 & W_y &= 0.3290 \end{align*} -++++++ +++++ NOTE: <>, which also describes these constants in a legacy -context, approximates D65 as latexmath:[$x = 0.313,\ y = 0.329$]. +context, approximates D65 as latexmath:[x = 0.313,\ y = 0.329]. Therefore to convert from linear color values defined in terms of BT.601 color primaries for 625-line systems to _XYZ_ space the formulae in <> result in the following matrix: [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{ccc} @@ -427,15 +425,15 @@ Z\end{array}\right) \approx 0.020182, & 0.129553, & 0.939322\end{array}\right) \left(\begin{array}{c} R_{601\textrm{EBU}} \\ G_{601\textrm{EBU}} \\ -B_{601\textrm{EBU}}\end{array}\right)$$ -++++++ +B_{601\textrm{EBU}}\end{array}\right) +++++ The inverse transformation, from the _XYZ_ space to a color defined in terms of BT.601 ``EBU'' 625-line color primaries, is: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{601\textrm{EBU}} \\ +++++ +\left(\begin{array}{c} R_{601\textrm{EBU}} \\ G_{601\textrm{EBU}} \\ B_{601\textrm{EBU}}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -445,13 +443,12 @@ B_{601\textrm{EBU}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{601\textrm{EBU}} \\ +++++ +\left(\begin{array}{c} R_{601\textrm{EBU}} \\ G_{601\textrm{EBU}} \\ B_{601\textrm{EBU}}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -461,8 +458,7 @@ B_{601\textrm{EBU}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] [[PRIMARIES_BT601_SMPTE]] @@ -475,22 +471,22 @@ the <> standard for NTSC). The following chromaticity coordinates are defined in BT.601 for 525-line digital systems and in SMPTE-170M: [latexmath] -++++++ +++++ \begin{align*} R_x &= 0.630 & R_y &= 0.340 \\ G_x &= 0.310 & G_y &= 0.595 \\ B_x &= 0.155 & B_y &= 0.070 \\ W_x &= 0.3127 & W_y &= 0.3290 \end{align*} -++++++ +++++ Therefore to convert from linear color values defined in terms of BT.601 color primaries for 525-line systems to _XYZ_ space the formulae in <> result in the following matrix: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{ccc} @@ -499,13 +495,13 @@ Z\end{array}\right) \approx 0.018739, & 0.111934, & 0.958385\end{array}\right) \left(\begin{array}{c} R_{601\textrm{SMPTE}} \\ G_{601\textrm{SMPTE}} \\ -B_{601\textrm{SMPTE}}\end{array}\right)$$ -++++++ +B_{601\textrm{SMPTE}}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{ccc} @@ -514,16 +510,16 @@ Z\end{array}\right) \approx 0.018739, & 0.111934, & 0.958385\end{array}\right) \left(\begin{array}{c} R_{601\textrm{SMPTE}} \\ G_{601\textrm{SMPTE}} \\ -B_{601\textrm{SMPTE}}\end{array}\right)$$ -++++++ +B_{601\textrm{SMPTE}}\end{array}\right) +++++ endif::[] The inverse transformation, from the _XYZ_ space to a color defined in terms of BT.601 525-line color primaries, is: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{601\textrm{SMPTE}} \\ +++++ +\left(\begin{array}{c} R_{601\textrm{SMPTE}} \\ G_{601\textrm{SMPTE}} \\ B_{601\textrm{SMPTE}}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -533,13 +529,12 @@ B_{601\textrm{SMPTE}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{601\textrm{SMPTE}} \\ +++++ +\left(\begin{array}{c} R_{601\textrm{SMPTE}} \\ G_{601\textrm{SMPTE}} \\ B_{601\textrm{SMPTE}}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -549,8 +544,7 @@ B_{601\textrm{SMPTE}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] NOTE: <> used a different white point, @@ -562,14 +556,14 @@ and therefore have a <> conversion matrix. The following chromaticity coordinates are defined in <> for ultra-high-definition television: [latexmath] -++++++ +++++ \begin{align*} R_x &= 0.708 & R_y &= 0.292 \\ G_x &= 0.170 & G_y &= 0.797 \\ B_x &= 0.131 & B_y &= 0.046 \\ W_x &= 0.3127 & W_y &= 0.3290 \end{align*} -++++++ +++++ The same primaries are used for <> for HDR TV. @@ -578,8 +572,8 @@ primaries to _XYZ_ space the formulae in <> result in the following matrix: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -588,13 +582,13 @@ Z\end{array}\right) \approx 0.&000000, & 0.&028073, & 1.&060985\end{array}\right) \left(\begin{array}{c} R_{2020} \\ G_{2020} \\ -B_{2020}\end{array}\right)$$ -++++++ +B_{2020}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{ccc} @@ -603,16 +597,16 @@ Z\end{array}\right) \approx 0.000000, & 0.028073, & 1.060985\end{array}\right) \left(\begin{array}{c} R_{2020} \\ G_{2020} \\ -B_{2020}\end{array}\right)$$ -++++++ +B_{2020}\end{array}\right) +++++ endif::[] The inverse transformation, from the _XYZ_ space to a color defined in terms of BT.2020 color primaries, is: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{2020} \\ +++++ +\left(\begin{array}{c} R_{2020} \\ G_{2020} \\ B_{2020}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -622,13 +616,12 @@ B_{2020}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{2020} \\ +++++ +\left(\begin{array}{c} R_{2020} \\ G_{2020} \\ B_{2020}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -638,8 +631,7 @@ B_{2020}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] <<< @@ -650,14 +642,14 @@ The following chromaticity coordinates are defined in <> and <> as a reference to the legacy NTSC standard: [latexmath] -++++++ +++++ \begin{align*} R_x &= 0.67 & R_y &= 0.33 \\ G_x &= 0.21 & G_y &= 0.71 \\ B_x &= 0.14 & B_y &= 0.08 \\ W_x &= 0.310 & W_y &= 0.316\ (\textrm{Illuminant C}) \end{align*} -++++++ +++++ NOTE: These primaries apply to the 1953 revision of the NTSC standard. Modern NTSC systems, which reflect displays that are optimized for @@ -676,8 +668,8 @@ primaries to _XYZ_ space the formulae in <> result in the following matrix: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -686,13 +678,13 @@ Z\end{array}\right) \approx 0.&000000, & 0.&066076, & 1.&117469\end{array}\right) \left(\begin{array}{c} R_{\textrm{NTSC}} \\ G_{\textrm{NTSC}} \\ -B_{\textrm{NTSC}}\end{array}\right)$$ -++++++ +B_{\textrm{NTSC}}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{ccc} @@ -701,16 +693,16 @@ Z\end{array}\right) \approx 0.000000, & 0.066076, & 1.117469\end{array}\right) \left(\begin{array}{c} R_{\textrm{NTSC}} \\ G_{\textrm{NTSC}} \\ -B_{\textrm{NTSC}}\end{array}\right)$$ -++++++ +B_{\textrm{NTSC}}\end{array}\right) +++++ endif::[] The inverse transformation, from the _XYZ_ space to a color defined in terms of NTSC 1953 color primaries, is: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{\textrm{NTSC}} \\ +++++ +\left(\begin{array}{c} R_{\textrm{NTSC}} \\ G_{\textrm{NTSC}} \\ B_{\textrm{NTSC}}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -720,13 +712,12 @@ B_{\textrm{NTSC}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{\textrm{NTSC}} \\ +++++ +\left(\begin{array}{c} R_{\textrm{NTSC}} \\ G_{\textrm{NTSC}} \\ B_{\textrm{NTSC}}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -736,8 +727,7 @@ B_{\textrm{NTSC}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] [[PRIMARIES_PAL525]] @@ -746,14 +736,14 @@ endif::[] <> defines the following chromaticity coordinates for legacy 525-line PAL systems: [latexmath] -++++++ +++++ \begin{align*} R_x &= 0.630 & R_y &= 0.340 \\ G_x &= 0.310 & G_y &= 0.595 \\ B_x &= 0.155 & B_y &= 0.070 \\ W_x &= 0.3101 & W_y &= 0.3162\ (\textrm{Illuminant C}) \end{align*} -++++++ +++++ NOTE: This matches the color primaries from <> analog NTSC and <> 525-line encoding, but the white point used is CIE Standard @@ -765,8 +755,8 @@ primaries to _XYZ_ space the formulae in <> result in the following matrix: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -775,13 +765,13 @@ Z\end{array}\right) \approx 0.&019781, & 0.&108679, & 1.&053387\end{array}\right) \left(\begin{array}{c} R_{\textrm{PAL525}} \\ G_{\textrm{PAL525}} \\ -B_{\textrm{PAL525}}\end{array}\right)$$ -++++++ +B_{\textrm{PAL525}}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{ccc} @@ -790,16 +780,16 @@ Z\end{array}\right) \approx 0.019781, & 0.108679, & 1.053387\end{array}\right) \left(\begin{array}{c} R_{\textrm{PAL525}} \\ G_{\textrm{PAL525}} \\ -B_{\textrm{PAL525}}\end{array}\right)$$ -++++++ +B_{\textrm{PAL525}}\end{array}\right) +++++ endif::[] The inverse transformation, from the _XYZ_ space to a color defined in terms of PAL 525-line 1953 color primaries, is: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{\textrm{PAL525}} \\ +++++ +\left(\begin{array}{c} R_{\textrm{PAL525}} \\ G_{\textrm{PAL525}} \\ B_{\textrm{PAL525}}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -809,13 +799,12 @@ B_{\textrm{PAL525}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{\textrm{PAL525}} \\ +++++ +\left(\begin{array}{c} R_{\textrm{PAL525}} \\ G_{\textrm{PAL525}} \\ B_{\textrm{PAL525}}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -825,8 +814,7 @@ B_{\textrm{PAL525}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] [[PRIMARIES_ACES]] @@ -834,22 +822,22 @@ endif::[] The following chromaticity coordinates are defined in <> [latexmath] -++++++ +++++ \begin{align*} R_x &= 0.73470 & R_y &= 0.26530 \\ G_x &= 0.0 & G_y &= 1.0 \\ B_x &= 0.00010 & B_y &= -0.0770 \\ W_x &= 0.32168 & W_y &= 0.33767 \end{align*} -++++++ +++++ Therefore to convert from linear color values defined in terms of ACES color primaries to _XYZ_ space the formulae in <> result in the following matrix: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -858,13 +846,13 @@ Z\end{array}\right) \approx 0.&0, & 0.&0, & 1.&0088251844\end{array}\right) \left(\begin{array}{c} R_{\textrm{ACES}} \\ G_{\textrm{ACES}} \\ -B_{\textrm{ACES}}\end{array}\right)$$ -++++++ +B_{\textrm{ACES}}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{ccc} @@ -873,15 +861,15 @@ Z\end{array}\right) \approx 0.0, & 0.0, & 1.0088251844\end{array}\right) \left(\begin{array}{c} R_{\textrm{ACES}} \\ G_{\textrm{ACES}} \\ -B_{\textrm{ACES}}\end{array}\right)$$ -++++++ +B_{\textrm{ACES}}\end{array}\right) +++++ endif::[] The inverse transformation, from the _XYZ_ space to a color defined in terms of ACES color primaries, is: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{\textrm{ACES}} \\ +++++ +\left(\begin{array}{c} R_{\textrm{ACES}} \\ G_{\textrm{ACES}} \\ B_{\textrm{ACES}}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -891,13 +879,12 @@ B_{\textrm{ACES}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{\textrm{ACES}} \\ +++++ +\left(\begin{array}{c} R_{\textrm{ACES}} \\ G_{\textrm{ACES}} \\ B_{\textrm{ACES}}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -907,8 +894,7 @@ B_{\textrm{ACES}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] [[PRIMARIES_ACESCC]] @@ -917,22 +903,22 @@ endif::[] The following chromaticity coordinates are defined in <> (ACEScct) and S-2014-003 (ACEScc), which share the same primaries: [latexmath] -++++++ +++++ \begin{align*} R_x &= 0.713 & R_y &= 0.293 \\ G_x &= 0.165 & G_y &= 0.830 \\ B_x &= 0.128 & B_y &= 0.044 \\ W_x &= 0.32168 & W_y &= 0.33767 \end{align*} -++++++ +++++ Therefore to convert from linear color values defined in terms of ACEScc/ACEScct color primaries to _XYZ_ space the formulae in <> result in the following matrix: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -941,13 +927,13 @@ Z\end{array}\right) \approx -0.&0055746495, & 0.&0040607335, & 1.&0103391003\end{array}\right) \left(\begin{array}{c} R_{\textrm{ACEScct}} \\ G_{\textrm{ACEScct}} \\ -B_{\textrm{ACEScct}}\end{array}\right)$$ -++++++ +B_{\textrm{ACEScct}}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{ccc} @@ -956,15 +942,15 @@ Z\end{array}\right) \approx -0.0055746495, & 0.0040607335, & 1.0103391003\end{array}\right) \left(\begin{array}{c} R_{\textrm{ACEScct}} \\ G_{\textrm{ACEScct}} \\ -B_{\textrm{ACEScct}}\end{array}\right)$$ -++++++ +B_{\textrm{ACEScct}}\end{array}\right) +++++ endif::[] The inverse transformation, from the _XYZ_ space to a color defined in terms of ACEScc/ACEScct color primaries, is: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{\textrm{ACEScc}} \\ +++++ +\left(\begin{array}{c} R_{\textrm{ACEScc}} \\ G_{\textrm{ACEScc}} \\ B_{\textrm{ACEScc}}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -974,13 +960,12 @@ B_{\textrm{ACEScc}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{\textrm{ACEScc}} \\ +++++ +\left(\begin{array}{c} R_{\textrm{ACEScc}} \\ G_{\textrm{ACEScc}} \\ B_{\textrm{ACEScc}}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -990,8 +975,7 @@ B_{\textrm{ACEScc}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] <<< @@ -1000,14 +984,14 @@ endif::[] The following chromaticity coordinates are defined in <>: [latexmath] -++++++ +++++ \begin{align*} R_x &= 0.6800 & R_y &= 0.3200 \\ G_x &= 0.2650 & G_y &= 0.6900 \\ B_x &= 0.1500 & B_y &= 0.0600 \\ W_x &= 0.3127 & W_y &= 0.3290 \end{align*} -++++++ +++++ NOTE: The DCI P3 color space defines the bounds of its gamut using these primaries, but actual color data in DCI P3 is encoded using @@ -1020,8 +1004,8 @@ color primaries to _XYZ_ space the formulae in <> result in the following matrix: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -1030,13 +1014,13 @@ Z\end{array}\right) \approx 0.&0000000000, & 0.&0451133819, & 1.&0439443689\end{array}\right) = \left(\begin{array}{c} R_{\textrm{DisplayP3}} \\ G_{\textrm{DisplayP3}} \\ -B_{\textrm{DisplayP3}}\end{array}\right)$$ -++++++ +B_{\textrm{DisplayP3}}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{ccc} @@ -1045,15 +1029,15 @@ Z\end{array}\right) \approx 0.0000000000, & 0.0451133819, & 1.0439443689\end{array}\right) = \left(\begin{array}{c} R_{\textrm{DisplayP3}} \\ G_{\textrm{DisplayP3}} \\ -B_{\textrm{DisplayP3}}\end{array}\right)$$ -++++++ +B_{\textrm{DisplayP3}}\end{array}\right) +++++ endif::[] The inverse transformation, from the _XYZ_ space to a color defined in terms of DisplayP3 color primaries, is: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{\textrm{DisplayP3}} \\ +++++ +\left(\begin{array}{c} R_{\textrm{DisplayP3}} \\ G_{\textrm{DisplayP3}} \\ B_{\textrm{DisplayP3}}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -1063,12 +1047,11 @@ B_{\textrm{DisplayP3}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] ifeval::["{svgpdf}"=="svg"] -++++++ -$$\left(\begin{array}{c} R_{\textrm{DisplayP3}} \\ +++++ +\left(\begin{array}{c} R_{\textrm{DisplayP3}} \\ G_{\textrm{DisplayP3}} \\ B_{\textrm{DisplayP3}}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -1078,14 +1061,13 @@ B_{\textrm{DisplayP3}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] NOTE: These matrices differ from those given in <> due to the choice of a D65 white point in Display P3. The matrices in 432-1 can be reproduced by applying a white point -of latexmath:[$W_x = 0.314,\ W_y = 0.351$] to the above primaries. +of latexmath:[W_x = 0.314,\ W_y = 0.351] to the above primaries. <<< [[PRIMARIES_ADOBERGB]] @@ -1094,21 +1076,21 @@ of latexmath:[$W_x = 0.314,\ W_y = 0.351$] to the above primaries. The following chromaticity coordinates are defined in <>: [latexmath] -++++++ +++++ \begin{align*} R_x &= 0.6400 & R_y &= 0.3300 \\ G_x &= 0.2100 & G_y &= 0.7100 \\ B_x &= 0.1500 & B_y &= 0.0600 \\ W_x &= 0.3127 & W_y &= 0.3290 \end{align*} -++++++ +++++ Therefore to convert from linear color values defined in terms of Adobe RGB (1998) color primaries to _XYZ_ space the formulae in <> result in the following matrix: [latexmath] -++++++ -$$\left(\begin{array}{c}X \\ +++++ +\left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) \approx \left(\begin{array}{ccc} @@ -1117,14 +1099,14 @@ Z\end{array}\right) \approx 0.0270313614, & 0.0706888525, & 0.9913375368\end{array}\right) = \left(\begin{array}{c} R_{\textrm{AdobeRGB}} \\ G_{\textrm{AdobeRGB}} \\ -B_{\textrm{AdobeRGB}}\end{array}\right)$$ -++++++ +B_{\textrm{AdobeRGB}}\end{array}\right) +++++ The inverse transformation, from the _XYZ_ space to a color defined in terms of Adobe RGB (1998) color primaries, is: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{\textrm{AdobeRGB}} \\ +++++ +\left(\begin{array}{c} R_{\textrm{AdobeRGB}} \\ G_{\textrm{AdobeRGB}} \\ B_{\textrm{AdobeRGB}}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -1134,13 +1116,12 @@ B_{\textrm{AdobeRGB}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{\textrm{AdobeRGB}} \\ +++++ +\left(\begin{array}{c} R_{\textrm{AdobeRGB}} \\ G_{\textrm{AdobeRGB}} \\ B_{\textrm{AdobeRGB}}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -1150,8 +1131,7 @@ B_{\textrm{AdobeRGB}}\end{array}\right) \approx \left(\begin{array}{c}X \\ Y \\ Z\end{array}\right) -$$ -++++++ +++++ endif::[] Adobe RGB (1998) defines a reference display white brightness of 160cd/m^2^ and @@ -1169,8 +1149,8 @@ as follows: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{601\textrm{EBU}} \\ +++++ +\left(\begin{array}{c} R_{601\textrm{EBU}} \\ G_{601\textrm{EBU}} \\ B_{601\textrm{EBU}}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -1183,13 +1163,13 @@ B_{601\textrm{EBU}}\end{array}\right) \approx 0.019331, & 0.119195, & 0.950532\end{array}\right) \left(\begin{array}{c} R_{709} \\ G_{709} \\ -B_{709}\end{array}\right)$$ -++++++ +B_{709}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{601\textrm{EBU}} \\ +++++ +\left(\begin{array}{c} R_{601\textrm{EBU}} \\ G_{601\textrm{EBU}} \\ B_{601\textrm{EBU}}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -1202,14 +1182,14 @@ B_{601\textrm{EBU}}\end{array}\right) \approx 0.019331, & 0.119195, & 0.950532\end{array}\right) \left(\begin{array}{c} R_{709} \\ G_{709} \\ -B_{709}\end{array}\right)$$ -++++++ +B_{709}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{601\textrm{EBU}} \\ +++++ +\left(\begin{array}{c} R_{601\textrm{EBU}} \\ G_{601\textrm{EBU}} \\ B_{601\textrm{EBU}}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -1218,13 +1198,13 @@ B_{601\textrm{EBU}}\end{array}\right) \approx 0.&0, & -0.&011934, & 1.&011934\end{array}\right) \left(\begin{array}{c} R_{709} \\ G_{709} \\ -B_{709}\end{array}\right)$$ -++++++ +B_{709}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{601\textrm{EBU}} \\ +++++ +\left(\begin{array}{c} R_{601\textrm{EBU}} \\ G_{601\textrm{EBU}} \\ B_{601\textrm{EBU}}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -1233,8 +1213,8 @@ B_{601\textrm{EBU}}\end{array}\right) \approx 0.0, & -0.011934, & 1.011934\end{array}\right) \left(\begin{array}{c} R_{709} \\ G_{709} \\ -B_{709}\end{array}\right)$$ -++++++ +B_{709}\end{array}\right) +++++ endif::[] Conversion from BT.601 625-line to BT.709 primaries can be performed @@ -1242,8 +1222,8 @@ using these matrices: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{709} \\ +++++ +\left(\begin{array}{c} R_{709} \\ G_{709} \\ B_{709}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -1256,13 +1236,13 @@ B_{709}\end{array}\right) \approx 0.020182, & 0.129553, & 0.939322\end{array}\right) \left(\begin{array}{c} R_{601\textrm{EBU}} \\ G_{601\textrm{EBU}} \\ -B_{601\textrm{EBU}}\end{array}\right)$$ -++++++ +B_{601\textrm{EBU}}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{709} \\ +++++ +\left(\begin{array}{c} R_{709} \\ G_{709} \\ B_{709}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -1275,14 +1255,14 @@ B_{709}\end{array}\right) \approx 0.020182, & 0.129553, & 0.939322\end{array}\right) \left(\begin{array}{c} R_{601\textrm{EBU}} \\ G_{601\textrm{EBU}} \\ -B_{601\textrm{EBU}}\end{array}\right)$$ -++++++ +B_{601\textrm{EBU}}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{709} \\ +++++ +\left(\begin{array}{c} R_{709} \\ G_{709} \\ B_{709}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -1291,13 +1271,13 @@ B_{709}\end{array}\right) \approx 0.&0, & 0.&011793, & 0.&988207\end{array}\right) \left(\begin{array}{c} R_{601\textrm{EBU}} \\ G_{601\textrm{EBU}} \\ -B_{601\textrm{EBU}}\end{array}\right)$$ -++++++ +B_{601\textrm{EBU}}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{709} \\ +++++ +\left(\begin{array}{c} R_{709} \\ G_{709} \\ B_{709}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -1306,8 +1286,8 @@ B_{709}\end{array}\right) \approx 0.0, & 0.011793, & 0.988207\end{array}\right) \left(\begin{array}{c} R_{601\textrm{EBU}} \\ G_{601\textrm{EBU}} \\ -B_{601\textrm{EBU}}\end{array}\right)$$ -++++++ +B_{601\textrm{EBU}}\end{array}\right) +++++ endif::[] === BT.709/BT.2020 primary conversion example @@ -1318,8 +1298,8 @@ as follows: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{2020} \\ +++++ +\left(\begin{array}{c} R_{2020} \\ G_{2020} \\ B_{2020}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -1332,13 +1312,13 @@ B_{2020}\end{array}\right) \approx 0.019331, & 0.119195, & 0.950532\end{array}\right) \left(\begin{array}{c} R_{709} \\ G_{709} \\ -B_{709}\end{array}\right)$$ -++++++ +B_{709}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{2020} \\ +++++ +\left(\begin{array}{c} R_{2020} \\ G_{2020} \\ B_{2020}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -1351,13 +1331,13 @@ B_{2020}\end{array}\right) \approx 0.019331, & 0.119195, & 0.950532\end{array}\right) \left(\begin{array}{c} R_{709} \\ G_{709} \\ -B_{709}\end{array}\right)$$ -++++++ +B_{709}\end{array}\right) +++++ endif::[] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{2020} \\ +++++ +\left(\begin{array}{c} R_{2020} \\ G_{2020} \\ B_{2020}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -1366,16 +1346,16 @@ B_{2020}\end{array}\right) \approx 0.016392, & 0.088013, & 0.895595\end{array}\right) \left(\begin{array}{c} R_{709} \\ G_{709} \\ -B_{709}\end{array}\right)$$ -++++++ +B_{709}\end{array}\right) +++++ Conversion from BT.2020 primaries to BT.709 primaries can be performed with the following matrices: ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{709} \\ +++++ +\left(\begin{array}{c} R_{709} \\ G_{709} \\ B_{709}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -1388,13 +1368,13 @@ B_{709}\end{array}\right) \approx 0.&000000, & 0.&028073, & 1.&060985\end{array}\right) \left(\begin{array}{c} R_{2020} \\ G_{2020} \\ -B_{2020}\end{array}\right)$$ -++++++ +B_{2020}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{709} \\ +++++ +\left(\begin{array}{c} R_{709} \\ G_{709} \\ B_{709}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -1407,14 +1387,14 @@ B_{709}\end{array}\right) \approx 0.000000, & 0.028073, & 1.060985\end{array}\right) \left(\begin{array}{c} R_{2020} \\ G_{2020} \\ -B_{2020}\end{array}\right)$$ -++++++ +B_{2020}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="pdf"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{709} \\ +++++ +\left(\begin{array}{c} R_{709} \\ G_{709} \\ B_{709}\end{array}\right) \approx \left(\begin{array}{r@{}lr@{}lr@{}l} @@ -1424,13 +1404,13 @@ B_{709}\end{array}\right) \approx \end{array}\right) \left(\begin{array}{c} R_{2020} \\ G_{2020} \\ -B_{2020}\end{array}\right)$$ -++++++ +B_{2020}\end{array}\right) +++++ endif::[] ifeval::["{svgpdf}"=="svg"] [latexmath] -++++++ -$$\left(\begin{array}{c} R_{709} \\ +++++ +\left(\begin{array}{c} R_{709} \\ G_{709} \\ B_{709}\end{array}\right) \approx \left(\begin{array}{ccc} @@ -1440,6 +1420,6 @@ B_{709}\end{array}\right) \approx \end{array}\right) \left(\begin{array}{c} R_{2020} \\ G_{2020} \\ -B_{2020}\end{array}\right)$$ -++++++ +B_{2020}\end{array}\right) +++++ endif::[] diff --git a/pvrtc.txt b/chapters/pvrtc.adoc similarity index 69% rename from pvrtc.txt rename to chapters/pvrtc.adoc index 57c513c..3aa84b3 100644 --- a/pvrtc.txt +++ b/chapters/pvrtc.adoc @@ -1,5 +1,6 @@ -// Copyright (c) 2014-2019 The Khronos Group Inc. -// Copyright notice at https://www.khronos.org/registry/speccopyright.html +// Copyright 2014-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 + [[PVRTC]] == PVRTC Compressed Texture Image Formats @@ -33,7 +34,7 @@ to reconstruct the original image. If combined with this encoding scheme, the <> is applied to the unquantized version of the _R′_, _G′_ and _B′_ channels (that is, -latexmath:[$\textit{R}_\textit{out} = \textit{EOTF}_{\textit{sRGB}}\left({\textit{R}'\over 255}\right)$], +latexmath:[\textit{R}_\textit{out} = \textit{EOTF}_{\textit{sRGB}}\left({\textit{R}'\over 255}\right)], etc.) at the end of the texel decode process, but the _A_ channel is interpreted linearly. @@ -43,10 +44,10 @@ interpreted linearly. For PVRTC1 4bpp, each 64-bit word _W_~_X_,_Y_~ at block coordinates (_X_,_Y_) contains the modulation information for a 4{times}4 block of texels beginning -at image pixels latexmath:[$(4\times\mathit{X}, 4\times\mathit{Y})$], and a +at image pixels latexmath:[(4\times\mathit{X}, 4\times\mathit{Y})], and a color sample for each low-resolution image which influences an overlapping 7{times}7 texel region of the final output, with each sample centered on -output pixel latexmath:[$((4\times\mathit{X})+2, (4\times\mathit{Y})+2)$]. +output pixel latexmath:[((4\times\mathit{X})+2, (4\times\mathit{Y})+2)]. Nearly every texel location requires data from a set of 2{times}2 data words in order to be decoded: the low-resolution encoded images are bilinearly interpolated to, in effect, generate a pair of full-resolution images prior to modulation, and this @@ -68,14 +69,14 @@ color contains a bit to describe whether it contains alpha data. .Texel Data format for PVRTC1 4bpp compressed texture formats [width="97%",cols="32*^"] -|======= +|==== 32+| *~Bits 64..32: Color data and flags~* | ~63~ | ~62~ | ~61~ | ~60~ | ~59~ | ~58~ | ~57~ | ~56~ | ~55~ | ~54~ | ~53~ | ~52~ | ~51~ | ~50~ | ~49~ | ~48~ | ~47~ | ~46~ | ~45~ | ~44~ | ~43~ | ~42~ | ~41~ | ~40~ | ~39~ | ~38~ | ~37~ | ~36~ | ~35~ | ~34~ | ~33~ | ~32~ 16+| *Color B* 15+| *Color A* | _M_ 32+| *~Bits 31..0: Modulation data bits [1..0] for pixel offset (_x_, _y_)~* | ~31~ | ~30~ | ~29~ | ~28~ | ~27~ | ~26~ | ~25~ | ~24~ | ~23~ | ~22~ | ~21~ | ~20~ | ~19~ | ~18~ | ~17~ | ~16~ | ~15~ | ~14~ | ~13~ | ~12~ | ~11~ | ~10~ | ~9~ | ~8~ | ~7~ | ~6~ | ~5~ | ~4~ | ~3~ | ~2~ | ~1~ | ~0~ 2+| 3,3 2+| 2,3 2+| 1,3 2+| 0,3 2+| 3,2 2+| 2,2 2+| 1,2 2+| 0,2 2+| 3,1 2+| 2,1 2+| 1,1 2+| 0,1 2+| 3,0 2+| 2,0 2+| 1,0 2+| 0,0 -|======= +|==== ==== PVRTC1 4bpp word offset calculation @@ -85,27 +86,27 @@ word _W~X,Y~_: [[Morton]] .Reflected Morton order 16×4-block image -image::images/Morton.{svgpdf}[title="Reflected Morton Order 16×4-block image",width="{svgpdf@pdf:321pt:426}",align="center"] +image::{images}/Morton.svg[title="Reflected Morton Order 16×4-block image",width="{svgpdf@pdf:321pt:426}",align="center"] Expressing each of the _X_ and _Y_ indices as an array of bits, the index of a particular PVRTC word can be found by interleaving the bits of the _X_ and _Y_ indices as follows: -Let _Xb_ be the number of bits used to express _X_ -- i.e. latexmath:[$\mathit{Xb} = \mathrm{log}_2\left(\left\lceil{\mathit{width}\over 4}\right\rceil\right)$]. +Let _Xb_ be the number of bits used to express _X_ -- i.e. latexmath:[\mathit{Xb} = \mathrm{log}_2\left(\left\lceil{\mathit{width}\over 4}\right\rceil\right)]. -Let _Yb_ be the number of bits used to express _Y_ -- i.e. latexmath:[$\mathit{Yb} = \mathrm{log}_2\left(\left\lceil{\mathit{height}\over 4}\right\rceil\right)$]. +Let _Yb_ be the number of bits used to express _Y_ -- i.e. latexmath:[\mathit{Yb} = \mathrm{log}_2\left(\left\lceil{\mathit{height}\over 4}\right\rceil\right)]. Then: [latexmath] -++++++ +++++ \begin{align*} \textit{Reflected Morton order offset W}_\textit{X,Y} &= \begin{cases} \mathit{X}^{\textit{Xb}}\ldots\mathit{X}^\textrm{n}\ldots\mathit{X}^{\textit{Yb}+1}\mathit{X}^{\textit{Yb}}\mathit{Y}^{\textit{Yb}}\ldots\mathit{X}^\textrm{m}\mathit{Y}^\textrm{m}\ldots\mathit{X}^0\mathit{Y}^0, & \textrm{width} \geq \textrm{height} \\ \mathit{Y}^{\textit{Yb}}\ldots\mathit{Y}^\textrm{n}\ldots\mathit{Y}^{\textit{Xb}+1}\mathit{X}^{\textit{Xb}}\mathit{Y}^{\textit{Xb}}\ldots\mathit{X}^\textrm{m}\mathit{Y}^\textrm{m}\ldots\mathit{X}^0\mathit{Y}^0, & \textrm{width} < \textrm{height} \end{cases} \\ \end{align*} -++++++ +++++ That is, to form the word offset, bits of _X_ and _Y_ are interleaved, with bits from _Y_ in the lower of each interleaved pair. @@ -118,8 +119,8 @@ larger, are appended to the offset bit pattern. For example, <> represents a 64{times}16-texel image represented by 16{times}4 = 64 words of 64 bits. The largest possible _X_ value in this example is -latexmath:[${64\over 4} - 1$] = 15; the largest possible -_Y_ value in this example is latexmath:[${16\over 4} - 1$] = 3. +latexmath:[{64\over 4} - 1] = 15; the largest possible +_Y_ value in this example is latexmath:[{16\over 4} - 1] = 3. The bottom four bits of the word offset are composed by interleaving the bottom two bits of _Y_ and the bottom two bits of _X_ (with _Y_ in the lowest bit). @@ -131,29 +132,30 @@ is constructed as follows: .Calculation of reflected Morton word offset for 13,2 [width="35%"] -|======= +|==== 2+^| _X_ ^| *1* ^| *1* 2+^| *0* 2+^| *1* 2+^| = 13 2+^| _W~13,2~_ ^| *1* ^| *1* ^| *0* ^| _1_ ^| *1* ^| _0_ 2+^| = 54 2+^| _Y_ 2+^| 2+^| _1_ 2+^| _0_ 2+^| = 2 -|======= +|==== Where _wordWidth_ and _wordHeight_ are the image width and height in units of 4{times}4 areas encoded by words: [latexmath] -++++++ +++++ \begin{align*} \textit{wordWidth} =& \left\lceil{\textit{width}\over 4}\right\rceil \\ \textit{wordHeight} =& \left\lceil{\textit{height}\over 4}\right\rceil \end{align*} -++++++ +++++ the word offset for -latexmath:[$\mathit{X} = \left\lfloor{\mathit{x}\over 4}\right\rfloor$] and -latexmath:[$\mathit{Y} = \left\lfloor{\mathit{y}\over 4}\right\rfloor$] can +latexmath:[\mathit{X} = \left\lfloor{\mathit{x}\over 4}\right\rfloor] and +latexmath:[\mathit{Y} = \left\lfloor{\mathit{y}\over 4}\right\rfloor] can be calculated iteratively as follows: ------ +[source] +---- uint32_t reflectedMortonOffset(const uint32_t X, const uint32_t Y, const uint32_t wordWidth, @@ -180,7 +182,7 @@ uint32_t reflectedMortonOffset(const uint32_t X, return offset; } ------ +---- <<< @@ -192,52 +194,52 @@ corresponding to the (_X~Low~_, _Y~Low~_) location of the colors in the low-resolution images. The image colors for a given pixel location (_x_, _y_) are reconstructed using the words containing the four nearest color samples: -latexmath:[$W_{X_\textit{Low},Y_\textit{Low}}$], -latexmath:[$W_{X_\textit{Low}+1,Y_\textit{Low}}$], -latexmath:[$W_{X_\textit{Low},Y_\textit{Low}+1}$] and -latexmath:[$W_{X_\textit{Low}+1,Y_\textit{Low}+1}$], +latexmath:[W_{X_\textit{Low},Y_\textit{Low}}], +latexmath:[W_{X_\textit{Low}+1,Y_\textit{Low}}], +latexmath:[W_{X_\textit{Low},Y_\textit{Low}+1}] and +latexmath:[W_{X_\textit{Low}+1,Y_\textit{Low}+1}], where _X~Low~_ and _Y~Low~_ are derived as follows: [latexmath] -++++++ +++++ \begin{align*} X_\textit{Low}=&\left\lfloor{{x - 2}\over 4}\right\rfloor & Y_\textit{Low}=&\left\lfloor{{y - 2}\over 4}\right\rfloor \end{align*} -++++++ +++++ [NOTE] -===== +==== <> shows a grid of pixels with (_x_ = 0, _y_ = 0) at top left. -Each word latexmath:[$W_{X_\mathit{Mod},Y_\mathit{Mod}}$] holds modulation +Each word latexmath:[W_{X_\mathit{Mod},Y_\mathit{Mod}}] holds modulation values for a 4{times}4 texel region -latexmath:[$\mathbf{M}_{\mathbf{X}_\mathbf{Mod},\mathbf{Y}_\mathbf{Mod}}$], +latexmath:[\mathbf{M}_{\mathbf{X}_\mathbf{Mod},\mathbf{Y}_\mathbf{Mod}}], as described in <>, where -latexmath:[$X_\mathit{Mod} = \left\lfloor{x\over 4}\right\rfloor$] -and latexmath:[$Y_\mathit{Mod} = \left\lfloor{y\over 4}\right\rfloor$]. +latexmath:[X_\mathit{Mod} = \left\lfloor{x\over 4}\right\rfloor] +and latexmath:[Y_\mathit{Mod} = \left\lfloor{y\over 4}\right\rfloor]. -For latexmath:[$X_\mathit{Low} = \left\lfloor{{x - 2}\over 4}\right\rfloor$] -and latexmath:[$Y_\mathit{Low} = \left\lfloor{{y - 2}\over 4}\right\rfloor$], +For latexmath:[X_\mathit{Low} = \left\lfloor{{x - 2}\over 4}\right\rfloor] +and latexmath:[Y_\mathit{Low} = \left\lfloor{{y - 2}\over 4}\right\rfloor], color reconstruction for the pixels shaded in <> requires data -from the words latexmath:[$W_{X_\mathit{Low},Y_\mathit{Low}}$] through -latexmath:[$W_{X_\mathit{Low}+1,Y_\mathit{Low}+1}$]; the pixels for +from the words latexmath:[W_{X_\mathit{Low},Y_\mathit{Low}}] through +latexmath:[W_{X_\mathit{Low}+1,Y_\mathit{Low}+1}]; the pixels for which these these words hold modulation values are shown as -latexmath:[$\mathbf{M}_{\mathbf{X}_\mathbf{Mod},\mathbf{Y}_\mathbf{Mod}}$] +latexmath:[\mathbf{M}_{\mathbf{X}_\mathbf{Mod},\mathbf{Y}_\mathbf{Mod}}] through -latexmath:[$\mathbf{M}_{\mathbf{X}_\mathbf{Mod}+1,\mathbf{Y}_\mathbf{Mod}+1}$], +latexmath:[\mathbf{M}_{\mathbf{X}_\mathbf{Mod}+1,\mathbf{Y}_\mathbf{Mod}+1}], outlined in red. All pixels within the region contained by the dashed outline have the same -values for latexmath:[$X_\mathit{Low}$] and latexmath:[$Y_\mathit{Low}$]. +values for latexmath:[X_\mathit{Low}] and latexmath:[Y_\mathit{Low}]. The remaining shaded pixels have different calculated -latexmath:[$X_\mathit{Low}$] and/or latexmath:[$Y_\mathit{Low}$] values, but +latexmath:[X_\mathit{Low}] and/or latexmath:[Y_\mathit{Low}] values, but due to <>, no contribution is required from additional words. [[PVRTCrecon]] .PVRTC1 image reconstruction -image::images/PVRTC1_image_reconstruction_simple.{svgpdf}[width="{svgpdf@pdf:350pt:550}",align="center"] -===== +image::{images}/PVRTC1_image_reconstruction_simple.svg[width="{svgpdf@pdf:350pt:550}",align="center"] +==== <<< @@ -245,27 +247,27 @@ The texture data words are wrapped toroidally, such that the ``nearest'' sample may exist on the opposite side of the image. [NOTE] -===== +==== For example, sampling a pixel in any corner of the image results in the words in all four corners being examined -- or sampling a pixel at the bottom of the image will result in words from the top of the image being examined, as shown in <>. In this example, the nearest samples ``below'' the shaded pixels in regions -latexmath:[$\mathbf{M}_{\mathbf{X}_\mathbf{Mod},\mathbf{Y}_\mathbf{Mod}}$] +latexmath:[\mathbf{M}_{\mathbf{X}_\mathbf{Mod},\mathbf{Y}_\mathbf{Mod}}] and -latexmath:[$\mathbf{M}_{\mathbf{X}_\mathbf{Mod}+1,\mathbf{Y}_\mathbf{Mod}}$] +latexmath:[\mathbf{M}_{\mathbf{X}_\mathbf{Mod}+1,\mathbf{Y}_\mathbf{Mod}}] the row of words at the top of the image, and the nearest samples ``above'' the shaded pixels in regions -latexmath:[$\mathbf{M}_{\mathbf{X}_\mathbf{Mod},\mathbf{Y}_\mathbf{Mod}+1}$] +latexmath:[\mathbf{M}_{\mathbf{X}_\mathbf{Mod},\mathbf{Y}_\mathbf{Mod}+1}] and -latexmath:[$\mathbf{M}_{\mathbf{X}_\mathbf{Mod}+1,\mathbf{Y}_\mathbf{Mod}+1}$] -are in words latexmath:[$W_{X_\mathit{Low},Y_\mathit{Low}}$] and -latexmath:[$W_{X_\mathit{Low}+1,Y_\mathit{Low}}$] at the bottom of the image. +latexmath:[\mathbf{M}_{\mathbf{X}_\mathbf{Mod}+1,\mathbf{Y}_\mathbf{Mod}+1}] +are in words latexmath:[W_{X_\mathit{Low},Y_\mathit{Low}}] and +latexmath:[W_{X_\mathit{Low}+1,Y_\mathit{Low}}] at the bottom of the image. [[PVRTCwraprecon]] .PVRTC1 image reconstruction (wrapping) -image::images/PVRTC1_image_reconstruction_wrap.{svgpdf}[width="{svgpdf@pdf:300pt:466}",align="center"] -===== +image::{images}/PVRTC1_image_reconstruction_wrap.svg[width="{svgpdf@pdf:300pt:466}",align="center"] +==== <<< @@ -279,7 +281,7 @@ The exact data layout of each color is described below: .Data layout of color segments in a PVRTC1 word [cols="^,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1",width="55%"] -|==================================================================== +|==== 16+s| ~*Color B* -- opaque color mode (opacity flag _Op_ = 1)~ | ~63~ | ~62~ | ~61~ | ~60~ | ~59~ | ~58~ | ~57~ | ~56~ | ~55~ | ~54~ | ~53~ | ~52~ | ~51~ | ~50~ | ~49~ | ~48~ | 1 5+| Red 5+| Green 5+| Blue @@ -292,7 +294,7 @@ The exact data layout of each color is described below: 16+s| ~*Color A* -- translucent color mode (opacity flag _Op_ = 0)~ | ~47~ | ~46~ | ~45~ | ~44~ | ~43~ | ~42~ | ~41~ | ~40~ | ~39~ | ~38~ | ~37~ | ~36~ | ~35~ | ~34~ | ~33~ | ~32~ | 0 3+| Alpha 4+| Red 4+| Green 3+| Blue | _M_ -|==================================================================== +|==== <<< @@ -317,27 +319,27 @@ For each channel _C_ of each color (*Color A* and *Color B*), the interpolation proceeds as follows: * For low-resolution image color channel -latexmath:[$\textbf{C}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] +latexmath:[\textbf{C}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] stored in word -latexmath:[$\textit{W}_{\textit{X}_\textit{Low},\textit{Y}_\textit{Low}}$]: -** _X~Low~_ = latexmath:[$\left\lfloor{{x-2}\over 4}\right\rfloor$], +latexmath:[\textit{W}_{\textit{X}_\textit{Low},\textit{Y}_\textit{Low}}]: +** _X~Low~_ = latexmath:[\left\lfloor{{x-2}\over 4}\right\rfloor], as described above. -** _Y~Low~_ = latexmath:[$\left\lfloor{{y-2}\over 4}\right\rfloor$], +** _Y~Low~_ = latexmath:[\left\lfloor{{y-2}\over 4}\right\rfloor], as described above. * Using relative coordinates: -** latexmath:[$x_r +** latexmath:[x_r = (x - 2) - \left(4\times\left\lfloor{{x - 2}\over 4}\right\rfloor\right) -= (x - 2) - (4 \times X_\textit{Low})$] -** latexmath:[$y_r += (x - 2) - (4 \times X_\textit{Low})] +** latexmath:[y_r = (y - 2) - \left(4\times\left\lfloor{{y - 2}\over 4}\right\rfloor\right) -= (y - 2) - (4 \times Y_\textit{Low})$] += (y - 2) - (4 \times Y_\textit{Low})] * Coordinates wrap at the edges of the image. * An interpolation is performed which is mathematically equivalent to <>. [[PVRTC1_4bpp_interpolation]] .PVRTC1 4bpp color channel interpolation [latexmath] -++++++ +++++ \begin{align*} \textit{C}_\textit{x,y} = & \left(\textbf{C}_{\textbf{X}_\textbf{Low}, \textbf{Y}_\textbf{Low}} @@ -350,26 +352,26 @@ as described above. \left(\textbf{C}_{\textbf{X}_\textbf{Low}+1, \textbf{Y}_\textbf{Low}+1} \times x_r \times y_r\right) \end{align*} -++++++ +++++ [NOTE] ==== The colors of **Image A** and **Image B** at -(latexmath:[$x = (4 \times X_\mathit{Low} + 2)$], -latexmath:[$y = (4 \times Y_\mathit{Low} + 2)$]) are exactly the +(latexmath:[x = (4 \times X_\mathit{Low} + 2)], +latexmath:[y = (4 \times Y_\mathit{Low} + 2)]) are exactly the corresponding colors that word -latexmath:[$W_{X_\mathit{Low}, Y_\mathit{Low}}$] encodes. -Texels in the same column as a texel block such that latexmath:[$x_r = 0$] +latexmath:[W_{X_\mathit{Low}, Y_\mathit{Low}}] encodes. +Texels in the same column as a texel block such that latexmath:[x_r = 0] are not influenced by the color samples from words -latexmath:[$W_{X_\mathit{Low}+1, Y_\mathit{Low}}$] and -latexmath:[$W_{X_\mathit{Low}+1, Y_\mathit{Low}+1}$]. -Texels in the same row as a texel block such that latexmath:[$y_r = 0$] +latexmath:[W_{X_\mathit{Low}+1, Y_\mathit{Low}}] and +latexmath:[W_{X_\mathit{Low}+1, Y_\mathit{Low}+1}]. +Texels in the same row as a texel block such that latexmath:[y_r = 0] are not influenced by the color samples from words -latexmath:[$W_{X_\mathit{Low}, Y_\mathit{Low}+1}$] and -latexmath:[$W_{X_\mathit{Low}+1, Y_\mathit{Low}+1}$]. -Therefore a single color sample at latexmath:[$C_{x,y}$] influences the +latexmath:[W_{X_\mathit{Low}, Y_\mathit{Low}+1}] and +latexmath:[W_{X_\mathit{Low}+1, Y_\mathit{Low}+1}]. +Therefore a single color sample at latexmath:[C_{x,y}] influences the interpolated color of all texels in the 7{times}7 region -from latexmath:[$C_{x-3,y-3}$] to latexmath:[$C_{x+3,y+3}$] centered on +from latexmath:[C_{x-3,y-3}] to latexmath:[C_{x+3,y+3}] centered on the color sample.   @@ -385,11 +387,11 @@ self-contained texel blocks of other schemes. For the red, green and blue channels, _C~x,y~_ is a 5.4-bit fixed-point value whose bit pattern can be converted to an 8-bit normalized value, i.e. UNORM, as -latexmath:[$\textbf{Image \{A,B\}}\{\textit{R,G,B}\}_{x,y} = \left\lfloor{{C_{x,y}}\over 2}\right\rfloor+\left\lfloor{{C_{x,y}}\over 64}\right\rfloor$]. +latexmath:[\textbf{Image \{A,B\}}\{\textit{R,G,B}\}_{x,y} = \left\lfloor{{C_{x,y}}\over 2}\right\rfloor+\left\lfloor{{C_{x,y}}\over 64}\right\rfloor]. For the alpha channel, _C~x,y~_ is a 4.4-bit fixed-point value whose bit pattern can be converted to an 8-bit normalized value as -latexmath:[$\textbf{Image \{A,B\}}\{\textit{A}\}_{x,y} = C_{x,y}+\left\lfloor{{C_{x,y}}\over 16}\right\rfloor$]. +latexmath:[\textbf{Image \{A,B\}}\{\textit{A}\}_{x,y} = C_{x,y}+\left\lfloor{{C_{x,y}}\over 16}\right\rfloor]. <<< @@ -400,9 +402,9 @@ The final image is created by linearly interpolating between the *Image A* and *Image B* texels, using the modulation data for each pixel to determine the weighting. The modulation information is retrieved from word -latexmath:[$W_{X_\textit{Mod},Y_\textit{Mod}}$] -where latexmath:[$X_\textit{Mod} = \left\lfloor{x\over 4}\right\rfloor$] -and latexmath:[$Y_\textit{Mod} = \left\lfloor{y\over 4}\right\rfloor$]. +latexmath:[W_{X_\textit{Mod},Y_\textit{Mod}}] +where latexmath:[X_\textit{Mod} = \left\lfloor{x\over 4}\right\rfloor] +and latexmath:[Y_\textit{Mod} = \left\lfloor{y\over 4}\right\rfloor]. The weight for the interpolation is derived from the 2 bits of the modulation data corresponding to the relevant pixel offset (_x~offset~_ = _x_ - (4 {times} _X~Mod~_), @@ -412,23 +414,23 @@ depending on the value of modulation flag _M_. [[PVRTC1ModulationWeights]] .Modulation weights for PVRTC1 4bpp [cols="10,10,1,10,10,10"] -|======= +|==== 2+^| *Standard bilinear* (_M_ = 0) .6+| 3+^| *Punch-through* (_M_ = 1) ^| *Modulation bits* ^| *Weight* ^| *Modulation bits* ^| *Weight* ^| *Alpha* ^| 00 ^| 0 ^| 00 ^| 0 .2+^.^| Normal ^| 01 ^| 3 ^| 01 .2+^.^| 4 ^| 10 ^| 5 ^| 10 ^| ``Punch-through'' ^| 11 ^| 8 | 11 ^| 8 ^| Normal -|======= +|==== [[PVRTCmodulate]] .PVRTC image modulation [latexmath] -++++++ +++++ \begin{align*} \textit{Final color}_\textit{x,y} = & \left\lfloor{{(\textbf{Image A}_\textit{x,y} \times (8 - \textit{weight})) + (\textbf{Image B}_\textit{x,y} \times \textit{weight})}\over 8}\right\rfloor \end{align*} -++++++ +++++ If punch-through mode is selected, and the modulation bits for a given pixel have a value of 0b10, the alpha value of the resulting color is 0x00. @@ -457,9 +459,9 @@ uses an 8{times}4 bilinear upscale. The inputs to the Morton order encoding for 2bpp mode are: -Let _Xb_ be the number of bits used to express _X_ -- i.e. latexmath:[$\mathit{Xb} = \mathrm{log}_2\left(\left\lceil{\mathit{width}\over 8}\right\rceil\right)$]. +Let _Xb_ be the number of bits used to express _X_ -- i.e. latexmath:[\mathit{Xb} = \mathrm{log}_2\left(\left\lceil{\mathit{width}\over 8}\right\rceil\right)]. -Let _Yb_ be the number of bits used to express _Y_ -- i.e. latexmath:[$\mathit{Yb} = \mathrm{log}_2\left(\left\lceil{\mathit{height}\over 4}\right\rceil\right)$]. +Let _Yb_ be the number of bits used to express _Y_ -- i.e. latexmath:[\mathit{Yb} = \mathrm{log}_2\left(\left\lceil{\mathit{height}\over 4}\right\rceil\right)]. ==== PVRTC1 2bpp image reconstruction @@ -468,25 +470,25 @@ For each channel _C_ of each color (*Color A* and *Color B*), the interpolation proceeds as follows: * For low-resolution image color channel -latexmath:[$\textbf{C}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] +latexmath:[\textbf{C}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] stored in word -latexmath:[$\textit{W}_{\textit{X}_\textit{Low},\textit{Y}_\textit{Low}}$]: -** _X~Low~_ = latexmath:[$\left\lfloor{{x-4}\over 8}\right\rfloor$] -** _Y~Low~_ = latexmath:[$\left\lfloor{{y-2}\over 4}\right\rfloor$] +latexmath:[\textit{W}_{\textit{X}_\textit{Low},\textit{Y}_\textit{Low}}]: +** _X~Low~_ = latexmath:[\left\lfloor{{x-4}\over 8}\right\rfloor] +** _Y~Low~_ = latexmath:[\left\lfloor{{y-2}\over 4}\right\rfloor] * Using relative coordinates: -** latexmath:[$x_r +** latexmath:[x_r = (x - 4) - \left(8\times\left\lfloor{{x - 4}\over 8}\right\rfloor\right) -= (x - 4) - (8 \times X_\textit{Low})$] -** latexmath:[$y_r += (x - 4) - (8 \times X_\textit{Low})] +** latexmath:[y_r = (y - 2) - \left(4\times\left\lfloor{{y - 2}\over 4}\right\rfloor\right) -= (y - 2) - (4 \times Y_\textit{Low})$] += (y - 2) - (4 \times Y_\textit{Low})] * Coordinates wrap at the edges of the image. * An interpolation is performed which is mathematically equivalent to <>. [[PVRTC1_2bpp_interpolation]] .PVRTC1 2bpp color channel interpolation [latexmath] -++++++ +++++ \begin{align*} \textit{C}_\textit{x,y} = & \left(\textbf{C}_{\textbf{X}_\textbf{Low}, \textbf{Y}_\textbf{Low}} @@ -499,23 +501,23 @@ latexmath:[$\textit{W}_{\textit{X}_\textit{Low},\textit{Y}_\textit{Low}}$]: \left(\textbf{C}_{\textbf{X}_\textbf{Low}+1, \textbf{Y}_\textbf{Low}+1} \times x_r \times y_r\right) \end{align*} -++++++ +++++ For the red, green and blue channels, _C~x,y~_ is a 5.5-bit fixed-point value whose bit pattern can be converted to an 8-bit normalized value as -latexmath:[$\textbf{Image \{A,B\}}\{\textit{R,G,B}\}_{x,y} = \left\lfloor{{C_{x,y}}\over 4}\right\rfloor+\left\lfloor{{C_{x,y}}\over 128}\right\rfloor$]. +latexmath:[\textbf{Image \{A,B\}}\{\textit{R,G,B}\}_{x,y} = \left\lfloor{{C_{x,y}}\over 4}\right\rfloor+\left\lfloor{{C_{x,y}}\over 128}\right\rfloor]. For the alpha channel, _C~x,y~_ is a 4.5-bit fixed-point value whose bit pattern can be converted to an 8-bit normalized value as -latexmath:[$\textbf{Image \{A,B\}}\{\textit{A}\}_{x,y} = \left\lfloor{{C_{x,y}}\over 2}\right\rfloor+\left\lfloor{{C_{x,y}}\over 32}\right\rfloor$]. +latexmath:[\textbf{Image \{A,B\}}\{\textit{A}\}_{x,y} = \left\lfloor{{C_{x,y}}\over 2}\right\rfloor+\left\lfloor{{C_{x,y}}\over 32}\right\rfloor]. <<< ==== PVRTC1 2bpp color modulation The modulation data, retrieved from word _W~X,Y~_ where -latexmath:[$X_\mathit{Mod} = \left\lfloor{x\over 8}\right\rfloor$] and -latexmath:[$Y_\mathit{Mod} = \left\lfloor{y\over 4}\right\rfloor$], are +latexmath:[X_\mathit{Mod} = \left\lfloor{x\over 8}\right\rfloor] and +latexmath:[Y_\mathit{Mod} = \left\lfloor{y\over 4}\right\rfloor], are interpreted differently in order to accommodate the additional pixels. Each word holds the modulation data which corresponds to pixels that have offsets (_x~offset~_ = _x_ - 8 {times} _X~Mod~_, @@ -529,7 +531,7 @@ affect the layout: .Texel Data format for PVRTC1 2bpp compressed texture formats [width="97%",cols="32*^"] -|======= +|==== 32+| *~Bits 64..32: Color data and flags~* 32+| _Identical to PVRTC1 4bpp_ 32+| *~Bits 31..0: Modulation data: direct encoding, 1 bit per pixel (modulation flag~* ~_M_~ *~= 0) for pixel offset (_x_, _y_)~* @@ -541,7 +543,7 @@ affect the layout: 32+| *~Bits 31..0: Modulation data, horizontally- or vertically-interpolated encoding, samples for pixel offset (_x_, _y_) (modulation flag~* ~_M_~ *~= 1, bit 0 flag = 1)~* | ~31~ | ~30~ | ~29~ | ~28~ | ~27~ | ~26~ | ~25~ | ~24~ | ~23~ | ~22~ | ~21~ | ~20~ | ~19~ | ~18~ | ~17~ | ~16~ | ~15~ | ~14~ | ~13~ | ~12~ | ~11~ | ~10~ | ~9~ | ~8~ | ~7~ | ~6~ | ~5~ | ~4~ | ~3~ | ~2~ | ~1~ | ~0~ 2+| 7,3 2+| 5,3 2+| 3,3 2+| 1,3 2+| 6,2 | 4,2 | _F_ 2+| 2,2 2+| 0,2 2+| 7,1 2+| 5,1 2+| 3,1 2+| 1,1 2+| 6,0 2+| 4,0 2+| 2,0 | 0,0 | 1 -|======= +|==== If the modulation flag _M_ is set to 0, each pixel only has a single bit of modulation data. @@ -550,11 +552,11 @@ and *Image B* for modulation data bit = 1. .Modulation modes for PVRTC1 2bpp [cols="2,2",width="75%"] -|======= +|==== ^| *Modulation flag value* _M_ ^| *Mode* ^| 0 ^| Standard Bilinear, 1bpp modulation ^| 1 ^| Punch-through, interpolated modulation -|======= +|==== If the modulation flag _M_ is set to 1, the pixels with 2-bit stored values have modulation weights equal to those of PVRTC1 4bpp for modulation mode 1, @@ -571,17 +573,17 @@ in bit 20 determine how they are reconstructed: * If bit~0~ is 0, the value is the mean of the weights of the four horizontally- and vertically-adjacent pixels, rounded to the nearest integer: -latexmath:[$\textit{weight}_{x,y} = \left\lfloor{{w(\textit{md}(x-1,y))+w(\textit{md}(x,y-1))+w(\textit{md}(x+1,y))+w(\textit{md}(x,y+1))+2}\over 4}\right\rfloor$]. +latexmath:[\textit{weight}_{x,y} = \left\lfloor{{w(\textit{md}(x-1,y))+w(\textit{md}(x,y-1))+w(\textit{md}(x+1,y))+w(\textit{md}(x,y+1))+2}\over 4}\right\rfloor]. * If bit~0~ is 1, and flag _F_ is 1, the value is the mean of the weights of the two vertically-adjacent pixels, rounded to the nearest integer: -latexmath:[$\textit{weight}_{x,y} = \left\lfloor{{w(\textit{md}(x,y-1))+w(\textit{md}(x,y+1))+1}\over 2}\right\rfloor$]. +latexmath:[\textit{weight}_{x,y} = \left\lfloor{{w(\textit{md}(x,y-1))+w(\textit{md}(x,y+1))+1}\over 2}\right\rfloor]. * If bit~0~ is 1, and flag _F_ is 0, the value is the mean of the weights from the horizontally-adjacent pixels, rounded to the nearest integer: -latexmath:[$\textit{weight}_{x,y} = \left\lfloor{{w(\textit{md}(x-1,y))+w(\textit{md}(x+1,y))+1}\over 2}\right\rfloor$]. +latexmath:[\textit{weight}_{x,y} = \left\lfloor{{w(\textit{md}(x-1,y))+w(\textit{md}(x+1,y))+1}\over 2}\right\rfloor]. where _md(x,y)_ is the modulation data for texel offset (_x_, _y_) and _w_() is the weighting described in <> @@ -619,18 +621,18 @@ discontinuities, or diverse color distributions. .Texel Data format for PVRTC2 4bpp compressed texture formats [width="97%",cols="32*^"] -|======= +|==== 32+| *~Bits 64..32: Color data and flags~* | ~63~ | ~62~ | ~61~ | ~60~ | ~59~ | ~58~ | ~57~ | ~56~ | ~55~ | ~54~ | ~53~ | ~52~ | ~51~ | ~50~ | ~49~ | ~48~ | ~47~ | ~46~ | ~45~ | ~44~ | ~43~ | ~42~ | ~41~ | ~40~ | ~39~ | ~38~ | ~37~ | ~36~ | ~35~ | ~34~ | ~33~ | ~32~ | _Op_ 15+| *Color B* | _H_ 14+| *Color A* | _M_ 32+| *~Bits 31..0: Modulation data bits [1..0] for pixel offset (_x_, _y_) -- identical to PVRTC1 4bpp~* | ~31~ | ~30~ | ~29~ | ~28~ | ~27~ | ~26~ | ~25~ | ~24~ | ~23~ | ~22~ | ~21~ | ~20~ | ~19~ | ~18~ | ~17~ | ~16~ | ~15~ | ~14~ | ~13~ | ~12~ | ~11~ | ~10~ | ~9~ | ~8~ | ~7~ | ~6~ | ~5~ | ~4~ | ~3~ | ~2~ | ~1~ | ~0~ 2+| 3,3 2+| 2,3 2+| 1,3 2+| 0,3 2+| 3,2 2+| 2,2 2+| 1,2 2+| 0,2 2+| 3,1 2+| 2,1 2+| 1,1 2+| 0,1 2+| 3,0 2+| 2,0 2+| 1,0 2+| 0,0 -|======= +|==== .Data layout of color segments in a PVRTC2 word [cols="^,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1,^1",width="55%"] -|==================================================================== +|==== 16+s| ~*Color B* -- opaque color mode (opacity flag _Op_ = 1)~ | ~63~ | ~62~ | ~61~ | ~60~ | ~59~ | ~58~ | ~57~ | ~56~ | ~55~ | ~54~ | ~53~ | ~52~ | ~51~ | ~50~ | ~49~ | ~48~ | 1 5+| Red 5+| Green 5+| Blue @@ -643,7 +645,7 @@ discontinuities, or diverse color distributions. 16+s| ~*Color A* -- translucent color mode (opacity flag _Op_ = 0)~ | ~47~ | ~46~ | ~45~ | ~44~ | ~43~ | ~42~ | ~41~ | ~40~ | ~39~ | ~38~ | ~37~ | ~36~ | ~35~ | ~34~ | ~33~ | ~32~ | _H_ 3+| Alpha 4+| Red 4+| Green 3+| Blue | _M_ -|==================================================================== +|==== There is one change to the interpretation of the color data relative to PVRTC1: as there is only one opacity flag for each PVRTC2 data word, to @@ -667,38 +669,38 @@ centered on boundaries of multiples of 4{times}4 texel regions, the hard transition flag _H_ changes the behavior of the entire red-dotted region shown in <>. This is a subset of the logical 4{times}4 pixel regions -latexmath:[$\textbf{M}_{\textbf{X}_\textbf{Mod},\textbf{Y}_\textbf{Mod}}$] +latexmath:[\textbf{M}_{\textbf{X}_\textbf{Mod},\textbf{Y}_\textbf{Mod}}] through -latexmath:[$\textbf{M}_{\textbf{X}_\textbf{Mod}+1,\textbf{Y}_\textbf{Mod}+1}$] +latexmath:[\textbf{M}_{\textbf{X}_\textbf{Mod}+1,\textbf{Y}_\textbf{Mod}+1}] that correspond to the modulation data stored in 64-bit data words -latexmath:[$W_{X_\mathit{Mod},Y_\mathit{Mod}}$] through -latexmath:[$W_{X_\mathit{Mod}+1,Y_\mathit{Mod}+1}$]. +latexmath:[W_{X_\mathit{Mod},Y_\mathit{Mod}}] through +latexmath:[W_{X_\mathit{Mod}+1,Y_\mathit{Mod}+1}]. The flag _H_ for this hard transition region is stored in -latexmath:[$W_{X_\mathit{Mod},Y_\mathit{Mod}}^{47}$]. +latexmath:[W_{X_\mathit{Mod},Y_\mathit{Mod}}^{47}]. [[PVRTC2HardTransition]] .PVRTC2 hard transition subsets -image::images/PVRTC2_hard_transition.{svgpdf}[title="PVRTC2 hard transition subsets",width="{svgpdf@pdf:130pt:200}",align="center"] +image::{images}/PVRTC2_hard_transition.svg[title="PVRTC2 hard transition subsets",width="{svgpdf@pdf:130pt:200}",align="center"] The hard transition region is further subdivided into four smaller subregions, shown with the dotted 2{times}2 texel outlines in <>, where it intersects the pixel regions -latexmath:[$\textbf{M}_{\textbf{X}_\textbf{Mod},\textbf{Y}_\textbf{Mod}}$] +latexmath:[\textbf{M}_{\textbf{X}_\textbf{Mod},\textbf{Y}_\textbf{Mod}}] through -latexmath:[$\textbf{M}_{\textbf{X}_\textbf{Mod}+1,\textbf{Y}_\textbf{Mod}+1}$]. +latexmath:[\textbf{M}_{\textbf{X}_\textbf{Mod}+1,\textbf{Y}_\textbf{Mod}+1}]. The hard transition flag _H_, coupled with the relevant modulation flag _M_ for the texel subregion, determines how the colors for each reconstructed pixel in the subregion are evaluated, as summarized in the table below. .Modulation modes for PVRTC2 4bpp [cols="1^,1^,2^"] -|======= +|==== ^| *Modulation flag* _M_ ^| *Hard transition flag* _H_ ^| *Mode* | 0 | 0 | Standard bilinear | 1 | 0 | Punch-through alpha | 0 | 1 | Non-interpolated | 1 | 1 | Local palette -|======= +|==== In `standard bilinear' the modulation behaves as described for PVRTC1 4bpp. @@ -732,131 +734,131 @@ Instead, the eight distinct colors from each surrounding word make up a local palette from which colors are selected. Denoting *Color B* and *Color A* from words -latexmath:[$W_{X_\textit{Low},Y_\textit{Low}}$] through -latexmath:[$W_{X_\textit{Low}+1,Y_\textit{Low}+1}$] as described +latexmath:[W_{X_\textit{Low},Y_\textit{Low}}] through +latexmath:[W_{X_\textit{Low}+1,Y_\textit{Low}+1}] as described above, the following colors are available: -latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$], -latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$], -latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$], -latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$], -latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$], -latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$], -latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}$] +latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}], +latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}], +latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}], +latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}], +latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}], +latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}], +latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}] and -latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}$]. +latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}]. Whilst 8 distinct colors exist in each of those four words, only two bits of modulation data are available for each pixel. Subsequently, each pixel at offset -latexmath:[$(x_r = (x - 2) - (4 \times X_\textit{Low}), -y_r = (y - 2) - (4 \times Y_\textit{Low}))$] relative to +latexmath:[(x_r = (x - 2) - (4 \times X_\textit{Low}), +y_r = (y - 2) - (4 \times Y_\textit{Low}))] relative to start of the hard transition region has access to a subset of the palette as follows: .Color mappings in local palette mode for PVRTC2 4bpp [cols="2^,5^,3^,3^,3^"] -|================================================================== +|==== | *~Modulation bits~* | *~0,0~* | *~1,0~* | *~2,0~* | *~3,0~* | 0 -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] | 1 -| latexmath:[$\left\lfloor{{5\times \textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}+3\times \textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}}\over 8}\right\rfloor$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] +| latexmath:[\left\lfloor{{5\times \textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}+3\times \textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}}\over 8}\right\rfloor] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] | 2 -| latexmath:[$\left\lfloor{{3\times \textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}+5\times \textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}}\over 8}\right\rfloor$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] +| latexmath:[\left\lfloor{{3\times \textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}+5\times \textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}}\over 8}\right\rfloor] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] | 3 -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] | *~Modulation bits~* | *~0,1~* | *~1,1~* | *~2,1~* | *~3,1~* | 0 -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}$] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}] | 1 -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] | 2 -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] | 3 -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] | *~Modulation bits~* |*~0,2~* | *~1,2~* | *~2,2~* | *~3,2~* | 0 -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}$] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}] | 1 -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}$] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}] | 2 -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] | 3 -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] | *~Modulation bits~* | *~0,3~* | *~1,3~* | *~2,3~* | *~3,3~* | 0 -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}$] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}] | 1 -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}$] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}+1}] | 2 -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{A}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}] | 3 -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}$] -| latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] -|================================================================== +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low},\textbf{Y}_\textbf{Low}+1}] +| latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] +|==== [NOTE] ==== The entry for offset 0,0 is interpolated as per PVRTC's standard bilinear filtering mode. It will thus only use colors from word -latexmath:[$W_{X_\textit{Low},Y_\textit{Low}}$]. +latexmath:[W_{X_\textit{Low},Y_\textit{Low}}].   The local palette mode shares with the other modes of PVRTC2 the property -that the column latexmath:[$x_r = 0$] has no contribution from words -latexmath:[$W_{X_\mathit{Low}+1, Y_\mathit{Low}}$] and -latexmath:[$W_{X_\mathit{Low}+1, Y_\mathit{Low}+1}$], -and that row latexmath:[$y_r = 0$] has no contribution from words -latexmath:[$W_{X_\mathit{Low}, Y_\mathit{Low}+1}$] and -latexmath:[$W_{X_\mathit{Low}+1, Y_\mathit{Low}+1}$]. +that the column latexmath:[x_r = 0] has no contribution from words +latexmath:[W_{X_\mathit{Low}+1, Y_\mathit{Low}}] and +latexmath:[W_{X_\mathit{Low}+1, Y_\mathit{Low}+1}], +and that row latexmath:[y_r = 0] has no contribution from words +latexmath:[W_{X_\mathit{Low}, Y_\mathit{Low}+1}] and +latexmath:[W_{X_\mathit{Low}+1, Y_\mathit{Low}+1}]. Therefore any 2{times}2 quad of texel values, required for example by bilinear filtering, can be evaluated from a single set of four adjacent texel blocks. @@ -866,7 +868,7 @@ texel blocks. pixel above. For instance, a modulation value of 3 (bit pattern 11) for pixel location 0,1 (which is offset 2,3 relative to the top left of block P) would - correspond to color latexmath:[$\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}$] being selected. + correspond to color latexmath:[\textbf{B}_{\textbf{X}_\textbf{Low}+1,\textbf{Y}_\textbf{Low}}] being selected. * The stored color values are first expanded, _where necessary_, to _ARGB_:4555 (via bit replication for _R_, _G_, or _B_ and via padding @@ -892,12 +894,12 @@ the single opacity flag _Op_, as specified in the PVRTC2 4bpp format. .Texel Data format for PVRTC2 2bpp compressed texture formats [width="50%"] -|======= +|==== ^s| Bits 63-32: Color data and flags ^| Identical to PVRTC2 4bpp ^s| Bits 31-0: Modulation data ^| Identical to PVRTC1 2bpp -|======= +|==== Color values are interpreted in the same manner as for the PVRTC2 4bpp format. @@ -906,13 +908,13 @@ uses the non-interpolated mode -- no local palette mode exists. .Modulation modes for PVRTC2 2bpp [cols="1^,1^,2^"] -|======= +|==== ^| *Modulation flag* _M_ ^| *Hard transition* _H_ ^| Mode | 0 | 0 | Standard bilinear, 1bpp modulation | 1 | 0 | Standard bilinear, interpolated modulation | 0 | 1 | Non-interpolated, 1bpp modulation | 1 | 1 | Non-interpolated, interpolated modulation -|======= +|==== If the hard transition flag _H_ for PVRTC2 2bpp is equal to 0, the format is interpreted in the same manner as the PVRTC1 2bpp format. diff --git a/quantization.txt b/chapters/quantization.adoc similarity index 85% rename from quantization.txt rename to chapters/quantization.adoc index af0be91..51cc009 100644 --- a/quantization.txt +++ b/chapters/quantization.adoc @@ -1,5 +1,5 @@ -// Copyright (c) 2017-2019 The Khronos Group Inc. -// Copyright notice at https://www.khronos.org/registry/speccopyright.html +// Copyright 2017-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 [[CONVERSION_QUANTIZATION]] == Quantization schemes @@ -20,7 +20,7 @@ between these limits is represented by the following encodings, for bit depth _n_ = {8, 10, 12}: [latexmath] -++++++ +++++ \begin{align*} \mathit{DG}' & = \lfloor 0.5 + (219\times G' + 16)\times 2^{n-8}\rfloor &\mathit{DB}' & = \lfloor 0.5 + (219\times B' + 16)\times 2^{n-8}\rfloor \\ @@ -35,11 +35,11 @@ for bit depth _n_ = {8, 10, 12}: &\mathit{DC}'_T & = \lfloor 0.5 + (224\times C'_T + 128)\times 2^{n-8}\rfloor \\ &&\mathit{DC}'_P & = \lfloor 0.5 + (224\times C'_P + 128)\times 2^{n-8}\rfloor \end{align*} -++++++ +++++ The dequantization formulae are therefore: [latexmath] -++++++ +++++ \begin{align*} G' & = {{{\mathit{DG}'\over{2^{n-8}}} - 16}\over{219}} & Y' & = {{{\mathit{DY}'\over{2^{n-8}}} - 16}\over{219}} & @@ -54,9 +54,9 @@ C'_R & = {{{\mathit{DC}'_R\over{2^{n-8}}} - 128}\over{224}} & C'_\mathit{CR} & = {{{\mathit{DC}'_\mathit{CR}\over{2^{n-8}}} - 128}\over{224}} & C'_P & = {{{\mathit{DC}'_P\over{2^{n-8}}} - 128}\over{224}} \end{align*} -++++++ +++++ -For consistency with latexmath:[$Y'_CC'_\mathit{BC}C'_\mathit{RC}$], these +For consistency with latexmath:[Y'_CC'_\mathit{BC}C'_\mathit{RC}], these formulae use the <> and <> terminology of prefixing a _D_ to represent the digital quantized encoding of a numerical value. @@ -65,14 +65,14 @@ value. That is, in ``narrow range'' encoding: [options="header",cols="18%,34%,48%"] -|====== +|==== | Value | Continuous encoding value | Quantized encoding | Black | {_R′_, _G′_, _B′_, _Y′_, -latexmath:[$Y'_C$], +latexmath:[Y'_C], _I_} = 0.0 | @@ -80,15 +80,15 @@ _I_} = _DG′_, _DB′_, _DY′_, -latexmath:[$\mathit{DY}'_C$], +latexmath:[\mathit{DY}'_C], _DI_} = -latexmath:[$16 \times 2^{n-8}$] +latexmath:[16 \times 2^{n-8}] | Peak brightness | {_R′_, _G′_, _B′_, _Y′_, -latexmath:[$Y'_C$], +latexmath:[Y'_C], _I_} = 1.0 | @@ -96,60 +96,60 @@ _I_} = _DG′_, _DB′_, _DY′_, -latexmath:[$\mathit{DY}'_C$], +latexmath:[\mathit{DY}'_C], _DI_} = -latexmath:[$235 \times 2^{n-8}$] +latexmath:[235 \times 2^{n-8}] | Minimum color difference value | -{latexmath:[$C'_B$], -latexmath:[$C'_R$], -latexmath:[$C'_\mathit{BC}$], -latexmath:[$C'_\mathit{RC}$], +{latexmath:[C'_B], +latexmath:[C'_R], +latexmath:[C'_\mathit{BC}], +latexmath:[C'_\mathit{RC}], _C~T~_, _C~P~_} = -0.5 | -{latexmath:[$\mathit{DC}'_B$], -latexmath:[$\mathit{DC}'_R$], -latexmath:[$\mathit{DC}'_\mathit{BC}$], -latexmath:[$\mathit{DC}'_\mathit{CR}$], +{latexmath:[\mathit{DC}'_B], +latexmath:[\mathit{DC}'_R], +latexmath:[\mathit{DC}'_\mathit{BC}], +latexmath:[\mathit{DC}'_\mathit{CR}], _DC~T~_, _DC~P~_} = -latexmath:[$16 \times 2^{n-8}$] +latexmath:[16 \times 2^{n-8}] | Maximum color difference value | -{latexmath:[$C'_B$], -latexmath:[$C'_R$], -latexmath:[$C'_\mathit{BC}$], -latexmath:[$C'_\mathit{RC}$], +{latexmath:[C'_B], +latexmath:[C'_R], +latexmath:[C'_\mathit{BC}], +latexmath:[C'_\mathit{RC}], _C~T~_, _C~P~_} = 0.5 | -{latexmath:[$\mathit{DC}'_B$], -latexmath:[$\mathit{DC}'_R$], -latexmath:[$\mathit{DC}'_\mathit{BC}$], -latexmath:[$\mathit{DC}'_\mathit{CR}$], +{latexmath:[\mathit{DC}'_B], +latexmath:[\mathit{DC}'_R], +latexmath:[\mathit{DC}'_\mathit{BC}], +latexmath:[\mathit{DC}'_\mathit{CR}], _DC~T~_, _DC~P~_} = -latexmath:[$240 \times 2^{n-8}$] +latexmath:[240 \times 2^{n-8}] | Achromatic colors | _R′_ = _G′_ = _B′_ -{latexmath:[$C'_B$], -latexmath:[$C'_R$], -latexmath:[$C'_\mathit{BC}$], -latexmath:[$C'_\mathit{RC}$], +{latexmath:[C'_B], +latexmath:[C'_R], +latexmath:[C'_\mathit{BC}], +latexmath:[C'_\mathit{RC}], _C~T~_, _C~P~_} = 0.0 | -{latexmath:[$\mathit{DC}'_B$], -latexmath:[$\mathit{DC}'_R$], -latexmath:[$\mathit{DC}'_\mathit{BC}$], -latexmath:[$\mathit{DC}'_\mathit{CR}$], +{latexmath:[\mathit{DC}'_B], +latexmath:[\mathit{DC}'_R], +latexmath:[\mathit{DC}'_\mathit{BC}], +latexmath:[\mathit{DC}'_\mathit{CR}], _DC~T~_, _DC~P~_} = -latexmath:[$128 \times 2^{n-8}$] -|====== +latexmath:[128 \times 2^{n-8}] +|==== If, instead of the quantized values, the input is interpreted as fixed-point values in the range 0.0..1.0, as might be the case if the values were treated @@ -157,7 +157,7 @@ as unsigned normalized quantities in a computer graphics API, the following conversions can be applied instead: [latexmath] -++++++ +++++ \begin{align*} G' & = {{{G'_{\mathit{norm}}\times{2^{n-1}}} - 16\times{2^{n-8}}}\over{219\times 2^{n-8}}} & B' & = {{{B'_{\mathit{norm}}\times{2^{n-1}}} - 16\times{2^{n-8}}}\over{219\times 2^{n-8}}} \\ @@ -184,7 +184,7 @@ I_\mathit{norm} & = {{{I\times{219\times 2^{n-8}}} + 16\times{2^{n-8}}}\over C'_\mathit{Tnorm} & = {{{\mathit{DC}'_{T}\times{224\times ^{n-8}}} + 128\times 2^{n-8}}\over{2^{n-1}}} \\ &&C'_\mathit{Pnorm} & = {{{\mathit{DC}'_{P}\times{224\times ^{n-8}}} + 128\times 2^{n-8}}\over{2^{n-1}}} \end{align*} -++++++ +++++ [[QUANTIZATION_FULL]] @@ -201,7 +201,7 @@ of their specifications, which is described <>. For bit depth _n_ = {8 (JFIF),10,12 (Rec.2100)}: [latexmath] -++++++ +++++ \begin{align*} \mathit{DG}' & = \textrm{Round}\left(G'\times (2^n-1)\right) & \mathit{DB}' & = \textrm{Round}\left(B'\times (2^n-1)\right) \\ @@ -216,12 +216,12 @@ For bit depth _n_ = {8 (JFIF),10,12 (Rec.2100)}: \mathit{DC}'_T & = \textrm{Round}\left(C'_T\times (2^n-1) + 2^{n-1}\right) \\ &&\mathit{DC}'_P & = \textrm{Round}\left(C'_P\times (2^n-1) + 2^{n-1}\right) \end{align*} -++++++ +++++ <>-1 defines Round() as: [latexmath] -++++++ +++++ \begin{align*} \textrm{Round}(x) &= \textrm{Sign}(x)\times\lfloor|x| + 0.5\rfloor \\ \textrm{Sign}(x) &= \begin{cases} @@ -230,11 +230,11 @@ For bit depth _n_ = {8 (JFIF),10,12 (Rec.2100)}: -1, & x < 0 \end{cases} \end{align*} -++++++ +++++ Note that a chroma channel value of exactly 0.5 corresponds to a quantized -encoding of latexmath:[$2^n$], and must therefore be clamped to the nominal -peak value of latexmath:[$2^n-1$]. +encoding of latexmath:[2^n], and must therefore be clamped to the nominal +peak value of latexmath:[2^n-1]. <> does not have this problem. A chroma channel value of -0.5 corresponds to a quantized encoding of 1, which is the nominal minimum peak value. @@ -243,7 +243,7 @@ In <> (which defines only n = 8), the corresponding formula is: [latexmath] -++++++ +++++ \begin{align*} \textrm{Round}(x) &= \textrm{Clamp}(\lfloor|x| + 0.5\rfloor) \\ \textrm{clamp}(x) &= \begin{cases} @@ -252,7 +252,7 @@ formula is: x, & \textrm{otherwise} \end{cases} \end{align*} -++++++ +++++ Allowing for the clamping at a chroma value of 0.5, these formulae are equivalent across the expected -0.5..0.5 range for chroma and 0.0..1.0 @@ -261,7 +261,7 @@ range for luma values. The dequantization formulae are therefore: [latexmath] -++++++ +++++ \begin{align*} G' & = {\mathit{DG}'\over{2^n - 1}} & Y' & = {\mathit{DY}'\over{2^n - 1}} & @@ -276,20 +276,20 @@ C'_R & = {\mathit{DC}'_R - 2^{n-1}\over{2^n - 1}} & C'_\mathit{CR} & = {\mathit{DC}'_\mathit{CR} - 2^{n-1}\over{2^n - 1}} & C'_P & = {\mathit{DC}'_P - 2^{n-1}\over{2^n - 1}} \end{align*} -++++++ +++++ <<< That is, in ``full range'' encoding: [options="header",cols="18%,34%,48%"] -|====== +|==== | Value | Continuous encoding value | Quantized encoding | Black | {_R′_, _G′_, _B′_, _Y′_, -latexmath:[$Y'_C$], +latexmath:[Y'_C], _I_} = 0.0 | @@ -297,7 +297,7 @@ _I_} = _DG′_, _DB′_, _DY′_, -latexmath:[$\mathit{DY}'_C$], +latexmath:[\mathit{DY}'_C], _DI_} = 0 | Peak brightness | @@ -305,7 +305,7 @@ _DI_} = _G′_, _B′_, _Y′_, -latexmath:[$Y'_C$], +latexmath:[Y'_C], _I_} = 1.0 | @@ -313,62 +313,62 @@ _I_} = _DG′_, _DB′_, _DY′_, -latexmath:[$\mathit{DY}'_C$], +latexmath:[\mathit{DY}'_C], _DI_} = 2^_n_^ - 1 | Minimum color difference value | -{latexmath:[$C'_B$], -latexmath:[$C'_R$], -latexmath:[$C'_\mathit{BC}$], -latexmath:[$C'_\mathit{RC}$], +{latexmath:[C'_B], +latexmath:[C'_R], +latexmath:[C'_\mathit{BC}], +latexmath:[C'_\mathit{RC}], _C~T~_, _C~P~_} = -0.5 | -{latexmath:[$\mathit{DC}'_B$], -latexmath:[$\mathit{DC}'_R$], -latexmath:[$\mathit{DC}'_\mathit{BC}$], -latexmath:[$\mathit{DC}'_\mathit{CR}$], +{latexmath:[\mathit{DC}'_B], +latexmath:[\mathit{DC}'_R], +latexmath:[\mathit{DC}'_\mathit{BC}], +latexmath:[\mathit{DC}'_\mathit{CR}], _DC~T~_, _DC~P~_} = 1 | Maximum color difference value | -{latexmath:[$C'_B$], -latexmath:[$C'_R$], -latexmath:[$C'_\mathit{BC}$], -latexmath:[$C'_\mathit{RC}$], +{latexmath:[C'_B], +latexmath:[C'_R], +latexmath:[C'_\mathit{BC}], +latexmath:[C'_\mathit{RC}], _C~T~_, _C~P~_} = 0.5 | -{latexmath:[$\mathit{DC}'_B$], -latexmath:[$\mathit{DC}'_R$], -latexmath:[$\mathit{DC}'_\mathit{BC}$], -latexmath:[$\mathit{DC}'_\mathit{CR}$], +{latexmath:[\mathit{DC}'_B], +latexmath:[\mathit{DC}'_R], +latexmath:[\mathit{DC}'_\mathit{BC}], +latexmath:[\mathit{DC}'_\mathit{CR}], _DC~T~_, _DC~P~_} = -latexmath:[$2^n - 1$] +latexmath:[2^n - 1] (clamped) | Achromatic colors | _R′_ = _G′_ = _B′_ -{latexmath:[$C'_B$], -latexmath:[$C'_R$], -latexmath:[$C'_\mathit{BC}$], -latexmath:[$C'_\mathit{RC}$], +{latexmath:[C'_B], +latexmath:[C'_R], +latexmath:[C'_\mathit{BC}], +latexmath:[C'_\mathit{RC}], _C~T~_, _C~P~_} = 0.0 | -{latexmath:[$\mathit{DC}'_B$], -latexmath:[$\mathit{DC}'_R$], -latexmath:[$\mathit{DC}'_\mathit{BC}$], -latexmath:[$\mathit{DC}'_\mathit{CR}$], +{latexmath:[\mathit{DC}'_B], +latexmath:[\mathit{DC}'_R], +latexmath:[\mathit{DC}'_\mathit{BC}], +latexmath:[\mathit{DC}'_\mathit{CR}], _DC~T~_, _DC~P~_} = 2^_n_-1^ -|====== +|==== If, instead of the quantized values, the input is interpreted as fixed-point values in the range 0.0..1.0, as might be the case if the values were treated @@ -376,7 +376,7 @@ as unsigned normalized quantities in a computer graphics API, the following conversions can be applied instead: [latexmath] -++++++ +++++ \begin{align*} G' & = G'_{\mathit{norm}} & B' & = B'_{\mathit{norm}} \\ @@ -403,7 +403,7 @@ I_{\mathit{norm}} & = I & C'_{\mathit{Tnorm}} & = \mathit{DC}'_{T} + {2^{n-1}\over{2^n - 1}} \\ &&C'_{\mathit{Pnorm}} & = \mathit{DC}'_{P} + {2^{n-1}\over{2^n - 1}} \end{align*} -++++++ +++++ <<< [[QUANTIZATION_LEGACY_FULL]] @@ -412,11 +412,11 @@ C'_{\mathit{Tnorm}} & = \mathit{DC}'_{T} + {2^{n-1}\over{2^n - 1}} \\ <>-0 formalized an optional encoding scheme that does not incorporate any reserved head-room or foot-room. The legacy <> similarly used the full range of 8-bit -channels to represent latexmath:[$Y'C_BC_R$] color. +channels to represent latexmath:[Y'C_BC_R] color. For bit depth _n_ = {8 (JFIF),10,12 (Rec.2100)}: [latexmath] -++++++ +++++ \begin{align*} \mathit{DG}' & = \lfloor 0.5 + G'\times 2^n\rfloor & \mathit{DB}' & = \lfloor 0.5 + B'\times 2^n\rfloor \\ @@ -431,12 +431,12 @@ For bit depth _n_ = {8 (JFIF),10,12 (Rec.2100)}: \mathit{DC}'_T & = \lfloor 0.5 + (C'_T + 0.5)\times 2^n\rfloor \\ &&\mathit{DC}'_P & = \lfloor 0.5 + (C'_P + 0.5)\times 2^n\rfloor \end{align*} -++++++ +++++ The dequantization formulae are therefore: [latexmath] -++++++ +++++ \begin{align*} G' & = \mathit{DG}'\times 2^{-n} & Y' & = \mathit{DY}'\times 2^{-n} & @@ -451,10 +451,10 @@ C'_R & = \mathit{DC}'_R\times 2^{-n}-0.5 & C'_\mathit{CR} & = \mathit{DC}'_\mathit{CR}\times 2^{-n}-0.5 & C'_P & = \mathit{DC}'_P\times 2^{-n}-0.5 \end{align*} -++++++ +++++ NOTE: These formulae map luma values of 1.0 and chroma values of 0.5 -to latexmath:[$2^n$], for bit depth latexmath:[$n$]. +to latexmath:[2^n], for bit depth latexmath:[n]. This has the effect that the maximum value (e.g. pure white) cannot be represented directly. Out-of-bounds values must be clamped to the largest representable @@ -477,7 +477,7 @@ as unsigned normalized quantities in a computer graphics API, the following conversions can be applied instead: [latexmath] -++++++ +++++ \begin{align*} G' & = {{G'_{\mathit{norm}}\times (2^n-1)}\over{2^n}} & B' & = {{B'_{\mathit{norm}}\times (2^n-1)}\over{2^n}} & @@ -492,10 +492,10 @@ I & = {{I'_{\mathit{norm}}\times (2^n-1)}\over{2^n}} & C'_T & = {{C'_{\mathit{Tnorm}}\times (2^n-1)}\over{2^n}} - 0.5 & C'_P & = {{C'_{\mathit{Pnorm}}\times (2^n-1)}\over{2^n}} - 0.5 \end{align*} -++++++ +++++ [latexmath] -++++++ +++++ \begin{align*} G_{norm}' & = {{G'\times 2^n}\over{2^n-1}} & B_{norm}' & = {{B'\times 2^n}\over{2^n-1}} & @@ -510,13 +510,13 @@ I_{\mathit{norm}} & = {{I'\times 2^n}\over{2^n-1}} & C'_{\mathit{Tnorm}} & = {{(C'_{T} + 0.5)\times 2^n}\over{2^n-1}} & C'_{\mathit{Pnorm}} & = {{(C'_{P} + 0.5)\times 2^n}\over{2^n-1}} \end{align*} -++++++ +++++ That is, to match the behavior described in these specifications, the inputs to color model conversion should be expanded such that the maximum representable value is that defined by the quantization of these encodings -latexmath:[$\left({255\over 256},\ {1023\over 1024}\ \textrm{or}\ {4095\over 4096}\right)$], +latexmath:[\left({255\over 256},\ {1023\over 1024}\ \textrm{or}\ {4095\over 4096}\right)], and the inverse operation should be applied to the result of the model conversion. @@ -524,9 +524,9 @@ For example, a legacy shader-based JPEG decoder may read values in a normalized 0..1 range, where the in-memory value 0 represents 0.0 and the in-memory value 1 represents 1.0. The decoder should scale the _Y′_ value by a factor of -latexmath:[$255\over 256$] to match the encoding in the <> -document, and latexmath:[$C'_B$] and _C~R~_ should be scaled by -latexmath:[$255\over 256$] and offset by 0.5. +latexmath:[255\over 256] to match the encoding in the <> +document, and latexmath:[C'_B] and _C~R~_ should be scaled by +latexmath:[255\over 256] and offset by 0.5. After the model conversion matrix has been applied, the _R′_, _G′_ and _B′_ values should be scaled by -latexmath:[$256\over 255$], restoring the ability to represent pure white. +latexmath:[256\over 255], restoring the ability to represent pure white. diff --git a/references.txt b/chapters/references.adoc similarity index 97% rename from references.txt rename to chapters/references.adoc index 6d758ad..df43754 100644 --- a/references.txt +++ b/chapters/references.adoc @@ -1,9 +1,9 @@ -// Copyright (c) 2019 The Khronos Group Inc. -// Copyright notice at https://www.khronos.org/registry/speccopyright.html +// Copyright 2019-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 -== External references == +== External references -*[[IEEE 754]]IEEE754-2008 - IEEE standard for floating-point arithmetic* +*[[IEEE-754]]IEEE754-2008 - IEEE standard for floating-point arithmetic* IEEE Std 754-2008 http://dx.doi.org/10.1109/IEEESTD.2008.4610935, @@ -120,7 +120,7 @@ link:https://webstore.iec.ch/preview/info_iec61966-2-2%7Bed1.0%7Den.pdf[https:// A working draft is freely available at link:https://web.archive.org/web/20110725185444/http://www.colour.org/tc8-05/Docs/colorspace/61966-2-2NPa.pdf[https://web.archive.org/web/20110725185444/http://www.colour.org/tc8-05/Docs/colorspace/61966-2-2NPa.pdf]. -link:http://www.color.org/sycc.pdf[http://www.color.org/sycc.pdf] - sYCC (the latexmath:[$Y'C_BC_R$] variant of sRGB) +link:http://www.color.org/sycc.pdf[http://www.color.org/sycc.pdf] - sYCC (the latexmath:[Y'C_BC_R] variant of sRGB) link:https://webstore.iec.ch/corrigenda/iec61966-2-2-cor1%7Bed1.0%7Den.pdf[https://webstore.iec.ch/corrigenda/iec61966-2-2-cor1%7Bed1.0%7Den.pdf] - Annex B: Non-linear encoding for scRGB : scRGB-nl and its YCC Transformation: scYCC-nl + diff --git a/rgtc.txt b/chapters/rgtc.adoc similarity index 76% rename from rgtc.txt rename to chapters/rgtc.adoc index d208bb7..c4b6016 100644 --- a/rgtc.txt +++ b/chapters/rgtc.adoc @@ -1,5 +1,6 @@ -// Copyright (C) 2008-2019 The Khronos Group Inc. All Rights Reserved. -// Copyright notice at https://www.khronos.org/registry/speccopyright.html +// Copyright 2008-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 + [[RGTC]] == RGTC Compressed Texture Image Formats @@ -19,36 +20,36 @@ size of _blocksize_ (8 or 16 bytes) is decoded, the corresponding image size (in bytes) is: [latexmath] -++++++++++++++++++++++ +++++ \begin{align*} \left\lceil { w \over 4 } \right\rceil \times \left\lceil { h \over 4 } \right\rceil \times \mathit{blocksize} \end{align*} -++++++++++++++++++++++ +++++ When decoding an RGTC image, the block containing the texel at offset -latexmath:[$(x,y)$] begins at an offset (in bytes) relative to the base of the image of: +latexmath:[(x,y)] begins at an offset (in bytes) relative to the base of the image of: [latexmath] -++++++++++++++++++++++ +++++ \begin{align*} \mathit{blocksize} \times \left( { \left\lceil { w \over 4 } \right\rceil \times \left\lfloor { y \over 4 } \right\rfloor + \left\lfloor { x \over 4 } \right\rfloor } \right) \end{align*} -++++++++++++++++++++++ +++++ The data corresponding to a specific texel (_x_, _y_) are extracted from a 4{times}4 texel block using a relative (_x_, _y_) value of [latexmath] -++++++++++++++++++++++ +++++ \begin{align*} (x \bmod 4,y \bmod 4) \end{align*} -++++++++++++++++++++++ +++++ There are four distinct RGTC image formats described in the following sections. @@ -64,16 +65,16 @@ Each red image data block is encoded as a sequence of 8 bytes, called (in order of increasing address): [latexmath] -++++++ +++++ \begin{align*} \mathit{red}_0, \mathit{red}_1, \mathit{bits}_0, \mathit{bits}_1, \mathit{bits}_2, \mathit{bits}_3, \mathit{bits}_4, \mathit{bits}_5 \end{align*} -++++++ +++++ The 6 _bits_~{0..5}~ bytes of the block are decoded into a 48-bit bit vector: [latexmath] -++++++++++++++++++++++ +++++ \begin{align*} \mathit{bits} & = \mathit{bits}_0 + @@ -87,23 +88,23 @@ The 6 _bits_~{0..5}~ bytes of the block are decoded into a 48-bit bit vector: \right) } \right) \end{align*} -++++++++++++++++++++++ +++++ _red_~0~ and _red_~1~ are 8-bit unsigned integers that are unpacked to red -values _RED_~0~ and _RED_~1~ by multiplying by latexmath:[$1\over 255$]. +values _RED_~0~ and _RED_~1~ by multiplying by latexmath:[1\over 255]. _bits_ is a 48-bit unsigned integer, from which a three-bit control code is extracted for a texel at location (_x_, _y_) in the block using: [latexmath] -++++++++++++++++++++++ +++++ \begin{align*} \mathit{code}(x,y) & = \mathit{bits} \left[ 3 \times (4 \times y + x) + 2 \dots 3 \times (4 \times y + x) + 0 \right] \end{align*} -++++++++++++++++++++++ +++++ where _bits_[47] is the most-significant and _bits_[0] is the least-significant bit. @@ -113,25 +114,25 @@ the block is given by <>. [[BC4blocks]] .Block decoding for BC4 [options="header",width="43%",cols="1,2"] -|========== +|==== ^| _R_ value ^| Condition ^| _RED_~0~ ^.^| _red_~0~ > _red_~1~, _code_(_x_, _y_) = 0 ^| _RED_~1~ ^.^| _red_~0~ > _red_~1~, _code_(_x_, _y_) = 1 -^| latexmath:[${ 6 \times \mathit{RED}_0 + \mathit{RED}_1 } \over 7$] ^.^| _red_~0~ > _red_~1~, _code_(_x_, _y_) = 2 -^| latexmath:[${ 5 \times \mathit{RED}_0 + 2 \times \mathit{RED}_1 } \over 7$] ^.^| _red_~0~ > _red_~1~, _code_(_x_, _y_) = 3 -^| latexmath:[${ 4 \times \mathit{RED}_0 + 3 \times \mathit{RED}_1 } \over 7$] ^.^| _red_~0~ > _red_~1~, _code_(_x_, _y_) = 4 -^| latexmath:[${ 3 \times \mathit{RED}_0 + 4 \times \mathit{RED}_1 } \over 7$] ^.^| _red_~0~ > _red_~1~, _code_(_x_, _y_) = 5 -^| latexmath:[${ 2 \times \mathit{RED}_0 + 5 \times \mathit{RED}_1 } \over 7$] ^.^| _red_~0~ > _red_~1~, _code_(_x_, _y_) = 6 -^| latexmath:[${ \mathit{RED}_0 + 6 \times \mathit{RED}_1 } \over 7$] ^.^| _red_~0~ > _red_~1~, _code_(_x_, _y_) = 7 +^| latexmath:[{ 6 \times \mathit{RED}_0 + \mathit{RED}_1 } \over 7] ^.^| _red_~0~ > _red_~1~, _code_(_x_, _y_) = 2 +^| latexmath:[{ 5 \times \mathit{RED}_0 + 2 \times \mathit{RED}_1 } \over 7] ^.^| _red_~0~ > _red_~1~, _code_(_x_, _y_) = 3 +^| latexmath:[{ 4 \times \mathit{RED}_0 + 3 \times \mathit{RED}_1 } \over 7] ^.^| _red_~0~ > _red_~1~, _code_(_x_, _y_) = 4 +^| latexmath:[{ 3 \times \mathit{RED}_0 + 4 \times \mathit{RED}_1 } \over 7] ^.^| _red_~0~ > _red_~1~, _code_(_x_, _y_) = 5 +^| latexmath:[{ 2 \times \mathit{RED}_0 + 5 \times \mathit{RED}_1 } \over 7] ^.^| _red_~0~ > _red_~1~, _code_(_x_, _y_) = 6 +^| latexmath:[{ \mathit{RED}_0 + 6 \times \mathit{RED}_1 } \over 7] ^.^| _red_~0~ > _red_~1~, _code_(_x_, _y_) = 7 ^| _RED_~0~ ^.^| _red_~0~ {leq} _red_~1~, _code_(_x_, _y_) = 0 ^| _RED_~1~ ^.^| _red_~0~ {leq} _red_~1~, _code_(_x_, _y_) = 1 -^| latexmath:[${ 4 \times \mathit{RED}_0 + \mathit{RED}_1 } \over 5$] ^.^| _red_~0~ {leq} _red_~1~, _code_(_x_, _y_) = 2 -^| latexmath:[${ 3 \times \mathit{RED}_0 + 2 \times \mathit{RED}_1 } \over 5$] ^.^| _red_~0~ {leq} _red_~1~, _code_(_x_, _y_) = 3 -^| latexmath:[${ 2 \times \mathit{RED}_0 + 3 \times \mathit{RED}_1 } \over 5$] ^.^| _red_~0~ {leq} _red_~1~, _code_(_x_, _y_) = 4 -^| latexmath:[${ \mathit{RED}_0 + 4 \times \mathit{RED}_1 } \over 5$] ^.^| _red_~0~ {leq} _red_~1~, _code_(_x_, _y_) = 5 +^| latexmath:[{ 4 \times \mathit{RED}_0 + \mathit{RED}_1 } \over 5] ^.^| _red_~0~ {leq} _red_~1~, _code_(_x_, _y_) = 2 +^| latexmath:[{ 3 \times \mathit{RED}_0 + 2 \times \mathit{RED}_1 } \over 5] ^.^| _red_~0~ {leq} _red_~1~, _code_(_x_, _y_) = 3 +^| latexmath:[{ 2 \times \mathit{RED}_0 + 3 \times \mathit{RED}_1 } \over 5] ^.^| _red_~0~ {leq} _red_~1~, _code_(_x_, _y_) = 4 +^| latexmath:[{ \mathit{RED}_0 + 4 \times \mathit{RED}_1 } \over 5] ^.^| _red_~0~ {leq} _red_~1~, _code_(_x_, _y_) = 5 ^| _RED~min~_ ^.^| _red_~0~ {leq} _red_~1~, _code_(_x_, _y_) = 6 ^| _RED~max~_ ^.^| _red_~0~ {leq} _red_~1~, _code_(_x_, _y_) = 7 -|========== +|==== _RED_~min~ and _RED_~max~ are 0.0 and 1.0 respectively. @@ -146,7 +147,7 @@ BC4 unsigned except _red_~0~, _red_~1~, _RED_~0~, _RED_~1~, _RED_~min~, and _RED_~max~ are signed values defined as follows: [latexmath] -++++++ +++++ \begin{align*} \mathit{RED}_0 & = \begin{cases} {\mathit{red}_0 \over 127.0}, & \mathit{red}_0 > -128 \\ @@ -159,7 +160,7 @@ _RED_~min~, and _RED_~max~ are signed values defined as follows: \mathit{RED}_{\mathit{min}} & = -1.0 \\ \mathit{RED}_{\mathit{max}} & = 1.0 \end{align*} -+++++++++++ +++++ _red_~0~ and _red_~1~ are 8-bit signed (two's complement) integers. diff --git a/s3tc.txt b/chapters/s3tc.adoc similarity index 77% rename from s3tc.txt rename to chapters/s3tc.adoc index b06acfb..1494c73 100644 --- a/s3tc.txt +++ b/chapters/s3tc.adoc @@ -1,5 +1,6 @@ -// Copyright (C) 2008-2019 The Khronos Group Inc. All Rights Reserved. -// Copyright notice at https://www.khronos.org/registry/speccopyright.html +// Copyright 2008-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 + [[S3TC]] == S3TC Compressed Texture Image Formats @@ -23,37 +24,37 @@ _blocksize_ (8 or 16 bytes) is decoded, the corresponding image size (in bytes) is: [latexmath] -++++++++++++++++ +++++ \begin{align*} \left\lceil { w \over 4 } \right\rceil \times \left\lceil { h \over 4 } \right\rceil \times blocksize \end{align*} -++++++++++++++++ +++++ When decoding an S3TC image, the block containing the texel at offset (_x_, _y_) begins at an offset (in bytes) relative to the base of the image of: [latexmath] -++++++++++++++ +++++ \begin{align*} blocksize \times \left( { \left\lceil { w \over 4 } \right\rceil \times \left\lfloor { y \over 4 } \right\rfloor + \left\lfloor { x \over 4 } \right\rfloor } \right) \end{align*} -++++++++++++++ +++++ The data corresponding to a specific texel (_x_, _y_) are extracted from a 4{times}4 texel block using a relative (_x_, _y_) value of [latexmath] -++++++++++++++ +++++ \begin{align*} (x \bmod 4,y \bmod 4) \end{align*} -++++++++++++++ +++++ There are four distinct S3TC image formats: @@ -67,22 +68,22 @@ Each _RGB_ image data block is encoded as a sequence of 8 bytes, called (in order of increasing address): [latexmath] -++++++ +++++ \begin{align*} c0_{\mathit{lo}}, c0_{\mathit{hi}}, c1_{\mathit{lo}}, c1_{\mathit{hi}}, \mathit{bits}_0, \mathit{bits}_1, \mathit{bits}_2, \mathit{bits}_3 \end{align*} -++++++ +++++ The 8 bytes of the block are decoded into three quantities: [latexmath] -++++++ +++++ \begin{align*} \mathit{color}_0 & = c0_{\mathit{lo}} + c0_{\mathit{hi}} \times 256 \\ \mathit{color}_1 & = c1_{\mathit{lo}} + c1_{\mathit{hi}} \times 256 \\ \mathit{bits} & = \mathit{bits}_0 + 256 \times (\mathit{bits}_1 + 256 \times (\mathit{bits}_2 + 256 \times \mathit{bits}_3)) \end{align*} -++++++ +++++ _color_~0~ and _color_~1~ are 16-bit unsigned integers that are unpacked to _RGB_ colors _RGB_~0~ and _RGB_~1~ as though they were 16-bit @@ -90,23 +91,23 @@ unsigned packed pixels with the _R_ channel in the high 5 bits, _G_ in the next 6 bits and _B_ in the low 5 bits: [latexmath] -++++++ +++++ \begin{align*} \mathit{R}_n & = {{\mathit{color}_n^{15..11}}\over 31} \\ \mathit{G}_n & = {{\mathit{color}_n^{10..5}}\over 63} \\ \mathit{B}_n & = {{\mathit{color}_n^{4..0}}\over 31} \end{align*} -++++++ +++++ _bits_ is a 32-bit unsigned integer, from which a two-bit control code is extracted for a texel at location (_x_, _y_) in the block using: [latexmath] -++++++ +++++ \begin{align*} \mathit{code}(x,y) & = \mathit{bits}[2\times (4\times y+x)+1\ \dots\ 2\times(4\times y+x)+0] \end{align*} -++++++ +++++ where _bits_[31] is the most significant and _bits_[0] is the least significant bit. @@ -117,17 +118,17 @@ in <>. [[BC1blocks]] .Block decoding for BC1 [options="header",cols="1,2",width="60%"] -|========== +|==== ^| Texel value ^| Condition ^.^| _RGB_~0~ ^.^| _color_~0~ > _color_~1~ and _code_(_x_, _y_) = 0 ^.^| _RGB_~1~ ^.^| _color_~0~ > _color_~1~ and _code_(_x_, _y_) = 1 -^| latexmath:[$(2\times \mathit{RGB}_0 + \mathit{RGB}_1)\over 3$] ^.^| _color_~0~ > _color_~1~ and _code_(_x_, _y_) = 2 -^| latexmath:[$(\mathit{RGB}_0 + 2\times RGB_1)\over 3$] ^.^| _color_~0~ > _color_~1~ and _code_(_x_, _y_) = 3 +^| latexmath:[(2\times \mathit{RGB}_0 + \mathit{RGB}_1)\over 3] ^.^| _color_~0~ > _color_~1~ and _code_(_x_, _y_) = 2 +^| latexmath:[(\mathit{RGB}_0 + 2\times RGB_1)\over 3] ^.^| _color_~0~ > _color_~1~ and _code_(_x_, _y_) = 3 ^.^| _RGB_~0~ ^.^| _color_~0~ {leq} _color_~1~ and _code_(_x_, _y_) = 0 ^.^| _RGB_~1~ ^.^| _color_~0~ {leq} _color_~1~ and _code_(_x_, _y_) = 1 -^| latexmath:[$(\mathit{RGB}_0+\mathit{RGB}_1)\over 2$] ^.^| _color_~0~ {leq} _color_~1~ and _code_(_x_, _y_) = 2 +^| latexmath:[(\mathit{RGB}_0+\mathit{RGB}_1)\over 2] ^.^| _color_~0~ {leq} _color_~1~ and _code_(_x_, _y_) = 2 ^.^| BLACK ^.^| _color_~0~ {leq} _color_~1~ and _code_(_x_, _y_) = 3 -|========== +|==== Arithmetic operations are done per component, and BLACK refers to an _RGB_ color where red, green, and blue are all zero. @@ -149,11 +150,11 @@ given by <>. [[BC1alpha]] .BC1 with alpha [options="header",cols="1,2",width="60%"] -|========== +|==== ^| Alpha value ^| Condition ^| 0.0 ^| _color_~0~ {leq} _color_~1~ and _code_(_x_, _y_) = 3 ^| 1.0 ^| otherwise -|========== +|==== // This is a discussion of the behavior of the encoder, not of the // format itself. @@ -176,19 +177,19 @@ of 0 should be encoded as zero (black). [NOTE] ==== <> shows an example BC1 texel block: -_color_~0~, encoded as latexmath:[$\left({{29}\over{31}}, {{60}\over{63}}, {{1}\over{31}}\right)$], -and _color_~1~, encoded as latexmath:[$\left({{20}\over{31}}, {{2}\over{63}}, {{30}\over{31}}\right)$], +_color_~0~, encoded as latexmath:[\left({{29}\over{31}}, {{60}\over{63}}, {{1}\over{31}}\right)], +and _color_~1~, encoded as latexmath:[\left({{20}\over{31}}, {{2}\over{63}}, {{30}\over{31}}\right)], are shown as circles. The interpolated values are shown as small diamonds. Since 29 > 20, there are two interpolated values, accessed when _code_(_x_, _y_) = 2 and _code_(_x_, _y_) = 3. [[Figure-bc1]] .BC1 two interpolated colors -image::images/bc1.{svgpdf}[width="{svgpdf@pdf:190.5pt:382.5}",align="center"] +image::{images}/bc1.svg[width="{svgpdf@pdf:190.5pt:382.5}",align="center"] <> shows the example BC1 texel block with the colors swapped: -_color_~0~, encoded as latexmath:[$\left({{20}\over{31}}, {{2}\over{63}}, {{30}\over{31}}\right)$], -and _color_~1~, encoded as latexmath:[$\left({{29}\over{31}}, {{60}\over{63}}, {{1}\over{31}}\right)$], +_color_~0~, encoded as latexmath:[\left({{20}\over{31}}, {{2}\over{63}}, {{30}\over{31}}\right)], +and _color_~1~, encoded as latexmath:[\left({{29}\over{31}}, {{60}\over{63}}, {{1}\over{31}}\right)], are shown as circles. The interpolated value is shown as a small diamonds. Since 20 {leq} 29, there is one interpolated value for _code_(_x_, _y_) = 2, and _code_(_x_, _y_) = 3 represents @@ -196,7 +197,7 @@ _code_(_x_, _y_) = 2, and _code_(_x_, _y_) = 3 represents [[Figure-bc1a]] .BC1 one interpolated color {plus} black -image::images/bc1a.{svgpdf}[width="{svgpdf@pdf:190.5pt:382.5}",align="center"] +image::{images}/bc1a.svg[width="{svgpdf@pdf:190.5pt:382.5}",align="center"] If the format is BC1 with alpha, _code_(_x_, _y_) = 3 is transparent (alpha = 0). @@ -223,37 +224,37 @@ Each alpha image data block is encoded as a sequence of 8 bytes, called (in order of increasing address): [latexmath] -++++++ +++++ \begin{align*} a_0, a_1, a_2, a_3, a_4, a_5, a_6, a_7 \end{align*} -++++++ +++++ The 8 bytes of the block are decoded into one 64-bit integer: [latexmath] -++++++ +++++ \begin{align*} \mathit{alpha} & = a_0 + 256 \times (a_1 + 256 \times (a_2 + 256 \times (a_3 + 256 \times (a_4 + 256 \times (a_5 + 256 \times (a_6 + 256 \times a_7)))))) \end{align*} -++++++ +++++ _alpha_ is a 64-bit unsigned integer, from which a four-bit alpha value is extracted for a texel at location (_x_, _y_) in the block using: [latexmath] -++++++ +++++ \begin{align*} \mathit{alpha}(x,y) & = \mathit{bits}[4\times(4\times y+x)+3 \dots 4\times(4\times y+x)+0] \end{align*} -++++++ +++++ where _bits_[63] is the most significant and _bits_[0] is the least significant bit. The alpha component for a texel at location (_x_, _y_) in the block is -given by latexmath:[$\mathit{alpha}(x,y)\over 15$]. +given by latexmath:[\mathit{alpha}(x,y)\over 15]. [[s3tc_bc3]] === BC3 @@ -271,34 +272,34 @@ Each alpha image data block is encoded as a sequence of 8 bytes, called (in order of increasing address): [latexmath] -++++++ +++++ \begin{align*} \mathit{alpha}_0, \mathit{alpha}_1, \mathit{bits}_0, \mathit{bits}_1, \mathit{bits}_2, \mathit{bits}_3, \mathit{bits}_4, \mathit{bits}_5 \end{align*} -++++++ +++++ The _alpha_~0~ and _alpha_~1~ are 8-bit unsigned bytes converted to alpha -components by multiplying by latexmath:[$1\over 255$]. +components by multiplying by latexmath:[1\over 255]. The 6 _bits_ bytes of the block are decoded into one 48-bit integer: [latexmath] -++++++ +++++ \begin{align*} \mathit{bits} & = \mathit{bits}_0 + 256 \times (\mathit{bits}_1 + 256 \times (\mathit{bits}_2 + 256 \times (\mathit{bits}_3 + 256 \times (\mathit{bits}_4 + 256 \times \mathit{bits}_5)))) \end{align*} -++++++ +++++ _bits_ is a 48-bit unsigned integer, from which a three-bit control code is extracted for a texel at location (_x_, _y_) in the block using: [latexmath] -++++++ +++++ \begin{align*} \mathit{code}(x,y) & = \mathit{bits}[3\times(4\times y+x)+2 \dots 3\times(4\times y+x)+0] \end{align*} -++++++ +++++ where _bits_[47] is the most-significant and _bits_[0] is the least-significant bit. @@ -310,20 +311,20 @@ given by <>. [[BC3alpha]] .Alpha encoding for BC3 blocks [options="header",cols="2,3",width="70%"] -|================= +|==== ^| Alpha value ^| Condition ^.^| _alpha_~0~ ^.^| _code_(_x_, _y_) = 0 ^.^| _alpha_~1~ ^.^| _code_(_x_, _y_) = 1 -^| latexmath:[$(6\times\mathit{alpha}_0 + 1\times\mathit{alpha}_1)\over 7$] ^.^| _alpha_~0~ > _alpha_~1~ and _code_(_x_, _y_) = 2 -^| latexmath:[$(5\times\mathit{alpha}_0 + 2\times\mathit{alpha}_1)\over 7$] ^.^| _alpha_~0~ > _alpha_~1~ and _code_(_x_, _y_) = 3 -^| latexmath:[$(4\times\mathit{alpha}_0 + 3\times\mathit{alpha}_1)\over 7$] ^.^| _alpha_~0~ > _alpha_~1~ and _code_(_x_, _y_) = 4 -^| latexmath:[$(3\times\mathit{alpha}_0 + 4\times\mathit{alpha}_1)\over 7$] ^.^| _alpha_~0~ > _alpha_~1~ and _code_(_x_, _y_) = 5 -^| latexmath:[$(2\times\mathit{alpha}_0 + 5\times\mathit{alpha}_1)\over 7$] ^.^| _alpha_~0~ > _alpha_~1~ and _code_(_x_, _y_) = 6 -^| latexmath:[$(1\times\mathit{alpha}_0 + 6\times\mathit{alpha}_1)\over 7$] ^.^| _alpha_~0~ > _alpha_~1~ and _code_(_x_, _y_) = 7 -^| latexmath:[$(4\times\mathit{alpha}_0 + 1\times\mathit{alpha}_1)\over 5$] ^.^| _alpha_~0~ {leq} _alpha_~1~ and _code_(_x_, _y_) = 2 -^| latexmath:[$(3\times\mathit{alpha}_0 + 2\times\mathit{alpha}_1)\over 5$] ^.^| _alpha_~0~ {leq} _alpha_~1~ and _code_(_x_, _y_) = 3 -^| latexmath:[$(2\times\mathit{alpha}_0 + 3\times\mathit{alpha}_1)\over 5$] ^.^| _alpha_~0~ {leq} _alpha_~1~ and _code_(_x_, _y_) = 4 -^| latexmath:[$(1\times\mathit{alpha}_0 + 4\times\mathit{alpha}_1)\over 5$] ^.^| _alpha_~0~ {leq} _alpha_~1~ and _code_(_x_, _y_) = 5 +^| latexmath:[(6\times\mathit{alpha}_0 + 1\times\mathit{alpha}_1)\over 7] ^.^| _alpha_~0~ > _alpha_~1~ and _code_(_x_, _y_) = 2 +^| latexmath:[(5\times\mathit{alpha}_0 + 2\times\mathit{alpha}_1)\over 7] ^.^| _alpha_~0~ > _alpha_~1~ and _code_(_x_, _y_) = 3 +^| latexmath:[(4\times\mathit{alpha}_0 + 3\times\mathit{alpha}_1)\over 7] ^.^| _alpha_~0~ > _alpha_~1~ and _code_(_x_, _y_) = 4 +^| latexmath:[(3\times\mathit{alpha}_0 + 4\times\mathit{alpha}_1)\over 7] ^.^| _alpha_~0~ > _alpha_~1~ and _code_(_x_, _y_) = 5 +^| latexmath:[(2\times\mathit{alpha}_0 + 5\times\mathit{alpha}_1)\over 7] ^.^| _alpha_~0~ > _alpha_~1~ and _code_(_x_, _y_) = 6 +^| latexmath:[(1\times\mathit{alpha}_0 + 6\times\mathit{alpha}_1)\over 7] ^.^| _alpha_~0~ > _alpha_~1~ and _code_(_x_, _y_) = 7 +^| latexmath:[(4\times\mathit{alpha}_0 + 1\times\mathit{alpha}_1)\over 5] ^.^| _alpha_~0~ {leq} _alpha_~1~ and _code_(_x_, _y_) = 2 +^| latexmath:[(3\times\mathit{alpha}_0 + 2\times\mathit{alpha}_1)\over 5] ^.^| _alpha_~0~ {leq} _alpha_~1~ and _code_(_x_, _y_) = 3 +^| latexmath:[(2\times\mathit{alpha}_0 + 3\times\mathit{alpha}_1)\over 5] ^.^| _alpha_~0~ {leq} _alpha_~1~ and _code_(_x_, _y_) = 4 +^| latexmath:[(1\times\mathit{alpha}_0 + 4\times\mathit{alpha}_1)\over 5] ^.^| _alpha_~0~ {leq} _alpha_~1~ and _code_(_x_, _y_) = 5 ^.^| 0.0 ^.^| _alpha_~0~ {leq} _alpha_~1~ and _code_(_x_, _y_) = 6 ^.^| 1.0 ^.^| _alpha_~0~ {leq} _alpha_~1~ and _code_(_x_, _y_) = 7 -|================= +|==== diff --git a/transferfunctions.txt b/chapters/transferfunctions.adoc similarity index 78% rename from transferfunctions.txt rename to chapters/transferfunctions.adoc index 47a81e5..b5a51d2 100644 --- a/transferfunctions.txt +++ b/chapters/transferfunctions.adoc @@ -1,5 +1,5 @@ -// Copyright (c) 2017-2019 The Khronos Group Inc. -// Copyright notice at https://www.khronos.org/registry/speccopyright.html +// Copyright 2017-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 [[TRANSFER_CONVERSION]] == Transfer functions @@ -25,11 +25,11 @@ represent darker intensities than their fraction of the representation of white would suggest. .Conversion curves between linear light and encoded values (sRGB example) -image::images/tf_curves.{svgpdf}[width="{svgpdf@pdf:350pt:576}",align="center"] +image::{images}/tf_curves.svg[width="{svgpdf@pdf:350pt:576}",align="center"] The behavior has historically been approximated by a power function -with an exponent conventionally called latexmath:[$\gamma$]: + -{_R_,_G_,_B_}~non-linear~ = {_R_,_G_,_B_}~linear~^latexmath:[$\gamma$]^. +with an exponent conventionally called latexmath:[\gamma]: + +{_R_,_G_,_B_}~non-linear~ = {_R_,_G_,_B_}~linear~^latexmath:[\gamma]^. Hence this conversion is colloquially known as _gamma correction_. NOTE: Many practical transfer functions incorporate a small linear @@ -63,7 +63,7 @@ approximating the behavior of a CRT with uncorrected signals. The background represents 50% gray. .Averaging checker values with different transfer functions -image::images/tf_sampling.{svgpdf}[width="{svgpdf@pdf:210pt:576}",align="center"] +image::{images}/tf_sampling.svg[width="{svgpdf@pdf:210pt:576}",align="center"] * *In row 1* black (0.0) and white (1.0) texels are averaged to calculate a 0.5 value in the frame buffer. @@ -104,18 +104,18 @@ Incorrectly-applied transfer functions can also introduce color shifts, as demonstrated by the saturation change in the following examples: ._R_, _G_, _B_ channels and combined color gradient with linear light intensity in each channel -image::images/tf_colorshift_intensitylinearvalues.png[width="{svgpdf@pdf:150pt:256}",align="center"] +image::{images}/tf_colorshift_intensitylinearvalues.png[width="{svgpdf@pdf:150pt:256}",align="center"] ._R′_, _G′_, _B′_ channels and combined color gradient with non-linear sRGB encoding in each channel -image::images/tf_colorshift_srgblinearvalues.png[width="{svgpdf@pdf:150pt:256}",align="center"] +image::{images}/tf_colorshift_srgblinearvalues.png[width="{svgpdf@pdf:150pt:256}",align="center"] <<< A standard for image representation typically defines one or both of two types of transfer functions: .Opto-electronics and electro-optical transfer functions -image::images/tf_scene_store_display.{svgpdf}[width="{svgpdf@pdf:450pt:800}",align="center"] +image::{images}/tf_scene_store_display.svg[width="{svgpdf@pdf:450pt:800}",align="center"] * An opto-electronic transfer function (OETF) defines the conversion between a normalized linear light intensity as recorded in the scene, @@ -183,7 +183,7 @@ Adaptation to the surround means that the top left and lower right images look similar. .Simultaneous contrast -image::images/tf_surround_luminance.{svgpdf}[width="{svgpdf@pdf:450pt:800}",align="center"] +image::{images}/tf_surround_luminance.svg[width="{svgpdf@pdf:450pt:800}",align="center"] In the context of a non-linear OOTF, an application should be aware of whether operations on the image are intended to reflect the representation of colors in @@ -245,7 +245,7 @@ The (OETF) conversion from linear (_R_,_G_,_B_) encoding to non-linear (_R′_,_G′_,_B′_) encoding is: [latexmath] -++++++ +++++ \begin{align*} \textit{R}' &= \begin{cases} \textit{R} \times 4.500, & \textit{R} < \beta \\ @@ -260,11 +260,11 @@ to non-linear (_R′_,_G′_,_B′_) encoding is: \alpha \times \textit{B}^{0.45} - (\alpha - 1), & \textit{B} \geq \beta \end{cases} \end{align*} -++++++ +++++ Where _α_ = 1.0993 and _β_ = 0.0181 for 12-bit encoding in the BT.2020 specification, and -latexmath:[$\alpha = 1.099$] and latexmath:[$\beta = 0.018$] otherwise. +latexmath:[\alpha = 1.099] and latexmath:[\beta = 0.018] otherwise. [[TRANSFER_ITU_INVOETF]] ==== ITU OETF^ -1^ @@ -272,7 +272,7 @@ latexmath:[$\alpha = 1.099$] and latexmath:[$\beta = 0.018$] otherwise. From this the inverse (OETF^ -1^) transformation can be deduced: [latexmath] -++++++ +++++ \begin{align*} \textit{R} &= \begin{cases} {{\textit{R}'}\over{4.500}}, & \textit{R}' < \delta \\ @@ -287,7 +287,7 @@ B &= \begin{cases} {\left({\textit{B}' + (\alpha - 1)}\over{\alpha}\right)}^{1\over{0.45}}, & \textit{B}' \geq \delta \end{cases} \end{align*} -++++++ +++++ _δ_ can be deduced from _α_ {times} _β_^0.45^ - (_α_ - 1) ≈ 0.0812. Note that this is subtly different from @@ -322,18 +322,18 @@ ITU standards deliberately chose a different transfer curve from that of a typical CRT in order to introduce a non-linear OOTF, as a means to compensate for the typically dim conditions in which a television is viewed. <> refers to the approximation of the OETF with a -square root latexmath:[$\left(\gamma = {1\over{2}}\right)$] function. +square root latexmath:[\left(\gamma = {1\over{2}}\right)] function. The following graph shows the close relationship between the ITU OETF (shown in red) and a pure power function with -latexmath:[$\gamma={1\over{2}}$] (in blue). +latexmath:[\gamma={1\over{2}}] (in blue). The difference between the curves is shown in black. The largest difference between the curve values at the same point when quantized to 8 bits is 15, mostly due to the sharp vertical gradient near 0. .ITU OETF vs pure gamma ^1^/~2~ -image::images/tf_ituvsgamma2_0.png[width="{svgpdf@pdf:160pt:257}",align="center"] +image::{images}/tf_ituvsgamma2_0.png[width="{svgpdf@pdf:160pt:257}",align="center"] [NOTE] ==== @@ -345,14 +345,14 @@ While both versions define a linear OOTF, there is no explicit mention that curve has substantially changed; this might be due to conflation of the 0.455 exponent in older specifications with the 0.45 exponent in the new formulae. The ITU OETF is actually a closer match to a gamma exponent of -latexmath:[$1\over{2.0}$], as shown above; it is a relatively poor match to a -gamma exponent of latexmath:[$1\over{2.2}$]; the following graph shows the +latexmath:[1\over{2.0}], as shown above; it is a relatively poor match to a +gamma exponent of latexmath:[1\over{2.2}]; the following graph shows the difference between the ITU OETF (shown in red) and a pure power function -with latexmath:[$\gamma={1\over{2.2}}$] (in blue). +with latexmath:[\gamma={1\over{2.2}}] (in blue). The difference between the curves is shown in black. .ITU OETF vs pure gamma ^1^/~2.2~ -image::images/tf_ituvsgamma2_2.png[width="{svgpdf@pdf:160pt:257}",align="center"] +image::{images}/tf_ituvsgamma2_2.png[width="{svgpdf@pdf:160pt:257}",align="center"] ==== ==== Derivation of the ITU alpha and beta constants (informative) @@ -377,51 +377,51 @@ At {_R_,_G_,_B_} = _β_, the linear and non-linear segments of the curv must calculate the same value: [latexmath] -++++++ -$$4.5 \times \beta = \alpha \times \beta^{0.45} - (\alpha - 1)$$ -++++++ +++++ +4.5 \times \beta = \alpha \times \beta^{0.45} - (\alpha - 1) +++++ Additionally, the derivatives of the linear and non-linear segments of the curve must match: [latexmath] -++++++ -$$4.5 = 0.45 \times \alpha \times \beta^{-0.55}$$ -++++++ +++++ +4.5 = 0.45 \times \alpha \times \beta^{-0.55} +++++ The derivative can be rearranged to give the equation: [latexmath] -++++++ -$$\alpha = 10 \times \beta^{0.55}$$ -++++++ +++++ +\alpha = 10 \times \beta^{0.55} +++++ Substituting this into the original equation results in the following: [latexmath] -++++++ -$$4.5 \times \beta = 10 \times \beta^{0.55} \times \beta^{0.45} - (10 \times \beta^{0.55} - 1)$$ -++++++ +++++ +4.5 \times \beta = 10 \times \beta^{0.55} \times \beta^{0.45} - (10 \times \beta^{0.55} - 1) +++++ This simplifies to: [latexmath] -++++++ -$$5.5 \times \beta - 10 \times \beta^{0.55} + 1 = 0$$ -++++++ +++++ +5.5 \times \beta - 10 \times \beta^{0.55} + 1 = 0 +++++ This can be solved numerically (for example by Newton-Raphson iteration), and results in values of: [latexmath] -++++++ +++++ \begin{align*} \beta &\approx 0.018053968510808\\ \alpha &\approx 1.099296826809443\\ \delta &= \alpha\times\beta^{0.45} - (\alpha-1) = 4.5\times\beta\\ &\approx 0.081242858298635\\ \end{align*} -++++++ +++++ <<< @@ -432,12 +432,12 @@ and results in values of: ==== sRGB EOTF The <> defines an electro-optical transfer function. -The EOTF conversion from non-linear latexmath:[$(R', G', B')$] encoding -to linear latexmath:[$(R, G, B)$] encoding is: +The EOTF conversion from non-linear latexmath:[(R', G', B')] encoding +to linear latexmath:[(R, G, B)] encoding is: [[srgbgamma]] [latexmath] -++++++ +++++ \begin{align*} R &= \begin{cases} {R' \over 12.92}, & R' \leq 0.04045 \\ @@ -452,17 +452,17 @@ to linear latexmath:[$(R, G, B)$] encoding is: \left({B' + 0.055} \over 1.055\right)^{2.4}, & B' > 0.04045 \end{cases} \end{align*} -++++++ +++++ [[TRANSFER_SRGB_INVEOTF]] ==== sRGB EOTF^-1^ The corresponding sRGB EOTF^ -1^ conversion from linear -latexmath:[$(R, G, B)$] encoding to non-linear latexmath:[$(R', G', B')$] +latexmath:[(R, G, B)] encoding to non-linear latexmath:[(R', G', B')] encoding is: [latexmath] -++++++ +++++ \begin{align*} R' &= \begin{cases} R \times 12.92, & R \leq 0.0031308 \\ @@ -477,7 +477,7 @@ encoding is: 1.055 \times B^{1\over 2.4} - 0.055, & B > 0.0031308 \end{cases} \end{align*} -++++++ +++++ [[TRANSFER_SRGB_EOTFVSGAMMA]] ==== sRGB EOTF vs gamma 2.2 @@ -497,32 +497,32 @@ its EOTF as the inverse of its (and BT.709's) OETF. <<< The following graph compares the sRGB EOTF (in red) and a pure power -function with latexmath:[$\gamma=2.2$] (in blue); the area between the +function with latexmath:[\gamma=2.2] (in blue); the area between the two curves is shown in black. The largest non-linear difference at the same linear value when quantized to 8 bits is 3. .sRGB EOTF vs pure gamma 2.2 -image::images/tf_srgbvsgamma.png[width="{svgpdf@pdf:192pt:257}",align="center"] +image::{images}/tf_srgbvsgamma.png[width="{svgpdf@pdf:192pt:257}",align="center"] NOTE: The sRGB standard assumes a quantization scheme in which 0.0 is represented by the value 0 and 1.0 is represented by 255. Despite the goal of complementing <>, this is different from the ITU ``full-range'' encoding scheme defined in <>, which represents 1.0 as -a power of two (not latexmath:[$2^n-1$]) and therefore cannot exactly +a power of two (not latexmath:[2^n-1]) and therefore cannot exactly represent 1.0. The following graph shows the relationship between the sRGB EOTF (shown in red) and the <> (shown in blue). The result of applying the two functions in turn, resulting in the OOTF of a combined ITU-sRGB system, is shown in black. Since the sRGB EOTF approximates a power function -with latexmath:[$\gamma=2.2$] and the ITU OETF approximates a power function with -latexmath:[$\gamma=2.0$], also shown in green is the resulting OOTF corresponding to a -power function with latexmath:[$\gamma={2.2\over{2.0}}=1.1$]. +with latexmath:[\gamma=2.2] and the ITU OETF approximates a power function with +latexmath:[\gamma=2.0], also shown in green is the resulting OOTF corresponding to a +power function with latexmath:[\gamma={2.2\over{2.0}}=1.1]. .sRGB EOTF and ITU OETF -image::images/tf_ituvssrgb256.png[width="{svgpdf@pdf:192pt:257}",align="center"] +image::{images}/tf_ituvssrgb256.png[width="{svgpdf@pdf:192pt:257}",align="center"] <<< [[TRANSFER_SCRGB_EOTF]] @@ -539,7 +539,7 @@ the absolute value of the input. That is: [latexmath] -++++++ +++++ \begin{align*} R' &= \begin{cases} -1.055 \times (-R)^{1\over 2.4} + 0.055, & R \leq -0.0031308 \\ @@ -557,10 +557,10 @@ That is: 1.055 \times B^{1\over 2.4} - 0.055, & B \geq 0.0031308 \end{cases} \end{align*} -++++++ +++++ NOTE: <> annex B changes the behavior of the -latexmath:[$\{R,G,B\} = 0.0031308$] case compared with the +latexmath:[\{R,G,B\} = 0.0031308] case compared with the <> specification. Since both calculations agree to seven decimal places, this is unlikely to be significant in most applications. @@ -568,7 +568,7 @@ scRGB annex B does not define the EOTF^ -1^, so the formulae below are derived by extending the sRGB formulae. [latexmath] -++++++ +++++ \begin{align*} R &= \begin{cases} -\left({0.055 - R'} \over 1.055\right)^{2.4}, & R' < -0.04045 \\ @@ -586,18 +586,18 @@ formulae below are derived by extending the sRGB formulae. \left({B' + 0.055} \over 1.055\right)^{2.4}, & B' > 0.04045 \end{cases} \end{align*} -++++++ +++++ [NOTE] ==== <> includes a hint that a 1cd/m^2^ level of flare should be assumed for the reference 80cd/m^2^ output, and that the black level -should therefore be assumed to be latexmath:[${1\over 80} = 0.0125$]. -It notes that the non-linear sRGB \{latexmath:[$R',G',B'$]\} values can +should therefore be assumed to be latexmath:[{1\over 80} = 0.0125]. +It notes that the non-linear sRGB \{latexmath:[R',G',B']\} values can be corrected as follows: [latexmath] -++++++ +++++ \begin{align*} E_{sYCC} &= \begin{cases} 0.0125 - \left({1-0.0125\over 1.055^{2.4}}\right) @@ -613,12 +613,12 @@ E_{sYCC} &= \begin{cases} E_{sYCC} &= (\textrm{linear}) \{R_{sYCC},G_{sYCC},B_{sYCC}\} \\ E'_{sRGB} &= (\textrm{non-linear}) \{R'_{sRGB},G'_{sRGB},B'_{sRGB}\} \end{align*} -++++++ +++++ This is equivalent to applying -latexmath:[$E_{sYCC} = 0.0125 + {1\over 1-0.0125} \times E_{sRGB}$] -to linear latexmath:[$\{R,G,B\}$] values. -The resulting linear latexmath:[$E_{sYCC}$] values then need to be +latexmath:[E_{sYCC} = 0.0125 + {1\over 1-0.0125} \times E_{sRGB}] +to linear latexmath:[\{R,G,B\}] values. +The resulting linear latexmath:[E_{sYCC}] values then need to be non-linearly encoded with the EOTF. ==== @@ -631,84 +631,84 @@ Similar to the ITU transfer function, the EOTF^ -1^ of the sRGB function can be written as: [latexmath] -++++++ +++++ \begin{align*} \{R,G,B\} &= \begin{cases} \{R',G',B'\} \times 12.92, & \{R',G',B'\} \leq \beta \\ \alpha \times \{R',G',B'\}^{1\over{2.4}} - (\alpha - 1), & \{R',G',B'\} < \beta \end{cases} \end{align*} -++++++ +++++ -Like the ITU transfer function above, the values of latexmath:[$\alpha$] -and latexmath:[$\beta$] in the sRGB function appear to have been chosen +Like the ITU transfer function above, the values of latexmath:[\alpha] +and latexmath:[\beta] in the sRGB function appear to have been chosen such that the linear segment and power segment meet at the same value and with the same derivative (that is, the linear segment meets the power segment at a tangent). -The latexmath:[$\alpha$] and latexmath:[$\beta$] values can be derived as +The latexmath:[\alpha] and latexmath:[\beta] values can be derived as follows: -At latexmath:[$\{R',G',B'\} = \beta$], the linear and non-linear segments +At latexmath:[\{R',G',B'\} = \beta], the linear and non-linear segments of the function must calculate the same value: [latexmath] -++++++ -$$12.92 \times \beta = \alpha \times \beta^{1\over{2.4}} - (\alpha - 1)$$ -++++++ +++++ +12.92 \times \beta = \alpha \times \beta^{1\over{2.4}} - (\alpha - 1) +++++ Additionally, the derivatives of the linear and non-linear segments of the function must match: [latexmath] -++++++ -$$12.92 = {{\alpha \times \beta^{{1\over{2.4}}-1}}\over{2.4}}$$ -++++++ +++++ +12.92 = {{\alpha \times \beta^{{1\over{2.4}}-1}}\over{2.4}} +++++ -This formula can be rearranged to give latexmath:[$\alpha$] in terms of -latexmath:[$\beta$]: +This formula can be rearranged to give latexmath:[\alpha] in terms of +latexmath:[\beta]: [latexmath] -++++++ -$$\alpha = 12.92\times 2.4\times \beta^{1-{1\over{2.4}}}$$ -++++++ +++++ +\alpha = 12.92\times 2.4\times \beta^{1-{1\over{2.4}}} +++++ -Substituting this into the formula for latexmath:[$\{R,G,B\}$]: +Substituting this into the formula for latexmath:[\{R,G,B\}]: [latexmath] -++++++ -$$12.92 \times \beta = 12.92\times 2.4\times \beta^{1-{1\over{2.4}}} \times \beta^{1\over{2.4}} - (12.92\times 2.4\times \beta^{1-{1\over{2.4}}} - 1)$$ -++++++ +++++ +12.92 \times \beta = 12.92\times 2.4\times \beta^{1-{1\over{2.4}}} \times \beta^{1\over{2.4}} - (12.92\times 2.4\times \beta^{1-{1\over{2.4}}} - 1) +++++ This equation simplifies to: [latexmath] -++++++ -$$1.4 \times 12.92 \times \beta - 2.4 \times 12.92 \times \beta^{1 - {1\over{2.4}}} + 1 = 0$$ -+++++ +++++ +1.4 \times 12.92 \times \beta - 2.4 \times 12.92 \times \beta^{1 - {1\over{2.4}}} + 1 = 0 +++++ This can be further simplified to: [latexmath] -++++++ -$$1.4 \times \beta - 2.4 \times \beta^{1 - {1\over{2.4}}} + {1\over{12.92}} = 0$$ -+++++ +++++ +1.4 \times \beta - 2.4 \times \beta^{1 - {1\over{2.4}}} + {1\over{12.92}} = 0 +++++ -The value of latexmath:[$\beta$] can be found numerically (for example by +The value of latexmath:[\beta] can be found numerically (for example by Newton-Raphson iteration, with a derivative of -latexmath:[$1.4-1.4\beta^{-{1\over{2.4}}}$]), and results in values of: +latexmath:[1.4-1.4\beta^{-{1\over{2.4}}}]), and results in values of: [latexmath] -++++++ +++++ \begin{align*} \beta &\approx 0.003041282560128\\ \alpha &\approx 1.055010718947587\\ \delta &= 12.92\times\beta = \alpha\times\beta^{1\over{2.4}}-(\alpha-1.0)\\ &\approx 0.039293370676848 \end{align*} -++++++ +++++ -Where latexmath:[$\delta$] is the value of the EOTF^ -1^ at -latexmath:[$\{R',G',B'\} = \beta$]. +Where latexmath:[\delta] is the value of the EOTF^ -1^ at +latexmath:[\{R',G',B'\} = \beta]. [NOTE] ==== @@ -728,12 +728,12 @@ practice. The EOTF can be written with these derived values as: [latexmath] -++++++ - $$\{R,G,B\} = \begin{cases} - {{\{R',G',B'\}}\over{12.92}}, & \{R',G',B'\} \leq \delta \\ - \left({{\{R',G',B'\}}\over{\alpha}} + {{\alpha-1}\over\alpha}\right)^{2.4}, & \{R',G',B'\} > \delta - \end{cases}$$ -++++++ +++++ +\{R,G,B\} = \begin{cases} + {{\{R',G',B'\}}\over{12.92}}, & \{R',G',B'\} \leq \delta \\ + \left({{\{R',G',B'\}}\over{\alpha}} + {{\alpha-1}\over\alpha}\right)^{2.4}, & \{R',G',B'\} > \delta +\end{cases} +++++ [NOTE] ==== @@ -743,45 +743,45 @@ The profile viewer in Apple's ColorSync utility reports that the EOTF is of the following form: [latexmath] -++++++ - $$f(x) = \begin{cases} +++++ +f(x) = \begin{cases} cx, & x < d \\ (ax+b)^\gamma, & x \geq d - \end{cases}$$ -++++++ +\end{cases} +++++ -The reported figures for latexmath:[$\gamma=2.4,\ a=0.948,\ b=0.52$] -and latexmath:[$c=0.077$] correspond to the equivalent values in +The reported figures for latexmath:[\gamma=2.4,\ a=0.948,\ b=0.52] +and latexmath:[c=0.077] correspond to the equivalent values in the sRGB specification: [latexmath] -++++++ +++++ \begin{align*} {1\over{\alpha}} &\approx 0.948 = a\\ {{\alpha-1}\over\alpha} &\approx 0.52 = b\\ {1\over{12.92}} &\approx 0.077 = c \end{align*} -++++++ +++++ These values are correct to the reported precision both for the value -latexmath:[$\alpha = 1.055$] in the sRGB specification and for the more -precise latexmath:[$\alpha \approx 1.055010718947587$] derived above. +latexmath:[\alpha = 1.055] in the sRGB specification and for the more +precise latexmath:[\alpha \approx 1.055010718947587] derived above.   However, where the sRGB specification states that -latexmath:[$\delta = 0.04045$], the profile viewer reports +latexmath:[\delta = 0.04045], the profile viewer reports a corresponding d = 0.039. The disparity can be explained if the profile values have been derived as described in this section: [latexmath] -++++++ -$$\delta \approx 0.039293370676848\approx 0.039 = d$$ -++++++ +++++ +\delta \approx 0.039293370676848\approx 0.039 = d +++++ Note that this value assumes a correspondingly corrected version -of latexmath:[$\alpha$] rather than latexmath:[$a = 1.055$]. +of latexmath:[\alpha] rather than latexmath:[a = 1.055].   @@ -795,31 +795,31 @@ range, the derived EOTF and EOTF^ -1^ agree with the official sRGB formulae to greater than 16-bit precision. ==== -Without allowing for adjusting the latexmath:[$\alpha = 1.055$] +Without allowing for adjusting the latexmath:[\alpha = 1.055] constant in the sRGB formula, the power function cannot be made to intersect perfectly at a tangent to the linear segment with gradient of 12.92. -However, the intersection point latexmath:[$\beta$] can be +However, the intersection point latexmath:[\beta] can be found by solving: [latexmath] -++++++ -$$1.055\times\beta^{1\over{2.4}}-12.92\times\beta-0.055 = 0$$ -++++++ +++++ +1.055\times\beta^{1\over{2.4}}-12.92\times\beta-0.055 = 0 +++++ This equation can give us a slightly more precise pair of values for the original sRGB equation: [latexmath] -++++++ +++++ \begin{align*} \beta &\approx 0.003130668 \\ \delta &\approx 0.040448236 \end{align*} -++++++ +++++ In practice this makes no measurable difference, but does suggest -that the values of latexmath:[$\beta = 0.0031308$] in the sRGB +that the values of latexmath:[\beta = 0.0031308] in the sRGB specification may have been incorrectly rounded. <<< @@ -833,34 +833,34 @@ represent a typical EOTF for CRTs and to document this to ensure consistency between other display technologies: [latexmath] -++++++ -$$L = a(\textrm{max}(V+b,0))^\gamma$$ -++++++ +++++ +L = a(\textrm{max}(V+b,0))^\gamma +++++ [width="40%",grid="none",frame="none"] -|============ +|==== <|_L_ = screen luminance in cd/m^2^ <|_V_ = input signal normalized to [0..1] <|_a_ = user gain (legacy ``contrast'') <|_b_ = black level lift (legacy ``brightness'') -<|latexmath:[$\gamma$] = 2.4 -|============ +<|latexmath:[\gamma] = 2.4 +|==== If _L~W~_ is the screen luminance of maximum white and _L~B~_ is the screen luminance of minimum black: [latexmath] -++++++ +++++ \begin{align*} L_B &= a \times b^\gamma \\ L_W &= a \times (1 + b)^\gamma \\ a &= (L_W^{1\over\gamma} - L_B^{1\over\gamma})^\gamma \\ b &= {{L_B^{1\over\gamma}}\over{L_W^{1\over\gamma} - L_B^{1\over\gamma}}} \end{align*} -++++++ +++++ <> proposes the use of a simple power function with a -latexmath:[$\gamma = 2.4$] as an approximation to this EOTF for the purposes +latexmath:[\gamma = 2.4] as an approximation to this EOTF for the purposes of color conversion, effectively assuming _b_ = 0 and _L~B~_ is pure black. The reference display described in BT.1886 has a maximum luminance level of 100cd/m^2^ (brighter than the equivalent <> reference @@ -870,11 +870,11 @@ The following graph shows the relationship between the BT.1886 EOTF (shown in re and the <> such as used for <> (shown in blue). The result of applying the two functions in turn, resulting in the OOTF of a combined BT.709-BT.1886 system, is shown in black. Since the ITU OETF approximates a power -function with latexmath:[$\gamma=2.0$], also shown in green is the resulting OOTF -corresponding to a power function with latexmath:[$\gamma={2.4\over{2.0}}=1.2$]. +function with latexmath:[\gamma=2.0], also shown in green is the resulting OOTF +corresponding to a power function with latexmath:[\gamma={2.4\over{2.0}}=1.2]. .BT.1886 EOTF and BT.709 OETF -image::images/tf_ituvsgamma256.png[width="{svgpdf@pdf:192pt:257}",align="center"] +image::{images}/tf_ituvsgamma256.png[width="{svgpdf@pdf:192pt:257}",align="center"] [NOTE] ==== @@ -882,24 +882,24 @@ image::images/tf_ituvsgamma256.png[width="{svgpdf@pdf:192pt:257}",align="center" match to CRT measured luminance than the standard formula listed above: [latexmath] -++++++ +++++ \begin{align*} L &= \begin{cases} k(V_C+b)^{(\alpha_1-\alpha_2)}(V+b)^{\alpha_2}, & V < V_C \\ k(V+b)^{\alpha_1}, & V_C \leq V \end{cases} \end{align*} -++++++ +++++ [width="60%",grid="none",frame="none"] -|============ +|==== <|_V~C~_ = 0.35 -<|latexmath:[$\alpha_1$] = 2.6 -<|latexmath:[$\alpha_2$] = 3.0 +<|latexmath:[\alpha_1] = 2.6 +<|latexmath:[\alpha_2] = 3.0 <|_k_ = coefficient of normalization (so that _V_ = 1 gives white), -<|latexmath:[$k=L_W(1+b)^{-\alpha_1}$] +<|latexmath:[k=L_W(1+b)^{-\alpha_1}] <|_b_ = black level lift (legacy ``brightness'') -|============ +|==== ==== @@ -919,21 +919,21 @@ The <> Hybrid Log Gamma description defines the following OETF for linear scene light: [latexmath] -++++++ - $$E'_\mathit{norm} = \textrm{OETF}(E) = \begin{cases} +++++ +E'_\mathit{norm} = \textrm{OETF}(E) = \begin{cases} \sqrt{3E}, & 0 \leq E \leq {1\over{12}} \\ a \times \textrm{ln}((12\times E) - b) + c, & {1\over{12}} < E \leq 1 - \end{cases}$$ -++++++ +\end{cases} +++++ [width="80%",grid="none",frame="none"] -|============ -<|latexmath:[$E$] = the latexmath:[$R_S$], latexmath:[$G_S$] or latexmath:[$B_S$] color component of linear scene light, normalized to [0..1] -<|latexmath:[$E'$] = the resulting non-linear latexmath:[$R_S'$], latexmath:[$G_S'$] or latexmath:[$B_S'$] non-linear scene light value in in the range [0..1] +|==== +<|latexmath:[E] = the latexmath:[R_S], latexmath:[G_S] or latexmath:[B_S] color component of linear scene light, normalized to [0..1] +<|latexmath:[E'] = the resulting non-linear latexmath:[R_S'], latexmath:[G_S'] or latexmath:[B_S'] non-linear scene light value in in the range [0..1] <|_a_ = 0.17883277 -<|_b_ = latexmath:[$1 - 4\times a = 0.28466892$] -<|_c_ = latexmath:[$0.5 - a\times ln(4\times a) \approx 0.55991073$] -|============ +<|_b_ = latexmath:[1 - 4\times a = 0.28466892] +<|_c_ = latexmath:[0.5 - a\times ln(4\times a) \approx 0.55991073] +|==== [NOTE] ==== @@ -941,34 +941,34 @@ BT.2100-0, in note 5b, defines these formulae equivalently, but slightly differently: [latexmath] -++++++ - $$E'_\mathit{norm} = \textrm{OETF}(E) = \begin{cases} +++++ +E'_\mathit{norm} = \textrm{OETF}(E) = \begin{cases} \sqrt{3E}, & 0 \leq E \leq {1\over{12}} \\ a \times \textrm{ln}(E - b_0) + c_0, & {1\over{12}} < E \leq 1 - \end{cases}$$ -++++++ +\end{cases} +++++ This formulation in BT.2100-0 uses different constants for _b_ and _c_ (_a_ is unmodified), as follows: [width="50%",options="header",cols="1,5,5"] -|============ +|==== | | BT.2100-2, BT.2100-1 | BT.2100-0 | _b_ | _b_~1~ = 0.28466892 | _b_~0~ = 0.02372241 | _c_ | _c_~1~ = 0.55991073 | _c_~0~ = 1.00429347 -|============ +|==== The BT.2100-0 variations can be derived from the BT.2100-2 numbers as: [latexmath] -++++++ +++++ \begin{align*} a \times \textrm{ln}((12 \times E) - b_1)+ c_1 & = a \times \textrm{ln}\left(12\times\left(E - {b_1\over{12}}\right)\right) + c_1\\ & = a \times \textrm{ln}\left(E - {{b_1}\over{12}}\right) + a\times\textrm{ln}(12) + c_1 \\ {{b_1}\over{12}} = {{0.28466892}\over{12}} &= 0.023772241 = b_0 \\ a\times\textrm{ln}(12) + c_1 = 0.17883277\times\textrm{ln}(12) + 0.55991073 &= 1.00429347 = c_0 \end{align*} -++++++ +++++ ==== @@ -979,17 +979,17 @@ a\times\textrm{ln}(12) + c_1 = 0.17883277\times\textrm{ln}(12) + 0.55991073 &= 1 The OETF^ -1^ of normalized HLG is: [latexmath] -++++++ - $$E = \textrm{OETF}^{-1}(E') = \begin{cases} +++++ +E = \textrm{OETF}^{-1}(E') = \begin{cases} {{E'^2}\over 3}, & 0 \leq E' \leq {1\over 2} \\ {1\over 12} \times \left({b + e^{(E'-c)/a}}\right), & {1\over 2} < E' \leq 1 - \end{cases}$$ -++++++ +\end{cases} +++++ _a_, _b_ and _c_ are defined as for the normalized HLG OETF. BT.2100-0 again defines an equivalent formula without the -latexmath:[$1\over{12}$] scale factor in the -latexmath:[${1\over 2}$] < latexmath:[$E' \leq 1$] term, +latexmath:[1\over{12}] scale factor in the +latexmath:[{1\over 2}] < latexmath:[E' \leq 1] term, using the modified _b_~0~ and _c_~0~ constants described in the note in the <> above. @@ -1003,21 +1003,21 @@ Only the variant normalized to the range [0..1] is described in the updated versions of the specification, BT.2100-1 and BT.2100-2. [latexmath] -++++++ - $$E' = \textrm{OETF}(E) = \begin{cases} +++++ +E' = \textrm{OETF}(E) = \begin{cases} {{\sqrt{E}}\over{2}}, & 0 \leq E \leq 1 \\ a \times \textrm{ln}(E-b) + c, & 1 < E - \end{cases}$$ -++++++ +\end{cases} +++++ [width="80%",grid="none",frame="none"] -|============ -<|latexmath:[$E'$] = the latexmath:[$R_S$], latexmath:[$G_S$] or latexmath:[$B_S$] color component of linear scene light, normalized to [0..12] -<|latexmath:[$E_S'$] = the resulting non-linear latexmath:[$R_S'$], latexmath:[$G_S'$] or latexmath:[$B_S'$] value in in the range [0..1] +|==== +<|latexmath:[E'] = the latexmath:[R_S], latexmath:[G_S] or latexmath:[B_S] color component of linear scene light, normalized to [0..12] +<|latexmath:[E_S'] = the resulting non-linear latexmath:[R_S'], latexmath:[G_S'] or latexmath:[B_S'] value in in the range [0..1] <|_a_ = 0.17883277 <|_b_ = 0.28466892 <|_c_ = 0.55991073 -|============ +|==== Note that these constants are the same as those used in the BT.2100-1 version of the <>. @@ -1028,12 +1028,12 @@ version of the <>. The OETF^ -1^ of ``unnormalized'' HLG (producing _E_ in the range [0..12]) is: [latexmath] -++++++ - $$E = \textrm{OETF}^{-1}(E') = \begin{cases} +++++ +E = \textrm{OETF}^{-1}(E') = \begin{cases} 4\times E'^2, & 0 \leq E' \leq {1\over 2} \\ b + e^{(E'-c)/a}, & {1\over 2} < E' - \end{cases}$$ -++++++ +\end{cases} +++++ _a_, _b_ and _c_ are defined as for the <>. @@ -1050,13 +1050,13 @@ HLG constants appear to have chosen _a_, _b_ and _c_ to meet the following constraints, which are easiest to express in terms of the unnormalized OETF^ -1^: - * The derivative of the latexmath:[$0 \leq E' \leq {1\over 2}$] term of + * The derivative of the latexmath:[0 \leq E' \leq {1\over 2}] term of the unnormalized OETF^ -1^ has the same value as the derivative of - the latexmath:[${1\over 2}$] < latexmath:[$E' \leq 1$] term - of the unnormalized OETF^ -1^ at latexmath:[$E' = {1\over 2}$]: + the latexmath:[{1\over 2}] < latexmath:[E' \leq 1] term + of the unnormalized OETF^ -1^ at latexmath:[E' = {1\over 2}]: + [latexmath] -++++++ +++++ \begin{align*} {{d(4\times E'^2)}\over{dE'}} = 8\times E' &= 8 \times {1\over 2} = 4 \textrm{ (derivative of the } 0 \leq E' \leq {1\over 2} \textrm{ case)}\\ @@ -1071,14 +1071,14 @@ OETF^ -1^: \implies c &= -\textrm{ln}\left({{(4\times a)^a}\over{e^{0.5}}}\right)\\ &= 0.5 - a\times\textrm{ln}(4\times a) \end{align*} -++++++ - * The latexmath:[$0 \leq E' \leq {1\over 2}$] term of the unnormalized +++++ + * The latexmath:[0 \leq E' \leq {1\over 2}] term of the unnormalized OETF^ -1^ has the same value as the - latexmath:[${1\over 2}$] < latexmath:[$E'\leq 1$] - term of the unnormalized OETF^ -1^ at latexmath:[$E' = {1\over 2}$]: + latexmath:[{1\over 2}] < latexmath:[E'\leq 1] + term of the unnormalized OETF^ -1^ at latexmath:[E' = {1\over 2}]: + [latexmath] -++++++ +++++ \begin{align*} 4\times{E'}^2 &= e^{{E' - c}\over a} + b \textrm{ (from the }0 \leq E' \leq {1\over 2}\textrm{ and }{1\over 2} < E' \textrm{ cases})\\ @@ -1087,12 +1087,12 @@ OETF^ -1^: &= e^{\textrm{ln}(4\times a)} + b\\ b &= 1 - 4\times a \end{align*} -++++++ - * At _E'_ = 1, the latexmath:[${1\over 2}$] < latexmath:[$E'$] +++++ + * At _E'_ = 1, the latexmath:[{1\over 2}] < latexmath:[E'] term of the unnormalized OETF^ -1^ = 12: + [latexmath] -++++++ +++++ \begin{align*} 12 &= e^{{E'-c}\over a} + b\\ &= {e^{{1 - 0.5 + a\times\textrm{ln}(4\times a)}\over a} + 1 - 4\times a} \\ @@ -1102,36 +1102,36 @@ b &= 1 - 4\times a {121\over{16\times a^2}} + {11\over{2\times a}} + 1 &= e^{1\over a}\\ {121\over{16}} + {a\times 11\over 2} + a^2 \times (1 - e^{1\over a}) = 0 \end{align*} -++++++ +++++ This last equation can be solved numerically to find: [latexmath] -++++++ +++++ \begin{align*} a \approx 0.1788327726569497656312771 \end{align*} -++++++ +++++ With this precision, more accurate values of the other constants are: [latexmath] -++++++ +++++ \begin{align*} b &= 0.28466890937 \\ c &= 0.55991072776 \end{align*} -++++++ +++++ The _b_ = 0.28466892 official figure assumes the rounded -_a_ = 0.17883277 value as an input to the _b_ = latexmath:[$1 - 4\times a$] +_a_ = 0.17883277 value as an input to the _b_ = latexmath:[1 - 4\times a] relation. [NOTE] ==== No explanation for the choice of [0..12] range in the official version of the formula is explicitly offered in BT.2100-0 (it does _not_, for example, -appear to relate to the <> OOTF latexmath:[$\gamma = 1.2$] -combined with the latexmath:[$10\times$] ratio between the +appear to relate to the <> OOTF latexmath:[\gamma = 1.2] +combined with the latexmath:[10\times] ratio between the <>cd/m^2^ of a standard HLG HDR TV and the <>cd/m^2^ of a standard dynamic range set). However, allowing for the difference in the maximum display brightness of @@ -1151,12 +1151,12 @@ The origins of both HLG and PQ are discussed in <>. As graphed in <>, the ``unnormalized'' HLG OETF (red) is a good approximation to the standard dynamic range ITU transfer function -(blue, output scaled by 0.5) up to latexmath:[$E \approx 1$] and -latexmath:[$\textrm{OETF}(E) = E' \approx 0.5$], with a smooth +(blue, output scaled by 0.5) up to latexmath:[E \approx 1] and +latexmath:[\textrm{OETF}(E) = E' \approx 0.5], with a smooth curve up to the maximum HLG representable scene light value of ``12'': .HLG OETF (red) vs ITU OETF/2 (blue) -image::images/tf_hlg.{svgpdf}[width="{svgpdf@pdf:200pt:300}",align="center"] +image::{images}/tf_hlg.svg[width="{svgpdf@pdf:200pt:300}",align="center"] ==== <<< @@ -1165,13 +1165,13 @@ image::images/tf_hlg.{svgpdf}[width="{svgpdf@pdf:200pt:300}",align="center"] The OOTF of HLG is described as: [latexmath] -+++++ +++++ \begin{align*} R_D &= \alpha\times Y_S^{\gamma-1}\times R_S \\ G_D &= \alpha\times Y_S^{\gamma-1}\times G_S \\ B_D &= \alpha\times Y_S^{\gamma-1}\times B_S \\ \end{align*} -+++++ +++++ where _R~D~_, _G~D~_ and _B~D~_ describe the luminance of the displayed linear component in cd/m^2^ and _R~S~_, _G~S~_ and _B~S~_ describe each @@ -1179,61 +1179,61 @@ color component in scene linear light, scaled by camera exposure and normalized to the representable range. NOTE: BT.2100 notes that some legacy displays apply the -latexmath:[$\gamma$] function to each channel separately, rather than +latexmath:[\gamma] function to each channel separately, rather than to the luminance component. That is, -latexmath:[$\{R_D,G_D,B_D\}=\alpha\times\{R_S,G_S,B_S\}^\gamma+\beta$]. +latexmath:[\{R_D,G_D,B_D\}=\alpha\times\{R_S,G_S,B_S\}^\gamma+\beta]. This is an approximation to the official OOTF. _Y~S~_ is the normalized scene luminance, defined as: [latexmath] -+++++ -$$Y_S = 0.2627\times R_S + 0.6780\times G_S + 0.0593\times B_S$$ -+++++ +++++ +Y_S = 0.2627\times R_S + 0.6780\times G_S + 0.0593\times B_S +++++ -latexmath:[$\alpha$] represents adjustable user gain (display ``contrast'') +latexmath:[\alpha] represents adjustable user gain (display ``contrast'') representing _L~W~_, the nominal peak luminance of achromatic pixels. [NOTE] -====== -Versions of BT.2100 prior to BT.2100-2 incorporated a latexmath:[$\beta$] +==== +Versions of BT.2100 prior to BT.2100-2 incorporated a latexmath:[\beta] black level offset (display ``brightness'') representing the display luminance of black in cd/m^2^: [latexmath] -+++++ +++++ \begin{align*} R_D &= \alpha\times Y_S^{\gamma-1}\times R_S + \beta \\ G_D &= \alpha\times Y_S^{\gamma-1}\times G_S + \beta \\ B_D &= \alpha\times Y_S^{\gamma-1}\times B_S + \beta \\ \end{align*} -+++++ +++++ -latexmath:[$\alpha$] then represented the relative display ``contrast'': +latexmath:[\alpha] then represented the relative display ``contrast'': [width="70%",options="header",cols="1,5,5"] -|============ +|==== | | Scene light normalized to [0..1] | Scene light normalized to [0..12] -| latexmath:[$\alpha$] | latexmath:[${L_W - L_B}$] | latexmath:[${{L_W - L_B}\over{\left(12\right)^\gamma}}$] -|============ +| latexmath:[\alpha] | latexmath:[{L_W - L_B}] | latexmath:[{{L_W - L_B}\over{\left(12\right)^\gamma}}] +|==== where _L~W~_ is the nominal peak luminance of the display in cd/m^2^, and _L~B~_ is the display luminance of black in cd/m^2^. -That is, in older versions of BT.2100, latexmath:[$\alpha$] represented +That is, in older versions of BT.2100, latexmath:[\alpha] represented the difference between minimum and maximum brightness, whereas in BT.2100-2 -latexmath:[$\alpha$] is independent of black level. -===== +latexmath:[\alpha] is independent of black level. +==== -latexmath:[$\gamma = 1.2$] for a nominal peak display luminance of 1000cd/m^2^. +latexmath:[\gamma = 1.2] for a nominal peak display luminance of 1000cd/m^2^. For displays with higher peak luminance or if peak luminance is reduced through a contrast control, -latexmath:[$\gamma = 1.2 + 0.42\times \textrm{log}_{10}\left({L_W\over 1000}\right)$]. +latexmath:[\gamma = 1.2 + 0.42\times \textrm{log}_{10}\left({L_W\over 1000}\right)]. For the purposes of general conversion, _L~W~_ can be assumed to be 1000cd/m^2^, and _L~B~_ can be approximated as 0, removing the constant -offset from the above equations and meaning latexmath:[$\gamma=1.2$]. +offset from the above equations and meaning latexmath:[\gamma=1.2]. <<< ==== HLG OOTF^ -1^ @@ -1241,27 +1241,27 @@ offset from the above equations and meaning latexmath:[$\gamma=1.2$]. The inverse OOTF for HLG can be defined as: [latexmath] -+++++ +++++ \begin{align*} R_S&=\left({{Y_D}\over\alpha}\right)^{(1/\gamma)-1}\times \left({{R_D}\over\alpha}\right) \\ G_S&=\left({{Y_D}\over\alpha}\right)^{(1/\gamma)-1}\times \left({{G_D}\over\alpha}\right) \\ B_S&=\left({{Y_D}\over\alpha}\right)^{(1/\gamma)-1}\times \left({{B_D}\over\alpha}\right) \\ Y_D&= 0.2627\times R_D + 0.6780\times G_D + 0.0593\times B_D \end{align*} -+++++ +++++ -For processing without reference to a specific display, latexmath:[$\alpha$] can be assumed +For processing without reference to a specific display, latexmath:[\alpha] can be assumed to be 1.0cd/m^2^. [NOTE] -===== -Versions of BT.2100 prior to BT.2100-2 incorporated a latexmath:[$\beta$] +==== +Versions of BT.2100 prior to BT.2100-2 incorporated a latexmath:[\beta] term into the OOTF. Using this formula from the OOTF leads to the following relationship between _Y~D~_ and _Y~S~_: [latexmath] -+++++ +++++ \begin{align*} Y_D &= 0.2627\times R_D + 0.6780\times G_D + 0.0593\times B_D \\ &= 0.2627\times(\alpha\times Y_S^{\gamma-1}\times R_S + \beta) + @@ -1273,11 +1273,11 @@ Y_D &= 0.2627\times R_D + 0.6780\times G_D + 0.0593\times B_D \\ \therefore Y_S =& \left({{Y_D-\beta}\over\alpha}\right)^{1\over\gamma}\\ Y_S^{1-\gamma} =& \left({{Y_D-\beta}\over\alpha}\right)^{(1-\gamma)/\gamma} \end{align*} -+++++ +++++ From this, the following relations can be derived: [latexmath] -+++++ +++++ \begin{align*} R_S &= {(R_D - \beta)\over{\alpha\times Y_S^{\gamma-1}}} = Y_S^{1-\gamma}\times{{(R_D-\beta)}\over\alpha} @@ -1292,15 +1292,15 @@ B_S &= {(B_D - \beta)\over{\alpha\times Y_S^{\gamma-1}}} = \left({{Y_D - \beta}\over\alpha}\right)^{(1-\gamma)/\gamma} \times \left({{B_D - \beta}\over{\alpha}}\right) \end{align*} -+++++ +++++ -For processing without knowledge of the display, latexmath:[$\alpha$] -can be treated as 1.0cd/m^2^ and latexmath:[$\beta$] can be considered +For processing without knowledge of the display, latexmath:[\alpha] +can be treated as 1.0cd/m^2^ and latexmath:[\beta] can be considered to be 0.0cd/m^2^. This simplifies the equations as follows: [latexmath] -+++++ +++++ \begin{align*} Y_S &= Y_D^{1/\gamma} \\ Y_S^{1-\gamma} &= Y_D^{(1/\gamma)-1} \\ @@ -1308,8 +1308,8 @@ R_S&=Y_D^{(1/\gamma)-1}\times R_D \\ G_S&=Y_D^{(1/\gamma)-1}\times G_D \\ B_S&=Y_D^{(1/\gamma)-1}\times B_D \end{align*} -+++++ -===== +++++ +==== <<< [[TRANSFER_HLG_EOTF_NORM]] @@ -1319,29 +1319,29 @@ The EOTF of BT.2100 HLG is defined in terms of the OETF and OOTF defined above: [latexmath] -+++++ +++++ \begin{align*} R_D &= \textrm{OOTF}\left(\textrm{OETF}^{-1}\left(\textrm{max}(0, (1-\beta)R_S' + \beta)\right)\right) \\ G_D &= \textrm{OOTF}\left(\textrm{OETF}^{-1}\left(\textrm{max}(0, (1-\beta)G_S' + \beta)\right)\right) \\ B_D &= \textrm{OOTF}\left(\textrm{OETF}^{-1}\left(\textrm{max}(0, (1-\beta)B_S' + \beta)\right)\right) \\ \beta &= \sqrt{3\times \left({{L_B}\over{L_W}}\right)^{1/\gamma}} \end{align*} -+++++ +++++ where _L~W~_ is the nominal peak luminance of the display in cd/m^2^, and _L~B~_ is the display luminance of black in cd/m^2^. [NOTE] -====== +==== Versions of BT.2100 prior to BT.2100-2 incorporated the black level -offset (display ``brightness'') latexmath:[$\beta$] into the definition +offset (display ``brightness'') latexmath:[\beta] into the definition of the OOTF, such that: [latexmath] -+++++ -$$\{R_D,G_D,B_D\}=\textrm{OOTF}(\textrm{OETF}^{-1}(\{R_S',G_S',B_S'\}))$$ -+++++ -====== +++++ +\{R_D,G_D,B_D\}=\textrm{OOTF}(\textrm{OETF}^{-1}(\{R_S',G_S',B_S'\})) +++++ +==== [[TRANSFER_HLG_IEOTF_NORM]] ==== HLG EOTF^ -1^ @@ -1349,26 +1349,26 @@ $$\{R_D,G_D,B_D\}=\textrm{OOTF}(\textrm{OETF}^{-1}(\{R_S',G_S',B_S'\}))$$ The EOTF^ -1^ can be derived as: [latexmath] -+++++ +++++ \begin{align*} R_S' &= {{\textrm{OETF}\left(\textrm{OOTF}^{-1}\left(R_D'\right)\right) - \beta}\over{1-\beta}} \\ G_S' &= {{\textrm{OETF}\left(\textrm{OOTF}^{-1}\left(G_D'\right)\right) - \beta}\over{1-\beta}} \\ B_S' &= {{\textrm{OETF}\left(\textrm{OOTF}^{-1}\left(B_D'\right)\right) - \beta}\over{1-\beta}} \\ \beta &= \sqrt{3\times \left({{L_B}\over{L_W}}\right)^{1/\gamma}} \end{align*} -+++++ +++++ [NOTE] -====== +==== Versions of BT.2100 prior to BT.2100-2 incorporated the black level -offset (display ``brightness'') latexmath:[$\beta$] into the definition +offset (display ``brightness'') latexmath:[\beta] into the definition of the OOTF, such that: [latexmath] -+++++ -$$\{R_S',G_S',B_S'\} = \textrm{OETF}(\textrm{OOTF}^{-1}(\{R_D,G_D,B_D\}))$$ -+++++ -===== +++++ +\{R_S',G_S',B_S'\} = \textrm{OETF}(\textrm{OOTF}^{-1}(\{R_D,G_D,B_D\})) +++++ +==== <<< [[TRANSFER_PQ]] @@ -1386,24 +1386,24 @@ The <> Perceptual Quantization description defines the following EOTF: [latexmath] -+++++ +++++ \begin{align*} F_D &= \textrm{EOTF}(E') = 10000\times Y \\ Y &= \left(\textrm{max}(({E'}^{1\over{m_2}} - c_1),0)\over{c_2 - c_3\times {E'}^{1\over{m_2}}}\right)^{1\over{m_1}} \end{align*} -+++++ +++++ -latexmath:[$E'$] is a non-linear color channel latexmath:[$\{R',G',B'\}$] or -latexmath:[$\{L',M',S'\}$] encoded as PQ in the range [0..1]. + -latexmath:[$F_D$] is the luminance of the displayed component in cd/m^2^ -(where the luminance of an latexmath:[$\{R_D,G_D,B_D\}$] or latexmath:[$Y_D$] -or latexmath:[$I_D$] component is considered to be the luminance of the +latexmath:[E'] is a non-linear color channel latexmath:[\{R',G',B'\}] or +latexmath:[\{L',M',S'\}] encoded as PQ in the range [0..1]. + +latexmath:[F_D] is the luminance of the displayed component in cd/m^2^ +(where the luminance of an latexmath:[\{R_D,G_D,B_D\}] or latexmath:[Y_D] +or latexmath:[I_D] component is considered to be the luminance of the color with all channels set to the same value as the component). + -When latexmath:[$R'=G'=B'$] the displayed pixel is monochromatic. + -latexmath:[$Y$] is a linear color value normalized to [0..1]. +When latexmath:[R'=G'=B'] the displayed pixel is monochromatic. + +latexmath:[Y] is a linear color value normalized to [0..1]. [latexmath] -+++++ +++++ \begin{align*} m_1 &= {2610\over 16384} = 0.1593017578125 \\ m_2 &= {2523\over 4096} \times 128 = 78.84375 \\ @@ -1411,7 +1411,7 @@ c_1 &= {3424\over 4096} = 0.8359375 = c_3 - c_2 + 1 \\ c_2 &= {2413\over 4096} \times 32 = 18.8515625 \\ c_3 &= {2392\over 4096} \times 32 = 18.6875 \end{align*} -+++++ +++++ [[TRANSFER_PQ_IEOTF]] ==== PQ EOTF^ -1^ @@ -1419,12 +1419,12 @@ c_3 &= {2392\over 4096} \times 32 = 18.6875 The corresponding EOTF^ -1^ is: [latexmath] -+++++ +++++ \begin{align*} Y &= {F_D\over 10000} \\ \textrm{EOTF}^{-1}(F_D) &= \left({c_1 + c_2\times Y^{m_1}\over 1 + c_3\times Y^{m_1}}\right)^{m_2} \end{align*} -+++++ +++++ <<< ==== PQ OOTF @@ -1433,18 +1433,18 @@ The OOTF of PQ matches that of <>'s EOTF combined with <>'s OETF: [latexmath] -+++++ -$$F_D = \textrm{OOTF}(E) = \textrm{G}_{1886}(\textrm{G}_{709}(E))$$ -+++++ +++++ +F_D = \textrm{OOTF}(E) = \textrm{G}_{1886}(\textrm{G}_{709}(E)) +++++ -where _E_ is one of latexmath:[$\{R_S,G_S,B_S,Y_S,I_S\}$], the linear +where _E_ is one of latexmath:[\{R_S,G_S,B_S,Y_S,I_S\}], the linear representation of scene light scaled by camera exposure and in the range [0..1], G~1886~ is the EOTF described in <>, and G~709~ is the OETF described in <> with a scale factor of 59.5208 applied to _E_: [latexmath] -+++++ +++++ \begin{align*} F_D &= \textrm{G}_{1886}(\textrm{G}_{709}(E)) &=\ &\textrm{G}_{1886}(E') = 100\times E'^{2.4} \\ E' &= \textrm{G}_{709}(E) &= &\begin{cases} @@ -1452,7 +1452,7 @@ E' &= \textrm{G}_{709}(E) &= &\begin{cases} 267.84\times E, & 0.0003024 \geq E \geq 0 \end{cases} \end{align*} -+++++ +++++ [NOTE] ==== @@ -1479,36 +1479,36 @@ while retaining the ability to encode extreme values.   As described in BT.2390, the OOTF of SDR is roughly -latexmath:[$\gamma = 1.2$] (deviating from this curve more near a 0 value), +latexmath:[\gamma = 1.2] (deviating from this curve more near a 0 value), so the maximum _scene_ light intensity that can be represented is roughly -latexmath:[$100^{1\over 1.2} \approx 46.42$] times that of a SDR encoding. +latexmath:[100^{1\over 1.2} \approx 46.42] times that of a SDR encoding.   Using exact equations from <> and <> -to create the OOTF, rather than the latexmath:[$\gamma = 1.2$] +to create the OOTF, rather than the latexmath:[\gamma = 1.2] approximation, the maximum representable scene brightness, if 1.0 is the maximum normalized SDR brightness is: [latexmath] -+++++ +++++ \begin{align*} \left({100^{1\over 2.4} + 0.099\over 1.099}\right)^{1\over 0.45} &\approx 59.5208 \end{align*} -+++++ +++++ The other constants in the G~709~ formula are derived as follows: [latexmath] -+++++ +++++ \begin{align*} {0.018\over 59.5208} &\approx 0.0003024 \\ 4.5\times 59.5208 &\approx 267.84 \end{align*} -+++++ +++++ Note that these constants differ slightly if the more accurate -latexmath:[$\alpha = 1.0993$] figure from <> is used +latexmath:[\alpha = 1.0993] figure from <> is used instead of 1.099. ==== @@ -1518,9 +1518,9 @@ instead of 1.099. The OETF of PQ is described in terms of the above OOTF: [latexmath] -+++++ -$$E' = \textrm{OETF}(E) = \textrm{EOTF}^{-1}(\textrm{OOTF}(E)) = \textrm{EOTF}^{-1}(F_D)$$ -+++++ +++++ +E' = \textrm{OETF}(E) = \textrm{EOTF}^{-1}(\textrm{OOTF}(E)) = \textrm{EOTF}^{-1}(F_D) +++++ <<< ==== PQ OOTF^ -1^ @@ -1528,16 +1528,16 @@ $$E' = \textrm{OETF}(E) = \textrm{EOTF}^{-1}(\textrm{OOTF}(E)) = \textrm{EOTF}^{ The PQ OOTF^ -1^ is: [latexmath] -+++++ -$$E=\textrm{OOTF}^{-1}(F_D)=\textrm{G}_{709}^{-1}(\textrm{G}_{1886}^{-1}(F_D))$$ -+++++ +++++ +E=\textrm{OOTF}^{-1}(F_D)=\textrm{G}_{709}^{-1}(\textrm{G}_{1886}^{-1}(F_D)) +++++ where _F~D~_, display intensity, is one of -latexmath:[$\{R_D,G_D,B_D,Y_D,I_D\}$], and +latexmath:[\{R_D,G_D,B_D,Y_D,I_D\}], and E is the corresponding normalized scene intensity. [latexmath] -+++++ +++++ \begin{align*} E' &= \textrm{G}_{1886}^{-1}(F_D) &= &\left({F_D\over 100}\right)^{1\over 2.4} \\ E &= \textrm{G}_{709}^{-1}(E') &= &\begin{cases} @@ -1545,7 +1545,7 @@ E &= \textrm{G}_{709}^{-1}(E') &= &\begin{cases} {E'\over{267.84}}, & 0.081\geq E'\geq 0 \implies {8.1}^{2.4}\geq F_D\geq 0 \end{cases} \end{align*} -+++++ +++++ [[TRANSFER_PQ_IOETF]] ==== PQ OETF^ -1^ @@ -1553,9 +1553,9 @@ E &= \textrm{G}_{709}^{-1}(E') &= &\begin{cases} The PQ OETF^ -1^ is described in terms of the OOTF^ -1^: [latexmath] -+++++ -$$E = \textrm{OETF}^{-1}(E') = \textrm{OOTF}^{-1}(\textrm{EOTF}(E')) = \textrm{OOTF}^{-1}(F_D)$$ -+++++ +++++ +E = \textrm{OETF}^{-1}(E') = \textrm{OOTF}^{-1}(\textrm{EOTF}(E')) = \textrm{OOTF}^{-1}(F_D) +++++ <<< [[TRANSFER_DCIP3]] @@ -1565,19 +1565,19 @@ $$E = \textrm{OETF}^{-1}(E') = \textrm{OOTF}^{-1}(\textrm{EOTF}(E')) = \textrm{O (applied to scaled CIE _XYZ_ values): [options="header",cols="^1,^1"] -|====== +|==== | EOTF^ -1^ | EOTF -| latexmath:[$X' = \left({X\over{52.37}}\right)^{1\over{2.6}}$] +| latexmath:[X' = \left({X\over{52.37}}\right)^{1\over{2.6}}] -latexmath:[$Y' = \left({Y\over{52.37}}\right)^{1\over{2.6}}$] +latexmath:[Y' = \left({Y\over{52.37}}\right)^{1\over{2.6}}] -latexmath:[$Z' = \left({Z\over{52.37}}\right)^{1\over{2.6}}$] -| latexmath:[$X = X'^{2.6}\times 52.37$] +latexmath:[Z' = \left({Z\over{52.37}}\right)^{1\over{2.6}}] +| latexmath:[X = X'^{2.6}\times 52.37] -latexmath:[$Y = Y'^{2.6}\times 52.37$] +latexmath:[Y = Y'^{2.6}\times 52.37] -latexmath:[$Z = Z'^{2.6}\times 52.37$] -|====== +latexmath:[Z = Z'^{2.6}\times 52.37] +|==== This power function is applied directly to scaled CIE _XYZ_ color coordinates: the ``primaries'' in DCI define the bounds of the gamut, @@ -1596,39 +1596,39 @@ section on the derivation of the sRGB constants). regional TV standard variants; an updated list of variant codes used by country is defined in <>. This standard, along with <>, documents a -simple EOTF power function with latexmath:[$\gamma = 2.2$] for NTSC display +simple EOTF power function with latexmath:[\gamma = 2.2] for NTSC display devices. [options="header",cols="^1,^1"] -|====== +|==== | EOTF^ -1^ | EOTF -| latexmath:[$R' = R^{1\over{2.2}}$] +| latexmath:[R' = R^{1\over{2.2}}] -latexmath:[$G' = G^{1\over{2.2}}$] +latexmath:[G' = G^{1\over{2.2}}] -latexmath:[$B' = B^{1\over{2.2}}$] -| latexmath:[$R = R'^{2.2}$] +latexmath:[B' = B^{1\over{2.2}}] +| latexmath:[R = R'^{2.2}] -latexmath:[$G = G'^{2.2}$] +latexmath:[G = G'^{2.2}] -latexmath:[$B = B'^{2.2}$] -|====== +latexmath:[B = B'^{2.2}] +|==== -This value of latexmath:[$\gamma$] is also used for N/PAL signals in the +This value of latexmath:[\gamma] is also used for N/PAL signals in the Eastern Republic of Uruguay, and was also adopted by <>. Combined with the reference in <> to a -latexmath:[$\gamma = 2.2$] being used in ``older documents'', this +latexmath:[\gamma = 2.2] being used in ``older documents'', this suggests a linear design OOTF for NTSC systems. <>, which partly replaced BT.470, also describes an ``assumed gamma of display device'' of 2.2 for PAL and SECAM systems; -this is distinct from the latexmath:[$\gamma = 2.8$] value listed in +this is distinct from the latexmath:[\gamma = 2.8] value listed in <>. Combined with the <> which approximates -latexmath:[$\gamma = {1\over{2.0}}$], the PAL OOTF retains a -latexmath:[$\gamma \approx 1.1$] when this value of -latexmath:[$\gamma = 2.2$] is used for the EOTF, similar to the figure +latexmath:[\gamma = {1\over{2.0}}], the PAL OOTF retains a +latexmath:[\gamma \approx 1.1] when this value of +latexmath:[\gamma = 2.2] is used for the EOTF, similar to the figure described under <>. In contrast, <> also includes @@ -1650,19 +1650,19 @@ That is, this standard defines an approximate OETF and OETF^ -1^ for PAL content: [options="header",cols="^1,^1"] -|====== +|==== | OETF | OETF^ -1^ -| latexmath:[$R' \approx R^{0.4}$] +| latexmath:[R' \approx R^{0.4}] -latexmath:[$G' \approx G^{0.4}$] +latexmath:[G' \approx G^{0.4}] -latexmath:[$B' \approx B^{0.4}$] -| latexmath:[$R \approx R'^{2.5}$] +latexmath:[B' \approx B^{0.4}] +| latexmath:[R \approx R'^{2.5}] -latexmath:[$G \approx G'^{2.5}$] +latexmath:[G \approx G'^{2.5}] -latexmath:[$B \approx B'^{2.5}$] -|====== +latexmath:[B \approx B'^{2.5}] +|==== [[TRANSFER_LEGACY_PAL_EOTF]] === Legacy PAL 625-line EOTF @@ -1672,56 +1672,56 @@ lists a number of regional TV standard variants; an updated list of variant codes used by country is defined in <>. This specification describes a simple EOTF power function with -latexmath:[$\gamma_{\textrm{EOTF}} = 2.8$] for most PAL and SECAM display devices: +latexmath:[\gamma_{\textrm{EOTF}} = 2.8] for most PAL and SECAM display devices: [options="header",cols="^1,^1"] -|====== +|==== | EOTF^ -1^ | EOTF -| latexmath:[$R' = R^{1\over{2.8}}$] +| latexmath:[R' = R^{1\over{2.8}}] -latexmath:[$G' = G^{1\over{2.8}}$] +latexmath:[G' = G^{1\over{2.8}}] -latexmath:[$B' = B^{1\over{2.8}}$] -| latexmath:[$R = R'^{2.8}$] +latexmath:[B' = B^{1\over{2.8}}] +| latexmath:[R = R'^{2.8}] -latexmath:[$G = G'^{2.8}$] +latexmath:[G = G'^{2.8}] -latexmath:[$B = B'^{2.8}$] -|====== +latexmath:[B = B'^{2.8}] +|==== -NOTE: Poynton describes a latexmath:[$\gamma$] of 2.8 as being ``unrealistically +NOTE: Poynton describes a latexmath:[\gamma] of 2.8 as being ``unrealistically high'' for actual CRT devices. Combined with the <> with -latexmath:[$\gamma_{\textrm{EOTF}} = 0.4$], the described system OOTF is: +latexmath:[\gamma_{\textrm{EOTF}} = 0.4], the described system OOTF is: [latexmath] -+++++ +++++ \begin{align*} R_{display} &\approx R_{scene}^{2.8\over{2.5}}\\ G_{display} &\approx G_{scene}^{2.8\over{2.5}}\\ B_{display} &\approx B_{scene}^{2.8\over{2.5}} \end{align*} -+++++ +++++ -Or latexmath:[$\gamma_{\textrm{OOTF}} \approx 1.12$]. +Or latexmath:[\gamma_{\textrm{OOTF}} \approx 1.12]. -The value of latexmath:[$\gamma_{\textrm{EOTF}} = 2.8$] is described in BT.470-6 as being +The value of latexmath:[\gamma_{\textrm{EOTF}} = 2.8] is described in BT.470-6 as being chosen for ``an overall system gamma'' (OOTF power function exponent) of ``approximately 1.2''; this suggests that the ``approximately 0.4'' exponent in -<> should be interpreted as nearer to latexmath:[${1.2\over{2.8}} -\approx 0.43$], or at least that there was enough variation in early devices for +<> should be interpreted as nearer to latexmath:[{1.2\over{2.8}} +\approx 0.43], or at least that there was enough variation in early devices for precise formulae to be considered irrelevant. [NOTE] ==== -The EOTF power function of latexmath:[$\gamma_{\textrm{EOTF}} = 2.2$] described in +The EOTF power function of latexmath:[\gamma_{\textrm{EOTF}} = 2.2] described in <> combines with the <> described in -<> (which approximates latexmath:[$\gamma_{\textrm{OETF}} \approx 0.5$]) -to give a similar system latexmath:[$\gamma_{\textrm{OOTF}} \approx 1.1$]. +<> (which approximates latexmath:[\gamma_{\textrm{OETF}} \approx 0.5]) +to give a similar system latexmath:[\gamma_{\textrm{OOTF}} \approx 1.1]. As described <>, the <> combined with the <> EOTF results in a more strongly non-linear -latexmath:[$\gamma_{\textrm{OOTF}} \approx {2.4\over{2.0}} = 1.2$]. +latexmath:[\gamma_{\textrm{OOTF}} \approx {2.4\over{2.0}} = 1.2]. ==== <<< @@ -1732,20 +1732,20 @@ The <>, formerly SMPTE240M, interim standard for HDTV defines the following OETF: [latexmath] -++++++ - $$R' = \begin{cases} +++++ +R' = \begin{cases} R \times 4, & 0 \leq R < 0.0228 \\ 1.1115 \times R^{0.45} - 0.1115, & 1 \geq R \geq 0.0228 - \end{cases}$$ - $$G' = \begin{cases} +\end{cases} \\ +G' = \begin{cases} G \times 4, & 0 \leq G < 0.0228 \\ 1.1115 \times G^{0.45} - 0.1115, & 1 \geq G \geq 0.0228 - \end{cases}$$ - $$B' = \begin{cases} +\end{cases} \\ +B' = \begin{cases} B \times 4, & 0 \leq B < 0.0228 \\ 1.1115 \times B^{0.45} - 0.1115, & 1 \geq B \geq 0.0228 - \end{cases}$$ -++++++ +\end{cases} +++++ Like <>, ST-240 defines a linear OOTF. Therefore the above relationship also holds for the EOTF^ -1^. @@ -1753,20 +1753,20 @@ Therefore the above relationship also holds for the EOTF^ -1^. The EOTF, and also OETF^ -1^, is: [latexmath] -++++++ - $$R = \begin{cases} +++++ +R = \begin{cases} {R' \over 4}, & 0 \leq R < 0.0913 \\ \left({R' + 0.1115\over 1.1115}\right)^{1\over 0.45} - 0.1115, & 1 \geq R' \geq 0.0228 - \end{cases}$$ - $$G = \begin{cases} +\end{cases} +G = \begin{cases} {G' \over 4}, & 0 \leq R < 0.0913 \\ \left({G' + 0.1115\over 1.1115}\right)^{1\over 0.45} - 0.1115, & 1 \geq G' \geq 0.0228 - \end{cases}$$ - $$B = \begin{cases} +\end{cases} +B = \begin{cases} {B' \over 4}, & 0 \leq R < 0.0913 \\ \left({B' + 0.1115\over 1.1115}\right)^{1\over 0.45} - 0.1115, & 1 \geq B' \geq 0.0228 - \end{cases}$$ -++++++ +\end{cases} +++++ [[TRANSFER_ADOBERGB]] === Adobe RGB (1998) transfer functions @@ -1776,26 +1776,26 @@ function between nonlinear encoding and linear light intensity (notable for not including a linear component): [latexmath] -+++++ +++++ \begin{align*} R &= R'^{2.19921875} \\ G &= G'^{2.19921875} \\ B &= B'^{2.19921875} \end{align*} -+++++ +++++ -2.19921875 is obtained from latexmath:[$2{51\over{256}}$] or hexadecimal 2.33. +2.19921875 is obtained from latexmath:[2{51\over{256}}] or hexadecimal 2.33. Therefore the inverse transfer function between linear light intensity and nonlinear encoding is: [latexmath] -+++++ +++++ \begin{align*} R' &= R^{256\over{563}} \\ G' &= G^{256\over{563}} \\ B' &= B^{256\over{563}} \end{align*} -+++++ +++++ <<< [[TRANSFER_SLOG]] @@ -1804,9 +1804,9 @@ B' &= B^{256\over{563}} The Sony <> OETF is defined for each color channel as: [latexmath] -+++++ -$$y = (0.432699 \times \textrm{log}_{10}(t + 0.037584) + 0.616596) + 0.03$$ -+++++ +++++ +y = (0.432699 \times \textrm{log}_{10}(t + 0.037584) + 0.616596) + 0.03 +++++ Linear camera input scaled by exposure _t_ ranges from 0 to 10.0; _y_ is the non-linear encoded value. @@ -1814,9 +1814,9 @@ _y_ is the non-linear encoded value. The OETF^ -1^ is: [latexmath] -+++++ -$$Y = 10.0^{t - 0.616596 - 0.03\over 0.432699} - 0.037584$$ -+++++ +++++ +Y = 10.0^{t - 0.616596 - 0.03\over 0.432699} - 0.037584 +++++ The encoded non-linear value _t_ ranges from 0 to 1.09; _Y_ is the linear scene light. @@ -1827,14 +1827,14 @@ linear scene light. <> defines the following OETF: [latexmath] -+++++ +++++ \begin{align*} y &= \begin{cases} (0.432699\times\textrm{log}_{10}\left({155.0\times x\over 219.0} + 0.037584\right) + 0.616596 + 0.03, &x \geq 0 \\ x \times 3.53881278538813 + 0.030001222851889303, &x < 0 \end{cases} \end{align*} -+++++ +++++ _x_ is the IRE in scene-linear space. + _y_ is the IRE in S-Log2 space. @@ -1842,14 +1842,14 @@ _y_ is the IRE in S-Log2 space. The OETF^ -1^ is: [latexmath] -+++++ +++++ \begin{align*} y &= \begin{cases} {219.0 \times 10.0^{x - 0.616596 - 0.03\over 0.432699}\over 155.0}, &x \geq 0.030001222851889303 \\ {x - 0.030001222851889303\over 3.53881278538813}, &x < 0.030001222851889303 \end{cases} \end{align*} -+++++ +++++ _x_ is the IRE in S-Log2 space. + _y_ is the IRE in scene-linear space. @@ -1865,13 +1865,13 @@ For each linear color channel _lin~AP1~_ transformed to the ACEScc primaries, the _ACEScc_ non-linear encoding is: [latexmath] -+++++ - $$ACEScc = \begin{cases} - {{\textrm{log}_\textrm{2}(2^{-16})+9.72}\over{17.52}}, & lin_{AP1} \leq 0 \\ - {{\textrm{log}_\textrm{2}(2^{-16} + lin_{AP1}\times 0.5) + 9.72}\over{17.52}}, & lin_{AP1} < 2^{-15} \\ - {{\textrm{log}_\textrm{2}(lin_{AP1})+9.72}\over{17.52}}, & lin_{AP1} \geq 2^{-15} - \end{cases}$$ -+++++ +++++ +ACEScc = \begin{cases} + {{\textrm{log}_\textrm{2}(2^{-16})+9.72}\over{17.52}}, & lin_{AP1} \leq 0 \\ + {{\textrm{log}_\textrm{2}(2^{-16} + lin_{AP1}\times 0.5) + 9.72}\over{17.52}}, & lin_{AP1} < 2^{-15} \\ + {{\textrm{log}_\textrm{2}(lin_{AP1})+9.72}\over{17.52}}, & lin_{AP1} \geq 2^{-15} +\end{cases} +++++ [[TRANSFER_ACESCCT]] === ACEScct transfer function @@ -1882,9 +1882,9 @@ For each linear color channel _lin~AP1~_ transformed to the ACEScc primaries, the _ACEScct_ non-linear encoding is: [latexmath] -+++++ - $$ACEScct = \begin{cases} - {10.5402377416545 \times lin_{AP1} + 0.0729055341958355}, & lin_{AP1} \leq 0.0078125 \\ - {{\textrm{log}_2(lin_{AP1})+9.72}\over{17.52}}, & lin_{AP1} > 0.0078125 - \end{cases}$$ -+++++ +++++ +ACEScct = \begin{cases} + {10.5402377416545 \times lin_{AP1} + 0.0729055341958355}, & lin_{AP1} \leq 0.0078125 \\ + {{\textrm{log}_2(lin_{AP1})+9.72}\over{17.52}}, & lin_{AP1} > 0.0078125 +\end{cases} +++++ diff --git a/compformats.txt b/compformats.txt deleted file mode 100644 index 8bfe66a..0000000 --- a/compformats.txt +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2014-2019 The Khronos Group Inc. -// Copyright notice at https://www.khronos.org/registry/speccopyright.html - -include::compintro.txt[] - -include::s3tc.txt[] - -include::rgtc.txt[] - -include::bptc.txt[] - -include::etc1.txt[] - -include::etc2.txt[] - -include::astc.txt[] - -include::pvrtc.txt[] diff --git a/config/README.adoc b/config/README.adoc new file mode 100644 index 0000000..db44354 --- /dev/null +++ b/config/README.adoc @@ -0,0 +1,39 @@ +// Copyright 2015-2024 The Khronos Group Inc. +// SPDX-License-Identifier: CC-BY-4.0 + += Data Format Asciidoc Configuration Files + +== Support for Math + +Asciidoctor is customized to insert KaTeX ` - - - diff --git a/config/docbook-xsl/common.xsl b/config/docbook-xsl/common.xsl deleted file mode 100644 index eccd619..0000000 --- a/config/docbook-xsl/common.xsl +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - 1 - 0 - - - - - - -images/icons/ -0 - - - - 0 - #E0E0E0 - - - -images/icons/ - - - margin-left: 0; margin-right: 10%; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -article toc,title -book toc,title,figure,table,example,equation - - -chapter toc,title -part toc,title -preface toc,title -qandadiv toc -qandaset toc -reference toc,title -sect1 toc -sect2 toc -sect3 toc -sect4 toc -sect5 toc -section toc -set toc,title - - - -article nop -book nop - - - - - diff --git a/config/docbook-xsl/pdf.xsl b/config/docbook-xsl/pdf.xsl deleted file mode 100644 index 3df11e7..0000000 --- a/config/docbook-xsl/pdf.xsl +++ /dev/null @@ -1,29 +0,0 @@ - - - - \begin{alltt} - \normalfont{} - - \end{alltt} - - - - - \pagebreak[4] - - - - - - \newline - - - - - \begin{center} - \line(1,0){444} - \end{center} - - - - diff --git a/config/docbook-xsl/xhtml.xsl b/config/docbook-xsl/xhtml.xsl deleted file mode 100644 index 4990d13..0000000 --- a/config/docbook-xsl/xhtml.xsl +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - diff --git a/config/fonts/mplus1p-regular-fallback.ttf b/config/fonts/mplus1p-regular-fallback.ttf new file mode 100644 index 0000000..d9d2e3d Binary files /dev/null and b/config/fonts/mplus1p-regular-fallback.ttf differ diff --git a/config/katex_replace.rb b/config/katex_replace.rb new file mode 100644 index 0000000..d15a2c4 --- /dev/null +++ b/config/katex_replace.rb @@ -0,0 +1,11 @@ +# Copyright 2016-2024 The Khronos Group Inc. +# +# SPDX-License-Identifier: Apache-2.0 + +#require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal' +RUBY_ENGINE == 'opal' ? (require 'katex_replace/extension') : (require_relative 'katex_replace/extension') + +# All the inline macros we need +Asciidoctor::Extensions.register do + postprocessor ReplaceMathjaxWithKatex +end diff --git a/config/katex_replace/extension.rb b/config/katex_replace/extension.rb new file mode 100644 index 0000000..f5a63de --- /dev/null +++ b/config/katex_replace/extension.rb @@ -0,0 +1,44 @@ +# Copyright 2016-2024 The Khronos Group Inc. +# +# SPDX-License-Identifier: Apache-2.0 + +require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal' + +include ::Asciidoctor + +class ReplaceMathjaxWithKatex < Extensions::Postprocessor + + MathJaXScript = / +' + + hide_script = '' + + output.sub! /(?=<\/head>)/, loaded_script + output.sub! /(
)/, '\1' + hide_script + output.sub! /(?=
\n" + end + output + end +end diff --git a/config/makedocinfologo b/config/makedocinfologo new file mode 100755 index 0000000..c166368 --- /dev/null +++ b/config/makedocinfologo @@ -0,0 +1,23 @@ +#!/bin/bash +# Copyright 2014-2024 The Khronos Group Inc. +# SPDX-License-Identifier: Apache-2.0 + +# makedocinfologo - generate HTML docinfo file from an SVG image. +# Usage: makedocinfologo file.svg alt-text > docinfo-header.html +# Example: makedocinfologo ../images/vulkansc-unscaled.svg "Vulkan SC Logo" > vulkansc/docinfo-header.html + +file=$1 +if test ! -r "$file" ; then + echo "Cannot read SVG file: $file" > /dev/stderr + exit 1 +fi +#echo "file: $file" > /dev/stderr +alt=${2-$file} +#echo "alt: $alt" > /dev/stderr + +echo '
' +echo -n ' '$2'' +echo ' ' +echo '
' diff --git a/config/mathjax-asciidoc.conf b/config/mathjax-asciidoc.conf deleted file mode 100644 index 1ba9ce1..0000000 --- a/config/mathjax-asciidoc.conf +++ /dev/null @@ -1,19 +0,0 @@ -# adoc.conf - add some asciidoc-specific (non-a2x) config stuff for html5.conf - -# Override html5.conf definition -[xref-inlinemacro] -xref -[xref-inlinemacro] -{0} -[xref2-inlinemacro] -{1} -[link-inlinemacro] -link{target} - -[latexmath-inlinemacro] -{passtext} - -[docinfo] -ifdef::mathjax[] -include1::mathjax.js[] -endif::[] diff --git a/config/mathjax-docbook.conf b/config/mathjax-docbook.conf deleted file mode 100644 index f8f0edc..0000000 --- a/config/mathjax-docbook.conf +++ /dev/null @@ -1,89 +0,0 @@ -# testdb.conf - override some Docbook-specific config stuff - -# Override docbook45 definition to not encapsulate LaTeX math -# This requires some cleverness in the latexmath macros to include -# the equation source in the alt block for PDF output, and in -# a Docbook block tag otherwise, using the a2x-format variable. - -# a2x-format can be one of: chunked, docbook, dvi, epub, htmlhelp, manpage, -# pdf (default), ps, tex, text, xhtml. - -[blockdef-pass] -ifeval::["{a2x-format}"=="pdf"] -latexmath-style=template="latexmathblock",subs=() -endif::[] -ifeval::["{a2x-format}"!="pdf"] -latexmath-style=template="latexmathblock" -subs=specialcharacters -endif::[] - -[latexmath-inlinemacro] - -ifeval::["{a2x-format}"=="pdf"] - -endif::[] - -ifeval::["{a2x-format}"!="pdf"] -{passtext} -endif::[] - - - -[latexmath-blockmacro] - -ifeval::["{a2x-format}"=="pdf"] - -endif::[] - -ifeval::["{a2x-format}"!="pdf"] -{passtext} -endif::[] - - - -[latexmathblock] -{title#}{title} -{title%} -ifeval::["{a2x-format}"=="pdf"] - -endif::[] - -ifeval::["{a2x-format}"!="pdf"] -| -endif::[] - -{title#} -{title%} - -# Attempt to turn HTML links into just the prefix, like the PDF version. Failure. Retained for reference. -# [link-inlinemacro] -# ifdef::basebackend-docbook[] -# {target} -# endif::basebackend-docbook[] -# ifdef::basebackend-xhtml[] -# {target} -# endif::basebackend-xhtml[] -# -# [xref-inlinemacro] -# ifdef::basebackend-docbook[] -# {0} -# {2%} -# endif::basebackend-docbook[] -# ifdef::basebackend-xhtml[] -# {2%} -# endif::basebackend-xhtml[] -# ifdef::basebackend-html[] -# {2%} -# endif::basebackend-html[] -# -# [xref2-inlinemacro] -# ifdef::basebackend-docbook[] -# {2} -# {2%} -# endif::basebackend-docbook[] -# ifdef::basebackend-xhtml[] -# {2%} -# endif::basebackend-xhtml[] -# ifdef::basebackend-html[] -# {2%} -# endif::basebackend-html[] diff --git a/config/mathjax.js b/config/mathjax.js deleted file mode 100644 index f079ab9..0000000 --- a/config/mathjax.js +++ /dev/null @@ -1,8 +0,0 @@ - - diff --git a/config/open_listing_block.rb b/config/open_listing_block.rb new file mode 100644 index 0000000..e617631 --- /dev/null +++ b/config/open_listing_block.rb @@ -0,0 +1,28 @@ +# Copyright 2023-2024 The Khronos Group Inc. +# SPDX-License-Identifier: Apache-2.0 + +# open_listing_block - allows a listing block to masquerade as an open +# block: +# +# [open] +# ---- +# (block content) +# ---- +# +# This allows nesting arbitrary open blocks inside 'refpage' open blocks. + +require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal' + +include ::Asciidoctor + +Asciidoctor::Extensions.register do + block do + named :open + on_context :listing + process do |parent, reader, attrs| + wrapper = create_open_block parent, [], {} + parse_content wrapper, reader + wrapper + end + end +end diff --git a/config/quiet-include-failure.rb b/config/quiet-include-failure.rb new file mode 100644 index 0000000..9342f3f --- /dev/null +++ b/config/quiet-include-failure.rb @@ -0,0 +1,30 @@ +# Copyright 2021-2024 The Khronos Group Inc. +# +# SPDX-License-Identifier: Apache-2.0 + +require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal' + +include Asciidoctor + +class ExistsIncludeProcessor < Extensions::IncludeProcessor + def handles? target + # Only handle files which do not exist + # This relies on the full absolute path to every include file being + # given, since relative directory information exists only in the + # process method. + + not File.exist? target + end + + def process doc, reader, target, attributes + # If we reach this point, we have been asked to include a file which + # does not exist. Do nothing, instead of raising an error. + + reader + end +end + +Extensions.register do + include_processor ExistsIncludeProcessor +end + diff --git a/config/rouge-extend-css.rb b/config/rouge-extend-css.rb new file mode 100644 index 0000000..c19dd74 --- /dev/null +++ b/config/rouge-extend-css.rb @@ -0,0 +1,60 @@ +# Copyright 2021-2024 The Khronos Group Inc. +# +# SPDX-License-Identifier: Apache-2.0 + +# Khronos overrides for Rouge 'github' theme CSS for accessibility. +# See (note that this code is evolving, works as of asciidoctor 2.0.12): +# https://github.com/asciidoctor/asciidoctor/blob/main/lib/asciidoctor/syntax_highlighter/rouge.rb + +include ::Asciidoctor + +class ExtendedRougeSyntaxHighlighter < (Asciidoctor::SyntaxHighlighter.for 'rouge') + register_for 'rouge' + + # Insert rouge stylesheet from super + # Then replace many 'github' theme colors for accessibility compliance + # It would be better to use rouge's stylesheet factory, if it has one + def docinfo location, doc, opts + overrides = %() + + # super can return either