// Copyright (c) 2014-2019 The Khronos Group Inc.
// Copyright notice at https://www.khronos.org/registry/speccopyright.html

= Khronos Data Format Specification =
Andrew Garrard <a.garrard@samsung.com>
:Author Initials: AG
v1.0 rev 5, March, 2019
:toc:
:toc-placement: manual

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

ifdef::backend-html5[]
Copyright (C) 2014-2019 The Khronos Group Inc. All Rights Reserved.

This specification is protected by copyright laws and contains material proprietary to the Khronos Group, Inc. It or any components may not be reproduced, republished, distributed, transmitted, displayed, broadcast, or otherwise exploited in any manner without the express prior written permission of Khronos Group. You may use this specification for implementing the functionality therein, without altering or removing any trademark, copyright or other notice from the specification, but the receipt or possession of this specification does not convey any rights to reproduce, disclose, or distribute its contents, or to manufacture, use, or sell anything that it may describe, in whole or in part.

Khronos Group grants express permission to any current Promoter, Contributor or Adopter member of Khronos to copy and redistribute UNMODIFIED versions of this specification in any fashion, provided that NO CHARGE is made for the specification and the latest available update of the specification for any version of the API is used whenever possible. Such distributed specification may be reformatted AS LONG AS the contents of the specification are not changed in any way. The specification may be incorporated into a product that is sold as long as such product includes significant independent work developed by the seller. A link to the current version of this specification on the Khronos Group website should be included whenever possible with specification distributions.

Khronos Group makes no, and expressly disclaims any, representations or warranties, express or implied, regarding this specification, including, without limitation, any implied warranties of merchantability or fitness for a particular purpose or non-infringement of any intellectual property. Khronos Group makes no, and expressly disclaims any, warranties, express or implied, regarding the correctness, accuracy, completeness, timeliness, and reliability of the specification. Under no circumstances will the Khronos Group, or any of its Promoters, Contributors or Members or their respective partners, officers, directors, employees, agents, or representatives be liable for any damages, whether direct, indirect, special or consequential damages for lost revenues, lost profits, or otherwise, arising from or in connection with these materials.

Khronos, SYCL, SPIR, WebGL, EGL, COLLADA, StreamInput, OpenVX, OpenKCam, glTF, OpenKODE, OpenVG, OpenWF, OpenSL ES, OpenMAX, OpenMAX AL, OpenMAX IL and OpenMAX DL are trademarks and WebCL is a certification mark of the Khronos Group Inc. OpenCL is a trademark of Apple Inc. and OpenGL and OpenML are registered trademarks and the OpenGL ES and OpenGL SC logos are trademarks of Silicon Graphics International used under license by Khronos. All other product names, trademarks, and/or company names are used solely for identification and belong to their respective owners.

:numbered!:

== Contributors ==

Frank Brill

Mark Callow

Sean Ellis

Andrew Garrard (editor)

Jonas Gustavsson

Chris Hebert

Daniel Koch

Thierry Lepley

Tommaso Maestri

Kathleen Mattson

Hans-Peter Nilsson

Alon Or-bach

Erik Rainey

Daniel Rakos

Graham Sellers

David Sena

toc::[]

:numbered:

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.

== Overview ==

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 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 strides, tiling or dimensionality. An example pixel format is
described in <<SimpleTexelBlock>>: a single 5:6:5-bit pixel with blue in
the low 5 bits, green in the next 6 bits, and red in the top 5 bits of a
16-bit word as laid out in memory on a little-endian machine (see
<<565DFD>>).

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

In some cases, the elements of bulk texture data may not correspond to a
conventional texel. For example, in a compressed texture it is common for
the atomic element of the buffer to represent a rectangular block of
texels. Alternatively the representation of the output of a camera may have
a repeating pattern according to a Bayer or other layout. It is this repeating
and self-contained atomic unit, termed a _texel block_, that is described by this
standard.

[[SimpleBayerBlock]]
.A Bayer-sampled image with a repeating 2×2 RG/GB texel block
image::images/Bayer.{svgpdf}[title="A Bayer-sampled image with a repeating 2×2 RG/GB texel block",width="{svgpdf@pdf:100pt:170}",align="center"]

The sampling or reconstruction of texel data is not a function of the
data format.
That is, a texture has the same format whether it is point sampled or
a bicubic filter is used, and the manner of reconstructing full color
data from a camera sensor is not defined.
Where information making up the data format has a spatial aspect, this
is part of the descriptor: it is part of the descriptor to define the
spatial configuration of color samples in a Bayer sensor or whether the
chroma difference channels in a _Y&prime;C~B~C~R~_ format are considered
to be centered or co-sited, but not how this information must be used to
generate coordinate-aligned full color values.

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. 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 applications
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.

.Data format descriptor and descriptor blocks
[width="75%",cols="1a"]
|=============
|_Data format descriptor_
[width="100%",cols="1"]
!=============
! _Descriptor block 1_
! _Descriptor block 2_
! :
!=============
|=============

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.

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

_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 with subsampled
channels, the texel block may describe 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.

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

_Plane:_
In some formats, a texel block is not contiguous in
memory. In a two-dimensional texture, the texel block may be
spread across multiple scan lines, or channels may be stored
independently. 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.

In many existing APIs, planes may be ``downsampled'' differently.
For example, in these APIs, a _Y&prime;C~B~C~R~_ (colloquially
_YUV_) 4:2:0 buffer as in <<yuv420>> (with byte offsets shown for
each channel/location) would typically be represented with three
planes (<<yuv420conventional>>), one for each channel, with the
luma (_Y&prime;_) plane containing four times as many pixels as
the chroma (_C~B~_ and _C~R~_) planes, and with two horizontal
lines of the luma held within the same plane for each horizontal
line of the chroma planes.

[[yuv420]]
.Possible memory representation of a 4×4 _Y&prime;C~B~C~R~_ 4:2:0 buffer
ifdef::a2xhtml[]
[cols="1a"]
endif::[]
ifndef::a2xhtml[]
[width="20%",cols="1a"]
endif::[]
|==============================
^|_Y&prime;_ channel
^|[cols="4*^",width="97%"]
!=====================
!0!1!2!3
!4!5!6!7
!8!9!10!11
!12!13!14!15
!=====================
^|_C~B~_ channel
^|
ifdef::a2xhtml[]
[cols="2"]
endif::[]
ifndef::a2xhtml[]
[width="50%",cols="2*^"]
endif::[]
!=====================
!16!17
!18!19
!=====================
^|_C~R~_ channel
^|
ifdef::a2xhtml[]
[cols="2"]
endif::[]
ifndef::a2xhtml[]
[width="50%",cols="2*^"]
endif::[]
!=====================
!20!21
!22!23
!=====================
|==============================

[[yuv420conventional]]
.Plane descriptors for the above _Y&prime;C~B~C~R~_-format buffer in a conventional API
[cols="2,2,3,3",width="70%"]
|==============================
| &nbsp; _Y&prime;_ plane | &nbsp; offset 0 | &nbsp; byte stride 4 | &nbsp; downsample 1×1
| &nbsp; _C~B~_ plane | &nbsp; offset 16 | &nbsp; byte stride 2 | &nbsp; downsample 2×2
| &nbsp; _C~R~_ plane | &nbsp; offset 20 | &nbsp; byte stride 2 | &nbsp; downsample 2×2
|==============================

This approach does not extend logically to more complex formats such
as a Bayer grid.
Therefore in this specification, we would instead define the luma
channel as in <<yuv420thisapi>>, using two planes, vertically interleaved
(in a linear mapping between addresses and samples) by the selection of
a suitable offset and line stride, with each line of luma samples
contiguous in memory.
Only one plane is used for each of the chroma channels (or one plane
collectively if the chroma samples are stored adjacently).

