// Copyright (c) 2014-2019 The Khronos Group Inc.
// Copyright notice at https://www.khronos.org/registry/speccopyright.html
ifdef::a2xhtml[]
= Khronos Data Format Specification =
endif::[]
[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
avoid replication of incompatible format descriptions between standards
and to provide a definitive mechanism for describing data that avoids
excluding useful information that may be ignored by other standards.
Other APIs are expected to map internal formats to this standard scheme,
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: &alpha;
:beta: &beta;
:gamma: &gamma;
:rho: &rho;
:leq: &#8804;
:geq: &#8805;
:cdot: &#183;
:asciidoc-numbered:

ifndef::a2xhtml[]
= Introduction
endif::[]

== Introduction ==

Many APIs operate on bulk data -- buffers, images, volumes, etc. -- each
composed of many elements with a fixed and often simple representation.
Frequently, multiple alternative representations of data are supported:
vertices can be represented with different numbers of dimensions,
textures may have different bit depths and channel orders, and so on.
Sometimes the representation of the data is highly specific to the
application, but there are many types of data that are common to multiple
APIs -- and these can reasonably be described in a portable manner. In
this standard, the term _data format_ describes the representation of
data.

It is typical for each API to define its own enumeration of the
data formats on which it can operate. This causes a problem when
multiple APIs are in use: the representations are likely to be
incompatible, even where the capabilities intersect. When additional
format-specific capabilities are added to an API which was designed
without them, the description of the data representation often
becomes inconsistent and disjoint. Concepts that are unimportant to the
core design of an API may be represented simplistically or inaccurately,
which can be a problem as the API is enhanced or when data is shared.

Some APIs do not have a strict definition of how to interpret their
data. For example, a rendering API may treat all color channels of
a texture identically, leaving the interpretation of each channel to
the user's choice of convention. This may be true even if color channels
are given names that are associated with actual colors -- in some APIs,
nothing stops the user from storing the blue quantity in the red channel
and the red quantity in the blue channel. Without enforcing a single
data interpretation on such APIs, it is nonetheless often useful to offer
a clear definition of the color interpretation convention that is in force,
both for code maintenance and for communication with external APIs which do
have a defined interpretation. Should the user wish to use an unconventional
interpretation of the data, an appropriate descriptor can be defined that
is specific to this choice, in order to simplify automated interpretation
of the chosen representation and to provide concise documentation.

Where multiple APIs are in use, relying on an API-specific representation
as an intermediary can cause loss of important information. For example,
a camera API may associate color space information with a captured image,
and a printer API may be able to operate with that color space, but if the
data is passed through an intermediate compute API for processing and that
API has no concept of a color space, the useful information may be discarded.

The intent of this standard is to provide a common, consistent, machine-readable
way to describe those data formats which are amenable to non-proprietary
representation. This standard provides a portable means of storing the most
common descriptive information associated with data formats, and an extension
mechanism that can be used when this common functionality must be supplemented.

While this standard is intended to support the description of many kinds of
data, the most common class of bulk data used in Khronos standards represents
color information. For this reason, the range of standard color representations
used in Khronos standards is diverse, and a significant portion of this
specification is devoted to color formats.

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::[]

== 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
a data structure has the following benefits:

* Ensuring a precise description of the portable data
* Simplifying the writing of generic functionality that acts on many types of data
* Offering portability of data between APIs

The ``bulk data'' may be, for example:

* Pixel/texel data
* Vertex data
* A buffer of simple type

The layout of proprietary data structures is beyond the remit of this
specification, but the large number of ways to describe colors, vertices
and other repeated data makes standardization useful.
The widest variety of standard representations and the most common
expected use of this API is to describe pixels or texels; as such the
terms ``texel'' and ``pixel'' are used interchangeably in this
specification when referring to elements of data, without intending to
imply a restriction in use.

The data structure in this specification describes the elements in the
bulk data in memory, not the layout of the whole.
For example, it may describe the size, location and interpretation of
color channels within a pixel, but is not responsible for determining the
mapping between spatial coordinates and the location of pixels in memory.
That is, two textures which share the same pixel layout can share the same
descriptor as defined in this specification, but may have different
sizes, line or plane strides, tiling or dimensionality; in common parlance,
two images that describe (for example) color data in the same way but which
are of different shapes or sizes are still described as having the same
``format''.

An example pixel representation is described in <<SimpleTexelBlock>>: a
single 5:6:5-bit pixel composed of a blue channel in the low 5 bits, a
green channel in the next 6 bits, and red channel in the top 5 bits of a
16-bit word as laid out in memory on a little-endian machine (see
<<exampledescriptor_565>>).

[[SimpleTexelBlock]]
.A simple one-texel texel block
image::images/565pixels.{svgpdf}[width="{svgpdf@pdf:400pt:800}",align="center"]

=== 1-D texel addressing

In bulk data, each element is interpreted first by addressing it in some
form, then by interpreting the addressed values.
Texels often represent a color (or other data) as a multi-dimensional set
of values, each representing a _channel_.
The bulk-data _image_ or _buffer_ then describes a number of these texels.
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:

-----
typedef struct _MyRGB {
  unsigned char red;
  unsigned char green;
  unsigned char blue;
} 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
the array and ++sizeof myRGB++.
Extracting the ++red++, ++green++ and ++blue++ components of
++myRGBarray[9]++ given its base address is, in a sense, orthogonal
to _finding_ the base address of ++myRGBarray[9]++.

Note also that ++sizeof(MyRGB)++ will often exceed the total size
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]]
.(Trivial) 1D address offsets for 1-byte elements, start of buffer
image::images/1DByteOffset.{svgpdf}[width="{svgpdf@pdf:290pt:450}",align="center"]

[[1DWords]]
.1D address offsets for 2-byte elements, start of buffer
image::images/1DWordOffset.{svgpdf}[width="{svgpdf@pdf:290pt:450}",align="center"]

[[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"]

An alternative representation is a ``structure of arrays'',
distinct from the ``array of structures'' ++myRGBarray++:

-----
typedef struct _MyRGBSoA {
  unsigned char *red;
  unsigned char *green;
  unsigned char *blue;
} MyRGBSoA;

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.
The best approach depends on the operations performed: calculations
on one whole ++MyRGB++ a time likely favor ++MyRGB++, those processing
multiple values from a single channel may prefer ++MyRGBSoA++.
A ``pixel'' need not fill an entire byte -- nor need _pixel stride_
be a whole number of bytes.
For example, a C{plus}{plus} ++std::vector<bool>++ can be considered to be
a 1-D bulk data structure of individual bits.

=== Simple 2-D texel addressing

The simplest way to represent two-dimensional data is in consecutive rows,
each representing a one-dimensional array -- as with a 2-D array in C.
There may be padding after each row to achieve the required alignment:
in some cases each row should begin at the start of a cache line, or
rows may be deliberately offset to different cache lines to ensure
that vertically-adjacent values can be cached concurrently.
The offset from the start of one horizontal row to the next is
a _line stride_ or _row stride_ (or just _stride_ for short), and is
necessarily at least the width of the row.
If each row holds an whole number of pixels, row stride can be
described either in bytes or pixels; it is rare not to start each row on
a byte boundary.
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
buffer, padding row stride to a multiple of four elements.

[[2DLinear]]
.2D linear texel offsets from coordinates
image::images/2DLinearOffsets.{svgpdf}[width="{svgpdf@pdf:350pt:540}",align="center"]

[[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]]
.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"]

By convention, this ``linear'' layout is in _y_-major order (with the
_x_ axis changing most quickly).
This does not necessarily imply that an API which accesses the 2D data
will do so in this orientation, and there are image layouts which have
_x_ and _y_ swapped.
The direction of the axes (particularly _y_) in relation to the image
orientation also varies between representations.

Each contiguous region described in this way can be considered as a
_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]]
.2D _R_,_G_,_B_ plane offsets from coordinates for 8{times}4 texels
image::images/2DRGBplanes.{svgpdf}[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;
combining 1-bit planes allowed, for example, 64-color, 6-bit pixels.
Storing six bits per pixel consecutively would make the number of memory
bytes holding a pixel vary by alignment; a planar layout needs simpler
hardware.
This hardware could often process a subset of the planes -- scrolling
text may require blitting just one plane, and changes to the display
controller start position for each plane independently provide
cheap parallax effects.

In modern architectures, planes are typically byte-aligned and
hold separate channels.
One motivation is avoiding padding.
Some common hardware can only access powers of two bytes for each pixel:
for example, texels of three 1-byte channels may need padding to four
bytes for alignment restrictions; separate planes of one byte per texel
need no padding.
Other benefits are supporting different downsampling of each channel
(described below), and more efficient independent processing of each
channel: many common operations (such as filtering and image
compression) treat channels separately.

Note that, once all the data from any contributing channels have been
combined, the interpretation of the resulting values is again orthogonal
to addressing the data.

<<<
=== More complex 2-D texel addressing

In many applications, the simple ``linear'' layout of memory has
disadvantages.
The primary concern is that data which is vertically adjacent in
two-dimensional space may be widely separated in memory address.
Many computer graphics rendering operations involve accessing the frame
buffer in an order not aligned with its x-axis; for example, traversing
horizontally across the width of a textured triangle while writing to
the frame buffer will result in a texture access pattern which depends
on the orientation of the texture relative to the triangle and the
triangle relative to the frame buffer.
If each texel access processed a different cache line, the resulting
performance would be heavily compromised.
Modern GPUs process multiple texels in parallel, meaning that many
nearby texels in different orientations may need to be accessed
quickly.
Additionally, texture filtering operations typically read a 2{times}2
quad of texels, inherently requiring access to texels which would be
distant in memory in the linear representation.

One solution to this is to divide the image into smaller rectangular
tiles of texels (of _tw_ {times} _th_) rather than horizontal rows.
The texel ordering within the tiles may be treated as though each tile
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)
+ \textit{tw}\times\left(y\ \%\ \textit{th}\right)
+ \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_):

-----
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:

-----
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:

-----
pixelOffset = (x & 3) | ((y & 3) << 2) | ((x & ~3) << 2) | ((y & ~3) * 16);
-----

[[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"]

Textures which have dimensions that are not a multiple of the tile
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
vertically-adjacent lines requires accessing outside a tile of height
_n_.
The larger the tile, the greater the probability that vertically-adjacent
accesses fall inside the same scan line.
However, horizontally-adjacent texels that cross a tile boundary are made
more distant in memory the larger the tile size, and tile sizes which do
not conveniently fit the cache and bus sizes of the memory subsystem
have inefficiencies; thus the tile size is an architectural trade-off.

While any non-linear representation is typically referred to as ``tiling'',
some hardware implementations actually use a more complex layout in order
to provide further locality of reference.
One such scheme is Morton order:

[[2DMorton]]
.Morton order texel offsets from coordinates (consecutive values linked in red)
image::images/2DMortonOffsets.{svgpdf}[width="{svgpdf@pdf:350pt:575}",align="center"]

-----
uint32_t mortonOffset(uint32_t x, uint32_t y,
                      uint32_t width, uint32_t height) {

    const uint32_t minDim = (width <= height) ? width : height;
    uint32_t offset = 0, shift = 0, mask;

    // Tests xy bounds AND that width and height != 0
    assert(x < width && y < height);

    // Smaller size must be a power of 2
    assert((minDim & (minDim - 1)) == 0);

    // Larger size must be a multiple of the smaller
    assert(width % minDim == 0 && height % minDim == 0);

    for (mask = 1; mask < minDim; mask <<= 1) {
        offset |= (((y & mask) << 1) | (x & mask)) << shift;
        shift++;
    }

    // At least one of width and height will have run out of most-significant bits
    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
a multiple of the smaller.
A practical hardware implementation of the calculation is likely much
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]]
.Hilbert curve order texel offsets from coordinates (consecutive values linked in red)
image::images/2DHilbertOffsets.{svgpdf}[width="{svgpdf@pdf:350pt:575}",align="center"]

-----
uint32_t h(uint32_t size, uint32_t x, uint32_t y) {
    const uint32_t z = x ^ y;
    uint32_t offset = 0;

    while (size >>= 1) { // Iterate in decreasing block size order
        // Accumulate preceding blocks of size * size
        offset += size * (((size & x) << 1) + (size & z));
        y = z ^ x; // Transpose x and y
        if (!(size & y)) x = (size & x) ? ~y : y; // Conditionally swap/mirror
    }
    return offset;
}

uint32_t hilbertOffset(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
    const uint32_t minDim = (width <= height) ? width : height;

    // Tests xy bounds AND that width and height != 0
    assert(x < width && y < height);

    // Smaller size must be a power of 2
    assert((minDim & (minDim - 1)) == 0);

    // Larger size must be a multiple of the smaller
    assert(width % minDim == 0 && height % minDim == 0);

    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.

Some implementations will mix these approaches -- for example, having
linear tiles arranged in Morton order, or Morton order texels within
tiles which are themselves in linear order.
Indeed, for non-square areas, the tiling, Morton and Hilbert orderings
shown here can be considered as a linear row of square areas with
edges of the shorter dimension.

In all these cases, the relationship between coordinates and the memory
storage location of the buffer depends on the image size and, other than
needing to know the amount of memory occupied by a single texel, is
orthogonal to the ``format''.
Tiling schemes tend to be complemented by proprietary hardware that
performs the coordinate-to-address mapping and depends on cache
details, so many APIs expose only a linear layout to end-users, keeping
the tiled representation opaque.
The variety of possible mappings between coordinates and addresses
mandates leaving the calculation to the application.

<<<
=== 3-dimensional texel addressing

These storage approaches can be extended to additional dimensions,
for example treating a 3-D image as being made up of 2-D ``planes'',
which are distinct from the concept of storing channels or bits of
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.
The _plane stride_ is therefore _height_ {times} _row stride_ plus
any additional padding.

Again, non-linear approaches can be used to increase the correlation
between storage address and coordinates.

-----
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) {
  // twb = tile width bits (log2 of tile width)
  // thb = tile height bits (log2 of tile height)
  // tdb = tile depth bits (log2 of tile depth)
  return (x & ((1 << twb) - 1)) |
         ((y & ((1 << thb) - 1)) << twb) |
         ((z & ((1 << tdb) - 1)) << (twb + thb)) |
         ((x & ~((1 << twb) - 1)) << (thb + tdb)) |
         ((y & ~((1 << thb) - 1)) << tdb) * lineStride |
         ((z & ~((1 << tdb) - 1)) * planeStride);
}
-----

-----
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;
    uint32_t offset = 0, shift = 0, mask;
    for (mask = 1; max > mask; mask <<= 1) {
        if (width > mask)  offset |= (x & mask) << shift++;
        if (height > mask) offset |= (y & mask) << shift++;
        if (depth > mask)  offset |= (z & mask) << shift++;
        --shift;
    }
    return offset;
}
-----

There are multiple 3D variations on the Hilbert curve; one such is this:

-----
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
    uint32_t offset = 0;
    while (size >>= 1) {
        uint32_t tx = (size & x) > 0, ty = (size & y) > 0, tz = (size & z) > 0;
        switch (tx + 2 * ty + 4 * tz) {
        case 0: tx =  z; ty =  y; tz =  x; break;
        case 1: tx =  x; ty =  z; tz =  y; offset += size * size * size; break;
        case 2: tx = ~y; ty = ~x; tz =  z; offset += size * size * size * 3; break;
        case 3: tx =  z; ty =  x; tz =  y; offset += size * size * size * 2; break;
        case 4: tx = ~z; ty =  y; tz = ~x; offset += size * size * size * 7; break;
        case 5: tx =  x; ty = ~z; tz = ~y; offset += size * size * size * 6; break;
        case 6: tx = ~y; ty = ~x; tz =  z; offset += size * size * size * 4; break;
        case 7: tx = ~z; ty =  x; tz = ~y; offset += size * size * size * 5; break;
        }
        x = tx; y = ty; z = tz;
    }
    return offset;
}
-----

<<<
=== Downsampled channels

The examples provided so far have assumed that a unique value from each
color channel is present at each access coordinate.
However, some common representations break this assumption.

One reason for this variation comes from representing the image in the
_Y&prime;C~B~C~R~_ color model, described in <<MODEL_YUV>>; in this
description, the _Y&prime;_ channel represents the intensity of light,
with _C~B~_ and _C~R~_ channels describing how the color differs from
a gray value of the same intensity in the blue and red axes.
Since the human eye is more sensitive to high spatial frequencies
in brightness than in the hue of a color, the _C~B~_ and _C~R~_
channels can be recorded at lower spatial resolution than the
_Y&prime;_ channel with little loss in visual quality, saving storage
space and bandwidth.

In one common representation known colloquially as _YUV_ 4:2:2,
each horizontal pair of _Y&prime;_ 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&prime;_ value for each element, but as shown in <<1DYCBCR_CBCR>>
the _C~B~_ and _C~R~_ values are shared across pairs of elements.

[[1DYCBCR_Y]]
.1-D _Y&prime;C~B~C~R~_ 4:2:2 buffer, texels associated with _Y&prime;_ values
image::images/1DYCbCr_Y.{svgpdf}[width="{svgpdf@pdf:320pt:520}",align="center"]

[[1DYCBCR_CBCR]]
.1-D _Y&prime;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"]

In this case, we can say that the 2{times}1 coordinate region forms
a _texel block_ which contains two _Y&prime;_ values, one _C~B~_ value
and one _C~R~_ value; our bulk-data buffer or image is composed of a
repeating pattern of these texel blocks.

<<<
Note that this representation raises a question: while we have assumed
so far that accessing a value at texel coordinates will provide the
value contained in the texel, how should the shared _C~B~_ and _C~R~_
values relate to the coordinates of the _Y&prime;_ channel?
Each texel coordinate represents a value in the coordinate space of
the image or buffer, which can be considered as a _sample_ of the
value of a continuous surface at that location.
The preferred means of reconstructing this surface is left to the
application: since this specification only defines the values in the
image and not how they are used, it is concerned with the sample
values rather than the reconstruction algorithm or means of access.
For example, in graphics APIs the coordinates used to access a 2-D
texture may offset the sample locations of a texture by half
a coordinate relative to the origin of sample space, and filtering
between samples is typically used to implement antialiasing.
However, to interpret the data correctly, any application still needs
to know the theoretical location associated with the samples, so
that information is within the remit of this specification.

Our _Y&prime;_ 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&prime;_ values as shown in
<<1DYCbCr_cosited>>, or could be defined as falling at the mid-point
between them as in <<1DYCbCr_midpoint>>.
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
some cases it may suffice to duplicate _C~B~_ and _C~R~_ across the
pair of _Y&prime;_ values, in others bilinear or bicubic filtering
may be more appropriate.

[[1DYCbCr_cosited]]
.1-D _Y&prime;C~B~C~R~_ 4:2:2 buffer, _C~B~_ and _C~R~_ cosited with even _Y&prime;_ values
image::images/1DYCbCr_cosited.{svgpdf}[width="{svgpdf@pdf:220pt:340}",align="center"]

[[1DYCbCr_midpoint]]
.1-D _Y&prime;C~B~C~R~_ 4:2:2 buffer, _C~B~_ and _C~R~_ midpoint between _Y&prime;_ values
image::images/1DYCbCr_midpoint.{svgpdf}[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
in the horizontal axis for these channels).

<<<
This concept can be extended to more dimensions.
Commonly, a two-dimensional image stored in _Y&prime;C~B~C~R~_ format
may store the _C~B~_ and _C~R~_ channels downsampled by a factor of two
in each dimension (``2{times}2 downsampling'', also known for historical
reasons as ``4:2:0'').
This approach is used in, for example, many JPEG images and MPEG video
streams.

Because there are twice as many rows of _Y&prime;_ 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
texel blocks outlined in red); in addition, image compression schemes
often work with the channels independently, which is amenable to planar
storage.