[[yuv420thisapi]]
.Plane descriptors for the above _Y&prime;C~B~C~R~_-format buffer using this standard
[cols="4",width="60%"]
|==============================
| &nbsp; _Y&prime;_ plane 1 | &nbsp; offset 0 | &nbsp; byte stride 8 | &nbsp; plane bytes 2
| &nbsp; _Y&prime;_ plane 2 | &nbsp; offset 4 | &nbsp; byte stride 8 | &nbsp; plane bytes 2
| &nbsp; _C~B~_ plane | &nbsp; offset 16 | &nbsp; byte stride 2 | &nbsp; plane bytes 1
| &nbsp; _C~R~_ plane | &nbsp; offset 20 | &nbsp; byte stride 2 | &nbsp; plane bytes 1
|==============================

The same approach can be used to represent a static interlaced image,
with a texel block consisting of two planes, one per field.
This mechanism is all that is required to represent a static image
without downsampled channels; however correct reconstruction of
interlaced, downsampled color difference formats (such as
_Y&prime;C~B~C~R~_), which typically involves interpolation of the nearest
chroma samples in a given _field_ rather than the whole _frame_, is beyond
the remit of this specification.
There are many proprietary and often heuristic approaches to sample
reconstruction, particularly for Bayer-like formats and for multi-frame
images, and it is not practical to document them here.

There is no expectation that the internal format used by an API that
wishes to make use of the Khronos Data Format Specification must use
this specification's representation internally: reconstructing
downsampling information from this standard's representation in order to
revert to the more conventional representation should be trivial if required.

There is no requirement that the number of bytes occupied by the
texel block be the same in each plane. The descriptor defines the
number of bytes that the texel block occupies in each plane,
which for most formats is sufficient to allow access to consecutive
elements. For a two-dimensional data structure, it is up to the
controlling interface to resolve byte stride between consecutive lines.
For a three-dimensional structure, the controlling API may need to add
a level stride. Since these strides are determined by the data size
and architecture alignment requirements, they are not considered to be
part of the format.

== Required concepts not contained in this format ==

This specification encodes how atomic data should be interpreted in a manner which is
independent of the layout and dimensionality of the collective data. Collections
of data may have a ``compatible format'' in that their format descriptor may be
identical, yet be different sizes. Some additional information is therefore
expected to be recorded alongside the ``format description''.

The API which controls the bulk data is responsible for controlling which memory
location corresponds to the indexing mechanism chosen. A texel block has the
concept of a coordinate offset within the block, which implies that if the data
is accessed in terms of spatial coordinates, a texel block has spatial locality
as well as referring to contiguous memory (per plane). For texel blocks which
represent only a single spatial location, this is irrelevant; for block-based
compression, for formats with downsampled channels, or for Bayer-like formats, the
texel block represents a finite extent in up to four dimensions. However, the mapping
from coordinate system to the memory location containing a texel block is beyond the
control of this API.

The minimum requirements for accessing a linearly-addressed buffer is to
store the start address and a stride (typically in bytes) between texels in
each dimension of the buffer, for each plane contributing to the texel block.
For the first dimension, the memory stride between texels may simply be the
byte size of texel block in that plane -- this implies that there are no
gaps between texel blocks. For other dimensions, the stride is a function
of the size of the data structure being represented -- for example, in a compact
representation of a two-dimensional buffer, the texel block at coordinate (_x_,_y_+1)
might be found at the address of coordinate (_x_,_y_) plus the buffer width multiplied
by the texel size in bytes. Similarly in a three-dimensional buffer, the address
of the pixel at (_x_,_y_,_z_+1) may be at the address of (_x_,_y_,_z_) plus the byte size of
a two-dimensional slice of the texture. In practice, even linear layouts may have
padding, and often more complex relationships between coordinates and memory
location are used to encourage locality of reference. The details of all of these
data structures are beyond the remit of this specification.

Most simple formats contain a single _plane_ of data. Those formats
which require additional planes compared with a conventional representation
are typically downsampled _Y&prime;C~B~C~R~_ formats, which already
have the concept of separate storage for different color channels.
While this specification uses multiple planes to describe texel
blocks that span multiple scan lines if the data is disjoint, there is
no expectation that the API using the data formats needs to maintain
this representation -- interleaved planes should be easy to identify
and coalesce if the API requires a more conventional representation of
downsampled formats.

Some image representations are composed of tiles of texels which are
held contiguously in memory, with the texels within the tile stored in
some order that improves locality of reference for multi-dimensional
access. This is a common approach to improve memory efficiency when
texturing. While it is possible to represent such a tile as a large
texel block (up to the maximum representable texel block size in this
specification), this is unlikely to be an efficient approach, since
a large number of samples will be needed and the layout of a tile
usually has a very limited number of possibilities. In most cases,
the layout of texels within the tile should be described by whatever
interface is aware of image-specific information such as size and stride,
and only the format of the texels should be described by a format descriptor.

The complication to this is where texel blocks larger than a single pixel
are themselves encoded using proprietary tiling. The spatial layout of
samples within a texel block is required to be fixed in the basic format
descriptor -- for example, if the texel block size is 2×2 pixels, the
top left pixel might always be expected to be in the first byte in that
texel block. In some proprietary memory tiling formats, such as ones
that store small rectangular blocks in raster order in consecutive bytes
or in Morton order, this relationship may be preserved, and the only proprietary
operation is finding the start of the texel block. In other proprietary
layouts such as Hilbert curver order, or when the texel block size does
not divide the tiling size, a direct representation of memory may be
impossible. In these cases, it is likely that this data format standard
would be used to describe the data as it would be seen in a linear format,
and the mapping from coordinates to memory would have to be hidden in
proprietary translation. As a logical format description, this is unlikely
to be critical, since any software which accesses such a layout will
necessarily need proprietary knowledge anyway.

== Translation to API-specific data format representations ==

The data format container described here is too unwieldy to be expected to
be used directly in most APIs. 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 returning 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.

== [[dataformatdescriptor]]Data format descriptor ==

The layout of the data structures described here are assumed to be
little-endian for the purposes of data transfer, but may be implemented
in the natural endianness of the platform for internal use.

The data format descriptor consists of a contiguous area of memory,
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.

.Data Format Descriptor layout
|=====================================
| *++uint32_t++* | *_totalSize_*
| _Descriptor block_ | _First descriptor_
| _Descriptor block_ | _Second descriptor (optional) etc._
|=====================================

The *_totalSize_* field, measured in bytes, allows the full format descriptor
to be copied without need for details of the descriptor to be interpreted.
*_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.

== [[descriptorblock]]Descriptor block ==

Each Descriptor Block has the same prefix:

.Descriptor Block layout
|================================
| *++uint32_t++* | *_vendorId_* \| (*_descriptorType_* << 16)
| *++uint32_t++* | *_versionNumber_* \| (*_descriptorBlockSize_* << 16)
2+| _Format-specific data_
|================================

The *_vendorId_* is a 16-bit value uniquely assigned to organisations,
allocated by Khronos; ID 0 is used to identify Khronos itself. The
ID 0xFFFF is reserved for internal use which is guaranteed not to
clash with third-party implementations; this ID should not be shipped
in libraries to avoid conflicts with development code.

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

The *_versionNumber_* is vendor-defined, and 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. 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 descriptor block.
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.

.Data format descriptor header and descriptor block headers
[width="75%",cols="1a"]
|=============
|*_totalSize_*
|
[width="100%"]
!=============
! *_vendorId_* \| (*_descriptorType_* << 16)
! *_versionNumber_* \| (*_descriptorBlockSize_* << 16)
! :
!=============
|
[width="100%"]
!=============
! *_vendorId_* \| (*_descriptorType_* << 16)
! *_versionNumber_* \| (*_descriptorBlockSize_* << 16)
! :
!=============
|=============


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

One _basic descriptor block_ is intended to cover a large amount of
metadata that is typically associated with common bulk data -- most notably
image or texture data. While this descriptor contains more information about
the data interpretation than is needed by many applications, having a relatively
comprehensive descriptor reduces the risk that metadata needed by different APIs
will be 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,
containing three samples, one of each color, in one plane.
A _Y&prime;C~B~C~R~_ 4:2:0 format may consist of a repeating 2×2 region
consisting of four _Y&prime;_ samples and one sample each of _C~B~_ and _C~R~_.

.Basic Data Format Descriptor layout
[options="header"]
|================================
| Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB)
2+| 0 (*_vendorId_*) 2+| 0 (*_descriptorType_*)
2+| 0 (*_versionNumber_*) 2+| 24 {plus} 16 × _#samples_ (*_descriptorBlockSize_*)
| *_colorModel_* | *_colorPrimaries_* | *_transferFunction_* | *_flags_* 
| *_texelBlockDimension0_* | *_texelBlockDimension1_* | *_texelBlockDimension2_* | *_texelBlockDimension3_*
| *_bytesPlane0_* | *_bytesPlane1_* | *_bytesPlane2_* | *_bytesPlane3_*
| *_bytesPlane4_* | *_bytesPlane5_* | *_bytesPlane6_* | *_bytesPlane7_*
4+|_Sample information for the first sample_
4+|_Sample information for the second sample (optional), etc._
|================================

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

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

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

=== *_versionNumber_* ===

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

=== *_descriptorBlockSize_* ===

The 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.

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

The available color models are described in the *++khr_df_model_e++* enumeration,
and are represented as an unsigned 8-bit value.

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.

==== *++KHR_DF_MODEL_UNSPECIFIED++* ====

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

This color model represents additive colors of three channels,
nominally red, green and blue, supplemented by channels for
alpha, depth and stencil. 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.

.Basic Data Format _RGBSDA_ channels
[width="100%",options="header"]
|================================
^| Channel number 2+| Name | Description
^| 0 2+| *++KHR_DF_CHANNEL_RGBSDA_RED++* | Red
^| 1 2+| *++KHR_DF_CHANNEL_RGBSDA_GREEN++* | Green
^| 2 2+| *++KHR_DF_CHANNEL_RGBSDA_BLUE++* | Blue
^| 13 2+| *++KHR_DF_CHANNEL_RGBSDA_STENCIL++* | Stencil
^| 14 2+| *++KHR_DF_CHANNEL_RGBSDA_DEPTH++* | Depth
^| 15 2+| *++KHR_DF_CHANNEL_RGBSDA_ALPHA++* | Alpha (opacity)
|================================

Portable representation of additive colors with more than three
primaries requires an extension to describe the full color space
of the channels present. There is no practical way to do this
portably without taking significantly more space.

==== *++KHR_DF_MODEL_YUVSDA++* ====

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.

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+| Name | Description
^| 0 2+| *++KHR_DF_CHANNEL_YUVSDA_Y++* | _Y_/_Y&prime;_ (luma/luminance)
^| 1 2+| *++KHR_DF_CHANNEL_YUVSDA_CB++* | _C~B~_ (alias for _U_)
^| 1 2+| *++KHR_DF_CHANNEL_YUVSDA_U++* | _U_ (alias for _C~B~_)
^| 2 2+| *++KHR_DF_CHANNEL_YUVSDA_CR++* | _C~R~_ (alias for _V_)
^| 2 2+| *++KHR_DF_CHANNEL_YUVSDA_V++* | _V_ (alias for _C~R~_)
^| 13 2+| *++KHR_DF_CHANNEL_YUVSDA_STENCIL++* | Stencil
^| 14 2+| *++KHR_DF_CHANNEL_YUVSDA_DEPTH++* | Depth
^| 15 2+| *++KHR_DF_CHANNEL_YUVSDA_ALPHA++* | Alpha (opacity)
|================================

==== *++KHR_DF_MODEL_YIQSDA++* ====

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+| Name | Description
^| 0 2+| *++KHR_DF_CHANNEL_YIQSDA_Y++* | _Y_ (luma)
^| 1 2+| *++KHR_DF_CHANNEL_YIQSDA_I++* | _I_ (in-phase)
^| 2 2+| *++KHR_DF_CHANNEL_YIQSDA_Q++* | _Q_ (quadrature)
^| 13 2+| *++KHR_DF_CHANNEL_YIQSDA_STENCIL++* | Stencil
^| 14 2+| *++KHR_DF_CHANNEL_YIQSDA_DEPTH++* | Depth
^| 15 2+| *++KHR_DF_CHANNEL_YIQSDA_ALPHA++* | Alpha (opacity)
|================================

==== *++KHR_DF_MODEL_LABSDA++* ====

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+| Name | Description
^| 0 2+| *++KHR_DF_CHANNEL_LABSDA_L++* | _L_* (luma)
^| 1 2+| *++KHR_DF_CHANNEL_LABSDA_A++* | _a_*
^| 2 2+| *++KHR_DF_CHANNEL_LABSDA_B++* | _b_*
^| 13 2+| *++KHR_DF_CHANNEL_LABSDA_STENCIL++* | Stencil
^| 14 2+| *++KHR_DF_CHANNEL_LABSDA_DEPTH++* | Depth
^| 15 2+| *++KHR_DF_CHANNEL_LABSDA_ALPHA++* | Alpha (opacity)
|================================

==== *++KHR_DF_MODEL_CMYKA++* ====

This color model represents secondary (subtractive) colors and
the combined key (black) channel, along with alpha.

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

==== *++KHR_DF_MODEL_XYZW++* ====

This ``color model'' represents channel data used for
coordinate values -- 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+| Name | Description
^| 0 2+| *++KHR_DF_CHANNEL_XYZW_X++* | _X_
^| 1 2+| *++KHR_DF_CHANNEL_XYZW_Y++* | _Y_
^| 2 2+| *++KHR_DF_CHANNEL_XYZW_Z++* | _Z_
^| 3 2+| *++KHR_DF_CHANNEL_XYZW_W++* | _W_
|================================

==== *++KHR_DF_MODEL_HSVA_ANG++* ====

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.
In this model, the hue relates to the angular offset on a color
wheel.

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

==== *++KHR_DF_MODEL_HSLA_ANG++* ====

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.
In this model, the hue relates to the angular offset on a color
wheel.

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

==== *++KHR_DF_MODEL_HSVA_HEX++* ====

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.
In this model, the hue is generated by interpolation between
extremes on a color hexagon.

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

==== *++KHR_DF_MODEL_HSLA_HEX++* ====

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.
In this model, the hue is generated by interpolation between
extremes on a color hexagon.

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

==== *++KHR_DF_MODEL_YCGCOA++* ====

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+| Name | Description
^| 0 2+| *++KHR_DF_CHANNEL_YCGCOA_Y++* | _Y_
^| 1 2+| *++KHR_DF_CHANNEL_YCGCOA_CG++* | _Cg_
^| 2 2+| *++KHR_DF_CHANNEL_YCGCOA_CO++* | _Co_
^| 15 2+| *++KHR_DF_CHANNEL_YCGCOA_ALPHA++* | Alpha (opacity)
|================================

<<<

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

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.

Floating-point compressed formats have lower and upper limits specified
in floating point format. 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.