[[2DYCbCr420_traditional]]
.2-D _Y&prime;C~B~C~R~_ 4:2:0 planes, downsampled _C~B~_ and _C~R~_ at midpoint between _Y&prime;_ values
image::images/2DYCbCr420_traditional.{svgpdf}[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&prime;_ plane, and also have half the line stride.
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
common _Y&prime;C~B~C~R~_ layouts, but does not extend conveniently to all
representations.
For example, one common representation used in camera sensors is a _Bayer
pattern_, in which there is only one of the red, green and blue channels
at each sample location: one red and blue value per 2{times}2 texel
block, and two green values offset diagonally, as in <<BayerOffsets>>.

[[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"]

A Bayer pattern can then be used to sample an image, as shown in
<<SimpleBayerBlock>>, and this sampled version can later be used to
reconstruct the original image by relying on heuristic correlations
between the channels.
Technology for image processing continues to develop, so in many cases
it is valuable to record the ``raw'' sensor data for later processing, and
to pass the raw data unmodified to a range of algorithms; the choice of
algorithm for reconstructing an image from samples is beyond the remit of
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"]

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.

<<<
More complex layouts are not uncommon.
For example, the X-Trans sample arrangement developed by Fujifilm for
their digital camera range, shown in <<XTrans>>, 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}$].

[[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"]

Allowing for possible alternative orientations of the samples (such as
whether the Bayer pattern starts with a row containing red or blue
samples, and whether the first sample is green or red/blue), trying
to encode these sample patterns implicitly is difficult.

== The Khronos Data Format Descriptor overview

The data structure defined in this specification is termed a
_<<dataformatdescriptor,data format descriptor>>_.
This is an extensible block of contiguous memory, with a defined layout.
The size of the data format descriptor depends on its content, but is also
stored in a field at the start of the descriptor, making it possible to
copy the data structure without needing to interpret all possible contents.

The data format descriptor is divided into one or more
_<<descriptorblock,descriptor blocks>>_, each also consisting of contiguous
data, as shown in <<DescriptorAndDescriptorBlocks>>.
These descriptor blocks may, themselves, be of different sizes, depending
on the data contained within.
The size of a descriptor block is stored as part of its data structure,
allowing an application to process a data format descriptor while skipping
contained descriptor blocks that it does not need to understand.
The data format descriptor mechanism is extensible by the addition of new
descriptor blocks.

[[DescriptorAndDescriptorBlocks]]
.Data format descriptor and descriptor blocks
[width="75%",cols="1a"]
|=============
^|_Data format descriptor_
[width="100%",cols="1"]
!=============
! _&nbsp;Descriptor block 1_
! _&nbsp;Descriptor block 2_
! &nbsp;:
!=============
|=============

The diversity of possible data makes a concise description that can
support every possible format impractical.
This document describes one type of descriptor block, a
_<<basicdescriptor,basic descriptor block>>_, that is expected to be the
first descriptor block inside the data format descriptor where present,
and which is sufficient for a large number of common formats,
particularly for pixels.
Formats which cannot be described within this scheme can use additional
descriptor blocks of other types as necessary.

Later sections of this specification describe several common color
spaces, and provide a description of the in-memory representation of a
number of common compressed texture formats.

<<<
[[texelblock]]
=== _Texel blocks_ in the Khronos Data Format Descriptor

Instead of an implicit representation, the descriptor specifies a
_texel block_, which is described in terms of its finite extent in each
of four dimensions, and which identifies the location of each sample
within that region.
The _texel block_ is therefore a self-contained, repeating, axis-aligned
pattern in the coordinate space of the image.
This description conveniently corresponds to the concept of _compressed
texel blocks_ used in common block-based texture compression schemes,
which similarly divide the image into (typically) small rectangular
regions which are encoded collectively.
The bounds of the texel block are chosen to be aligned to integer
coordinates.

Although it is most common to consider one- and two-dimensional textures
and texel blocks, it can be convenient to record additional dimensions;
for example, the ASTC compressed texture format described in <<ASTC>> can
support compressed texel blocks with three dimensions.
For convenience of encoding, this specification uses a four-dimensional
space to define sample locations within a texel block -- there is no
meaning imposed on how those dimensions should be interpreted.

In many formats, all color channels refer to the same location, and
the _texel block_ defines a 1{times}1{times}1{times}1 region --
that is, a single texel.

NOTE: Tiling schemes for texel addressing can also be seen to break
the image into rectangular (or higher-dimensional) sub-regions, and
in many schemes these sub-regions are repeating and axis-aligned.
Within reason, it is possible to define some coordinate-to-texel
mapping in terms of a texel block; for example, instead of a simple
tiled layout of 4{times}4 texels, it would be possible to describe
the image in terms of a linear pattern of texel blocks, each of
which contain 4{times}4 samples.
In general, this is not a useful approach: it is very verbose to list
each sample individually, it does not extend well to larger block
sizes (or to infinite ranges in approaches such as Morton order),
it does not handle special cases well (such as the ``tail'' of a
mip chain), and encodings such as Hilbert order do not have a
repeating mapping.
In most contexts where these concepts exist, tiling is not considered
to be part of a ``format''.

<<<
[[plane]]
=== _Planes_ in the Khronos Data Format Specification

The description above has shown that the data contributing to a texel
may be stored in separate locations in memory; for example, _R_,
_G_ and _B_ stored in separate planes may need to be combined to
produce a single texel.
For the purposes of this specification, a _plane_ is defined to be
*a contiguous region of bytes in memory that contributes to a single
texel block*.

This interpretation contradicts the traditional interpretation of
downsampled channels: if two rows of _Y&prime;_ data correspond to a
single row of _C~B~_ and _C~R~_ (in a linear, non-tiled memory layout),
the _Y&prime;_ channel contribution to the texel block is _not_
``a contiguous region of bytes''.
Instead, each row of _Y&prime;_ contributing to a texel block can be
treated as a separate ``plane''.

In linear layout, this can be represented by offsetting rows of
_Y&prime;_ data with odd _y_ coordinates by the row stride of the
original _Y&prime;_ plane; each new _Y&prime;_ plane's stride is then
double that of the original _Y&prime;_ plane, as in <<2DYCbCr420_KDFS>>
(c.f. <<2DYCbCr420_traditional>>).
If the planes of a 6{times}4 _Y&prime;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 <<yuv420conventional>>, the representation used by
this specification would be that shown in <<yuv420thisapi>>.

[[yuv420conventional]]
.Plane descriptors of a 6{times}4 _Y&prime;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&prime;_ ^| 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&prime;C~B~C~R~_-format buffer using this standard
[cols="4",width="60%",options="header"]
|==============================
^| Plane ^| Byte offset ^| Byte stride ^| Bytes per plane
^|_Y&prime;_ plane 1 ^| 0 ^| 12 ^| 2
^|_Y&prime;_ 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
explicit support for the special case of integer chroma downsampling
to detect interleaved planes and to deduce that they should be
treated as a single plane of double vertical resolution.
Many APIs will not support the full flexibility of formats supported
by this specification, and will map to a more restrictive internal
representation.

The Khronos Basic Descriptor Block indicates a number of bytes
contributing to the texel block from each of up to eight planes
-- if more than eight planes are required, an extension is needed.
Eight planes are enough to encode, for example:

* 8-bit data stored as individual bit planes
* Stereo planar _R_, _G_, _B_, _A_ data
* 4{times} vertically-downsampled _Y&prime;C~B~C~R~_ data, as might
be produced by rotating a (relatively common) 4{times}
horizontally-downsampled _Y&prime;C~B~C~R~_ (4:1:1) video frame
* A 2{times}2{times}2{times}2 4-D texel block in a linear layout
* Interlaced _Y&prime;C~B~C~R~_ 4:2:0 data with each field stored
separately

If a plane contributes less than a byte to a texel (or a non-integer
number of bytes), the texel block size should be expanded to cover
more texels until a whole number of bytes are covered -- q.v.
<<exampledescriptor_1bpp>>.

<<<
NOTE: Interlaced _Y&prime;C~B~C~R~_ data may associate chroma channels
with _Y&prime;_ samples only from the same field, not the frame as a
whole.
This distinction is not made explicit, in part because a number of
interlacing schemes exist.
One suggested convention for interlaced data is that the field of a
sample be encoded in the fourth sample coordinate (the first field
as *_samplePosition3_* = 0, the second field as *_samplePosition3_*
= 1, etc.)
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]]
.2-D _Y&prime;C~B~C~R~_ 4:2:0 planes, with separate even and odd _Y&prime;_ planes
image::images/2DYCbCr420_KDFS.{svgpdf}[width="{svgpdf@pdf:310pt:480}",align="center"]

<<<
=== Bit pattern interpretation and _samples_

For the purposes of description, the bytes contributed by each plane
are considered to be concatenated into a single contiguous _logical bit
stream_.
This ``concatenation'' of bits is purely conceptual for the purposes of
determining the interpretation of the bits that contribute to the texel
block, and is not expected to be the way that actual decoders would
process the data.

That is, if planes zero and one contribute two bytes of data each and
planes two and three contribute one byte of data each, this bit stream
would consist of the two bytes from plane zero followed by the two bytes
from plane one, then the byte from plane two, then the byte from plane
three.

The data format descriptor then describes a series of _samples_ that
are contained within the texel block.
Each sample represents a series of contiguous bits from the bit stream,
interpreted in little-endian order, and is associated with a single
channel and four-dimensional coordinate offset within the texel block;
in formats for which only a single texel is being described, this
coordinate offset will always be 0,0,0,0.

The descriptor block for a _Y&prime;C~B~C~R~_ 4:2:0 layout is shown in
<<exampledescriptor_ycbcr>>.
<<2DYCbCr420Encoding>> 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.
These are concatenated into a 48-bit logical bit stream (shown in blue,
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]]
._Y&prime;C~B~C~R~_ 4:2:0 described in six samples
image::images/2DYCbCrKDFSEncoding.{svgpdf}[width="{svgpdf@pdf:475pt:800}",align="center"]

<<<
Consecutive samples with the same channel, location and flags may describe
additional bits that contribute to the same final value, and appear in
increasing order.
For example, a 16-bit big-endian word in memory can be described by one
sample describing bits 0..7, coming from the higher byte address, followed
by one sample describing bits 8..15, coming from the lower address.
These samples comprise a single _virtual sample_, of 16 bits.

<<RGB565BEEncoding>> shows how multiple contributions to single value
can be used to represent a channel which, due to a big-endian native
word type (high bits stored in lower byte addresses), is not contiguous
in a little-endian representation (low bits stored in lower byte
addresses).
Here, channels are comprised of consecutive bits from a 16-bit big-endian
word; the bits of each channel cease to be contiguous when the memory
bytes are interpreted in little-endian order for the logical bit stream.
The bit contributions to each channel from each bit location are shown in
superscript, as later in this specification; the channel contributions
start at bit 0 with the first sample contributing to the value, and are
deduced implicitly from the number of bits each sample contributes.
This example assumes that we are describing a single texel, with the
same 0,0,0,0 coordinates (not shown) for each sample.
The descriptor block for this format is shown in
<<exampledescriptor_bigendian>>.

[[RGB565BEEncoding]]
._RGB_ 565 big-endian encoding
image::images/RGB565BEKDFSEncoding.{svgpdf}[width="{svgpdf@pdf:490pt:850}",align="center"]

In <<RGB565BEEncoding>>, bit 0 of the logical bit stream corresponds to
bit 3 of the virtual sample that describes the green channel; therefore
the first channel to be encoded is green.
Bits 0 to 2 of the green channel virtual sample correspond to bits 13..15
of the logical bit stream, so these are described by the first sample.
The second sample continues describing bits 3..5 of the green channel
virtual sample, in bits 0..2 of the logical bit stream.
The next bit from the logical bit stream that has not yet been
described is bit 3, which corresponds to bit 0 of the red channel.
The third sample is therefore used to describe bits 3..7 of the
logical bit stream as a 5-bit red channel.
The last sample encodes the remaining 5-bit blue channel that forms
bits 8..12 of the logical bit stream.
Note that in the case where some bits of the data are ignored, they
do not need to be covered by samples; bits may also appear repeatedly
if they contribute to multiple samples.

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
coordinate; this approach allows large texel blocks, half-texel offsets
for representations such as _Y&prime;C~B~C~R~_ 4:2:0, and precise
fractional offsets for recording multisampled pattern locations.

The sequence of bits in the (virtual) sample defines a numerical range
which may be interpreted as a fixed-point or floating-point value and
signed or unsigned.
Many common representations specify this range.
For example, 8-bit _RGB_ data may be interpreted in ``unsigned
normalized'' form as meaning ``0.0'' (zero color contribution) when
the channel bits are 0 and ``1.0'' (maximum color contribution) when
the channel is 255.
In _Y&prime;C~B~C~R~_ ``narrow-range'' encoding, there is head-room
and foot-room to the encoding: ``black'' is encoded in the _Y&prime;_
channel as the value 16, and ``white'' is encoded as 235, as shown
in <<QUANTIZATION_NARROW>>.
To allow the bit pattern of simply-encoded numerical encodings
to be mapped to the desired values, each sample has an _upper_
and _lower_ value associated with it, usually representing 1.0
and either 0.0 or -1.0 depending on whether the sample is signed.

Note that it is typically part of the ``format'' to indicate the
numbers which are being encoded; how the application chooses to
process these numbers is not part of the ``format''.
For example, some APIs may have two separate ``formats'', in which
the 8-bit pattern 0x01 may be interpreted as either the float
value 1.0 or the integer value 1; for the purposes of this
specification, these formats are identical -- ``1'' means ``1''.

A sample has an associated color channel in the color model of the
descriptor block -- for example, if the descriptor block indicates an
_RGB_ color model, the sample's channel field could specify the _R_
channel.
The descriptor block enumerates a range of common color models, color
primary values and transfer functions, which apply to the samples.

<<<
[[Canonical]]
=== Canonical representation

There is some redundancy in the data format descriptor when it comes
to the ordering of planes and samples.
In the interests of simplifying comparison between formats, it is
helpful to define a canonical ordering.

* Planes should be described first in order of the first channel
with which they are associated, then in increasing raster order
of coordinates, then in increasing bit order (in a little-endian
interpretation).
For example:
 - In the _Y&prime;C~B~C~R~_ 4:2:0 format described above, the
    _Y&prime;_ planes should come before the _C~B~_ and _C~R~_
    planes in that order, because of the channel order.
 - The _Y&prime;_ plane corresponding to even _y_ addresses
    should come before the _Y&prime;_ plane corresponding to
    odd _y_ coordinates, because row 0 is even.
  - Planes should be ordered such that sample values that are split
    across multiple planes should be ordered in increasing order --
    e.g. in an 8-bit format with one bit per plane, planes
    0 through 7 should encode bits 0 through 7 in that order
    (thereby minimizing the number of samples required to describe
    the value).

The order of samples should be defined by the following rules:

* Samples sharing a channel and location appear consecutively in
  increasing order of bits contributed to the virtual sample.
** For example, a big-endian 16-bit red channel at location
   0,0 may be composed of two samples: one referencing the
   eight consecutive virtual bit stream bits from 0..7
   (*_bitOffset_* = 0, *_bitLength_* = 8) and the other
   referencing the eight consecutive virtual bit stream
   bits from 8..15 (*_bitOffset_* = 8, *_bitLength_* = 8).
   Since the least-significant 8 bits of the virtual red
   value come from the sample that references bits 8..15
   of the virtual bit stream, this sample should appear
   first, immediately followed by the sample that references
   bits 0..8, which define the most-significant 8 bits of
   the virtual value.
   <<exampledescriptor_48bit>> shows a similar virtual
   sample, split across three samples of contiguous bits.
* A minimum number of samples describes each sequence of
  contiguous virtual bit stream bits in a virtual sample value.
** If an additional sample is required to represent the sample's
   *_sampleLower_* and *_sampleUpper_* values because more than 32
   bits are encoded and the existing extension rules for
   *_sampleLower_* and *_sampleUpper_* do not result in the desired
   behavior, the earlier sample(s) should be limited to 32 bits,
   ensuring that the subsequent sample holds at least one bit
   (*_bitLength_* is greater than or equal to 0).
** Otherwise, if the contiguous sequence of bits from the virtual
   bit stream is longer than 256 bits, samples should be concatenated
   such that only the last sample describes fewer than 256 bits.
* Samples that qualify an existing virtual sample immediately
  follow it.
** Specifically, in an explicitly-described floating-point
   format, any sample describing a sign bit immediately
   follows the unsigned mantissa, and any exponent follows
   thereafter, as seen in <<exampledescriptor_float16explicit>>.
* Virtual samples are described in increasing order of the
  virtual bit stream bits to which they apply.
** This means that if bit 0 of the virtual bit stream is part of
   a virtual sample, that virtual sample should be described first;
   this does not require that the first sample directly describes
   bit 0, as in the green channel of <<exampledescriptor_bigendian>>.
* If the same bit in the virtual bit stream in increasing bit
  order is the first to be associated with more than one virtual
  sample, virtual samples are listed in channel number order.
** For example, an alpha channel may be encoded in bits 0..7 of
   the virtual bits stream, followed by red, green and blue
   channels sharing bits 8..15. The sample describing alpha should
   be listed first, since it uniquely describes bit 0 of the virtual
   bits stream. Bit 8 of the virtual bit stream is the first bit of
   the red, green and blue, and since red, green and blue are channel
   numbers 0, 1 and 2, the corresponding samples are described in
   this order. See, for example, <<exampledescriptor_AcornTint>>
   and <<exampledescriptor_intensity>>.
* Virtual samples that share bits and channel number but not location
  would be extremely unusual, but would appear in increasing raster
  order of the location (that is, sorted first by coordinate three,
  then two, then one, then zero).

Finally:

* Fields which are irrelevant (for example, the alpha behavior
  for a format with no alpha channel) should be set to zero.
* Samples describing a channel of a single bit should have a
  linear transfer function -- either by selecting the transfer
  function *++KHR_DF_TRANSFER_LINEAR++* for the descriptor
  as a whole if all samples are linear, or by
  setting the sample's *++KHR_DF_SAMPLE_DATATYPE_LINEAR++*
  bit if other samples have multiple bits and a non-linear
  transfer function is needed.

<<<
=== Related concepts outside the ``format''

The data format descriptor describes only concepts which are
conventionally part of the ``format''.
Additional information is required to access the image data:

* A formula for mapping accessed coordinates to byte data for
  each channel.
  * This may be expected to require, for each channel, a start
    address and a stride in each dimension.
  * This transformation depends on the image size, and may be
    parameterized by the texel block dimensions and the number
    of bytes contributed by each plane.
* (Optionally) for each dimension, a maximum (and arguably
  minimum) range.
  * Note that padding is independent of the ``format''.

For example, if texels are laid out in memory in linear order:

-----
int numPlanes;
char *planeBaseAddresses[8];
unsigned int strides[8][4];

// Note: The strides here are assumed to be in units of the
// corresponding dimension of the texel block
char *planeAddress(uint32_t descriptor, int plane, float coords[4]) {
  return planeBaseAddresses[plane]
    // Block stride
    + ((int) (coords[0] / descriptorSize(descriptor, 0))) * strides[plane][0]
    // Row stride
    + ((int) (coords[1] / descriptorSize(descriptor, 1))) * strides[plane][1]
    // Plane stride
    + ((int) (coords[2] / descriptorSize(descriptor, 2))) * strides[plane][2]
    // Volume(?) stride
    + ((int) (coords[3] / descriptorSize(descriptor, 3))) * strides[plane][3];
}