==== *++KHR_DF_MODEL_DXT1A++*/*++KHR_DF_MODEL_BC1A++* ====

This model represents the DXT1 or BC1 format. Channel 0 indicates
color. If a second sample is present it should use channel 1 to indicate
that the ``special value'' of the format should represent transparency --
otherwise the ``special value'' represents opaque black.

==== *++KHR_DF_MODEL_DXT2++*/*++3++*/*++KHR_DF_MODEL_BC2++* ====

This model represents the DXT2/3 format, also described as BC2. The
alpha premultiplication state (the distinction between DXT2 and DXT3)
is recorded separately in the descriptor. This model has two channels:
ID 0 contains the color information and ID 15 contains the alpha
information. 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.

==== *++KHR_DF_MODEL_DXT4++*/*++5++*/*++KHR_DF_MODEL_BC3++* ====

This model represents the DXT4/5 format, also described as BC3. The
alpha premultiplication state (the distinction between DXT4 and DXT5)
is recorded separately in the descriptor. This model has two channels:
ID 0 contains the color information and ID 15 contains the alpha
information. The alpha channel is 64 bits and at offset 0; the color
channel is 64 bits and at offset 64.

==== *++KHR_DF_MODEL_BC4++* ====

This model represents the Direct3D BC4 format for single-channel
interpolated 8-bit data. The model has a single channel of id 0
with offset 0 and length 64 bits.

==== *++KHR_DF_MODEL_BC5++* ====

This model represents the Direct3D BC5 format for dual-channel
interpolated 8-bit data. 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.

==== *++KHR_DF_MODEL_BC6H++* ====

This model represents the Direct3D BC6H format for _RGB_ floating-point data.
The model has a single channel 0, representing all three channels, and
occupying 128 bits.

==== *++KHR_DF_MODEL_BC7++* ====

This model represents the Direct3D BC7 format for _RGBA_ data. This model
has a single channel 0 of 128 bits.

==== *++KHR_DF_MODEL_ETC1++* ====

This model represents the original Ericsson Texture Compression format,
with a guarantee that the format does not rely on ETC2 extensions. It
contains a single channel of _RGB_ data.

==== *++KHR_DF_MODEL_ETC2++* ====

This model represents the updated Ericsson Texture Compression format,
ETC2. Channel 0 represents red, and is used for the R11 EAC format.
Channel 1 represents green, and both red and green should be present
for the RG11 EAC format. Channel 2 represents _RGB_ combined content.
Channel 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. 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.

==== *++KHR_DF_MODEL_ASTC++* ====

This model represents <<astc,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. The single sample has a size of 128 bits.

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

==== *++KHR_DF_PRIMARIES_UNSPECIFIED++* ====

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

This value represents the Color Primaries defined by the
<<bt709,ITU-R BT.709 specification>>, 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.
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++* ====

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

==== *++KHR_DF_PRIMARIES_BT601_SMPTE++* ====

This value represents the Color Primaries defined in the
<<bt601,ITU-R BT.601 specification>> for standard-definition television,
particularly for 525-line signals.
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.

==== *++KHR_DF_PRIMARIES_BT2020++* ====

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

==== *++KHR_DF_PRIMARIES_CIEXYZ++* ====

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

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

=== *_transferFunction_* ===

Many color representations contain a nonlinear transfer function
which maps between a linear (intensity-based) representation and
a more perceptually-uniform encoding. Common Transfer Functions are
encoded in the *++khr_df_transfer_e++* enumeration and represented as an
unsigned 8-bit integer. 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.

==== *++KHR_DF_TRANSFER_UNSPECIFIED++* ====

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

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

This value represents the nonlinear Transfer Function defined in
the <<srgb,sRGB specification>> for mapping between numerical pixel values
and intensity.

==== *++KHR_DF_TRANSFER_ITU++* ====

This value represents the nonlinear Transfer Function defined by
the ITU and used in the BT.601, BT.709 and BT.2020 specifications.

==== *++KHR_DF_TRANSFER_NTSC++* ====

This value represents the nonlinear Transfer Function defined by
the original NTSC television broadcast specification.

==== *++KHR_DF_TRANSFER_SLOG++* ====

This value represents a nonlinear Transfer Function used by some
Sony video cameras to represent an increased dynamic range.

==== *++KHR_DF_TRANSFER_SLOG2++* ====

This value represents a nonlinear Transfer Function used by some
Sony video cameras to represent a further increased dynamic range.

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

In this version of the specification, the only flag defined is
*++KHR_DF_FLAG_ALPHA_PREMULTIPIED++*. If this bit is set, any color
information in the data should be interpreted as having been
previously scaled by the alpha channel when performing blending
operations. The value *++KHR_DF_FLAG_ALPHA_STRAIGHT++* is provided to
represent this flag not being set, which indicates that the 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.
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
|================================

=== *_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 texels (of up to 255 bytes). 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.

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 that plane contributes
to the format. 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.

As an exception, if *_bytesPlane0_* has the value 0, the first plane
is considered to hold indices into a color palette, which is described
by one or more additional planes and samples in the normal way. The
first sample in this case should describe a 1×1×1×1 texel holding an
unsigned integer value. The number of bits used by the index should be
encoded in this sample, with a maximum value of the largest palette
entry held in *_sampleUpper_*. Subsequent samples describe the entries in
the palette, starting at an offset of bit 0. Note that the texel block in
the index plane is not required to be byte-aligned in this case, and will
not be for paletted formats which have small palettes. The channel type
for the index is irrelevant.

For example, consider a 5-color paletted texture which describes each of
these colors using 8 bits of red, green, blue and alpha. The color model
would be _RGBSDA_, and the format would be described with two planes.
*_bytesPlane0_* would be 0, indicating the special case of a palette, and
*_bytesPlane1_* would be 4, representing the size of the palette entry.
The first sample would then have a number of bits corresponding to the
number of bits for the palette -- in this case, three bits, corresponding
to the requirements of a 5-color palette. The *_sampleUpper_* value for this
sample is 4, indicating only 5 palette entries. Four subsequent samples
represent the red, green, blue and alpha channels, starting from bit 0
as though the index value were not present, and describe the contents of
the palette. The full data format descriptor for this example is
<<palette,provided>> as one of the example format descriptors.

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

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 nonconsecutive 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. Note that 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
<<bigendian,example>> in the list of format descriptors provided.
In this case, the *_sampleLower_* and *_sampleUpper_* fields for the
combined sample are taken from the first sample to belong uniquely
to this channel/position pair.

By convention, to avoid aliases for formats, samples should be
listed in order starting with channels at the lowest bits of this
bit stream.

The number of samples present in the format is determined by the
*_descriptorBlockSize_* field.
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).

.Basic Data Format Descriptor Sample Information
[options="header"]
|================================
| Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB)
2+| *_bitOffset_* | *_bitLength_* | *_channelType_*
| *_samplePosition0_* | *_samplePosition1_* | *_samplePosition2_* | *_samplePosition3_*
4+| *_sampleLower_*
4+| *_sampleUpper_*
|================================

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

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

==== *_channelType_* ====

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_* field for the list of channels for each model.

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

If the *++KHR_DF_SAMPLE_DATATYPE_LINEAR++* bit is not set, the sample value is
modified by the transfer function defined in the format's *_transferFunction_*
field; if this bit is set, the sample is considered to contain a
linearly-encoded value irrespective of the format's *_transferFunction_*.

If the *++KHR_DF_SAMPLE_DATATYPE_EXPONENT++* bit is set, this sample holds an
exponent (in integer form) for this channel. For example, this would be
used to describe the shared exponent location in shared exponent formats
(with the exponent bits listed separately under each channel). An exponent
is applied to any integer sample of the same type. If this bit is not set,
the sample is considered to contain mantissa information. If the
*++KHR_DF_SAMPLE_DATATYPE_SIGNED++* bit 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 sample's lower and upper values.
The presence or absence of an implicit leading digit in the mantissa of a
format with an exponent can be determined by the upper value.

If the *++KHR_DF_SAMPLE_DATATYPE_SIGNED++* bit 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 is set, the sample holds floating
point data in a conventional format of 10, 11, 16, 32, or 64-bits.
*++KHR_DF_SAMPLE_DATATYPE_SIGNED++* should be set unless a genuine unsigned
format is intended. Less common floating point representations can be
generated with multiple samples and a combination of signed integer,
unsigned integer and exponent fields.

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

The sample has an associated location within the 4-dimensional space of
the texel block. Each sample has an offset relative to the 0,0 position
of the texel block, determined in units of half a coordinate. This allows
the common situation of downsampled channels to have samples conceptually
sited at the midpoint between full resolution samples. Support for offsets
other than multiples of a half coordinates require an extension. 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.

Each *_samplePosition_* is an 8-bit unsigned integer quantity.
*_samplePosition0_* is the X offset of the sample, *_samplePosition1_*
is the Y offset of the sample, etc. Formats which use an offset
larger than 127.5 in any dimension require an extension.

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

==== *_sampleLower_* ====

*_sampleLower_*, combined with *_sampleUpper_*, is used to represent 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''.

If the channel encoding is an integer format, the *_sampleLower_* value
is represented as a 32-bit integer -- signed or unsigned according to
whether the channel encoding is signed. If the channel encoding is a
floating point value, the *_sampleLower_* value is also floating point.
If the number of bits in the sample is greater than 32, the lowest
representable value for *_sampleLower_* is interpreted as the smallest
value representable in the channel format.

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. In this case, *_sampleLower_* should contain the value 16.

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 is equivalent to
defining an ``snorm'' texture.

==== *_sampleUpper_* ====

*_sampleUpper_*, combined with *_sampleLower_*, is used to represent the
mapping between the numerical value stored in the format and the
conceptual numerical interpretation. *_sampleUpper_* typically represents
the value which should be interpreted as ``1.0'' (the ``white point'').

If the channel encoding is an integer format, the *_sampleUpper_* value
is represented as a 32-bit integer -- signed or unsigned according to
whether the channel encoding is signed. If the channel encoding is a
floating point value, the *_sampleUpper_* value is also floating point.
If the number of bits in the sample is greater than 32, the highest
representable value for *_sampleUpper_* is interpreted as the largest
value representable in the channel format.

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. In this case, *_sampleUpper_* should contain the value 235.

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

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.

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

As an example, consider a single-channel 32-bit depth buffer. 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 0xFFFF 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.

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.

.Example of a depth buffer with an extension to indicate a virtual allocation
[width="100%",cols="1a"]
|=============
|56 (*_totalSize_*: total size of the two blocks plus one 32-bit value)
[width="100%",cols="4"]
!=============
4+^! ~Basic descriptor block~
2+! 0 (*_vendorId_*) 2+! 0 (*_descriptorType_*)
2+! 0 (*_versionNumber_*) 2+! 40 (*_descriptorBlockSize_*)
! *++RGBSDA++* (*_colorModel_*) ! *++UNSPECIFIED++* (*_colorPrimaries_*) ! *++UNSPECIFIED++* (*_transferFunction_*) ! 0 (*_flags_*)
! 0 (*_texelBlockDimension0_*) ! 0 (*_texelBlockDimension1_*) ! 0 (*_texelBlockDimension2_*) ! 0 (*_texelBlockDimension3_*)
! 4 (*_bytesPlane0_*) ! 0 (*_bytesPlane1_*) ! 0 (*_bytesPlane2_*) ! 0 (*_bytesPlane3_*)
! 0 (*_bytesPlane4_*) ! 0 (*_bytesPlane5_*) ! 0 (*_bytesPlane6_*) ! 0 (*_bytesPlane7_*)
4+^! ~Sample information for the depth value~
2+! 0 (*_bitOffset_*) ! 31 (= ``32'') (*_bitLength_*) ! *++SIGNED++* \| *++FLOAT++* \| *++DEPTH++*
! 0 (*_samplePosition0_*) ! 0 (*_samplePosition1_*) ! 0 (*_samplePosition2_*) ! 0 (*_samplePosition3_*)
4+! 0xbf800000 (*_sampleLower_*: -1.0f)
4+! 0x3f800000U (*_sampleUpper_*: 1.0f)
4+^! ~Extension descriptor block~
2+! 0xFFFF (*_vendorId_*) 2+! 0 (*_descriptorType_*)
2+! 0 (*_versionNumber_*) 2+! 12 (*_descriptorBlockSize_*)
4+! _Data specific to the extension follows_
4+! 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 nonlinear 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..


== 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 behaviours. 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 behaviour 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 format 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.

== External references ==

=== [[astc]]Adaptive Scalable Texture Compression ===

link:https://www.khronos.org/registry/gles/extensions/KHR/texture_compression_astc_hdr.txt[https://www.khronos.org/registry/gles/extensions/KHR/texture_compression_astc_hdr.txt]

=== [[bt601]]ITU-T BT.601 specification for digital television ===

link:http://www.itu.int/rec/R-REC-BT.601/en[http://www.itu.int/rec/R-REC-BT.601/en]

=== [[bt709]]ITU-T BT.709 specification for HDTV ===

link:http://www.itu.int/rec/R-REC-BT.709-5-200204-I/en[http://www.itu.int/rec/R-REC-BT.709-5-200204-I/en]

=== [[bt2020]]ITU-T BT.2020 specification for UHDTV ===

link:http://www.itu.int/rec/R-REC-BT.2020/en[http://www.itu.int/rec/R-REC-BT.2020/en]

=== [[ciexyz]]CIE 1931 _XYZ_ tristimulus values ===

link:http://cie.co.at/index.php?i_ca_id=823[http://cie.co.at/index.php?i_ca_id=823]

=== [[aces]]Academy Color Encoding System ===

link:http://www.oscars.org/science-technology/sci-tech-projects/aces[http://www.oscars.org/science-technology/sci-tech-projects/aces]

=== [[srgb]]sRGB specification ===

link:http://www.w3.org/Graphics/Color/srgb[http://www.w3.org/Graphics/Color/srgb]

== Example format descriptors ==

.Four co-sited 8-bit sRGB channels, assuming premultiplied alpha
[options="header"]
|================================
| Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB)
4+| 92 (*_totalSize_*)
2+| 0 (*_vendorId_*) 2+| 0 (*_descriptorType_*)
2+| 0 (*_versionNumber_*) 2+| 88 (*_descriptorBlockSize_*)
| *++RGBSDA++* (*_colorModel_*) | *++BT709++* (*_colorPrimaries_*) | *++SRGB++* (*_transferFunction_*) | *++PREMULTIPLIED++* (*_flags_*)
| 0 (*_texelBlockDimension0_*) | 0 (*_texelBlockDimension1_*) | 0 (*_texelBlockDimension2_*) | 0 (*_texelBlockDimension3_*)
| 4 (*_bytesPlane0_*) | 0 (*_bytesPlane1_*) | 0 (*_bytesPlane2_*) | 0 (*_bytesPlane3_*)
| 0 (*_bytesPlane4_*) | 0 (*_bytesPlane5_*) | 0 (*_bytesPlane6_*) | 0 (*_bytesPlane7_*)
4+^|~Sample information for the first sample~
2+| 0 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 0 (*_channelType_*) (*++RED++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 255 (*_sampleUpper_*)
4+^|~Sample information for the second sample~
2+| 8 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 1 (*_channelType_*) (*++GREEN++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 255 (*_sampleUpper_*)
4+^|~Sample information for the third sample~
2+| 16 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 2 (*_channelType_*) (*++BLUE++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 255 (*_sampleUpper_*)
4+^|~Sample information for the fourth sample~
2+| 24 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 31 (*_channelType_*)

(*++ALPHA++* \| *++LINEAR++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 255 (*_sampleUpper_*)
|================================

[[565DFD]]
.565 _RGB_ packed 16-bit format as written to memory by a little-endian architecture
[options="header"]
|================================
| Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB)
4+| 76 (*_totalSize_*)
2+| 0 (*_vendorId_*) 2+| 0 (*_descriptorType_*)
2+| 0 (*_versionNumber_*) 2+| 72 (*_descriptorBlockSize_*)
| *++RGBSDA++* (*_colorModel_*) | *++BT709++* (*_colorPrimaries_*) | *++LINEAR++* (*_transferFunction_*) | *++ALPHA_STRAIGHT++* (*_flags_*)
| 0 (*_texelBlockDimension0_*) | 0 (*_texelBlockDimension1_*) | 0 (*_texelBlockDimension2_*) | 0 (*_texelBlockDimension3_*)
| 2 (*_bytesPlane0_*) | 0 (*_bytesPlane1_*) | 0 (*_bytesPlane2_*) | 0 (*_bytesPlane3_*)
| 0 (*_bytesPlane4_*) | 0 (*_bytesPlane5_*) | 0 (*_bytesPlane6_*) | 0 (*_bytesPlane7_*)
4+^|~Sample information for the first sample: 5 bits of blue~
2+| 0 (*_bitOffset_*) | 4 (= ``5'') (*_bitLength_*) | 2 (*_channelType_*) (*++BLUE++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 31 (*_sampleUpper_*)
4+^|~Sample information for the second sample: 6 bits of green~
2+| 5 (*_bitOffset_*) | 5 (= ``6'') (*_bitLength_*) | 1 (*_channelType_*) (*++GREEN++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 63 (*_sampleUpper_*)
4+^|~Sample information for the third sample: 5 bits of red~
2+| 11 (*_bitOffset_*) | 4 (= ``5'') (*_bitLength_*) | 0 (*_channelType_*) (*++RED++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 31 (*_sampleUpper_*)
|================================

.A single 8-bit monochrome channel
[options="header"]
|================================
| Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB)
4+| 44 (*_totalSize_*)
2+| 0 (*_vendorId_*) 2+| 0 (*_descriptorType_*)
2+| 0 (*_versionNumber_*) 2+| 40 (*_descriptorBlockSize_*)
| *++YUVSDA++* (*_colorModel_*) | *++BT709++* (*_colorPrimaries_*) | *++ITU++* (*_transferFunction_*) | *++ALPHA_STRAIGHT++* (*_flags_*)
| 0 (*_texelBlockDimension0_*) | 0 (*_texelBlockDimension1_*) | 0 (*_texelBlockDimension2_*) | 0 (*_texelBlockDimension3_*)
| 4 (*_bytesPlane0_*) | 0 (*_bytesPlane1_*) | 0 (*_bytesPlane2_*) | 0 (*_bytesPlane3_*)
| 0 (*_bytesPlane4_*) | 0 (*_bytesPlane5_*) | 0 (*_bytesPlane6_*) | 0 (*_bytesPlane7_*)
4+^|~Sample information for the first sample~
2+| 0 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 255 (*_sampleUpper_*)
|================================

.A single 1-bit monochrome channel, as an 8×1 texel block to allow byte-alignment
[options="header"]
|================================
| Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB)
4+| 156 (*_totalSize_*)
2+| 0 (*_vendorId_*) 2+| 0 (*_descriptorType_*)
2+| 0 (*_versionNumber_*) 2+| 152 (*_descriptorBlockSize_*)
| *++YUVSDA++* (*_colorModel_*) | *++BT709++* (*_colorPrimaries_*) | *++LINEAR++* (*_transferFunction_*) | *++ALPHA_STRAIGHT++* (*_flags_*)
| 7 (*_texelBlockDimension0_*) | 0 (*_texelBlockDimension1_*) | 0 (*_texelBlockDimension2_*) | 0 (*_texelBlockDimension3_*)
| 1 (*_bytesPlane0_*) | 0 (*_bytesPlane1_*) | 0 (*_bytesPlane2_*) | 0 (*_bytesPlane3_*)
| 0 (*_bytesPlane4_*) | 0 (*_bytesPlane5_*) | 0 (*_bytesPlane6_*) | 0 (*_bytesPlane7_*)
4+^|~Sample information for the first sample~
2+| 0 (*_bitOffset_*) | 0 (= ``1'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 1 (*_sampleUpper_*)
4+^|~Sample information for the second sample~
2+| 1 (*_bitOffset_*) | 0 (= ``1'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
| 2 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 1 (*_sampleUpper_*)
4+^|~Sample information for the third sample~
2+| 2 (*_bitOffset_*) | 0 (= ``1'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
| 4 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 1 (*_sampleUpper_*)
4+^|~Sample information for the fourth sample~
2+| 3 (*_bitOffset_*) | 0 (= ``1'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
| 6 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 1 (*_sampleUpper_*)
4+^|~Sample information for the fifth sample~
2+| 4 (*_bitOffset_*) | 0 (= ``1'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
| 8 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 1 (*_sampleUpper_*)
4+^|~Sample information for the sixth sample~
2+| 5 (*_bitOffset_*) | 0 (= ``1'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
| 10 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 1 (*_sampleUpper_*)
4+^|~Sample information for the seventh sample~
2+| 6 (*_bitOffset_*) | 0 (= ``1'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
| 12 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 1 (*_sampleUpper_*)
4+^|~Sample information for the eighth sample~
2+| 7 (*_bitOffset_*) | 0 (= ``1'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
| 14 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 1 (*_sampleUpper_*)
|================================

.2×2 Bayer pattern: four 8-bit distributed sRGB channels, spread across two lines (so two planes)
[options="header"]
|================================
| Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB)
4+| 92 (*_totalSize_*)
2+| 0 (*_vendorId_*) 2+| 0 (*_descriptorType_*)
2+| 0 (*_versionNumber_*) 2+| 88 (*_descriptorBlockSize_*)
| *++RGBSDA++* (*_colorModel_*) | *++BT709++* (*_colorPrimaries_*) | *++SRGB++* (*_transferFunction_*) | *++ALPHA_STRAIGHT++* (*_flags_*)
| 1 (*_texelBlockDimension0_*) | 1 (*_texelBlockDimension1_*) | 0 (*_texelBlockDimension2_*) | 0 (*_texelBlockDimension3_*)
| 2 (*_bytesPlane0_*) | 2 (*_bytesPlane1_*) | 0 (*_bytesPlane2_*) | 0 (*_bytesPlane3_*)
| 0 (*_bytesPlane4_*) | 0 (*_bytesPlane5_*) | 0 (*_bytesPlane6_*) | 0 (*_bytesPlane7_*)
4+^|~Sample information for the first sample~
2+| 0 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 0 (*_channelType_*) (*++RED++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 255 (*_sampleUpper_*)
4+^|~Sample information for the second sample~
2+| 8 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 1 (*_channelType_*) (*++GREEN++*)
| 2 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 255 (*_sampleUpper_*)
4+^|~Sample information for the third sample~
2+| 16 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 1 (*_channelType_*) (*++GREEN++*)
| 0 (*_samplePosition0_*) | 2 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 255 (*_sampleUpper_*)
4+^|~Sample information for the fourth sample~
2+| 24 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 2 (*_channelType_*) (*++BLUE++*)
| 2 (*_samplePosition0_*) | 2 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 255 (*_sampleUpper_*)
|================================

.[[palette]]Four co-sited 8-bit channels in the sRGB color space described by an 5-entry, 3-bit palette
[options="header"]
|================================
| Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB)
4+| 108 (*_totalSize_*)
2+| 0 (*_vendorId_*) 2+| 0 (*_descriptorType_*)
2+| 0 (*_versionNumber_*) 2+| 104 (*_descriptorBlockSize_*)
| *++RGBSDA++* (*_colorModel_*) | *++BT709++* (*_colorPrimaries_*) | *++SRGB++* (*_transferFunction_*) | *++PREMULTIPLIED++* (*_flags_*)
| 0 (*_texelBlockDimension0_*) | 0 (*_texelBlockDimension1_*) | 0 (*_texelBlockDimension2_*) | 0 (*_texelBlockDimension3_*)
| 0 (*_bytesPlane0_*) | 4 (*_bytesPlane1_*) | 0 (*_bytesPlane2_*) | 0 (*_bytesPlane3_*)
| 0 (*_bytesPlane4_*) | 0 (*_bytesPlane5_*) | 0 (*_bytesPlane6_*) | 0 (*_bytesPlane7_*)
4+^|~Sample information for the palette index~
2+| 0 (*_bitOffset_*) | 2 (= ``3'') (*_bitLength_*) | 0 (*_channelType_*) (irrelevant)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 4 (*_sampleUpper_*) -- this specifies that there are 5 palette entries
4+^|~Sample information for the first sample~
2+| 0 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 0 (*_channelType_*) (*++RED++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 255 (*_sampleUpper_*)
4+^|~Sample information for the second sample~
2+| 8 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 1 (*_channelType_*) (*++GREEN++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 255 (*_sampleUpper_*)
4+^|~Sample information for the third sample~
2+| 16 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 2 (*_channelType_*) (*++BLUE++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 255 (*_sampleUpper_*)
4+^|~Sample information for the fourth sample~
2+| 24 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 31 (*_channelType_*)

(*++ALPHA++* \| *++LINEAR++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 255 (*_sampleUpper_*)
|================================

._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_ samples
[options="header"]
|================================
| Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB)
4+| 124 (*_totalSize_*)
2+| 0 (*_vendorId_*) 2+| 0 (*_descriptorType_*)
2+| 0 (*_versionNumber_*) 2+| 120 (*_descriptorBlockSize_*)
| *++YUVSDA++* (*_colorModel_*) | *++BT709++* (*_colorPrimaries_*) | *++ITU++* (*_transferFunction_*) | *++ALPHA_STRAIGHT++* (*_flags_*)
| 1 (*_texelBlockDimension0_*) | 1 (*_texelBlockDimension1_*) | 0 (*_texelBlockDimension2_*) | 0 (*_texelBlockDimension3_*)
| 2 (*_bytesPlane0_*) | 2 (*_bytesPlane1_*) | 1 (*_bytesPlane2_*) | 1 (*_bytesPlane3_*)
| 0 (*_bytesPlane4_*) | 0 (*_bytesPlane5_*) | 0 (*_bytesPlane6_*) | 0 (*_bytesPlane7_*)
4+^|~Sample information for the first _Y_ sample~
2+| 0 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 16 (*_sampleLower_*)
4+| 235 (*_sampleUpper_*)
4+^|~Sample information for the second _Y_ sample~
2+| 8 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
| 2 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 16 (*_sampleLower_*)
4+| 235 (*_sampleUpper_*)
4+^|~Sample information for the third _Y_ sample~
2+| 16 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
| 0 (*_samplePosition0_*) | 2 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 16 (*_sampleLower_*)
4+| 235 (*_sampleUpper_*)
4+^|~Sample information for the fourth _Y_ sample~
2+| 24 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
| 2 (*_samplePosition0_*) | 2 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 16 (*_sampleLower_*)
4+| 235 (*_sampleUpper_*)
4+^|~Sample information for the _U_ sample~
2+| 32 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 1 (*_channelType_*) (*++U++*)
| 1 (*_samplePosition0_*) | 1 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 16 (*_sampleLower_*)
4+| 240 (*_sampleUpper_*)
4+^|~Sample information for the _V_ sample~
2+| 36 (*_bitOffset_*) | 7 (= ``8'') (*_bitLength_*) | 2 (*_channelType_*) (*++V++*)
| 1 (*_samplePosition0_*) | 1 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 16 (*_sampleLower_*)
4+| 240 (*_sampleUpper_*)
|================================

[[bigendian]]
.565 _RGB_ packed 16-bit format as written to memory by a big-endian architecture
[options="header"]
|================================
| Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB)
4+| 92 (*_totalSize_*)
2+| 0 (*_vendorId_*) 2+| 0 (*_descriptorType_*)
2+| 0 (*_versionNumber_*) 2+| 88 (*_descriptorBlockSize_*)
| *++RGBSDA++* (*_colorModel_*) | *++BT709++* (*_colorPrimaries_*) | *++SRGB++* (*_transferFunction_*) | *++ALPHA_STRAIGHT++* (*_flags_*)
| 0 (*_texelBlockDimension0_*) | 0 (*_texelBlockDimension1_*) | 0 (*_texelBlockDimension2_*) | 0 (*_texelBlockDimension3_*)
| 2 (*_bytesPlane0_*) | 0 (*_bytesPlane1_*) | 0 (*_bytesPlane2_*) | 0 (*_bytesPlane3_*)
| 0 (*_bytesPlane4_*) | 0 (*_bytesPlane5_*) | 0 (*_bytesPlane6_*) | 0 (*_bytesPlane7_*)
4+^|~Sample information for the first sample: bit 0 belongs to green, bits 0..2 of channel in 13..15~
2+| 13 (*_bitOffset_*) | 2 (= ``3'') (*_bitLength_*) | 1 (*_channelType_*) (*++GREEN++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 63 (*_sampleUpper_*)
4+^|~Sample information for the second sample: bits 3..5 of green in 0..2~
2+| 0 (*_bitOffset_*) | 2 (= ``3'') (*_bitLength_*) | 1 (*_channelType_*) (*++GREEN++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*) -- ignored, taken from first sample
4+| 0 (*_sampleUpper_*) -- ignored, taken from first sample
4+^|~Sample information for the third sample~
2+| 3 (*_bitOffset_*) | 4 (= ``5'') (*_bitLength_*) | 2 (*_channelType_*) (*++BLUE++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 31 (*_sampleUpper_*)
4+^|~Sample information for the fourth sample~
2+| 8 (*_bitOffset_*) | 4 (= ``5'') (*_bitLength_*) | 1 (*_channelType_*) (*++RED++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 31 (*_sampleUpper_*)
|================================

.R9G9B9E5 shared-exponent format
[options="header"]
|================================
| Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB)
4+| 124 (*_totalSize_*)
2+| 0 (*_vendorId_*) 2+| 0 (*_descriptorType_*)
2+| 0 (*_versionNumber_*) 2+| 120 (*_descriptorBlockSize_*)
| *++RGBSDA++* (*_colorModel_*) | *++BT709++* (*_colorPrimaries_*) | *++LINEAR++* (*_transferFunction_*) | *++ALPHA_STRAIGHT++* (*_flags_*)
| 0 (*_texelBlockDimension0_*) | 0 (*_texelBlockDimension1_*) | 0 (*_texelBlockDimension2_*) | 0 (*_texelBlockDimension3_*)
| 4 (*_bytesPlane0_*) | 0 (*_bytesPlane1_*) | 0 (*_bytesPlane2_*) | 0 (*_bytesPlane3_*)
| 0 (*_bytesPlane4_*) | 0 (*_bytesPlane5_*) | 0 (*_bytesPlane6_*) | 0 (*_bytesPlane7_*)
4+^|~Sample information for the _R_ mantissa~
2+| 0 (*_bitOffset_*) | 8 (= ``9'') (*_bitLength_*) | 0 (*_channelType_*) (*++RED++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 256 (*_sampleUpper_*) -- mantissa at 1.0
4+^|~Sample information for the _R_ exponent~
2+| 27 (*_bitOffset_*) | 4 (= ``5'') (*_bitLength_*) | 32 (*_channelType_*)

(*++RED++* \| *++EXPONENT++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 15 (*_sampleUpper_*) -- exponent bias
4+^|~Sample information for the _G_ mantissa~
2+| 9 (*_bitOffset_*) | 8 (= ``9'') (*_bitLength_*) | 1 (*_channelType_*) (*++GREEN++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 256 (*_sampleUpper_*) -- mantissa at 1.0
4+^|~Sample information for the _G_ exponent~
2+| 27 (*_bitOffset_*) | 4 (= ``5'') (*_bitLength_*) | 33 (*_channelType_*)

(*++GREEN++* \| *++EXPONENT++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 15 (*_sampleUpper_*) -- exponent bias
4+^|~Sample information for the _B_ mantissa~
2+| 18 (*_bitOffset_*) | 8 (= ``9'') (*_bitLength_*) | 2 (*_channelType_*) (*++BLUE++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 256 (*_sampleUpper_*) -- mantissa at 1.0
4+^|~Sample information for the _B_ exponent~
2+| 27 (*_bitOffset_*) | 4 (= ``5'') (*_bitLength_*) | 34 (*_channelType_*)

(*++BLUE++* \| *++EXPONENT++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 15 (*_sampleUpper_*) -- exponent bias
|================================

.Acorn 256-color format (2 bits each independent _RGB_, 2 bits shared ``tint'')
[options="header"]
|================================
| Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB)
4+| 108 (*_totalSize_*)
2+| 0 (*_vendorId_*) 2+| 0 (*_descriptorType_*)
2+| 0 (*_versionNumber_*) 2+| 104 (*_descriptorBlockSize_*)
| *++RGBSDA++* (*_colorModel_*) | *++BT709++* (*_colorPrimaries_*) | *++LINEAR++* (*_transferFunction_*) | *++ALPHA_STRAIGHT++* (*_flags_*)
| 0 (*_texelBlockDimension0_*) | 0 (*_texelBlockDimension1_*) | 0 (*_texelBlockDimension2_*) | 0 (*_texelBlockDimension3_*)
| 1 (*_bytesPlane0_*) | 0 (*_bytesPlane1_*) | 0 (*_bytesPlane2_*) | 0 (*_bytesPlane3_*)
| 0 (*_bytesPlane4_*) | 0 (*_bytesPlane5_*) | 0 (*_bytesPlane6_*) | 0 (*_bytesPlane7_*)
4+^|~Sample information for the _R_ value and tint (shared low bits)~
2+| 0 (*_bitOffset_*) | 3 (= ``4'') (*_bitLength_*) | 0 (*_channelType_*) (*++RED++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 15 (*_sampleUpper_*) -- unique _R_ upper value
4+^|~Sample information for the _G_ tint (shared low bits)~
2+| 0 (*_bitOffset_*) | 1 (= ``2'') (*_bitLength_*) | 1 (*_channelType_*) (*++GREEN++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 0 (*_sampleUpper_*) -- ignored, not unique
4+^|~Sample information for the _G_ unique (high) bits~
2+| 4 (*_bitOffset_*) | 1 (= ``2'') (*_bitLength_*) | 1 (*_channelType_*) (*++GREEN++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 15 (*_sampleUpper_*) -- unique _G_ upper value
4+^|~Sample information for the _B_ tint (shared low bits)~
2+| 0 (*_bitOffset_*) | 1 (= ``2'') (*_bitLength_*) | 2 (*_channelType_*) (*++BLUE++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 0 (*_sampleUpper_*) -- ignored, not unique
4+^|~Sample information for the _B_ unique (high) bits~
2+| 6 (*_bitOffset_*) | 1 (= ``2'') (*_bitLength_*) | 2 (*_channelType_*) (*++BLUE++*)
| 0 (*_samplePosition0_*) | 0 (*_samplePosition1_*) | 0 (*_samplePosition2_*) | 0 (*_samplePosition3_*)
4+| 0 (*_sampleLower_*)
4+| 15 (*_sampleUpper_*) -- unique _B_ upper value
|================================

.V210 format (full-range _Y&prime;C~B~C~R~_) part 1 of 2
[options="header"]
|================================
| Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB)
4+| 220 (*_totalSize_*)
2+| 0 (*_vendorId_*) 2+| 0 (*_descriptorType_*)
2+| 0 (*_versionNumber_*) 2+| 216 (*_descriptorBlockSize_*) -- 12 samples
| *++YUVSDA++* (*_colorModel_*) | *++BT709++* (*_colorPrimaries_*) | *++ITU++* (*_transferFunction_*) | *++ALPHA_STRAIGHT++* (*_flags_*)
| 5 (*_dimension0_*) | 0 (*_dimension1_*) | 0 (*_dimension2_*) | 0 (*_dimension3_*)
| 16 (*_bytesPlane0_*) | 0 (*_bytesPlane1_*) | 0 (*_bytesPlane2_*) | 0 (*_bytesPlane3_*)
| 0 (*_bytesPlane4_*) | 0 (*_bytesPlane5_*) | 0 (*_bytesPlane6_*) | 0 (*_bytesPlane7_*)
4+^|~Sample information for the shared _U0_/_U1_ value~
2+|0 (*_bitOffset_*)     | 9 (= ``10'') (*_bitLength_*) | 1 (*_channelType_*) (*++U++*)
|1 (assume mid-sited)      |  0       | 0       | 0
4+|0 (*_sampleLower_*)
4+|1023 (*_sampleUpper_*)
4+^|~Sample information for the _Y&prime;0_ value~
2+|10 (*_bitOffset_*)    | 9 (= ``10'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
|0       |  0       | 0       | 0
4+|0 (*_sampleLower_*)
4+|1023 (*_sampleUpper_*)
4+^|~Sample information for the shared _V0_/_V1_ value~
2+|20 (*_bitOffset_*)    | 9 (= ``10'') (*_bitLength_*) | 2 (*_channelType_*) (*++V++*)
|1 (assume mid-sited)      |  0       | 0       | 0
4+|0 (*_sampleLower_*)
4+|1023 (*_sampleUpper_*)
4+^|~Sample information for the _Y&prime;1_ value~
2+|32 (*_bitOffset_*)    | 9 (= ``10'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
|2       |  0       | 0       | 0
4+|0 (*_sampleLower_*)
4+|1023 (*_sampleUpper_*)
4+^|~Sample information for the shared _U2_/_U3_ value~
2+|42 (*_bitOffset_*)    | 9 (= ``10'') (*_bitLength_*) | 1 (*_channelType_*) (*++U++*)
|5 (assume mid-sited)      |  0       | 0       | 0
4+|0 (*_sampleLower_*)
4+|1023 (*_sampleUpper_*)
4+^|~Sample information for the _Y&prime;2_ value~
2+|52 (*_bitOffset_*)    | 9 (= ``10'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
|4       |  0       | 0       | 0
4+|0 (*_sampleLower_*)
4+|1023 (*_sampleUpper_*)
|================================

.V210 format (full-range _Y&prime;C~B~C~R~_) part 2 of 2
[options="header"]
|================================
| Byte 0 (LSB) | Byte 1 | Byte 2 | Byte 3 (MSB)
4+^|~Sample information for the shared _V2_/_V3_ value~
2+|64 (*_bitOffset_*)    | 9 (= ``10'') (*_bitLength_*) | 2 (*_channelType_*) (*++V++*)
|5 (assume mid-sited)      |  0       | 0       | 0
4+|0 (*_sampleLower_*)
4+|1023 (*_sampleUpper_*)
4+^|~Sample information for the _Y&prime;3_ value~
2+|74 (*_bitOffset_*)    | 9 (= ``10'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
|6       |  0       | 0       | 0
4+|0 (*_sampleLower_*)
4+|1023 (*_sampleUpper_*)
4+^|~Sample information for the shared _U4_/_U5_ value~
2+|84 (*_bitOffset_*)    | 9 (= ``10'') (*_bitLength_*) | 1 (*_channelType_*) (*++U++*)
|9 (assume mid-sited)      |  0       | 0       | 0
4+|0 (*_sampleLower_*)
4+|1023 (*_sampleUpper_*)
4+^|~Sample information for the _Y&prime;4_ value~
2+|96 (*_bitOffset_*)    | 9 (= ``10'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
|8       |  0       | 0       | 0
4+|0 (*_sampleLower_*)
4+|1023 (*_sampleUpper_*)
4+^|~Sample information for the shared _V4_/_V5_ value~
2+|106 (*_bitOffset_*)   | 9 (= ``10'') (*_bitLength_*) | 2 (*_channelType_*) (*++V++*)
|9 (assume mid-sited)      |  0       | 0       | 0
4+|0 (*_sampleLower_*)
4+|1023 (*_sampleUpper_*)
4+^|~Sample information for the _Y&prime;4_ value~
2+|116 (*_bitOffset_*)   | 9 (= ``10'') (*_bitLength_*) | 0 (*_channelType_*) (*++Y++*)
|10      |  0       | 0       | 0
4+|0 (*_sampleLower_*)
4+|1023 (*_sampleUpper_*)
|================================