decodeTexelGivenCoords(uint32_t *descriptor, float coords[4]) {
  char *addresses[8];
  for (int i = 0; i < numPlanes; ++i) {
    addresses[i] = planeAddress(i, coords);
  }

  // processTexel reads bytesPlane[] bytes from each address and
  // 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.
For example, if the texel block size is 2{times}2, the block and row
stride provide the offset in bytes between adjacent blocks in the first
two dimensions.
++processTexel++ would then work with the data corresponding to the
2{times}2 region with ++coords[0]++ and ++coords[1]++ in the range [0..2).
For formats that describe a single texel, ++coords++ can be considered
to be an integer.
Note that for more complex formats such as Bayer layouts, reconstructing
an _R_,_G_,_B_ value at a location may require information from more than
one texel block, depending on the algorithm used, in a manner analogous
to sampling using bilinear filtering.

The stride values may be stored explicitly, or derived implicitly
from the *_bytesPlane_* values and image size information, with
application-specific knowledge about alignment constraints.

<<<
=== Translation to API-specific representations

Despite being designed to balance size against flexibility, the data
format container described here is too unwieldy to be expected to be
used directly in most APIs, which will generally support only a subset
of possible formats.
The expectation is that APIs and users will define data descriptors in
memory, but have API-specific names for the formats that the API supports.
If these names are enumeration values, a mapping can be provided by having
an array of pointers to the data descriptors, indexed by the enumeration.
It may commonly be necessary to provide API-specific supplementary
information in the same array structure, particularly where the
API natively associates concepts with the data which is not uniquely
associated with the content.

In this approach, it is likely that an API would predefine a number of
common data formats which are natively supported.
If there is a desire to support dynamic creation of data formats, this
array could be made extensible with a manager assigning unique handles.

Even where an API supports only a fixed set of formats, it is flexible
to provide a comparison with user-provided format descriptors in order
to establish whether a format is compatible (and differs only in a
manner irrelevant to the API).

Some APIs have the concept of a _native data type_ for a format,
if each channel is stored separately.
Since this specification describes a number of bytes per plane and
separately contiguous bit sequences, there is no such explicit concept.
However, if a sample's *_bitOffset_* and *_bitLength_* are byte-aligned
and no further samples contribute to the same value, the *_bitLength_*
trivially defines a little-endian native data type size.
Big-endian data types can be identified by observing that in a big-endian
format, a sequence of bits in the top bits of byte _n_ may continue in
the low bits of byte _n_ - 1.
Finally, ``packed'' formats consist of consecutive bit sequences per
channel in either little- or big-endian order; little-endian sequences
are a single stand-alone sample, and a big-endian sequence consists of
a number of samples adjacent to byte boundaries in decreasing byte
order (see <<RGB565BEEncoding>>); the packed field size can typically
be deduced from the *_bytesPlane0_* value.
There is no way to distinguish a logically ``packed'', byte-aligned
samples from distinct but consecutively-stored channels that have the
same in-memory representation.

<<<
=== Glossary

_Data format:_
The interpretation of individual elements in bulk data. Examples
include the channel ordering and bit positions in pixel data or
the configuration of samples in a Bayer image. The format describes
the elements, not the bulk data itself: an image's size, stride, tiling,
dimensionality, border control modes, and image reconstruction filter are
not part of the format and are the responsibility of the application.

_<<dataformatdescriptor,Data format descriptor>>:_
A contiguous block of memory containing information about how data is
represented, in accordance with this specification. A data format
descriptor is a container, within which can be found one or more
descriptor blocks. This specification does not define where or how
the the data format descriptor should be stored, only its content.
For example, the descriptor may be directly prepended to the bulk
data, perhaps as part of a file format header, or the descriptor may
be stored in a CPU memory while the bulk data that it describes resides
within GPU memory; this choice is application-specific.

_<<descriptorblock,(Data format) descriptor block>>:_
A contiguous block of memory with a defined layout, held within a
data format descriptor. Each descriptor block has a common header
that allows applications to identify and skip descriptor blocks
that it does not understand, while continuing to process any other
descriptor blocks that may be held in the data format descriptor.

_<<basicdescriptor,Basic (data format) descriptor block>>:_
The initial form of descriptor block as described in this standard.
Where present, it must be the first descriptor block held in the
data format descriptor. This descriptor block can describe a large
number of common formats and may be the only type of descriptor block
that many portable applications will need to support.

_<<texelblock,Texel block>>:_
The units described by the Basic Data Format Descriptor: a repeating
element within bulk data.
In simple texture formats, a texel block may describe a single pixel.
In formats where the bytes of each plane do not correspond uniquely
to single pixels, as for example with subsampled channels, the texel
block may cover several pixels.
In a block-based compressed texture, the texel block typically describes
the compression block unit.
The basic descriptor block supports texel blocks of up to four
dimensions.

_<<plane,Plane>>:_
In the Basic Data Format Descriptor, a plane describes a contiguous
sequence of bytes that contribute to the texel block.
The basic format descriptor block defines a texel block as being made
of a number of concatenated bits which may come from different regions
of memory, where each region is considered a separate _plane_.
For common formats, it is sufficient to require that the contribution
from each plane is an integer number of bytes.
This specification places no requirements on the ordering of planes in
memory -- the plane locations are described outside the format.
This allows support for multiplanar formats which have proprietary
padding requirements that are hard to accommodate in a more terse
representation.

_<<sample,Sample>>:_
In this standard, texel blocks are considered to be composed of
contiguous bit patterns with a single channel or component type and
a single spatial location.
A typical _ARGB_ pixel has four samples, one for each channel, held at
the same coordinate.
A texel block from a Bayer sensor might have a different location for
different channels, and may have multiple samples representing the
same channel at multiple locations.
A _Y&prime;C~B~C~R~_ buffer with downsampled chroma may have more luma
samples than chroma, each at different locations.

== [[dataformatdescriptor]]Khronos Data Format Descriptor ==

The data format descriptor consists of a contiguous area of memory,
as shown in <<DataFormatDescriptorOverview>>, divided into one or more
_descriptor blocks_, which are tagged by the type of descriptor that
they contain.
The size of the data format descriptor varies according to its content.

[[DataFormatDescriptorOverview]]
.Data Format Descriptor layout
[width="60%",cols="1,2"]
|=====================================
>| *++uint32_t++* &nbsp; ^| &nbsp; *_totalSize_*
>| _Descriptor block_ &nbsp; ^| &nbsp; _First descriptor_
>| _Descriptor block_ &nbsp; ^| &nbsp; _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.
*_totalSize_* includes its own *++uint32_t++*, not just the following
descriptor blocks.
For example, we will see below that a four-sample Khronos Basic
Data Format Descriptor Block occupies 88 bytes; if there are no
other descriptor blocks in the data format descriptor, the *_totalSize_*
field would then indicate 88 {plus} 4 bytes (for the *_totalSize_* field
itself) for a final value of 92.

For consistency of decode, each descriptor block should be aligned
to a multiple of four bytes relative to the start of the descriptor;
*_totalSize_* will therefore be a multiple of four.

NOTE: This restriction was not present in versions of the Khronos
Data Format Specification prior to version 1.3.

The layout of the data structures described here are comprised solely
of 32-bit words, and for canonical communication between devices are
assumed to be stored with a little-endian representation.
For efficiency, applications may choose to convert the descriptor
to the native endianness of the underlying hardware where all
software using the data structure is prepared for this conversion.
Extensions which are composed of quantities other than 32-bit words
(for example if a data structure belonging to another standard is
incorporated directly) may define the expected impact of endianness
changes on the layout.
Since the environment is expected to know its own endianness, there
is no explicit means of automatically determining the endianness of a
descriptor, although it can be observed that it is highly unlikely
that a valid descriptor would be large enough for its size to need
to be represented in more than 16 bits -- meaning that the endianness
of most descriptors can be deduced by which half of the *++uint32_t++*
*_totalSize_* field is non-zero.

NOTE: To avoid expanding the size of the data structure, there is no
``magic identifier'' for a data format descriptor: applications are
expected to know the type of the data structure being accessed, and
to provide their own means of identifying a data format descriptor if
one is embedded in a multi-purpose byte stream.

<<<
=== [[descriptorblock]]Descriptor block

Each _descriptor block_ has the same prefix, shown in <<DescriptorPrefix>>.

[[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,
this should occupy bits 0..15, with bit 16 set to 0.
Other organizations should apply to Khronos of a unique identifier,
which will be assigned consecutively starting with 65536.
The identifier 0x1FFFF is reserved for internal use which is guaranteed
not to clash with third-party implementations; this identifier should
not be shipped in libraries to avoid conflicts with development code.

The *_descriptorType_* is a unique 15-bit identifier defined by the
vendor to distinguish between potential data representations.

NOTE: Prior to version 1.3 of the Khronos Data Format Specification,
the *_vendorId_* field was 16-bit, and purely assigned through the
auspices of this specification; the *_descriptorType_* was consequently
also 16-bit.
Since no vendor has requested an identifier and Khronos does not have
a descriptor block with type 1, this change should not cause any
ambiguity.
This change is intended to allow consistency with the vendor IDs
used by the Vulkan specification.

The *_versionNumber_* is vendor-defined, and is intended to allow for
backwards-compatible updates to existing descriptor blocks.

The _DescriptorBlockSize_ indicates the size in bytes of this
Descriptor Block, remembering that there may be multiple
Descriptor Blocks within one container, as shown in
<<DataFormatDescriptorHeaderExample>>.
The *_descriptorBlockSize_* therefore gives the offset between the
start of the current Descriptor Block and the start of the next -- so the
size includes the *_vendorId_*, *_descriptorType_*, *_versionNumber_*
and *_descriptorBlockSize_* fields, which collectively contribute 8 bytes.

Having an explicit *_descriptorBlockSize_* allows implementations to skip
a descriptor block whose format is unknown, allowing known data to be
interpreted and unknown information to be ignored. Some descriptor
block types may not be of a uniform size, and may vary according to
the content within.

This specification initially describes only one type of stand-alone
descriptor block, plus two extension blocks which modify the description
in the first.
Future revisions may define additional descriptor block types for additional
applications -- for example, to describe data with a large number of channels
or pixels described in an arbitrary color space. Vendors can also implement
proprietary descriptor blocks to hold vendor-specific information within the
standard descriptor.

Unless otherwise specified, descriptor blocks can appear in any order,
to make it easier to add and remove additional informative descriptor
blocks to a preexisting data format descriptor as part of processing.
Descriptor blocks that provide additional capabilities beyond a basic
scheme (such as the descriptor block for supporting additional planes
beyond the Khronos Basic Descriptor Block) should not be present unless
their additional capabilities are needed; that is, redundancy should be
resolved so as to minimize the number of descriptor blocks in the data
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_*
32+^| ~First descriptor block~
15+^| *_descriptorType_* 17+^| *_vendorId_*
16+^| *_descriptorBlockSize_* 16+^| *_versionNumber_*
32+^| _Descriptor body_
32+^| ~Second descriptor block~
15+^| *_descriptorType_* 17+^| *_vendorId_*
16+^| *_descriptorBlockSize_* 16+^| *_versionNumber_*
32+^| _Descriptor body_
|====================

== [[basicdescriptor]]Khronos Basic Data Format Descriptor Block ==

A _basic descriptor block_ (<<BasicDescriptorBlock>>) is designed to
encode common metadata associated with bulk data -- especially image or
texture data.
While this descriptor holds more information about the data interpretation
than is needed by many applications, a comprehensive encoding reduces the
risk of metadata needed by different APIs being lost in translation.

The format is described in terms of a repeating axis-aligned _texel block_
composed of _samples_. Each sample contains a single channel of information
with a single spatial offset within the texel block, and consists of an amount
of contiguous data. This _descriptor block_ consists of information about the
interpretation of the texel block as a whole, supplemented by a description of
a number of samples taken from one or more _planes_ of contiguous memory. For
example, a 24-bit red/green/blue format may be described as a 1×1 pixel region,
in one plane of three samples, one describing each channel.
A _Y&prime;C~B~C~R~_ 4:2:0 format may consist of a repeating 2×2 region:
four _Y&prime;_ 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
16+^| *_descriptorBlockSize_* = 24 + 16 {times} _#samples_ 16+^| *_versionNumber_* = 2
8+^| *_flags_* 8+^| *_transferFunction_* 8+^| *_colorPrimaries_* 8+^| *_colorModel_*
8+^| *_texelBlockDimension3_* 8+^| *_texelBlockDimension2_* 8+^| *_texelBlockDimension1_* 8+^| *_texelBlockDimension0_*
8+^| *_bytesPlane3_* 8+^| *_bytesPlane2_* 8+^| *_bytesPlane1_* 8+^| *_bytesPlane0_*
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.

The fields of the Basic Data Format Descriptor Block are described in
the following sections.

<<<
To simplify code using the Basic Data Format Descriptor Block, the header
++khr_df.h++ provides enums of the following form for accessing descriptor
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:

*_xxx_* = *++KHR_DF_MASK_xxx++* & (++bdb++[*++KHR_DF_WORD_xxx++*] >> *++KHR_DF_SHIFT_xxx++*);

The macro *++KHR_DFDVAL++*(++BDB++, ++X++) is provided to perform this
calculation.
For example, *++KHR_DFDVAL++*(++bdb++, *++MODEL++*) returns the value:

*++KHR_DF_MASK_MODEL++* & (++bdb++[*++KHR_DF_WORD_MODEL++*] >> *++KHR_DF_SHIFT_MODEL++*)

<<<
=== *_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_* ===

The *_descriptorType_* for the Basic Data Format Descriptor Block is 0,
a value reserved in the enum of Khronos-specific descriptor types,
*++khr_df_khr_descriptortype_e++*, as *++KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT++*.

.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_* ===

The *_versionNumber_* relating to the Basic Data Format Descriptor Block
as described in this specification is 2.

NOTE: The *_versionNumber_* is incremented to indicate an incompatible change
in the descriptor.
The addition of enumerant values, for example to represent more compressed
texel formats, does not constitute an ``incompatible change'', and
implementations should be resilient against enumerants that have been added
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_* ===

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
are 24 bytes of shared data plus 16 bytes per sample. The *_descriptorBlockSize_*
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_* ===

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
of the possible channels from the *_colorModel_* be present. Most data fits
into a small number of common color models, but compressed texture formats
each have their own color model enumeration. Note that the data need not
actually represent a color -- this is just the most common type of content
using this descriptor. Some standards use _color container_ for this concept.

The available color models are described in the *++khr_df_model_e++* enumeration,
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++*);

Note that the numbering of the component channels is chosen such that those
channel types which are common across multiple color models have the same
enumeration value. That is, alpha is always encoded as channel ID 15,
depth is always encoded as channel ID 14, and stencil is always encoded as
channel ID 13. Luma/Luminance is always in channel ID 0. This numbering
convention is intended to simplify code which can process a range of color
models. Note that there is no guarantee that models which do not support
these channels will not use this channel ID. Particularly, _RGB_ formats
do not have luma in channel 0, and a 16-channel undefined format is not
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) ====

When the data format is unknown or does not fall into a predefined
category, utilities which perform automatic conversion based on an
interpretation of the data cannot operate on it. This format should
be used when there is no expectation of portable interpretation of
the data using only the basic descriptor block.

For portability reasons, it is recommended that pixel-like formats
with up to sixteen channels, but which cannot have those channels
described in the basic block, be represented with a basic descriptor
block with the appropriate number of samples from *++UNSPECIFIED++* channels,
and then for the channel description to be stored in an extension block.
This allows software which understands only the basic descriptor to
be able to perform operations that depend only on channel location,
not channel interpretation (such as image cropping). For example, a
camera may store a raw format taken with a modified Bayer sensor,
with _RGBW_ (red, green, blue and white) sensor sites, or _RGBE_
(red, green, blue and ``emerald''). Rather than trying to encode the
exact color coordinates of each sample in the basic descriptor,
these formats could be represented by a four-channel *++UNSPECIFIED++*
model, with an extension block describing the interpretation of
each channel.

<<<
==== *++KHR_DF_MODEL_RGBSDA++* (= 1) ====

This color model represents additive colors of three channels,
nominally red, green and blue, supplemented by channels for
alpha, depth and stencil, as shown in <<RGBSDAChannels>>.
Note that in many formats, depth and
stencil are stored in a completely independent buffer, but there
are formats for which integrating depth and stencil with color
data makes sense.

[[RGBSDAChannels]]
.Basic Data Format _RGBSDA_ channels
[width="100%",options="header"]
|================================
^| Channel number 2+| &nbsp; Name | &nbsp; Description
^| 0 2+| &nbsp; *++KHR_DF_CHANNEL_RGBSDA_RED++* | &nbsp; Red
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_RGBSDA_GREEN++* | &nbsp; Green
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_RGBSDA_BLUE++* | &nbsp; Blue
^| 13 2+| &nbsp; *++KHR_DF_CHANNEL_RGBSDA_STENCIL++* | &nbsp; Stencil
^| 14 2+| &nbsp; *++KHR_DF_CHANNEL_RGBSDA_DEPTH++* | &nbsp; Depth
^| 15 2+| &nbsp; *++KHR_DF_CHANNEL_RGBSDA_ALPHA++* | &nbsp; 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) ====

This color model represents color differences with three channels,
nominally luma (_Y&prime;_) and two color-difference chroma channels,
_U_ (_C~B~_) and _V_ (_C~R~_), supplemented by channels for alpha, depth
and stencil, as shown in <<YUVSDAChannels>>.
These formats are distinguished by _C~B~_ and _C~R~_ being a delta between
the _Y&prime;_ channel and the blue and red channels respectively, rather
than requiring a full color matrix.
The conversion between _Y&prime;C~B~C~R~_ and _RGB_ color spaces is defined
in this case by the choice of value in the *_colorPrimaries_* field as
described in <<MODEL_YUV>>.

NOTE: Most single-channel luma/luminance monochrome data formats should
select *++KHR_DF_MODEL_YUVSDA++* and use only the _Y_ channel, unless there is
a reason to do otherwise.

[[YUVSDAChannels]]
.Basic Data Format _YUVSDA_ channels
[width="100%",options="header"]
|================================
^| Channel number 2+| &nbsp; Name | &nbsp; Description
^| 0 2+| &nbsp; *++KHR_DF_CHANNEL_YUVSDA_Y++* | &nbsp; _Y_/_Y&prime;_ (luma/luminance)
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_YUVSDA_CB++* | &nbsp; _C~B~_ (alias for _U_)
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_YUVSDA_U++* | &nbsp; _U_ (alias for _C~B~_)
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_YUVSDA_CR++* | &nbsp; _C~R~_ (alias for _V_)
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_YUVSDA_V++* | &nbsp; _V_ (alias for _C~R~_)
^| 13 2+| &nbsp; *++KHR_DF_CHANNEL_YUVSDA_STENCIL++* | &nbsp; Stencil
^| 14 2+| &nbsp; *++KHR_DF_CHANNEL_YUVSDA_DEPTH++* | &nbsp; Depth
^| 15 2+| &nbsp; *++KHR_DF_CHANNEL_YUVSDA_ALPHA++* | &nbsp; 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
weighted average of color channels, then calculating color differences by
subtracting two of the color channels from this monochrome value. Proper names
vary for each variant of the ensuing numbers, but _YUV_ is colloquially used
for all of them. In the television standards from which this terminology is
derived, _Y&prime;C~B~C~R~_ is more formally used to describe the representation
of these color differences. See <<MODEL_YUV>> for more detail.

<<<
==== *++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_,
supplemented by channels for alpha, depth and stencil, as shown in
<<YIQSDAChannels>>. This format is distinguished by _I_ and _Q_ each
requiring all three additive channels to evaluate.
_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+| &nbsp; Name | &nbsp; Description
^| 0 2+| &nbsp; *++KHR_DF_CHANNEL_YIQSDA_Y++* | &nbsp; _Y_ (luma)
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_YIQSDA_I++* | &nbsp; _I_ (in-phase)
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_YIQSDA_Q++* | &nbsp; _Q_ (quadrature)
^| 13 2+| &nbsp; *++KHR_DF_CHANNEL_YIQSDA_STENCIL++* | &nbsp; Stencil
^| 14 2+| &nbsp; *++KHR_DF_CHANNEL_YIQSDA_DEPTH++* | &nbsp; Depth
^| 15 2+| &nbsp; *++KHR_DF_CHANNEL_YIQSDA_ALPHA++* | &nbsp; Alpha (opacity)
|================================

==== *++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
shown in <<LABSDAChannels>>.

[[LABSDAChannels]]
.Basic Data Format _LABSDA_ channels
[width="100%",options="header"]
|================================
^| Channel number 2+| &nbsp; Name | &nbsp; Description
^| 0 2+| &nbsp; *++KHR_DF_CHANNEL_LABSDA_L++* | &nbsp; _L_* (luma)
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_LABSDA_A++* | &nbsp; _a_*
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_LABSDA_B++* | &nbsp; _b_*
^| 13 2+| &nbsp; *++KHR_DF_CHANNEL_LABSDA_STENCIL++* | &nbsp; Stencil
^| 14 2+| &nbsp; *++KHR_DF_CHANNEL_LABSDA_DEPTH++* | &nbsp; Depth
^| 15 2+| &nbsp; *++KHR_DF_CHANNEL_LABSDA_ALPHA++* | &nbsp; Alpha (opacity)
|================================

==== *++KHR_DF_MODEL_CMYKA++* (= 5) ====

This color model represents secondary (subtractive) colors and
the combined key (black) channel, along with alpha, as shown in
<<CMYKAChannels>>.

[[CMYKAChannels]]
.Basic Data Format _CMYKA_ channels
[width="100%",options="header"]
|================================
^| Channel number 2+| &nbsp; Name | &nbsp; Description
^| 0 2+| &nbsp; *++KHR_DF_CHANNEL_CMYKA_CYAN++* | &nbsp; Cyan
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_CMYKA_MAGENTA++* | &nbsp; Magenta
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_CMYKA_YELLOW++* | &nbsp; Yellow
^| 3 2+| &nbsp; *++KHR_DF_CHANNEL_CMYKA_KEY++* | &nbsp; Key/Black
^| 15 2+| &nbsp; *++KHR_DF_CHANNEL_CMYKA_ALPHA++* | &nbsp; Alpha (opacity)
|================================

<<<
==== *++KHR_DF_MODEL_XYZW++* (= 6) ====

This ``color model'' represents channel data used for
coordinate values, as shown in <<XYZWChannels>> --
for example, as a representation of the surface normal in
a bump map.
Additional channels for higher-dimensional coordinates can
be used by extending the channel number within the 4-bit limit
of the *_channelType_* field.

[[XYZWChannels]]
.Basic Data Format _XYZW_ channels
[width="100%",options="header"]
|================================
^| Channel number 2+| &nbsp; Name | &nbsp; Description
^| 0 2+| &nbsp; *++KHR_DF_CHANNEL_XYZW_X++* | &nbsp; _X_
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_XYZW_Y++* | &nbsp; _Y_
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_XYZW_Z++* | &nbsp; _Z_
^| 3 2+| &nbsp; *++KHR_DF_CHANNEL_XYZW_W++* | &nbsp; _W_
|================================

==== *++KHR_DF_MODEL_HSVA_ANG++* (= 7) ====

This color model represents color differences with three channels,
_value_ (luminance or luma), _saturation_ (distance from monochrome)
and _hue_ (dominant wavelength), supplemented by an alpha channel,
as shown in <<HSVAAngChannels>>.
In this model, the hue relates to the angular offset on a color
wheel.

[[HSVAAngChannels]]
.Basic Data Format angular _HSVA_ channels
[width="100%",options="header"]
|================================
^| Channel number 2+| &nbsp; Name | &nbsp; Description
^| 0 2+| &nbsp; *++KHR_DF_CHANNEL_HSVA_ANG_VALUE++* | &nbsp; _V_ (value)
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_HSVA_ANG_SATURATION++* | &nbsp; _S_ (saturation)
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_HSVA_ANG_HUE++* | &nbsp; _H_ (hue)
^| 15 2+| &nbsp; *++KHR_DF_CHANNEL_HSVA_ANG_ALPHA++* | &nbsp; Alpha (opacity)
|================================

==== *++KHR_DF_MODEL_HSLA_ANG++* (= 8) ====

This color model represents color differences with three channels,
_lightness_ (maximum intensity), _saturation_ (distance from monochrome)
and _hue_ (dominant wavelength), supplemented by an alpha channel,
as shown in <<HSLAAngChannels>>.
In this model, the hue relates to the angular offset on a color
wheel.

[[HSLAAngChannels]]
.Basic Data Format angular _HSLA_ channels
[width="100%",options="header"]
|================================
^| Channel number 2+| &nbsp; Name | &nbsp; Description
^| 0 2+| &nbsp; *++KHR_DF_CHANNEL_HSLA_ANG_LIGHTNESS++* | &nbsp; _L_ (lightness)
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_HSLA_ANG_SATURATION++* | &nbsp; _S_ (saturation)
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_HSLA_ANG_HUE++* | &nbsp; _H_ (hue)
^| 15 2+| &nbsp; *++KHR_DF_CHANNEL_HSLA_ANG_ALPHA++* | &nbsp; Alpha (opacity)
|================================

<<<
==== *++KHR_DF_MODEL_HSVA_HEX++* (= 9) ====

This color model represents color differences with three channels,
_value_ (luminance or luma), _saturation_ (distance from monochrome)
and _hue_ (dominant wavelength), supplemented by an alpha channel,
as shown in <<HSVAHexChannels>>.
In this model, the hue is generated by interpolation between
extremes on a color hexagon.

[[HSVAHexChannels]]
.Basic Data Format hexagonal _HSVA_ channels
[width="100%",options="header"]
|================================
^| Channel number 2+| &nbsp; Name | &nbsp; Description
^| 0 2+| &nbsp; *++KHR_DF_CHANNEL_HSVA_HEX_VALUE++* | &nbsp; _V_ (value)
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_HSVA_HEX_SATURATION++* | &nbsp; _S_ (saturation)
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_HSVA_HEX_HUE++* | &nbsp; _H_ (hue)
^| 15 2+| &nbsp; *++KHR_DF_CHANNEL_HSVA_HEX_ALPHA++* | &nbsp; Alpha (opacity)
|================================

==== *++KHR_DF_MODEL_HSLA_HEX++* (= 10) ====

This color model represents color differences with three channels,
_lightness_ (maximum intensity), _saturation_ (distance from monochrome)
and hue (dominant wavelength), supplemented by an alpha channel,
as shown in <<HSLAHexChannels>>.
In this model, the hue is generated by interpolation between
extremes on a color hexagon.

[[HSLAHexChannels]]
.Basic Data Format hexagonal _HSLA_ channels
[width="100%",options="header"]
|================================
^| Channel number 2+| &nbsp; Name | &nbsp; Description
^| 0 2+| &nbsp; *++KHR_DF_CHANNEL_HSLA_HEX_LIGHTNESS++* | &nbsp; _L_ (lightness)
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_HSLA_HEX_SATURATION++* | &nbsp; _S_ (saturation)
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_HSLA_HEX_HUE++* | &nbsp; _H_ (hue)
^| 15 2+| &nbsp; *++KHR_DF_CHANNEL_HSLA_HEX_ALPHA++* | &nbsp; Alpha (opacity)
|================================

==== *++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,
_Cg_ (green/purple color difference) and _Co_ (orange/cyan color difference),
supplemented by a channel for alpha, as shown in <<YCoCgAChannels>>.

[[YCoCgAChannels]]
.Basic Data Format _YCoCgA_ channels
[width="100%",options="header"]
|================================
^| Channel number 2+| &nbsp; Name | &nbsp; Description
^| 0 2+| &nbsp; *++KHR_DF_CHANNEL_YCGCOA_Y++* | &nbsp; _Y_
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_YCGCOA_CG++* | &nbsp; _Cg_
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_YCGCOA_CO++* | &nbsp; _Co_
^| 15 2+| &nbsp; *++KHR_DF_CHANNEL_YCGCOA_ALPHA++* | &nbsp; Alpha (opacity)
|================================

<<<
==== *++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
optional representation in ITU-T BT.2020 and described in <<MODEL_YCCBCCRC>>.

[[YCBCCRCChannels]]
.Basic Data Format _Y&prime;~C~C&prime;~BC~C&prime;~RC~_ channels
[width="100%",options="header"]
|================================
^| Channel number 2+| &nbsp; Name | &nbsp; Description
^| 0 2+| &nbsp; *++KHR_DF_CHANNEL_YCCBCCRC_YC++* | &nbsp; latexmath:[$Y'_C$] (luminance)
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_YCCBCCRC_CBC++* | &nbsp; latexmath:[$C'_\mathit{BC}$]
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_YCCBCCRC_CRC++* | &nbsp; latexmath:[$C'_\mathit{RC}$]
^| 13 2+| &nbsp; *++KHR_DF_CHANNEL_YCCBCCRC_STENCIL++* | &nbsp; Stencil
^| 14 2+| &nbsp; *++KHR_DF_CHANNEL_YCCBCCRC_DEPTH++* | &nbsp; Depth
^| 15 2+| &nbsp; *++KHR_DF_CHANNEL_YCCBCCRC_ALPHA++* | &nbsp; Alpha (opacity)
|================================

==== *++KHR_DF_MODEL_ICTCP++* (= 13) ====

This color model represents the ``Constant intensity
_IC~T~C~P~_ color model'' defined as an optional
representation in ITU-T BT.2100 and described in <<MODEL_ICTCP>>.

[[ICTCPChannels]]
.Basic Data Format _IC~T~C~P~_ channels
[width="100%",options="header"]
|================================
^| Channel number 2+| &nbsp; Name | &nbsp; Description
^| 0 2+| &nbsp; *++KHR_DF_CHANNEL_ICTCP_I++* | &nbsp; _I_ (intensity)
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_ICTCP_CT++* | &nbsp; _C~T~_
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_ICTCP_CP++* | &nbsp; _C~P~_
^| 13 2+| &nbsp; *++KHR_DF_CHANNEL_ICTCP_STENCIL++* | &nbsp; Stencil
^| 14 2+| &nbsp; *++KHR_DF_CHANNEL_ICTCP_DEPTH++* | &nbsp; Depth
^| 15 2+| &nbsp; *++KHR_DF_CHANNEL_ICTCP_ALPHA++* | &nbsp; Alpha (opacity)
|================================

<<<
==== *++KHR_DF_MODEL_CIEXYZ++* (= 14) ====

This color model represents channel data used to describe
color coordinates in the <<ciexyz,CIE 1931 XYZ>> coordinate
space, as shown in <<CIEXYZChannels>>.

[[CIEXYZChannels]]
.Basic Data Format CIE _XYZ_ channels
[width="100%",options="header"]
|================================
^| Channel number 2+| &nbsp; Name | &nbsp; Description
^| 0 2+| &nbsp; *++KHR_DF_CHANNEL_CIEXYZ_X++* | &nbsp; _X_
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_CIEXYZ_Y++* | &nbsp; _Y_
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_CIEXYZ_Z++* | &nbsp; _Z_
|================================

==== *++KHR_DF_MODEL_CIEXYY++* (= 15) ====

This color model represents channel data used to describe
chromaticity coordinates in the <<ciexyz,CIE 1931 xyY>> coordinate
space, as shown in <<CIEXYYChannels>>.

[[CIEXYYChannels]]
.Basic Data Format CIE _xyY_ channels
[width="100%",options="header"]
|================================
^| Channel number 2+| &nbsp; Name | &nbsp; Description
^| 0 2+| &nbsp; *++KHR_DF_CHANNEL_CIEXYZ_X++* | &nbsp; _x_
^| 1 2+| &nbsp; *++KHR_DF_CHANNEL_CIEXYZ_YCHROMA++* | &nbsp; _y_
^| 2 2+| &nbsp; *++KHR_DF_CHANNEL_CIEXYZ_YLUMA++* | &nbsp; _Y_
|================================

<<<
[[CompressedFormatModels]]
=== *_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
compression block size. Most contain a single sample of channel type 0
at offset 0,0 -- where further samples are required, they should also
be sited at 0,0. By convention, models which have multiple channels that
are disjoint in memory have these channel locations described
independently as separate samples; this can simplify some decoders.

The ASTC family of formats have a number of possible channels,
and are distinguished by samples which reference some set of these
channels. The *_texelBlockDimension_* fields determine the compression
ratio for ASTC and PVRTC.

Compressed formats necessarily do not have an equivalent integer
representation in which to describe the *_sampleLower_* and
*_sampleUpper_* ranges -- in particular, some have different ranges
on a block-by-block format.
Floating-point compressed formats have lower and upper limits specified
in floating point format, since this representation indicates the output
of compressed decoding.
Integer compressed formats with a lower and upper of 0 and *++UINT32_MAX++*
(for unsigned formats) or *++INT32_MIN++* and *++INT32_MAX++* (for signed
formats) are assumed to map the full representable range to 0..1 or -1..1
respectively.

If a format has a non-linear transfer function, any samples with channel
ID 15 (that is, the format has separate alpha encoding, for example
*++KHR_DF_BC2_ALPHA++*) should set the *++KHR_DF_SAMPLE_DATATYPE_LINEAR++*
bit for that sample.

Example descriptors for compressed formats are provided after each
model in this section.

<<<
==== *++KHR_DF_MODEL_DXT1A++*/*++KHR_DF_MODEL_BC1A++* (= 128) ====

This model represents the DXT1 or BC1 format, described in
<<S3TC>>.
Each compressed texel block consists of 4{times}4 texels in
8 bytes.
A single sample with channel ID 0 indicates that the ``special value''
should be interpreted as black, as described in <<s3tc_bc1_noalpha>>
-- a descriptor block representing this is shown in
<<dxt1a_example_noalpha>>.
A single sample with channel ID 1 indicates that the ``special value''
should represent transparency, as described in <<s3tc_bc1_alpha>>
-- a descriptor block representing this is shown in
<<dxt1a_example_alpha>>.

Enumerant names for these channel ids are listed in <<bc1_channels>>.

[[bc1_channels]]
.BC1A channel names
[options="header"]
|====================
^| Enumerant ^| Value
^| *++KHR_DF_CHANNEL_DXT1A_COLOR++* 1.2+^.^| 0
^| *++KHR_DF_CHANNEL_BC1A_COLOR++*
^| *++KHR_DF_CHANNEL_DXT1A_ALPHAPRESENT++* 1.4+^.^| 1
^| *++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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++DXT1A++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 8
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++DXT1A++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 8
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++ALPHA++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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) ====

This model represents the DXT2/3 format, also known as BC2,
and described in <<s3tc_bc2>>.
Each compressed texel block consists of 4{times}4 texels in
16 bytes.
The alpha premultiplication state (the distinction between DXT2 and DXT3)
is recorded separately in the descriptor in the *_flags_* field.
This model has two channels, recorded as separate samples:
Sample 0 with channel ID 15 contains the alpha information.
Sample 1 with channel ID 0 contains the color information.

Enumerant names for these channel ids are listed in <<bc2_channels>>.

[[bc2_channels]]
.BC2 channel names
[options="header"]
|====================
^| Enumerant ^| Value
^| *++KHR_DF_CHANNEL_DXT2_COLOR++* 1.3+^.^| 0
^| *++KHR_DF_CHANNEL_DXT3_COLOR++*
^| *++KHR_DF_CHANNEL_BC2_COLOR++*
^| *++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.
No attempt is made to describe the 16 alpha samples for this position
independently, since understanding the other channels for any pixel
requires the whole texel block.

.Example DXT2 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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 2) = 56 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++DXT2++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Alpha sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++ALPHA++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Color sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 64
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
|================================

<<<
.Example DXT3 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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 2) = 56 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++PREMULTIPLIED++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++DXT3++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Alpha sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++ALPHA++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Color sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 64
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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) ====

This model represents the DXT4/5 format, also known as BC3,
and described in <<s3tc_bc3>>.
Each compressed texel block consists of 4{times}4 texels in
16 bytes.
The alpha premultiplication state (the distinction between DXT4 and DXT5)
is recorded separately in the descriptor in the *_flags_* field.
This model has two channels, recorded as separate samples:
Sample 0 with channel ID 15 contains the alpha information.
Sample 1 with channel ID 0 contains the color information.

Enumerant names for these channel ids are listed in <<bc3_channels>>.

[[bc3_channels]]
.BC3 channel names
[options="header"]
|====================
^| Enumerant ^| Value
^| *++KHR_DF_CHANNEL_DXT4_COLOR++* 1.3+^.^| 0
^| *++KHR_DF_CHANNEL_DXT5_COLOR++*
^| *++KHR_DF_CHANNEL_BC3_COLOR++*
^| *++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.
No attempt is made to describe the 16 alpha samples for this position
independently, since understanding the other channels for any pixel
requires the whole texel block.

.Example DXT4 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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 2) = 56 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++DXT4++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Alpha sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++ALPHA++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Color sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 64
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
|================================

<<<
.Example DXT5 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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 2) = 56 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++PREMULTIPLIED++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++DXT5++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Alpha sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++ALPHA++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Color sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 64
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
|================================

<<<
==== *++KHR_DF_MODEL_BC4++* (= 131) ====

This model represents the Direct3D BC4 format for single-channel
interpolated 8-bit data, as described in <<rgtc_bc4>>.

Each compressed texel block consists of 4{times}4 texels in
8 bytes.
The model has a single channel of id 0 with offset 0 and length 64 bits.

The enumerant name for this channel id is listed in <<bc4_channel>>.

[[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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++BC4++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 8
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++DATA++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++BC4++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 8
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 1 ^| 0 ^| 0 4+^| *++DATA++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* *++INT32_MIN++*
32+^| *_sampleUpper:_* *++INT32_MAX++*
|================================

<<<
==== *++KHR_DF_MODEL_BC5++* (= 132) ====

This model represents the Direct3D BC5 format for dual-channel
interpolated 8-bit data, as described in <<rgtc_bc5>>.

Each compressed texel block consists of 4{times}4 texels in
16 bytes.
The model has two channels, 0 (red) and 1 (green),
which should have their bit depths and offsets independently described:
the red channel has offset 0 and length 64 bits and the green channel
has offset 64 and length 64 bits.

Enumerant names for these channel ids are listed in <<bc5_channels>>.

[[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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 2) = 56 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++BC5++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Red sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Green sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 64
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 2) = 56 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++BC5++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Red sample information~
^| 0 ^| 1 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* *++INT32_MIN++*
32+^| *_sampleUpper:_* *++INT32_MAX++*
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Green sample information~
^| 0 ^| 1 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 64
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 2) = 56 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++BC5++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Red sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Green sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 64
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
|================================

<<<
==== *++KHR_DF_MODEL_BC6H++* (= 133) ====

This model represents the Direct3D BC6H format for _RGB_ floating-point
data, as described in <<bptc_bc6h>>.

Each compressed texel block consists of 4{times}4 texels in
16 bytes.
The model has a single channel 0, representing all three channels, and
occupying 128 bits.

The enumerant names for this channel id are listed in <<bc6h_channel>>.

[[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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++BC6H++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 1 ^| 1 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 127 (= ``128'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++BC6H++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 1 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 127 (= ``128'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0xBF800000U -- -1.0f
32+^| *_sampleUpper:_* 0x7F800000U -- 1.0f
|================================

<<<
==== *++KHR_DF_MODEL_BC7++* (= 134) ====

This model represents the Direct3D BC7 format for _RGBA_ data, as
described in <<bptc_bc7>>.

Each compressed texel block consists of 4{times}4 texels in
16 bytes.
The model has a single channel 0, representing all four channels, and
occupying 128 bits.

The enumerant names for this channel id are listed in <<bc7_channel>>.

[[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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++BC7++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 127 (= ``128'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
|================================

<<<
==== *++KHR_DF_MODEL_ETC1++* (= 160) ====

This model represents the original Ericsson Texture Compression format,
described in <<ETC1>>, with a guarantee that the format does not rely
on the ETC2 extensions described in <<ETC2>>.

Each compressed texel block consists of 4{times}4 texels in
8 bytes.
The model has a single channel 0, representing all three channels, and
occupying 64 bits.

The enumerant names for this channel id are listed in <<etc1_channel>>.

[[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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++ETC1++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 8
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
|================================

<<<
==== *++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.
Each compressed texel block consists of 4{times}4 texels.

The enumerant names for these channel ids are listed in <<etc2_channels>>.

[[etc2_channels]]
.ETC2 channel names
[options="header"]
|====================
^| Enumerant ^| Value
^| *++KHR_DF_CHANNEL_ETC2_RED++* 1.2+^.^| 0
^| *++KHR_DF_CHANNEL_ETC2_R++*
^| *++KHR_DF_CHANNEL_ETC2_GREEN++* 1.2+^.^| 1
^| *++KHR_DF_CHANNEL_ETC2_G++*
^| *++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 <<Section-r11eac>>; the texel block size in this format
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++ETC2++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 8
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++ETC2++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 8
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 1 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
and green, in that order, indicates the RG11 EAC format as described in
<<Section-rg11eac>>, which consists of a total of 16 bytes of data.

[[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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 2) = 56 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++ETC2++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Red sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Green sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 64
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 2) = 56 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++ETC2++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Red sample information~
^| 0 ^| 1 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* *++INT32_MIN++*
32+^| *_sampleUpper:_* *++INT32_MAX++*
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Green sample information~
^| 0 ^| 1 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 64
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
<<RGBETC2>>.
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++ETC2++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 8
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
|================================

<<<
Channel ID 15 indicates the presence of alpha.
If the texel block size is 8 bytes and the _RGB_ and alpha channels are
co-sited, ``punch through'' alpha is supported as described in
<<RGBETC2_PUNCHTHROUGH>>.

[[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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 56 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++ETC2++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 8
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Color sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Alpha sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++ALPHA++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
first 8 bytes, followed by 8 bytes for the _RGB_ channel, 8-bit separate
alpha is supported, as described in <<RGBAETC2>>.

[[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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 56 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++ETC2++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Alpha sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++ALPHA++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Color sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 64
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
|================================

<<<
==== *++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
LDR (low dynamic range) modes are distinguished by the *_channelId_* containing
the flag *++KHR_DF_SAMPLE_DATATYPE_FLOAT++*: an ASTC texture that is guaranteed by
the user to contain only LDR-encoded blocks should have the *_channelId_*
*++KHR_DF_SAMPLE_DATATYPE_FLOAT++* bit clear, and an ASTC texture that may include
HDR-encoded blocks should have the *_channelId_* *++KHR_DF_SAMPLE_DATATYPE_FLOAT++*
bit set to 1.
ASTC supports a number of compression ratios defined by different texel block
sizes; these are selected by changing the texel block size fields in the data
format.

ASTC encoding is described in <<ASTC>>.

The single sample, of ID 0, has a size of 128 bits.

The enumerant name for this channel id is listed in <<astc_channels>>.

[[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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++ASTC++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++DATA++* 8+^| *_bitLength:_* 127 (= ``128'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++ASTC++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 4 (= ``5'') 8+^| 7 (= ``8'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 1 ^| 1 ^| 0 ^| 0 4+^| *++DATA++* 8+^| *_bitLength:_* 127 (= ``128'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0xBF800000U -- -1.0f
32+^| *_sampleUpper:_* 0x7F800000U -- 1.0f
|================================

<<<
==== *++KHR_DF_MODEL_ETC1S++* (= 163) ====

This model represents a subset of the original Ericsson Texture
Compression format, described in <<ETC1S>>, which is restricted
in order to facilitate image compression.

Each compressed texel block consists of 4{times}4 texels in
8 bytes.
The model has a single channel 0, representing all three channels, and
occupying 64 bits.

The enumerant names for this channel id are listed in <<etc1s_channel>>.

[[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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++ETC1S++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 8
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
|================================

<<<
==== *++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
represents a 4{times}4 texel block; 2-bit-per-pixel mode represents an
8{times}4 texel block, and these can be distinguished by changing the texel
block size fields in the data format. The single sample has a size of 64
bits.

The enumerant names for this channel id are listed in <<pvrtc_channel>>.

[[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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++PVRTC++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 8
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++PVRTC++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 7 (= ``8'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 8
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
|================================

<<<
==== *++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
represents a 4{times}4 texel block; 2-bit-per-pixel mode represents an
8{times}4 texel block, and these can be distinguished by changing the texel
block size fields in the data format. The single sample has a size of 64
bits.

The enumerant names for this channel id are listed in <<pvrtc2_channel>>.

[[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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++PVRTC2++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 3 (= ``4'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 8
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++PVRTC2++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 3 (= ``4'') 8+^| 7 (= ``8'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 8
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++COLOR++* 8+^| *_bitLength:_* 63 (= ``64'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* *++UINT32_MAX++*
|================================

<<<
=== *_colorPrimaries_* ===

It is not sufficient to define a buffer as containing, for example,
additive primaries. Additional information is required to define
what ``red'' is provided by the ``red'' channel. A full definition of
primaries requires an extension which provides the full color space
of the data, but a subset of common primary spaces can be identified
by the *++khr_df_primaries_e++* enumeration, represented as an unsigned 8-bit
integer.

More information about color primaries is provided in <<PRIMARY_CONVERSION>>.

.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) ====

This ``set of primaries'' identifies a data representation whose color
representation is unknown or which does not fit into this list of
common primaries. Having an ``unspecified'' value here precludes users
of this data format from being able to perform automatic color conversion
unless the primaries are defined in another way. Formats which require
a proprietary color space -- for example, raw data from a Bayer sensor
that records the direct response of each filtered sample -- can still
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) ====

This value represents the Color Primaries defined by the
<<bt709,ITU-R BT.709 specification>> and described in <<PRIMARIES_BT709>>,
which are also shared by sRGB.

_RGB_ data is distinguished between BT.709 and sRGB by the Transfer Function.
Conversion to and from BT.709 _Y&prime;C~B~C~R~_ (_YUV_) representation uses the
color conversion matrix defined in the <<bt709,BT.709>> specification, and described
in <<MODEL_BT709>>, except in the case of sYCC (which can be distinguished
by the use of the sRGB transfer function), in which case conversion to and
from BT.709 _Y&prime;C~B~C~R~_ representation uses the color conversion
matrix defined in the <<bt601,BT.601>> specification, and described
in <<MODEL_BT601>>.
This is the preferred set of color primaries used by HDTV and sRGB, and likely
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) ====

This value represents the Color Primaries defined in the
<<bt601,ITU-R BT.601 specification>> for standard-definition television,
particularly for 625-line signals, and described in <<PRIMARIES_BT601_EBU>>.
Conversion to and from BT.601 _Y&prime;C~B~C~R~_ (_YUV_) typically uses the color conversion
matrix defined in the BT.601 specification and described in <<MODEL_BT601>>.

==== *++KHR_DF_PRIMARIES_BT601_SMPTE++* (= 3) ====

This value represents the Color Primaries defined in the
<<bt601,ITU-R BT.601 specification>> for standard-definition television,
particularly for 525-line signals, and described in <<PRIMARIES_BT601_SMPTE>>.
Conversion to and from BT.601 _Y&prime;C~B~C~R~_ (_YUV_) typically uses the color conversion
matrix defined in the BT.601 specification and described in <<MODEL_BT601>>.

==== *++KHR_DF_PRIMARIES_BT2020++* (= 4) ====

This value represents the Color Primaries defined in the
<<bt2020,ITU-R BT.2020 specification>> for ultra-high-definition television
and described in <<PRIMARIES_BT2020>>. Conversion to and from BT.2020 _Y&prime;C~B~C~R~_
(_YUV_ uses the color conversion matrix defined in the BT.2020 specification
and described in <<MODEL_BT2020>>.

==== *++KHR_DF_PRIMARIES_CIEXYZ++* (= 5) ====

This value represents the theoretical Color Primaries defined
by the International Color Consortium for the <<ciexyz,ICC XYZ>> linear
color space.

==== *++KHR_DF_PRIMARIES_ACES++* (= 6) ====

This value represents the Color Primaries defined
for the <<aces,Academy Color Encoding System>> and
described in <<PRIMARIES_ACES>>.

==== *++KHR_DF_PRIMARIES_ACESCC++* (= 7) ====

This value represents the Color Primaries defined
for the <<aces,Academy Color Encoding System>>
compositor and described in <<PRIMARIES_ACESCC>>.

==== *++KHR_DF_PRIMARIES_NTSC1953++* (= 8) ====

This value represents the Color Primaries defined for the
NTSC 1953 color television transmission standard and described
in <<PRIMARIES_NTSC>>.

==== *++KHR_DF_PRIMARIES_PAL525++* (= 9) ====

This value represents the Color Primaries defined for
525-line PAL signals, described in <<PRIMARIES_PAL525>>.

==== *++KHR_DF_PRIMARIES_DISPLAYP3++* (= 10) ====

This value represents the Color Primaries defined for
the Display P3 color space, described in <<PRIMARIES_DISPLAYP3>>.

==== *++KHR_DF_PRIMARIES_ADOBERGB++* (= 11) ====

This value represents the Color Primaries defined in
<<adobergb,Adobe RGB (1998)>>, described in <<PRIMARIES_ADOBERGB>>.

<<<
=== *_transferFunction_* ===

Many color representations contain a non-linear _transfer function_
which maps between a linear (intensity-based) representation and
a more perceptually-uniform encoding; more information is provided
in <<TRANSFER_CONVERSION>>.
Common transfer functions are represented as an unsigned 8-bit integer
and encoded in the enumeration *++khr_df_transfer_e++*.
A fully-flexible transfer function requires an extension with a full
color space definition.
Where the transfer function can be described as a simple power curve,
applying the function is commonly known as ``gamma correction''.
The transfer function is applied to a sample only when the sample's
*++KHR_DF_SAMPLE_DATATYPE_LINEAR++* bit is 0; if this bit is 1, the
sample is represented linearly irrespective of the *_transferFunction_*.

When a color model contains more than one channel in a sample and
the transfer function should be applied only to a subset of those
channels, the convention of that model should be used when applying
the transfer function. For example, ASTC stores both alpha and _RGB_
data but is represented by a single sample; in ASTC, any sRGB transfer
function is not applied to the alpha channel of the ASTC texture.
In this case, the *++KHR_DF_SAMPLE_DATATYPE_LINEAR++* bit being zero means
that the transfer function is ``applied'' to the ASTC sample in a way that
only affects the _RGB_ channels. This is not a concern for most color
models, which explicitly store different channels in each sample.

If all the samples are linear, *++KHR_DF_TRANSFER_LINEAR++* should be used.
In this case, no sample should have the *++KHR_DF_SAMPLE_DATATYPE_LINEAR++*
bit set.
If the samples encode a single bit, *++KHR_DF_TRANSFER_LINEAR++* or
*++KHR_DF_TRANSFER_UNSPECIFIED++* should be used, since there are no
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++*);

The enumerant value for each of the following transfer functions is
shown in parentheses alongside the title.

==== *++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) ====

This value represents a linear transfer function: for color data,
there is a linear relationship between numerical pixel values and
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) ====

This value represents the non-linear transfer function defined in
the <<srgb,sRGB specification>> for mapping between numerical pixel
values and displayed light intensity, as described in <<TRANSFER_SRGB>>.

[width="60%",cols="^8,^2,^3"]
|==========
| Mapping from linear intensity to encoding | EOTF^&nbsp;-1^ | <<TRANSFER_SRGB_INVEOTF>>
| Mapping from encoding to linear intensity | EOTF | <<TRANSFER_SRGB_EOTF>>
|==========

Encoded values outside the range 0..1 use the extended formulae
for EOTF and EOTF^-1^ described in <<TRANSFER_SCRGB_EOTF>>.

==== *++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
for mapping between represented scene light intensity and numerical
pixel values, as described in <<TRANSFER_ITU>>.

[width="60%",cols="^8,^2,^3"]
|==========
| Mapping from linear intensity to encoding | OETF | <<TRANSFER_ITU_OETF>>
| Mapping from encoding to linear intensity | OETF^&nbsp;-1^ | <<TRANSFER_ITU_INVOETF>>
|==========

==== *++KHR_DF_TRANSFER_NTSC++* (= 4) ====

This value represents the non-linear transfer function defined by
the original NTSC television broadcast specification for mapping
between represented scene light intensity or display light intensity
and numerical pixel values, as described in <<TRANSFER_LEGACY_NTSC>>.

[width="60%",cols="^8,^4"]
|==========
| Mapping from linear intensity to encoding | EOTF^&nbsp;-1^ / OETF
| Mapping from encoding to linear intensity | EOTF / OETF^&nbsp;-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) ====

This value represents a nonlinear Transfer Function between linear
scene light intensity and nonlinear pixel values, used by some
Sony video cameras to represent an increased dynamic range,
and is described in <<TRANSFER_SLOG>>.

[width="60%",cols="^8,^2"]
|==========
| Mapping from linear intensity to encoding | OETF
| Mapping from encoding to linear intensity | OETF^&nbsp;-1^
|==========

==== *++KHR_DF_TRANSFER_SLOG2++* (= 6) ====

This value represents a nonlinear Transfer Function between linear
scene light intensity and nonlinear pixel values, used by some
Sony video cameras to represent a further increased dynamic range,
and is described in <<TRANSFER_SLOG2>>.

[width="60%",cols="^8,^2"]
|==========
| Mapping from linear intensity to encoding | OETF
| Mapping from encoding to linear intensity | OETF^&nbsp;-1^
|==========

==== *++KHR_DF_TRANSFER_BT1886++* (= 7) ====

This value represents the nonlinear latexmath:[$\gamma = 2.4$]
EOTF between encoded pixel values and linear image intensity defined
in <<bt1886,BT.1886>> and described in <<TRANSFER_BT1886>>.

[width="70%",cols="^8,^2,^5"]
|==========
| Mapping from linear intensity to encoding | EOTF^&nbsp;-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) ====

This value represents the Hybrid Log Gamma OETF between linear
scene light intensity and nonlinear pixel values, defined by the
ITU in BT.2100 for high dynamic range television, and described
in <<TRANSFER_HLG>>.

[width="60%",cols="^8,^2,^3"]
|==========
| Mapping from linear intensity to encoding | OETF | <<TRANSFER_HLG_OETF_NORM>>
| Mapping from encoding to linear intensity | OETF^&nbsp;-1^ | <<TRANSFER_HLG_IOETF_NORM>>
|==========

==== *++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
in BT.2100 for high dynamic range television, and described in
<<TRANSFER_HLG>>.

[width="60%",cols="^8,^2,^3"]
|==========
| Mapping from linear intensity to encoding | EOTF^&nbsp;-1^ | <<TRANSFER_HLG_IEOTF_NORM>>
| Mapping from encoding to linear intensity | EOTF | <<TRANSFER_HLG_EOTF_NORM>>
|==========

==== *++KHR_DF_TRANSFER_PQ_EOTF++* (= 10) ====

This value represents the Perceptual Quantization EOTF between
nonlinear pixel values and linear image light intensity, defined
by the ITU in BT.2100 for high dynamic range television, and
described in <<TRANSFER_PQ>>.

[width="60%",cols="^8,^2,^3"]
|==========
| Mapping from linear intensity to encoding | EOTF^&nbsp;-1^ | <<TRANSFER_PQ_IEOTF>>
| Mapping from encoding to linear intensity | EOTF | <<TRANSFER_PQ_EOTF>>
|==========

==== *++KHR_DF_TRANSFER_PQ_OETF++* (= 11) ====

This value represents the Perceptual Quantization OETF between
linear scene light intensity and nonlinear pixel values, defined
by the ITU in BT.2100 for high dynamic range television, and
described in <<TRANSFER_PQ>>.

[width="60%",cols="^8,^2,^3"]
|==========
| Mapping from linear intensity to encoding | OETF | <<TRANSFER_PQ_OETF>>
| Mapping from encoding to linear intensity | OETF^&nbsp;-1^ | <<TRANSFER_PQ_IOETF>>
|==========

==== *++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 <<TRANSFER_DCIP3>>.

[width="60%",cols="^8,^2"]
|==========
| Mapping from linear intensity to encoding | EOTF^&nbsp;-1^
| Mapping from encoding to linear intensity | EOTF
|==========

<<<
==== *++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 <<TRANSFER_LEGACY_PAL_OETF>>.

[width="60%",cols="^8,^2"]
|==========
| Mapping from linear intensity to encoding | OETF
| Mapping from encoding to linear intensity | OETF^&nbsp;-1^
|==========

==== *++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 <<TRANSFER_LEGACY_PAL_EOTF>>.

[width="60%",cols="^8,^2"]
|==========
| Mapping from linear intensity to encoding | EOTF^&nbsp;-1^
| Mapping from encoding to linear intensity | EOTF
|==========

==== *++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 <<TRANSFER_ST240>>.

[width="60%",cols="^8,^4"]
|==========
| Mapping from linear intensity to encoding | EOTF^&nbsp;-1^ / OETF
| Mapping from encoding to linear intensity | EOTF / OETF^&nbsp;-1^
|==========

==== *++KHR_DF_TRANSFER_ACESCC++* (= 16) ====

This value represents the nonlinear transfer function between
linear scene light intensity and nonlinear pixel values used in
the ACEScc Academy Color Encoding System logarithmic encoding system
for use within Color Grading Systems, S-2014-003, defined in
<<aces,ACES>>. This is described in <<TRANSFER_ACESCC>>.

[width="60%",cols="^8,^2"]
|==========
| Mapping from linear intensity to encoding | OETF
| Mapping from encoding to linear intensity | OETF^&nbsp;-1^
|==========

==== *++KHR_DF_TRANSFER_ACESCCT++* (= 17) ====

This value represents the nonlinear transfer function between
linear scene light intensity and nonlinear pixel values used in
the ACEScc Academy Color Encoding System quasi-logarithmic encoding
system for use within Color Grading Systems, S-2016-001, defined in
<<aces,ACES>>. This is described in <<TRANSFER_ACESCCT>>.

[width="60%",cols="^8,^2"]
|==========
| Mapping from linear intensity to encoding | OETF
| Mapping from encoding to linear intensity | OETF^&nbsp;-1^
|==========

==== *++KHR_DF_TRANSFER_ADOBERGB++* (= 18) ====

This value represents the transfer function defined in the
Adobe RGB (1998) specification and described in <<TRANSFER_ADOBERGB>>.

<<<
=== *_flags_* ===

The format supports some configuration options in the form of
boolean flags; these are described in the enumeration
*++khr_df_flags_e++* and represented in an unsigned 8-bit integer value.

.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) ====

If the *++KHR_DF_FLAG_ALPHA_PREMULTIPLIED++* bit is set, any color
information in the data should be interpreted as having been
previously scaled/modulated by the alpha channel when performing
blending operations.

The value *++KHR_DF_FLAG_ALPHA_STRAIGHT++* (= 0) is provided
to represent this flag not being set, which indicates that color
values in the data should be interpreted as needing to be scaled
by the alpha channel when performing blending operations.
This flag has no effect if there is no alpha channel in the format.

<<<

=== *_texelBlockDimension[0..3]_* ===

The *_texelBlockDimension_* fields define an integer bound on the range
of coordinates covered by the repeating block described by the samples;
that is, the texel block covers an integer range in each dimension of
coordinate space.
Four separate values, represented as unsigned 8-bit integers, are
supported, corresponding to successive dimensions: the Basic Data Format
Descriptor Block supports up to four dimensions of encoding within a
texel block, supporting, for example, a texture with three spatial
dimensions and one temporal dimension.
Nothing stops the data structure as a whole from having higher
dimensionality: for example, a two-dimensional texel block can be used
as an element in a six-dimensional look-up table.

The value held in each of these fields is one fewer than the
size of the block in that dimension -- that is, a value of 0
represents a size of 1, a value of 1 represents a size of 2,
etc. A texel block which covers fewer than four dimensions
should have a size of 1 in each dimension that it lacks,
and therefore the corresponding fields in the representation
should be 0.

For example, a _Y&prime;C~B~C~R~_ 4:2:0 representation may use a Texel Block
of 2×2 pixels in the nominal coordinate space, corresponding to
the four _Y&prime;_ samples, as shown in <<YUV420Basic>>.
The texel block dimensions in this case
would be 2×2×1×1 (in the X, Y, Z and T dimensions, if the fourth
dimension is interpreted as T). The *_texelBlockDimension[0..3]_*
values would therefore be:

[[YUV420Basic]]
.Example Basic Data Format *_texelBlockDimension_* values for _Y&prime;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
*_texelBlockDimension_* field, but with the represented number in parentheses
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
^| *++KHR_DF_SHIFT_TEXELBLOCKDIMENSION1++* ^| 8
^| *++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++*);

*++uint32_t++* *_texelBlockDimension1_* = *++KHR_DF_MASK_TEXELBLOCKDIMENSION1++* & +
(++bdb++[*++KHR_DF_WORD_TEXELBLOCKDIMENSION1++*] >> *++KHR_DF_SHIFT_TEXELBLOCKDIMENSION1++*);

*++uint32_t++* *_texelBlockDimension2_* = *++KHR_DF_MASK_TEXELBLOCKDIMENSION2++* & +
(++bdb++[*++KHR_DF_WORD_TEXELBLOCKDIMENSION2++*] >> *++KHR_DF_SHIFT_TEXELBLOCKDIMENSION2++*);

*++uint32_t++* *_texelBlockDimension3_* = *++KHR_DF_MASK_TEXELBLOCKDIMENSION3++* & +
(++bdb++[*++KHR_DF_WORD_TEXELBLOCKDIMENSION3++*] >> *++KHR_DF_SHIFT_TEXELBLOCKDIMENSION3++*);

<<<
=== *_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.
The requirement that planes consist of consecutive data means that
formats with distinct subsampled channels -- such as _Y&prime;C~B~C~R~_
4:2:0 -- may require multiple planes to describe a channel.
A typical _Y&prime;C~B~C~R~_ 4:2:0 image has _two_ planes for the
_Y&prime;_ channel in this representation, offset by one line vertically.

The use of byte granularity to define planes is a choice to allow large
texel blocks.
A consequence of this is that formats which are not byte-aligned on each
addressable unit, such as 1-bit-per-pixel formats, need to represent a
texel block of multiple samples, covering multiple texels -- as, for
example, in <<exampledescriptor_1bpp>>.

A maximum of eight independent planes is supported in the Basic Data
Format Descriptor. Formats which require more than eight planes --
which are rare -- require an extension.

The *_bytesPlane[0..7]_* fields each contain an unsigned 8-bit integer
which represents the number of bytes which a plane contributes to the
format.
If the top bit of a *_bytesPlane[n]_* field is set, bits 6..0 of the
*_bytesPlane[n{plus}1]_* field form bits 13..7 of the number of bytes in
the plane (and the next plane is described by field *_bytesPlane[n{plus}2]_*).
For example, if *_bytesPlane0_* is 0xC0 and *_bytesPlane1_* is 0x02,
the first plane holds 0x40 {plus} 128 {times} 0x02 = 0x140 bytes;
*_bytesPlane2_* then describes the number of bytes in the second plane..
Since only sixteen bits are used to encode a bit offset for each sample,
14 bits (two bytes excluding the top bits) are sufficient to encode any
useful number of bytes -- there is no need to ``extend'' the higher byte.
Few formats are expected to require this ``extension bit'', so for
most of this specification, the number of bytes in a plane is considered
to be synonymous with the *_bytesPlane_* value.

The first field which contains the value 0 indicates
that only a subset of the 8 possible planes are present; that is,
planes which are not present should be given the *_bytesPlane_* value
of 0, and any *_bytesPlane_* values after the first 0 are ignored. If
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
^| *++KHR_DF_WORD_BYTESPLANE[4..7]++* {plus} 1 ^| 6
1.8+^.^| Start bit within word ^| *++KHR_DF_SHIFT_BYTESPLANE0++* ^| 0
^| *++KHR_DF_SHIFT_BYTESPLANE1++* ^| 8
^| *++KHR_DF_SHIFT_BYTESPLANE2++* ^| 16
^| *++KHR_DF_SHIFT_BYTESPLANE3++* ^| 24
^| *++KHR_DF_SHIFT_BYTESPLANE4++* ^| 0
^| *++KHR_DF_SHIFT_BYTESPLANE5++* ^| 8
^| *++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]++*);

NOTE: In versions of this specification prior to 1.3, there was no
facility for the ``extension bit'', and a *_bytesPlane0_*  value of
0 indicated a paletted format.
The scheme for encoding paletted formats as of version 1.3 is
described in <<PALETTED>>.

<<<
=== [[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
channel of data and with a single corresponding position within
the texel block, as shown in <<SampleOverview>>.

[[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.
Each sample occupies *++KHR_DF_WORD_SAMPLEWORDS++* = 4 32-bit words,
and is stored consecutively.

The bytes from the plane data contributing to the format are
treated as though they have been concatenated into a bit stream,
with the first byte of the lowest-numbered plane providing the
lowest bits of the result.
Each sample consists of a number of consecutive bits from this bit
stream.

If the content for a channel cannot be represented in a single
sample, for example because the data for a channel is
non-consecutive within this bit stream, additional samples with
the same coordinate position and channel number should follow
from the first, in order increasing from the least significant
bits from the channel data; the corresponding bits from the
bit stream are concatenated in the increasing order of reference
to provide the value representing the channel.

For example, some native big-endian formats may need to be supported
with multiple samples in a channel, since the constituent bits may
not be consecutive in a little-endian interpretation.
There is an example, <<exampledescriptor_bigendian>>, in the list
of example format descriptors provided.

See <<Canonical>> for more information about the order in which
samples should appear in the descriptor block.

The number of samples present in the format is determined by the
*_descriptorBlockSize_* field:

*_numSamples_* = +
(((*++KHR_DFDVAL++*(++BDB++, *++DESCRIPTORBLOCKSIZE++*) >> 2) - *++KHR_DF_WORD_SAMPLESTART++*) +
/ *++KHR_DF_WORD_SAMPLEWORDS++*);

The macro *++KHR_DFDSAMPLECOUNT++*(++BDB++) is provided to perform
this calculation.

There is no limit on the number of samples which may be present,
other than the maximum size of the Data Format Descriptor Block.
There is no requirement that samples should access unique parts of
the bit-stream: formats such as combined intensity and alpha, or
shared exponent formats, require that bits be reused.
Nor is there a requirement that all the bits in a plane be used
(a format may contain padding).

It is unusual but legal for a descriptor block to contain no
samples provided the color model is *++KHR_DF_MODEL_UNSPECIFIED++*.
See <<UNSIZED>> for details.

<<<
To simplify code using the Basic Data Format Descriptor Block, the
header ++khr_df.h++ provides enums of the following form for accessing
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:

*_xxx_* = *++KHR_DF_SAMPLEMASK_xxx++* & +
(++bdb++[*++KHR_DF_WORD_SAMPLESTART++* {plus} _sample_ {times} *++KHR_DF_WORD_SAMPLEWORDS++* +
{plus} *++KHR_DF_SAMPLEWORD_xxx++*] >> *++KHR_DF_SAMPLESHIFT_xxx++*);

The macro *++KHR_DFDSVAL++*(++BDB++, ++S++, ++X++) is provided to perform this
calculation.

For example, *++KHR_DFDSVAL++*(++bdb++, 2, *++CHANNELID++*) returns the value:

*++KHR_DF_SAMPLEMASK_CHANNELID++* & +
(++bdb++[*++KHR_DF_WORD_SAMPLESTART++* {plus} 2 {times} *++KHR_DF_WORD_SAMPLEWORDS++* +
{plus} *++KHR_DF_SAMPLEWORD_CHANNELID++*] >> *++KHR_DF_SAMPLESHIFT_CHANNELID++*)

<<<
=== Sample *_bitOffset_* ===

The *_bitOffset_* field describes the offset of the least significant
bit of this sample from the least significant bit of the least
significant byte of the concatenated bit stream for the format.
Typically the *_bitOffset_* of the first sample is therefore 0; a sample
which begins at an offset of one byte relative to the data format
would have a *_bitOffset_* of 8.
The *_bitOffset_* is an unsigned 16-bit integer quantity.

In the special case that the *_bitOffset_* field contains the reserved
value 0xFFFF, the sample contributes a constant value of the specified bit
length, encoded in the *_sampleLower_* field.
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_* ===

The *_bitLength_* field describes the number of consecutive bits from
the concatenated bit stream that contribute to the sample. This field
is an unsigned 8-bit integer quantity, and stores the number of bits
contributed minus 1; thus a single-byte channel should have a *_bitLength_*
field value of 7. If a *_bitLength_* of more than 256 is required, further
samples should be added; the value for the sample is composed in
increasing order from least to most significant bit as subsequent
samples are processed.

Note that a large *_bitLength_* value means a sample can encode more
bits than can be described in the *_sampleLower_* and *_sampleUpper_*
fields.
If the rules for expanding the *_sampleLower_* and *_sampleUpper_*
values in this case produce the desired result, *_bitLength_* can exceed
32; otherwise the *_bitLength_* should be limited and multiple samples
used to encode *_sampleLower_* and *_sampleUpper_*: there is no way to
indicate a sample contribution of zero bits for a sample that exists only
to expand upon *_sampleLower_* and *_sampleUpper_*.

Except in the case of a paletted texture (described in <<PALETTED>>) or
where the special *_bitOffset_* value 0xFFFF is used to indicate constant bits,
the *_bitLength_* added to *_bitOffset_* should not be greater than eight
times the total number of bytes contributed to the logical bit stream by
the *_bytesPlane_* values.

In the descriptor block examples in this specification, bit lengths are
shown as the value to be stored in the *_bitLength_* field, but with the
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 ===

The *_channelType_* field is an unsigned 8-bit quantity.

The bottom four bits of the *_channelType_* indicates which channel is being
described by this sample. The list of available channels is determined by
the *_colorModel_* field of the Basic Data Format Descriptor Block, and the
*_channelType_* field contains the number of the required channel within this
list -- see the <<COLORMODEL,*_colorModel_*>> field for the list of channels
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++*) +
{plus} *++KHR_DF_SAMPLEWORD_CHANNELID++*]) >> *++KHR_DF_SAMPLESHIFT_CHANNELID++*);

The top four bits of the *_channelType_* are described by the
*++khr_df_sample_datatype_qualifiers_e++* enumeration:

.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++*) +
{plus} *++KHR_DF_SAMPLEWORD_QUALIFIERS++*]) >> *++KHR_DF_SAMPLESHIFT_QUALIFIERS++*);

If the *++KHR_DF_SAMPLE_DATATYPE_EXPONENT++* bit, shown as *_E_* in
<<SampleOverview>>, is not set, the sample contributes to a _base value_;
multiple samples with the same color channel (bottom four bits of
*_channelType_*) and same *_samplePos_* values are accumulated into
the virtual sample in increasing bit order from lowest to highest.

For samples in which the *++KHR_DF_SAMPLE_DATATYPE_EXPONENT++* bit is not set:

* If the *++KHR_DF_SAMPLE_DATATYPE_LINEAR++* bit, shown as *_L_* in
  <<SampleOverview>>, is not set, the final sample value (after any
  modifier has been applied to the base value) is modified by the
  transfer function defined in the *_transferFunction_* field  of the
  descriptor; if this bit _is_ set, the sample is considered to
  contain a linearly-encoded value irrespective of the format's
  *_transferFunction_*.
  All samples referring to the same base value should have the same
  value stored in the *++KHR_DF_SAMPLE_DATATYPE_LINEAR++* bit.

* If the *++KHR_DF_SAMPLE_DATATYPE_SIGNED++* bit, shown as *_S_* in
  <<SampleOverview>>, is set, the sample holds a signed value in two's
  complement form.
  If this bit is _not_ set, the sample holds an unsigned value.
  It is possible to represent a sign/magnitude integer value by having a
  sample of unsigned integer type with the same channel and sample location,
  as a 1-bit signed sample.

* If the *++KHR_DF_SAMPLE_DATATYPE_FLOAT++* bit, shown as *_F_* in
  <<SampleOverview>>, is set, the sample holds floating point data in a
  conventional format of 10, 11 or 16 bits, as described in <<fpformats>>,
  or of 32, or 64 bits as described in <<IEEE 754>>.
  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
  multiple samples and a combination of signed integer, unsigned integer
  and exponent fields, as described above and in <<customfp>>.

<<<
If the *++KHR_DF_SAMPLE_DATATYPE_EXPONENT++* bit, shown as *_E_* in
<<SampleOverview>>, _is_ set, the sample applies a _modifier_ to the base
value, with the interpretation of the modifier determined according to
<<exponentqualifiers>>.
In this case, the virtual sample contains both a base value and
a modifier.

All samples contributing to a modifier for the same base value should
contain the same *_L_* and *_F_* bits (it is not legal, for example, to
define both a multiplier and a divisor).
Samples which apply a modifier should directly follow the samples that
describe the base value.
If no samples have the *_E_* bit set for this channel and position, the
base value directly represents the pixel value; it is not legal for
a virtual sample to describe a modifier but no base value.

NOTE: The same bits of the format may contribute to modifiers for
more than one channel -- this is commonly the case for high dynamic range
formats with a shared exponent or divisor.
The descriptor in this case should contain samples for each color channel
in turn, with the description of the shared bits replicated for each
channel, as shown in <<exampledescriptor_r9g9b9e5>>.

[[exponentqualifiers]]
.Qualifier interpretation when *++KHR_DF_SAMPLE_DATATYPE_EXPONENT++* = 1
[cols="^1,^1,^1,4,^5", width="50%"]
|===========
| *_E_* | *_L_* | *_F_* |&nbsp; *Interpretation* | *Formula*
| 1 | 0 | 0 |&nbsp; Exponent | latexmath:[$\mathit{base\ value}\times 2^\mathit{modifier}$]
| 1 | 0 | 1 |&nbsp; Multiplier | latexmath:[$\mathit{base\ value}\times\mathit{modifier}$]
| 1 | 1 | 0 |&nbsp; Divisor | latexmath:[$\mathit{base\ value}\over\mathit{modifier}$]
| 1 | 1 | 1 |&nbsp; Power | latexmath:[$\mathit{base\ value}^\mathit{modifier}$]
|===========

For samples in which the *++KHR_DF_SAMPLE_DATATYPE_EXPONENT++* bit is set:

* If the *++KHR_DF_SAMPLE_DATATYPE_LINEAR++* and
  *++KHR_DF_SAMPLE_DATATYPE_FLOAT++* bits are clear, this modifier holds
  an exponent (in integer form) describing a floating-point offset for
  this channel.
  For example, this would be used to describe the exponent of a custom
  floating point format, as shown in <<exampledescriptor_float16explicit>>,
  or a shared exponent location in shared exponent formats (with the
  exponent bits listed separately under each channel as shown in
  <<exampledescriptor_r9g9b9e5>>).
  If this modifer is used, the base value is considered to contain
  mantissa information and the samples describing it would not normally
  have the *++KHR_DF_SAMPLE_DATATYPE_FLOAT++* bit set.
  If the *++KHR_DF_SAMPLE_DATATYPE_SIGNED++* bit (*_S_*) is also set,
  the exponent is considered to be two's complement -- otherwise it is
  treated as unsigned.
  The bias of the exponent can be determined by the exponent's
  *_sampleLower_* value.
  The presence or absence of an implicit leading digit in the mantissa of
  a format with an exponent can be determined by the *_sampleUpper_* value
  of the mantissa.
  The use of the exponent is described in more detail in <<customfp>>.

* If the *++KHR_DF_SAMPLE_DATATYPE_FLOAT++* bit is set and the
  *++KHR_DF_SAMPLE_DATATYPE_LINEAR++* bit is clear, this sample holds
  a multiplier (in integer form) for this channel, such that the encoded
  value is a product of this modifier value and the base value.
  This approach is useful for encoding a shared multiplier as part of
  a high dynamic range color image, for example.

* If the *++KHR_DF_SAMPLE_DATATYPE_LINEAR++* bit is set and the
  *++KHR_DF_SAMPLE_DATATYPE_FLOAT++* bit is clear, this sample holds
  a divisor (in integer form) for this channel, such that the encoded
  value is the base value divided by this modifier value.
  This approach is useful for encoding a shared divisor as part of
  a high dynamic range color image, for example.

* If both *++KHR_DF_SAMPLE_DATATYPE_FLOAT++* and
  *++KHR_DF_SAMPLE_DATATYPE_LINEAR++* are set, this sample holds
  a power term (in integer form) for this channel, such that the encoded
  value is the base value raised to the power of the modifier value.
  This approach is useful for encoding a shared multiplier as part of
  a high dynamic range color image, for example.

Note that in the multiplier, divisor and power cases, the
*_sampleLower_* and *_sampleUpper_* values allow the modifier value
to be represented in fixed-point terms, and the values may be signed
depending on whether the *_S_* bit is set.

<<<
=== *_samplePosition[0..3]_* ===

The sample has an associated location within the 4-dimensional space of
the texel block.
Therefore each sample has an offset relative to the 0,0 position
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++*) +
{plus} *++KHR_DF_SAMPLEWORD_SAMPLEPOSITION0++*]) >> *++KHR_DF_SAMPLESHIFT_SAMPLEPOSITION0++*);

*++khr_df_model_channels_e++* *_samplePosition1_* = *++KHR_DF_SAMPLEMASK_SAMPLEPOSITION1++* & +
((++bdb++[*++KHR_DF_WORD_SAMPLESTART++* {plus} (_sample_ {times} *++KHR_DF_WORD_SAMPLEWORDS++*) +
{plus} *++KHR_DF_SAMPLEWORD_SAMPLEPOSITION1++*]) >> *++KHR_DF_SAMPLESHIFT_SAMPLEPOSITION1++*);

*++khr_df_model_channels_e++* *_samplePosition2_* = *++KHR_DF_SAMPLEMASK_SAMPLEPOSITION2++* & +
((++bdb++[*++KHR_DF_WORD_SAMPLESTART++* {plus} (_sample_ {times} *++KHR_DF_WORD_SAMPLEWORDS++*) +
{plus} *++KHR_DF_SAMPLEWORD_SAMPLEPOSITION2++*]) >> *++KHR_DF_SAMPLESHIFT_SAMPLEPOSITION2++*);

*++khr_df_model_channels_e++* *_samplePosition3_* = *++KHR_DF_SAMPLEMASK_SAMPLEPOSITION3++* & +
((++bdb++[*++KHR_DF_WORD_SAMPLESTART++* {plus} (_sample_ {times} *++KHR_DF_WORD_SAMPLEWORDS++*) +
{plus} *++KHR_DF_SAMPLEWORD_SAMPLEPOSITION3++*]) >> *++KHR_DF_SAMPLESHIFT_SAMPLEPOSITION3++*);

The interpretation of each *_samplePosition_* field depends on the
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}$].
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}$].
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''.

The adjusted _coordinateOffset_ must be less than the corresponding
texel block dimension.
That is, since _coordinateOffset_ can represent fractional offsets,
_coordinateOffset_ < (*_texelBlockDimension_* {plus} 1) for each
dimension.

This approach allows the common situation of downsampled channels to
have samples conceptually sited at the midpoint between full resolution
samples.
The direction of the sample offsets is determined by the coordinate
addressing scheme used by the API.
There is no limit on the dimensionality of the data, but if more than
four dimensions need to be contained within a single texel block, an
extension will be required.

It is legal, but unusual, to use the same bits to represent multiple
samples at different coordinate locations.

NOTE: Versions of this specification prior to 1.3 always recorded the
sample position in a 7.1 fixed-point format (with half-coordinate
granularity).
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_* ===

The *_sampleLower_* and *_sampleUpper_* fields are used to define
the mapping between the numerical value stored in the format and the
conceptual numerical interpretation.

For unsigned formats, *_sampleLower_* typically represents the value
which should be interpreted as zero (the black point).
For signed formats, *_sampleLower_* typically represents ``-1''.
For color difference models such as _Y&prime;C~B~C~R~_, *_sampleLower_*
for chroma channels represents the lower extent of the color difference
range (which corresponds to an encoding of -0.5 in numerical terms).

*_sampleUpper_* typically represents the value which should be interpreted
as ``1.0'' (the ``white point'').
For color difference models such as _Y&prime;C~B~C~R~_, *_sampleUpper_*
for chroma channels represents the upper extent of the color difference
range (which corresponds to an encoding of 0.5 in numerical terms).

[[sampleRangeConversion]]
.Sample range conversion rules
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
the _Y&prime;_ value stored in an 8-bit encoding should fall between
the range 16 and 235, as described in <<QUANTIZATION_NARROW>>.
In this case, *_sampleLower_* should contain the value 16 and
*_sampleUpper_* 235.

Sensor data from a camera typically does not cover the full range of
the bit depth used to represent it. *_sampleUpper_* can be used to specify
an upper limit on sensor brightness -- or to specify the value which should
map to white on the display, which may be less than the full dynamic range
of the captured image.

There is no guarantee or expectation that image data be guaranteed to
fall between *_sampleLower_* and *_sampleUpper_* unless the users of a
format agree that convention.
For example, high dynamic range video formats may define ``1.0'' as a
nominal brightness level substantially lower than the maximum, and
coordinates may encode an arbitrary range.
In some formats, the integer value should be interpreted directly
as a number, in which case *_sampleUpper_* and *_sampleLower_* should
hold ``1'' and either ``0'' or ``-1'' depending on whether the format
is signed, respectively.

If the channel encoding is an integer format, the *_sampleLower_* and
*_sampleUpper_* values are represented as 32-bit integers -- signed or
unsigned according to whether the channel encoding is signed.
Signed negative values should be sign-extended if the channel has fewer
than 32 bits, such that the value encoded in *_sampleLower_* and
*_sampleUpper_* values are themselves negative if the encoded values
are negative.
If the channel encoding is a floating point value, the *_sampleLower_*
and *_sampleUpper_* values are also described in floating point.

If the number of bits in the sample is greater than 32, *_sampleLower_*
and *_sampleUpper_* are converted to a data type of the actual number
of bits as follows:
A floating point value is converted to the native representation (for
example, a ++float++ value is converted to ++double++ in the normal way).
An integer value is expanded by preserving any sign bit and replicating
the top non-sign bit (for example, signed 0x80000000 is extended to
the 40-bit value 0x8000000000).
If these rules do not produce the desired result, it may be necessary
to describe the contribution to the channel in multiple samples of
no more than 32 bits.
In this case, the samples corresponding to lower *_bitOffset_* values
should occupy 32 bits, with any residual bits encoded in samples
corresponding to higher *_bitOffset_* values.

<<<
If multiple samples contribute to a single value, for example because
the bits of a channel are non-contiguous in the logical bit stream,
the *_sampleLower_* and *_sampleUpper_* fields of each sample are
concatenated in increasing bit order to produce virtual *_sampleLower_*
and *_sampleUpper_* values; each sample contributes a number of bits
equal to the number of data bits that the sample describes.
If this contribution is fewer than 32 bits and the value being encoded
is signed, the sign bit of the final *_sampleLower_* and *_sampleUpper_*
values should be used to pad the fields of the sample.

For example, if a signed 16-bit value with a minimum value of -32767
(0xFFFE) is described as two 8-bit values, the first sample should have
a *_sampleLower_* value of 0xFFFFFFFE -- of which the bottom 8 bits
(0xFE) corresponds to the bottom 8 bits of the final minimum value and
the upper 24 bits (0xFFFFFF00) are a result of replicating the sign of
bit 15 of the final minimum value.
The second sample should have a *_sampleLower_* value of 0xFFFFFFFF
-- of which the bottom 8 bits (0xFF) correspond to the top 8 bits of
the final minimum value and the upper 24 bits (0xFFFFFF00) are a result
of sign-extending this value.
Only the sample corresponding to the top bits of the channel may have a
*_sampleLower_* or *_sampleUpper_* occupying more bits than the input.

The *_sampleLower_* value for an exponent should represent the exponent
bias -- the value that should be subtracted from the encoded exponent
to indicate that the mantissa's *_sampleUpper_* value will represent 1.0.
The *_sampleUpper_* value for an exponent should represent the largest
conventional legal exponent value.
If the encoded exponent exceeds this value, the encoded floating point
value encodes either an infinity or a _NaN_ value, depending on the
mantissa.
See <<customfp>> for more detail on this.

If the channel encoding is the mantissa of a custom floating point
format (that is, the encoding is integer but the same sample location
and channel is shared by a sample that encodes an exponent), the
presence of an implicit ``1'' digit can be represented by setting the
*_sampleUpper_* value to a value one larger than can be encoded in the
available bits for the mantissa, as described in <<customfp>>.

In OpenGL terminology, a ``normalized'' channel contains an integer value
which is mapped to the range 0..1.0; a channel which is not normalized
contains an integer value which is mapped to a floating point equivalent
of the integer value.
Similarly an ``snorm'' channel is a signed normalized value mapping from
-1.0 to 1.0.
Setting *_sampleLower_* to the minimum signed integer value representable
in the channel (which is often the negative version of the maximum signed
integer, for example -127 rather than -128 for an 8-bit value in order to
allow the value 0.0 to be represented exactly) is equivalent to defining
an ``snorm'' texture.
Setting *_sampleUpper_* to the maximum signed integer value representable
in the channel for a signed channel type is equivalent to defining an
``snorm'' texture.
Setting *_sampleUpper_* to the maximum unsigned value representable in
the channel for an unsigned channel type is equivalent to defining a
``normalized'' texture.
Setting *_sampleUpper_* to ``1'' is equivalent to defining an
``unnormalized'' texture.

In the special case that the sample *_bitOffset_* field is 0xFFFF, only
the bottom 16 bits of the *_sampleLower_* field indicate a contribution to
the sample lower limit; the upper 16 bits are taken as a constant
contribution to the interpreted value; in this case, the *_bitLength_*
field of the sample must be no more than 16.
For example, a 4-bit value which is interpreted as being zero-extended
to eight bits before conversion may have four bits with the value 0
stored in bits 19..16 of *_sampleLower_*, indicated by a *_bitOffset_*
of 0xFFFF.

These ``virtual bits'' may be needed to encode some numerical
representations.
For example, if an 8-bit integer encodes the value ``-0.5'' as 0
and ``0.5'' as 255 (in the manner of the color difference channel
in <<sampleRangeConversion>>, but if we wish to apply this mapping to
a channel other than color difference), <<sampleRangeConversion>>
suggests that *_sampleLower_* should hold -127.5 and *_sampleUpper_*
should hold 382.5.
This is impossible to encode, since *_sampleLower_* and *_sampleUpper_*
are integers.
However, if a virtual 0-bit is added below the encoded value (such
that the effective range is 0..510), storing *_sampleLower_* as
-255 and *_sampleUpper_* as 765 will have the desired effect.
Note that in this case, the original 8-bits of data are unsigned, but
the bounds must encode a negative value; this can be achieved by
describing the data as a signed value that is guaranteed to be positive
by another sample storing a virtual 0 bit in bit 9 (so the data is
treated as a signed 10-bit quantity, of which the top and bottom bits
are guaranteed to be 0).
The cost of this flexibility is that multiple samples are needed per
channel, which is why the common case of chroma channels which should
map to the -0.5..0.5 range are treated specially.

<<<
[[PALETTED]]
=== Paletted formats

The storage of the palette is considered to be outside the remit of this
specification; however, the ``format'' describes both the encoding of
the bits which index into the palette and the format of the entries in
the palette itself.

NOTE: The convention for encoding paletted formats was different in
revisions of this specification prior to 1.3.

If the *_bitOffset_* field of any of the samples equals eight times
the total number of bytes indicated by the *_bytesPlane_* channels
(that is, indicating an offset after the end of the logical bit stream),
this sample indicates a palette entry.
Samples with offsets within the range of the logical bit stream describe
the index of the palette; *_sampleUpper_* is used to indicate the number
of entries in the palette (which may be lower than could be addressed by
the number of bits available).
The index can be comprised of multiple samples, supporting non-contiguous
bits.

The four bits encoding *_channelType_* indicate a choice of palette in
the index samples.
The palette entries indicate which palette they are associated with by
encoding the corresponding palette id in the *_samplePosition0_* field,
with the other *_samplePosition_* fields set to 0.
This approach allows both a simple palette in which each entry represents
a complete color and per-channel look-up tables.

The index samples should be described first, as though the format were not
paletted; samples for palette entries should then follow, sorted first by
palette id, then by channel id.

The descriptor's *_colorModel_*, *_colorPrimaries_*, *_transferFunction_*
and *_flags_* apply to the palette entries.
The *_texelBlockDimension_* values on the other hand refer to the storage
of per-texel indices.

<<exampledescriptor_simplepalette>> shows a 240-entry palette with an index
encoded in eight bits, and six bits for each of _R_, _G_ and _B_ per
palette entry.
<<exampledescriptor_LUT>> shows a 24-bit format with 256-entry palettes
indexed by each of three 256-bit channels, with a 10-bit _R_, _G_ and _B_
palette associated with the corresponding channels.

[[UNSIZED]]
=== Unsized formats

The data format descriptor can be a convenient representation for
describing some data which does not follow the constraint that
texel blocks are of a fixed size.
For example, it may be useful to use a descriptor to encode the
color space of an image which is compressed with a variable-rate
compressor (meaning there is no data-independent mapping between
memory locations and corresponding pixels).
There are two ways to do this, each with its own uses.
Only the color primaries and transfer function may be encoded or these
and the presence of color and alpha samples may be encoded.

In the first case *++KHR_DF_MODEL_UNSPECIFIED++* is used in a descriptor
with no samples.
In this case all *_texelBlockDimension_* and *_bytesPlane_* values must
be zero.

In the second case the appropriate color model is used,
e.g.*++KHR_DF_MODEL_RGBSDA++*.
The presence of color and alpha samples is used to indicate the
presence of these samples in the image.
In this case, all *_texelBlockDimension_* and *_bytesPlane_*  values
and the *_bitOffset_*, *_bitLength_* and *_samplePosition_* fields
of any samples must be set to 0.

<<<
=== C99 struct mapping (informative)

The basic descriptor block has been specified in terms of an array of
++uint32_t++ value.
C99 provides a more direct representation, but this relies on the bit
ordering of bitfields (which is implementation-defined) and _flexible
array members_, which are not supported in C++.

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:

-----
typedef struct _DFDSampleType {
  uint32_t bitOffset: 16;
  uint32_t bitLength: 8;
  uint32_t channelType: 8; // Includes qualifiers
  uint32_t samplePosition0: 8;
  uint32_t samplePosition1: 8;
  uint32_t samplePosition2: 8;
  uint32_t samplePosition3: 8;
  uint32_t lower;
  uint32_t upper;
} DFDSampleType;

typedef struct _BasicDataFormatDescriptor {
  uint32_t vendorId: 17;
  uint32_t descriptorType: 15;
  uint32_t model: 8;
  uint32_t primaries: 8;
  uint32_t transfer: 8;
  uint32_t flags: 8;
  uint32_t texelBlockDimension0: 8;
  uint32_t texelBlockDimension1: 8;
  uint32_t texelBlockDimension2: 8;
  uint32_t texelBlockDimension3: 8;
  uint32_t bytesPlane0: 8;
  uint32_t bytesPlane1: 8;
  uint32_t bytesPlane2: 8;
  uint32_t bytesPlane3: 8;
  uint32_t bytesPlane4: 8;
  uint32_t bytesPlane5: 8;
  uint32_t bytesPlane6: 8;
  uint32_t bytesPlane7: 8;
  DFDSampleType samples[];
} BasicDataFormatDescriptor;
-----

== 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,
it is expected than an extension will be available which places an ICC color
profile block into the descriptor block, allowing more color channels to
be specified in more precise ways. This will significantly enlarge the
space required for the descriptor, and is not expected to be needed for
most common uses. A vendor may also use an extension block to associate
metadata with the descriptor -- for example, information required as part
of hardware rendering. So long as software which uses the data format descriptor
always uses the *_totalSize_* field to determine the size of the descriptor,
this should be transparent to user code.

The extension mechanism is the preferred way to support even simple extensions
such as additional color spaces transfer functions that can be supported by
an additional enumeration. This approach improves compatibility with code
which is unaware of the additional values. Simple extensions of this form
that have cross-vendor support have a good chance of being incorporated more
directly into future revisions of the specification, allowing application code
to distinguish them by the *_versionId_* field.

If bit 13, *++KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_WRITE_BIT++*, of the
*_descriptorType_* field of an extension is set, an application must
understand the extension in order to write data coherently.
If this bit is clear, copying the bits which correspond to one texel to
another can be expected to result in a correct transfer of the texel even
if the application does not understand the extension.

If bit 14, *++KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_DECODE_BIT++*, of the
*_descriptorType_* field of an extension is set, an application must
understand the extension in order to decode the contents of the texel
coherently.
If this bit is clear, the data held in the extension can be considered to be
``informative'' and that ignoring the extension will still result in correct
values to the extent specified by the basic descriptor block.
For example, an extension may associate an absolute brightness level with
a format, but software which does not have need of this concept can continue
processing the texel contents correctly.

<<<
As an example of the description of an extension, consider a single-channel
32-bit depth buffer, as shown in <<DepthExtensionExample>>.
A tiled renderer may wish to indicate that this buffer is ``virtual'': it
will be allocated real memory only if needed, and will otherwise exist only
a subset at a time in an on-chip representation.
Someone developing such a renderer may choose to add a vendor-specific
extension (with ID 0x1FFFF to indicate development work and avoid the need
for a vendor ID) which uses a boolean to establish whether this depth buffer
exists only in virtual form.
Note that the mere presence or absence of this extension within the data
format descriptor itself forms a boolean, but for this example we will
assume that an extension block is always present, and that a boolean is
stored within.
We will give the enumeration 32 bits, in order to simplify the possible
addition of further extensions and pad to the alignment requirements.

In this example (which should not be taken as an implementation suggestion),
the data descriptor would first contain a descriptor block describing the
depth buffer format as conventionally described, followed by a second
descriptor block that contains only the enumeration.
The descriptor itself has a *_totalSize_* that includes both of these
descriptor blocks.
Note that *++KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_WRITE_BIT++* is not
set, indicating that depth data can be written without knowing about the
extension, and *++KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_DECODE_BIT++* is not
set, indicating that software can safely ignore the information about the
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
32+^| ~Basic descriptor block~
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| ~*_flags_*~ 8+^| ~*_transferFunction_*~ 8+^| ~*_colorPrimaries_*~ 8+^| ~*_colorModel_*~
8+^| *++ALPHA_STRAIGHT++* 8+^| *++UNSPECIFIED++* 8+^| *++UNSPECIFIED++* 8+^| *++RGBSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 4
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for depth~
^| 1 ^| 1 ^| 0 ^| 0 4+^| *++DEPTH++* 8+^| *_bitLength:_* 31 (= ``32'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0xBF800000U -- -1.0f
32+^| *_sampleUpper:_* 0x7F800000U -- 1.0f
32+^| ~Extension descriptor block~
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0x1FFFF
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.
Since different implementations have different kinds of non-linear ordering
and proprietary alignment requirements, this is not described as part of the
standard. By many conventional definitions, this information is not part of
the ``format'', and particularly it ensures that an identical copy of the image
will have a different descriptor block (because the addresses will have changed)
and so a simple bitwise comparison of two descriptor blocks will disagree even
though the ``format'' matches. Additionally, many APIs will use the format
descriptor only for external communication, and have an internal representation
that is more concise and less flexible. In this case, it is likely that address
information will need to be represented separately from the format anyway. For
these reasons, it is an implementation choice whether to store this information
in an extension block, and how to do so, rather than being specified in this
standard.

== Additional planes descriptor block

Under some relatively unusual circumstances, either the number of planes
described by the basic descriptor block or the number of bytes that can be
contributed to a texel may be insufficient to describe the memory layout of bulk
data.
For example, a format may describe 12-bit colors (4 bits each or red, green and
blue), and have the contributing bits stored as separate planes.
An extension descriptor block, with *_vendorId_* = *++KHR_DF_VENDORID_KHRONOS++*
and *_descriptorType_* = *++KHR_DF_DESCRIPTORTYPE_ADDITIONAL_PLANES++*,
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
16+^| *_descriptorBlockSize:_* 8 + (4 {times} _number of planes_) 16+^| *_versionNumber:_* 0
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
_n_ is taken directly from word _n_ {plus} 2 of the descriptor block.
The number of planes described can be determined by the descriptor block
size.

This extension both allows an arbitrary number of planes and makes it
easy to specify planes that contribute a large number of bytes to the
virtual bit stream.
Note that the sample *_bitOffset_* field remains limited to 16 bits,
so the total texel block memory footprint is limited.

NOTE: Since knowing the bit stream contribution from all planes is
necessary when interpreting data, this *_descriptorType_* sets
*++KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_DECODE_BIT++*.
Since the memory mapping is necessary when writing data,
this *_descriptorType_* sets
*++KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_WRITE_BIT++*.

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.

== Additional dimensions descriptor block

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$]
of a coordinate.
Under rare circumstances, this may provide insufficient flexibility.
An extension descriptor block, with *_vendorId_* = *++KHR_DF_VENDORID_KHRONOS++*
and *_descriptorType_* = *++KHR_DF_DESCRIPTORTYPE_ADDITIONAL_DIMENSIONS++*,
describes additional dimensions.
Note that in some cases where this solution might be useful, a texel block
is an inappropriate unit.
For example, this extension block allows the direct representation of
large texel tiling patterns, but it does so in a manner that is very
inefficient, having much more potential flexibility than is needed by the
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
16+^| *_descriptorBlockSize:_* 8+(4 {times} _dimensions_ {times} (_samples_{plus}1)) 16+^| *_versionNumber:_* 0
32+^| *++uint32_t++* *_texelBlockDimension0_*
32+^| *++uint32_t++* *_texelBlockDimension1_* _(optional)_
32+^| _(etc.)_
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
basic descriptor block, the value stored is the corresponding dimension
minus 1 (so a stored value of ``0'' corresponds to a dimension of 1).
The *_texelBlockDimension[0..7]_* fields of the basic descriptor block
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}}$]
for each dimension, with all dimensions for a sample described before
describing the next sample.
*_samplePos_* and *_samplePosDivisor_* should be minimized, leaving an
irreducible fraction.
The *_samplePos_* fields of the basic descriptor block are ignored.
These fields are present even for samples corresponding to palette
entries.

Since the number of samples in the texel block can be deduced from the
size of the basic descriptor block, the number of dimensions that are to be
described by the additional dimensions descriptor block can be deduced from
its size: _numDimensions_ = (*_descriptorBlockSize_* - 8) / (_numSamples_ + 1).

NOTE: Since knowing the mapping from coordinates to samples is
necessary when interpreting data, this *_descriptorType_* sets
*++KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_DECODE_BIT++*.
Since the coordinate mapping is necessary for writing data,
this *_descriptorType_* sets
*++KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_WRITE_BIT++*.

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 ==

=== 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
on a critical path in an application, it is still expected that comparison
between formats may be time-sensitive. The data format descriptor is designed
to allow relatively efficient queries for subsets of properties, to allow
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? ===

Formats in FourCC.org do not describe in detail sufficient information for
many APIs, and are sometimes inconsistent.

=== 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
was defined. Software often behaves differently according to properties
of a format, and must perform a look-up on the enumeration -- if it knows
what it is -- in order to change behaviors. A descriptive format allows
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? ===

Khronos supports multiple standards that have a range of internal data
representations. There is no requirement that this standard be used
specifically with other Khronos standards, but it is hoped that multiple
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? ===

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
users of data -- particularly pixel-like data -- to have additional
requirements. Capturing these requirements portably reduces the need
for additional metadata to be associated with a proprietary descriptor.
It is also common for additional functionality to be added retrospectively
to existing libraries -- for example, _Y&prime;C~B~C~R~_ support is often an
afterthought in rendering APIs.
Having a consistent and flexible representation in place from the start
can reduce the pain of retrofitting this functionality.

Note that there is no expectation that the format descriptor from this
standard be used directly, although it can be. The impact of providing
a mapping between internal formats and format descriptors is expected
to be low, but offers the opportunity both for simplified access from
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? ===

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
concurrently, reducing the cost of comparisons. When transferring
data formats, the packing reduces the overhead. Within these constraints,
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? ===

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
comment sections. However, since many multilingual text representations
do not have a fixed character size, this use is not seen as an obvious match
for this standard.

:frame: all
:grid: all
:halign: center
:valign: center

[[fpformats]]
== Floating-point formats ==

Some common floating-point numeric representations are defined in
<<IEEE 754>>. Additional floating point formats are defined in this
section.

[[16bitfp]]
=== 16-bit floating-point numbers

A 16-bit floating-point number has a 1-bit sign (_S_), a 5-bit
exponent (_E_), and a 10-bit mantissa (_M_).
The value _V_ of a 16-bit floating-point number is determined by the
following:

[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\[
V =
  \begin{cases}
    (-1)^S \times 0.0,                      & E = 0, M = 0     \\
    (-1)^S \times 2^{-14} \times { M \over 2^{10} },
                                            & E = 0,  M \neq 0 \\
    (-1)^S \times 2^{E-15} \times { \left( 1 + { M \over 2^{10} } \right) },
                                            & 0 < E < 31       \\
    (-1)^S \times \mathit{Inf},             & E = 31, M = 0             \\
    \mathit{NaN},                           & E = 31, M \neq 0
  \end{cases}
\]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

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.$$
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

[[11bitfp]]
=== Unsigned 11-bit floating-point numbers

An unsigned 11-bit floating-point number has no sign bit, a 5-bit exponent
(_E_), and a 6-bit mantissa (_M_).
The value _V_ of an unsigned 11-bit floating-point number is determined by
the following:

[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\[
V =
  \begin{cases}
    0.0,                                    & E = 0, M = 0    \\
    2^{-14} \times { M \over 64 },          & E = 0, M \neq 0 \\
    2^{E-15} \times { \left( 1 + { M \over 64 } \right) },
                                            & 0 < E < 31      \\
    \mathit{Inf},                           & E = 31, M = 0            \\
    \mathit{NaN},                           & E = 31, M \neq 0
  \end{cases}
\]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

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.$$
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

[[10bitfp]]
=== Unsigned 10-bit floating-point numbers

An unsigned 10-bit floating-point number has no sign bit, a 5-bit
exponent (_E_), and a 5-bit mantissa (_M_).
The value _V_ of an unsigned 10-bit floating-point number is
determined by the following:

[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\[
V =
  \begin{cases}
    0.0,                                    & E = 0, M = 0    \\
    2^{-14} \times { M \over 32 },          & E = 0, M \neq 0 \\
    2^{E-15} \times { \left( 1 + { M \over 32 } \right) },
                                            & 0 < E < 31      \\
    \mathit{Inf},                           & E = 31, M = 0   \\
    \mathit{NaN},                           & E = 31, M \neq 0
  \end{cases}
\]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

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.$$
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

[[customfp]]
=== Non-standard floating point formats

Rather than attempting to enumerate every possible floating-point
format variation in this specification, the data format descriptor
can be used to describe the components of arbitrary floating-point
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
is provided in <<exampledescriptor_float16explicit>>.
Note that this is provided for example only, and this particular
format would be better described using the standard 16-bit floating
point format as documented in <<exampledescriptor_float16implicit>>.

==== The mantissa

The mantissa of a custom floating point format should be represented
as an integer *_channelType_*. If the mantissa represents a signed
quantity encoded in two's complement, the *++KHR_DF_SAMPLE_DATATYPE_SIGNED++*
bit should be set. To encode a signed mantissa represented in
sign-magnitude format, the main part of the mantissa should be
represented as an unsigned integer quantity (with
*++KHR_DF_SAMPLE_DATATYPE_SIGNED++* not set), and an additional one-bit
sample _with_ *++KHR_DF_SAMPLE_DATATYPE_SIGNED++* set should be used
to identify the sign bit. By convention, a sign bit should be encoded
in a later sample than the corresponding mantissa.

The *_sampleUpper_* and *_sampleLower_* values for the mantissa should be
set to indicate the representation of 1.0 and 0.0 (for unsigned formats)
or -1.0 (for signed formats) respectively when the exponent is in a
0 position after any bias has been corrected. If there is an implicit
``1'' bit, these values for the mantissa will exceed what can be
represented in the number of available mantissa bits.

For example, the shared exponent formats shown in
<<exampledescriptor_r9g9b9e5>> does not have an implicit ``1'' bit, and
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>>,
*_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
representation.

By convention, the *_sampleUpper_* and *_sampleLower_* values for a sign
bit are 0 and -1 respectively.

==== The exponent

The *++KHR_DF_SAMPLE_DATATYPE_EXPONENT++* bit should be set in a sample
which contains the exponent of a custom floating point format.

The *_sampleLower_* for the exponent should indicate the exponent bias.
That is, the mantissa should be scaled by two raised to the power of
the stored exponent minus this *_sampleLower_* value.

The *_sampleUpper_* for the exponent indicates the maximum legal
exponent value. Values above this are used to encode infinities and
not-a-number (_NaN_) values. *_sampleUpper_* can therefore be used to
indicate whether or not the format supports these encodings.

==== Special values

Floating point values encoded with an exponent of 0 (before bias)
and a mantissa of 0 are used to represent the value 0. An explicit
sign bit can distinguish between +0 and -0.

Floating point values encoded with an exponent of 0 (before bias)
and a non-zero mantissa are assumed to indicate a denormalized
number, if the format has an implicit ``1'' bit. That is, when
the exponent is 0, the ``1'' bit becomes explicit and the exponent
is considered to be the negative sample bias minus one.

Floating point values encoded with an exponent larger than the
exponent's *_sampleUpper_* value and with a mantissa of 0 are
interpreted as representing +/- infinity, depending on the value
of an explicit sign bit. Note that in some formats, no exponent
above *_sampleUpper_* is possible -- for example,
<<exampledescriptor_r9g9b9e5>>.

Floating point values encoded with an exponent larger than the
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 <<IEEE 754>>.

==== Conversion formulae

Given an optional sign bit _S_, a mantissa value of _M_ and an
exponent value of _E_, a format with an implicit ``1'' bit can
be converted from its representation to a real value as follows:

[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\[
V =
  \begin{cases}
    (-1)^S \times 0.0,             & E = 0, M = 0    \\
    (-1)^S \times 2^{-(E_\mathit{sampleLower}-1)} \times { M \over M_\mathit{sampleUpper} },  & E = 0, M \neq 0 \\
    (-1)^S \times 2^{E-E_\mathit{sampleLower}} \times { \left( 1 + { M \over M_\mathit{sampleUpper} } \right) },
                                   & 0 < E \leq E_\mathit{sampleUpper}   \\
    (-1)^S \times \mathit{Inf},    & E > E_\mathit{sampleUpper}, M = 0   \\
    \mathit{NaN},                  & E > E_\mathit{sampleUpper}, M \neq 0.
  \end{cases}
\]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

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]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
\[
V =
  \begin{cases}
    (-1)^S \times 2^{E-E_{\mathit{sampleUower}}} \times { \left( { M \over M_\mathit{sampleUpper} } \right) },
                                   & 0 < E \leq E_\mathit{sampleUpper}   \\
    (-1)^S \times \mathit{Inf},    & E > E_\mathit{sampleUpper}, M = 0   \\
    \mathit{NaN},                  & E > E_\mathit{sampleUpper}, M \neq 0.
  \end{cases}
\]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

A descriptor block for a format without an implicit ``1'' (and with the
added complication of having the same exponent bits shared across multiple
channels, which is why an implicit ``1'' bit does not make sense) is shown
in <<exampledescriptor_r9g9b9e5>>. In the case of this particular example, the above
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)}$$
+++++++++++++++++++

Where:

[latexmath]
+++++++++++++++++++
   $$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 ==

NOTE: Example data format descriptors for compressed formats can
be found under the *_colorModel_* field in <<CompressedFormatModels>>.

[[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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 3) = 72 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++RGBSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 2
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~First sample: low five bits blue~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++BLUE++* 8+^| *_bitLength:_* 4 (= ``5'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 31
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Second sample: middle six bits green~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 5 = (``6'') 16+^| *_bitOffset:_* 6
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 63
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^|  ~Third sample: top five bits red~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 4 (= ``5'') 16+^| *_bitOffset:_* 11
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 4) = 88 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++PREMULTIPLIED++* 8+^| *_transferFunction:_* *++SRGB++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++RGBSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 4
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the first sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 255
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the second sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 8
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 255
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the third sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++BLUE++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 16
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 255
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the fourth sample~
^| 0 ^| 0 ^| 0 ^| 1 4+^| *++ALPHA++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 24
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 1) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++ITU++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++YUVSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 1
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 8 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
endif::[]
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 8) = 142 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++YUVSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 7 (= ``8'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 1
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the first sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 0 (= ``1'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the second sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 0 (= ``1'') 16+^| *_bitOffset:_* 1
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0x20
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::[]
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the third sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 0 (= ``1'') 16+^| *_bitOffset:_* 2
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0x40
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| _~Sample information for the fourth sample~_
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 0 (= ``1'') 16+^| *_bitOffset:_* 3
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0x60
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| _~Sample information for the fifth sample~_
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 0 (= ``1'') 16+^| *_bitOffset:_* 4
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0x80
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| _~Sample information for the sixth sample~_
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 0 (= ``1'') 16+^| *_bitOffset:_* 5
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0xA0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| _~Sample information for the seventh sample~_
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 0 (= ``1'') 16+^| *_bitOffset:_* 6
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0xC0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| _~Sample information for the eighth sample~_
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 0 (= ``1'') 16+^| *_bitOffset:_* 7
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 4) = 88 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++SRGB++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++RGBSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 1 (height = ``2'') 8+^| 1 (width = ``2'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 2 8+^| *_bytesPlane0:_* 2
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the first sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0x00 (_y_ = ``0'') 8+^| 0x00 (_x_ = ``0'')
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 255
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the second sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 8
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0x00 (_y_ = ``0'') 8+^| 0x80 (_x_ = ``1'')
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 255
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the third sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 16
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0x80 (_y_ = ``1'') 8+^| 0x00 (_x_ = ``0'')
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 255
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the fourth sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++BLUE++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 24
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 4) = 88 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++SRGB++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++RGBSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 1
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the 8-bit index~
^| 0 ^| 0 ^| 0 ^| 0 4+^| 0 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 239
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Red channel of the palette entries~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 3 (= ``4'') 16+^| *_bitOffset:_* 8 (palette entry)
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0 (palette id)
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 15
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Green channel of the palette entries~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 3 (= ``4'') 16+^| *_bitOffset:_* 8 (palette entry)
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0 (palette id)
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 15
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Blue channel of the palette entries~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++BLUE++* 8+^| *_bitLength:_* 3 (= ``4'') 16+^| *_bitOffset:_* 8 (palette entry)
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 6) = 120 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++RGBSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 4
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Red channel palette index~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 255
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Green channel palette index~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 8
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 255
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Blue channel palette index~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++BLUE++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 16
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 255
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Red palette entry~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 9 (= ``10'') 16+^| *_bitOffset:_* 32 (palette entry)
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0 (*++RED++* palette)
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1023
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Green palette entry~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 9 (= ``10'') 16+^| *_bitOffset:_* 32 (palette entry)
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 1 (*++GREEN++* palette)
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1023
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Blue palette entry~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 9 (= ``10'') 16+^| *_bitOffset:_* 32 (palette entry)
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 2 (*++BLUE++* palette)
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1023
|================================

[[exampledescriptor_ycbcr]]
._Y&prime;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&prime;_ 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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 6) = 120 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++ITU++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++YUVSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 1 (height = ``2'')  8+^| 1 (width = ``2'')
8+^| *_bytesPlane3:_* 1 8+^| *_bytesPlane2:_* 1 8+^| *_bytesPlane1:_* 2 8+^| *_bytesPlane0:_* 2
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the first _Y&prime;_ sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0x00 (_y_ = ``0.0'') 8+^| 0x00 (_x_ = ``0.0'')
32+^| *_sampleLower:_* 16
32+^| *_sampleUpper:_* 235
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the second _Y&prime;_ sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 8
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0x00 (_y_ = ``0.0'') 8+^| 0x80 (_x_ = ``1.0'')
32+^| *_sampleLower:_* 16
32+^| *_sampleUpper:_* 235
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the third _Y&prime;_ sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 16
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0x80 (_y_ = ``1.0'') 8+^| 0x00 (_x_ = ``0.0'')
32+^| *_sampleLower:_* 16
32+^| *_sampleUpper:_* 235
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the fourth _Y&prime;_ sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 24
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0x80 (_y_ = ``1.0'') 8+^| 0x80 (_x_ = ``1.0'')
32+^| *_sampleLower:_* 16
32+^| *_sampleUpper:_* 235
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the _U_ sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++U++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 32
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0x40 (_y_ = ``0.5'') 8+^| 0x40 (_x_ = ``0.5'')
32+^| *_sampleLower:_* 16
32+^| *_sampleUpper:_* 240
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the _V_ sample~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++V++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 40
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 4) = 88 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++RGBSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 2
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Bit 0 is green, green bits 0..2 in bits 5..7 of the higher byte address (less-significant half of the big-endian word)~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 2 (= ``3'') 16+^| *_bitOffset:_* 13
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0 -- lower 3 bits of 6-bit value 0
32+^| *_sampleUpper:_* 7 -- lower 3 bits of 6-bit value 63
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Continuation: green bits 3..5 in bits 0..2 of the lower byte address (more-significant half of the big-endian word)~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 2 (= ``3'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0 -- upper 3 bits of 6-bit value 0
32+^| *_sampleUpper:_* 7 -- upper 3 bits of 6-bit value 63
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Next undescribed bit: red in bits 3..7 of the lower byte address (more-significant half of the big-endian word)~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 4 (= ``5'') 16+^| *_bitOffset:_* 3
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 31
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Remaining bits: blue in bits 0..4 of the higher byte address (less-significant half of the big-endian word)~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++BLUE++* 8+^| *_bitLength:_* 4 (= ``5'') 16+^| *_bitOffset:_* 8
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 6) = 120 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++RGBSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 4
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the _R_ mantissa~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 8 (= ``9'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 256 -- mantissa at 1.0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the _R_ exponent~
^| 0 ^| 0 ^| 1 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 4 (= ``5'') 16+^| *_bitOffset:_* 27
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 15 -- exponent bias
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the _G_ mantissa~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 8 (= ``9'') 16+^| *_bitOffset:_* 9
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 256 -- mantissa at 1.0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the _G_ exponent~
^| 0 ^| 0 ^| 1 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 4 (= ``5'') 16+^| *_bitOffset:_* 27
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 15 -- exponent bias
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the _B_ mantissa~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++BLUE++* 8+^| *_bitLength:_* 8 (= ``9'') 16+^| *_bitOffset:_* 18
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 256 -- mantissa at 1.0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information for the _B_ exponent~
^| 0 ^| 0 ^| 1 ^| 0 4+^| *++BLUE++* 8+^| *_bitLength:_* 4 (= ``5'') 16+^| *_bitOffset:_* 27
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 5) = 104 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++RGBSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 1
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| _~First sample: four bits of red starting at bit 0, including two shared bits 0..1~_
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 3 (= ``4'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 15
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Second sample: two bits of green ``tint'' shared with red~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 1 (= ``2'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 3
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Third sample: two bits unique to green~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 1 (= ``2'') 16+^| *_bitOffset:_* 4
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 3
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Fourth sample: two bits of blue ``tint'' shared with red~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++BLUE++* 8+^| *_bitLength:_* 1 (= ``2'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 3
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Fifth sample: two bits unique to blue~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++BLUE++* 8+^| *_bitLength:_* 1 (= ``2'') 16+^| *_bitOffset:_* 6
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 3
|================================

ifdef::a2xhtml[]
.V210 format (full-range _Y&prime;C~B~C~R~_)
endif::[]
ifndef::a2xhtml[]

.V210 format (full-range _Y&prime;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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 12) = 216 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++ITU++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++YUVSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 5 (width = ``6'')
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 16
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~First sample: shared mid-sited _U0/U1_~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++U++* 8+^| *_bitLength:_* 10 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0x10 (_x_ = ``0.5'')
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1023
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Second sample: _Y&prime;0_~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 9 (= ``10'') 16+^| *_bitOffset:_* 10
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0x00 (_x_ = ``0.0'')
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1023
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Third sample: shared mid-sited _V0/V1_~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++V++* 8+^| *_bitLength:_* 9 (= ``10'') 16+^| *_bitOffset:_* 20
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0x10 (_x_ = ``0.5'')
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1023
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Fourth sample: _Y&prime;1_~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 9 (= ``10'') 16+^| *_bitOffset:_* 32
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0x20 (_x_ = ``1.0'')
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1023
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Fifth sample: shared mid-sited _U2/U3_~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++U++* 8+^| *_bitLength:_* 9 (= ``10'') 16+^| *_bitOffset:_* 42
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0x50 (_x_ = ``2.5'')
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1023
ifndef::a2xhtml[]
|================================

.V210 format (full-range _Y&prime;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::[]
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sixth sample: _Y&prime;2_~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 9 (= ``10'') 16+^| *_bitOffset:_* 52
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0x40 (_x_ = ``2.0'')
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1023
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Seventh sample: shared mid-sited _V2/V3_~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++V++* 8+^| *_bitLength:_* 9 (= ``10'') 16+^| *_bitOffset:_* 64
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0x50 (_x_ = ``2.5'')
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1023
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Eighth sample: _Y&prime;3_~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 9 (= ``10'') 16+^| *_bitOffset:_* 74
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0x60 (_x_ = ``3.0'')
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1023
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Ninth sample: shared mid-sited _U4/U5_~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++U++* 8+^| *_bitLength:_* 9 (= ``10'') 16+^| *_bitOffset:_* 84
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0x90 (_x_ = ``4.5'')
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1023
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Tenth sample: _Y&prime;4_~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 9 (= ``10'') 16+^| *_bitOffset:_* 96
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0x80 (_x_ = ``4.0'')
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1023
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Eleventh sample: shared mid-sited _V4/V5_~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++V++* 8+^| *_bitLength:_* 9 (= ``10'') 16+^| *_bitOffset:_* 106
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0x90 (_x_ = ``4.5'')
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1023
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Twelfth sample: _Y&prime;5_~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++Y++* 8+^| *_bitLength:_* 9 (= ``10'') 16+^| *_bitOffset:_* 116
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 4) = 88 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++RGBSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 1
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~First sample: red~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 255
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Second sample: green~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++GREEN++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 255
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Third sample: blue~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++BLUE++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 255
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Fourth sample: alpha~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++ALPHA++* 8+^| *_bitLength:_* 7 (= ``8'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 3) = 72 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++RGBSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 6
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~First sample: bits 0..15 of the 48-bit value, in memory bytes 4..5~
^| 0 ^| 1 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 15 (= ``16'') 16+^| *_bitOffset:_* 32
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0xFFFF0000U -- bottom 16 bits of 0x800000000000, sign-extended
32+^| *_sampleUpper:_* 0x0000FFFFU -- bottom 16 bits of 0x7FFFFFFFFFFF
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Second sample: bits 16..31 of the 48-bit value, in memory bytes 2..3~
^| 0 ^| 1 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 15 (= ``16'') 16+^| *_bitOffset:_* 16
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0xFFFF0000U -- middle 16 bits of 0x800000000000, sign-extended
32+^| *_sampleUpper:_* 0x0000FFFFU -- middle 16 bits of 0x7FFFFFFFFFFF
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Third sample: bits 32..47 of the 48-bit value, in memory bytes 0..1~
^| 0 ^| 1 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 15 (= ``16'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 3) = 72 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++RGBSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 2
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~First sample: mantissa~
^| 0 ^| 0 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 9 (= ``10'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 0
32+^| *_sampleUpper:_* 1024 -- implicit 1.0 bit since 1024 > 2^*_bitLength_*^ - 1
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Second sample: sign of mantissa~
^| 0 ^| 1 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 0 (= ``1'') 16+^| *_bitOffset:_* 15
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
32+^| *_sampleLower:_* 1 -- 1-bit ``-1''
32+^| *_sampleUpper:_* 0 -- 1-bit ``0''
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Third sample: exponent~
^| 0 ^| 0 ^| 1 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 4 (= ``5'') 16+^| *_bitOffset:_* 10
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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
15+^| *_descriptorType:_* 0 17+^| *_vendorId:_* 0
16+^| *_descriptorBlockSize:_* 24 + (16 {times} 3) = 40 16+^| *_versionNumber:_* 2
8+^| *_flags:_* *++ALPHA_STRAIGHT++* 8+^| *_transferFunction:_* *++LINEAR++* 8+^| *_colorPrimaries:_* *++BT709++* 8+^| *_colorModel:_* *++RGBSDA++*
8+^| *_~texelBlockDimension3~_* 8+^| *_~texelBlockDimension2~_* 8+^| *_~texelBlockDimension1~_* 8+^| *_~texelBlockDimension0~_*
8+^| 0 8+^| 0 8+^| 0 8+^| 0
8+^| *_bytesPlane3:_* 0 8+^| *_bytesPlane2:_* 0 8+^| *_bytesPlane1:_* 0 8+^| *_bytesPlane0:_* 2
8+^| *_bytesPlane7:_* 0 8+^| *_bytesPlane6:_* 0 8+^| *_bytesPlane5:_* 0 8+^| *_bytesPlane4:_* 0
^| *_~F~_* ^| *_~S~_* ^| *_~E~_* ^| *_~L~_* 4+^| *_~channelType~_* 24+^| ~Sample information~
^| 1 ^| 1 ^| 0 ^| 0 4+^| *++RED++* 8+^| *_bitLength:_* 15 (= ``16'') 16+^| *_bitOffset:_* 0
8+^| *_~samplePosition3~_* 8+^| *_~samplePosition2~_* 8+^| *_~samplePosition1~_* 8+^| *_~samplePosition0~_*
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::[]

include::conversions.txt[]

ifndef::a2xhtml[]
= Compressed Texture Formats
endif::[]

include::compformats.txt[]

ifndef::a2xhtml[]
= References and contributors
endif::[]

include::references.txt[]

== Contributors ==

Frank Brill

Mark Callow

Sean Ellis

Simon Fenney

Jan-Harald Fredriksen

Andrew Garrard

Fabien Giesen

Courtney Goeltzenleuchter

Jonas Gustavsson

Chris Hebert

Tobias Hector

Alexey Knyazev

Daniel Koch

Jon Leech

Thierry Lepley

Tommaso Maestri

Kathleen Mattson

Hans-Peter Nilsson

XianQuan Ooi

Alon Or-bach

Jan Outters

Erik Rainey

Daniel Rakos

Donald Scorgie

Graham Sellers

David Sena

Stuart Smith

Alex Walters

Eric Werness

David Wilkinson

// vim: filetype=asciidoc ai expandtab tw=72 ts=4 sts=2 sw=2

