Today HTML
Canvas supports
only 8 bit per color channel and two PredefinedColorSpace
color spaces (srgb
and display-p3
).
This is insufficient for High-Dynamic Range (HDR) imagery, which is in widespread use today:
-
As detailed, for example, at Ultra HD Blu-ray Format Video Characteristics , 8-bit quantization (bit depth) results in contouring and banding, even for traditional standard dynamic range (SDR) imagery, like sRGB, which covers a typical luminance range between 0 and 100 cd/m2. These quantization artifacts become unacceptable with High-Dynamic Range (HDR) imagery, which supports luminance ranges between 0 and up to 10,000 cd/m2.
-
As specified at Rec. ITU-R BT.2100, two color spaces tailored for HDR imagery have been developed: BT.2100 PQ and BT.2100 HLG. All movies and TV shows are distributed using either of these two color spaces. Products with HDMI and/or DisplayPort interfaces also use these color spaces for HDR support.
-
To reproduce an HDR image on a display, it is useful to have information on both the color volume of that display and the color volume of the image since one can be significantly smaller than the other.
Accordingly, the following API modifications are needed to manipulate HDR images in HTML Canvas:
- add BT.2100 color spaces to
PredefinedColorSpace
- add higher bit depth capabilities to
CanvasRenderingContext2DSettings
- add higher bit depth capabilities to
ImageDataSettings
- add image color volume information to
ImageDataSettings
andCanvasRenderingContext2DSettings
- add display color volume information to the
Screen
interface of the CSS Object Model, to determine the characteristics of the display on which the image is being reproduced
As illustrated below, the primary use case is the drawing of HDR images into an
HTML Canvas element such that the images are displayed as they would have been
if they had been introduced in an img
or video
element.
Example applications include:
- drawing images retrieved from a file whose format is not supported by the
img
orvideo
elements - collage of images, both HDR and SDR
- adding graphics to an HDR image
- drawing of visual elements that are related to an HDR presentation in a
video
element, with the expectation that the former match the look of the latter - authoring HDR images
We propose a minimal extension to the Web Platform to allow the HTML Canvas API to manipulate High Dynamic Range (HDR) images expressed using the widespread BT.2100 PQ and BT.2100 HLG color spaces.
This proposal:
- does not preclude adding other HDR capabilities to HTML Canvas, such as support for additional color spaces like a linear high-dynamic range color space.
- neither specifies nor requires new capabilities for compositing
canvas
elements with other HTML elements.
Extend PredefinedColorSpace
to
include the following HDR color spaces.
partial enum PredefinedColorSpace {
/*
* Currently defined values: "srgb", "display-p3"
*/
"rec2100-hlg",
"rec2100-pq",
"rec2100-display-linear",
}
Extending PredefinedColorSpace
automatically extends
CanvasRenderingContext2DSettings
and ImageDataSettings
.
A Canvas that is initialized with an HDR color space is an HDR Canvas; otherwise it is an SDR Canvas.
When drawing an image into a Canvas, the image will be transformed unless the
color spaces of the image and the Canvas match. Annex A specifies transformation
to and from rec2100-pq
and rec2100-hlg
.
At the time of this writing, the current draft of CSS Color HDR Module Level 1
provides detailed definitions ofrec2100-hlg
, rec2100-pq
and
rec2100-display-linear
(called rec2100-linear
in that document).
The non-linear component signals {R', G', B'} are mapped to red, green and blue tristimulus values according to the Hybrid Log-Gamma (HLG) system specified in Rec. ITU-R BT.2100.
The non-linear component signals {R', G', B'} are mapped to red, green and blue tristimulus values according to the Perceptual Quantizer (PQ) system system specified in Rec. ITU-R BT.2100.
NOTE: {R', G', B'} are in the range [0, 1], i.e. they are not expressed in cd/m2
The linear display-referred component signals {R, G, B} are mapped to red, green and blue tristimulus values such that R = G = B = 1.0 represents HDR reference white with a nominal luminance of 203 cd/m².
Add to CanvasRenderingContext2DSettings
a CanvasDataType
member that
specifies the representation of each pixel of the output bitmap of a
CanvasRenderingContext2D
and OffscreenCanvasRenderingContext2D
.
partial dictionary CanvasRenderingContext2DSettings {
/*
* Currently defined attributes:
*
* boolean alpha = true;
* boolean desynchronized = false;
* PredefinedColorSpace colorSpace = "srgb";
* boolean willReadFrequently = false;
*/
CanvasDataType dataType = "unorm8";
};
enum CanvasDataType {
"unorm8",
"float16",
};
When dataType = "unorm8"
, the non-linear component signals {R', G', B'} are
quantized using full range quantization, i.e. they are multiplied by 255 and
rounded to the nearest integer. For example, R' = 0.5 is represented by the
integer value 128.
When dataType = "float16"
, the non-linear component signals {R', G', B'} are
not quantized, i.e. R' = 0.5 is represented by the floating point value 0.5.
NOTE: dataType = "unorm8"
corresponds to HTML Canvas as it exists today and
should not be used to represent HDR signal, as detailed in the introduction.
The HTMLCanvasElement
methods toDataURL()
and toBlob()
should produce
resources that preserve the color space of the underlying Canvas context
For example, CICP metadata or an ICC profile.
Add to
ImageDataSettings
a ImageDataType
member that specifies the conversion semantics and type of
each of the items of the data
member array of ImageData
.
partial dictionary ImageDataSettings {
/*
* Currently defined attributes:
*
* PredefinedColorSpace colorSpace;
*/
ImageDataType dataType = "unorm8";
};
enum ImageDataType {
"unorm8",
"float16",
"float32"
// and potentially others
};
The values "unorm8"
, "float16"
and "float32"
result in data
returning an
array with the type Uint8ClampedArray
, Float16Array
, Float32Array
,
respectively.
NOTE: The strawman requires at least one of "float16"
and "float32"
to
support HDR imagery. Both are listed above to emphasize that the strawman can
work with both or either.
Add a new CanvasColorMetadata dictionary:
dictionary CanvasColorMetadata {
optional ColorVolumeInfo contentColorVolume;
}
dictionary Chromaticities {
// The color primaries and white point of a color volume, in CIE 1931 xy
// coordinates.
required double redPrimaryX;
required double redPrimaryY;
required double greenPrimaryX;
required double greenPrimaryY;
required double bluePrimaryX;
required double bluePrimaryY;
required double whitePointX;
required double whitePointY;
}
dictionary ColorVolumeInfo {
optional Chromaticities chromaticity;
optional double minimumLuminance;
optional double maximumLuminance;
}
Add a mechanism for specifying this on CanvasRenderingContext2D
and
OffscreenCanvasRenderingContext2D
.
partial interface CanvasRenderingContext2D/OffscreenCanvasRenderingContext2D {
attribute CanvasColorMetadata colorMetadata;
}
contentColorVolume
specifies the nominal color volume occupied by
the image content in the CIE 1931 XYZ color space. The boundaries of the color
volume are defined by:
- the xy coordinates, as defined in ISO
11664-3, of three color primaries:
redPrimaryX
,redPrimaryY
,greenPrimaryX
,greenPrimaryY
,bluePrimaryX
, andbluePrimaryY
; - the xy coordinates of a white point:
whitePointX
andwhitePointY
; and - a minimum and maximum luminance in cd/m²:
minimumLuminance
andmaximumLuminance
.
If omitted, chromaticities
is equal to the chromaticity of the color space of
the Canvas.
If omitted, minimumLuminance
is equal to 0 cd/m².
If omitted, maximumLuminance
is equal to 1,000 cd/m².
The color volume is nominal because it MAY be smaller or larger than the actual color volume of image content, but SHOULD not be smaller.
If present, contentColorVolume
SHOULD completely define the color volume mapping
algorithm used when rendering the image to a display. For example, the
rec2100-pq to srgb mapping specified in Annex A uses the minimumLuminance
and maximumLuminance
parameters.
If contentColorVolume
is not present, the color volume mapping algorithm is left
entirely to the implementation.
contentColorVolume
SHOULD be set if known, e.g. if obtained from metadata
contained in a source image, and omitted otherwise. This is particularly
important when drawing a temporal sequence of images. If contentColorVolume
is not set, the color volume mapping algorithm can vary over the sequence, resulting in
temporal artifacts.
For example, contentColorVolume
can be set according to the Mastering Display
Color Volume and Content Light Level Information chunks found in a PNG image:
the color volume of the image content is typically smaller than, or coincides
with, that of the mastering display. For the color primaries and white point of
the color volume, the colour primaries and white point parameters of the
Mastering Display Color Volume chunk can be used. For the minimumLuminance
parameter, the minimum luminance parameter of the Mastering Display Color Volume
chunk can be used. For the maximumLuminance
parameter, the MaxCLL parameter of
the Content Light Level Information chunk can provide more accurate information
than the maximum luminance parameter of the Mastering Display Color Volume
chunk.
As specified below, the platform does not generally apply color volume mapping if the color volume of the image is smaller than that of the display.
Add, in the CSSOM View Module, a new
colorInfo
attribute to the Screen
interface:
partial interface Screen {
optional ScreenColorInfo colorInfo;
}
dictionary ScreenColorInfo {
optional ColorVolumeInfo colorVolume;
optional double referenceWhiteLuminance;
}
If present,
colorVolume
specifies, as defined above, the set of colors that the screen of the output device can reproduce without significant color volume mapping; andreferenceWhiteLuminance
specifies the luminance of reference white as reproduced by the screen of the output device, and reflects viewing environment and user settings.
When omitted, the value of a parameter is unspecified. It is preferable to omit parameters than to provide default or nominal values that are not known to be valid or accurate.
referenceWhiteLuminance
must be larger than or equal to minimumLuminance
,
and smaller than or equal to maximumLuminance
. The ratio of maximumLuminance
to referenceWhiteLuminance
effectively specifies the headroom available for
HDR imagery.
Reference white is also commonly referred to as diffuse white and graphics white.
EXAMPLE: Report ITU-R BT.2408 specifies that the luminance of reference white for a PQ reference display, or a 1 000 cd/m² HLG display, is 203 cd/m².
EXAMPLE: A PC monitor in a bright environment might report a
maximumLuminance
of 600 cd/m² and a referenceWhiteLuminance
of 400 cd/m².
colorInfo
can, for example, be used in the following scenarios:
- an authoring application can use the information to (i) avoid image colors
exceeding the color volume of the output device and (ii) correspondingly set
contentColorVolume
inCanvasColorMetadata
(see above). - a player application can use the information to map the colors of the image to the color volume of the output device if some of the former are outside the latter -- this allows the application to use its own mapping algorithm, substituting those provided by the underlying platform.
In absence of some or all the parameters of colorInfo
:
- the
dynamic-range
media query can be used to determine whether the output device supports high-dynamic range imagery; and - the
color-gamut
media query feature can be used to determine whether the output device supports wide color gamut imagery.
As illustrated by (b) below, when the the color volume of the image is not a subset of the color volume of the display, the platform performs color volume mapping, i.e. modifies the colors of the image to make them fit within the capabilities of the display.
Conversely and as illustrated by (a) below, the platform does not perform color volume mapping if the color volume of the image is a subset of the color volume of the display.
It is possible for an application to avoid color volume mapping by the platform
by ensuring that the color volume of the image, as specified
bycontentColorVolume
, is within colorInfo
. This can be achieved,
for example, by:
- preventing in the first place an author from creating colors exceeding the display color volume.
- the application performing its own color volume mapping such that the resulting image color volume is within the display color volume, as illustrated by (c) below.
In general, applications should avoid conversions between color spaces and maintain imagery in its original color space: conversions between color spaces are not necessarily reversible and do not necessarily result in the same image appearance. In particular, conversion of an HDR image to SDR will result in a significant loss of information and an SDR image that is different from the SDR image that would have been mastered from the same source material. From that perspective, converting from HDR to SDR imagery is similar to converting RGBA images to 16-color palette images.
Nevertheless, the HTML specification allows color space conversion in several scenarios, e.g., when drawing images to a canvas, retrieving image data from a canvas, among others being added). The conversions between predefined SDR color spaces are defined at https://www.w3.org/TR/css-color-4/, and this proposal similarly defines conversions for HDR color spaces.
The following illustrates the conversions that are explicitly specified:
These conversions fall into two broad categories:
- conversion between HDR color spaces
- conversion between between images with different luminance dynamic ranges (tone mapping)
Rep. ITU-R BT.2408, Annex 5 specifies a method to render an HDR image to an HDR display with a lower dynamic range.
The conversion between rec2100-pq
and rec2100-hlg
is specified at Report
ITU-R BT.2408-5, Clause 6
Color volume mapping from rec2100-pq
to srgb
is performed using the
following steps:
- apply the EETF specified at Rep. ITU-R BT.2408, Annex
5 using the following parameter values:
- LB =
ColorVolumeInfo::minimumLuminance
|| 0; - LW =
ColorVolumeInfo::maximumLuminance
|| 1000; - Lmin = 0
- Lmax = 203
- LB =
- convert to sRGB using
rec2100PQtoSRGB()
below
function simpleInverseTransform(value, gamma) {
if (value < 0) {
return -1.0 * Math.pow(-1.0 * value, 1.0 / gamma);
} else {
return Math.pow(value, 1.0 / gamma);
}
}
function rec2100PQtoSRGB(r, g, b) {
let rt = 10000 * pqEOTF(r) / 203;
let gt = 10000 * pqEOTF(g) / 203;
let bt = 10000 * pqEOTF(b) / 203;
[rt, gt, bt] = matrixXYZtoSRGB(matrixBT2020toXYZ(rt, gt, bt));
const srgbGamma = 2.2;
const r2 = simpleInverseTransform(rt, srgbGamma);
const g2 = simpleInverseTransform(gt, srgbGamma);
const b2 = simpleInverseTransform(bt, srgbGamma);
const [r3, g3, b3] = limitToSRGBGamut(r2, g2, b2);
return [r3, g3, b3];
}
The method is demonstrated at https://www.sandflow.com/public/tone-mapping/index.html.
Input: Full-range non-linear floating-point rec2100-hlg
pixel with black at
0.0 and diffuse white at 0.75. Values may exist outside the range 0.0 to 1.0.
Output: Full-range non-linear floating-point srgb
pixel with black at 0.0
and diffuse white at 1.0. Values may exist outside the range 0.0 to 1.0.
Process:
- Pseudo-linearize the HLG signal exploiting its backwards compatibility with SDR consumer displays
- Convert from ITU BT.2100 color space to sRGB color space
- Convert to non-linear sRGB values
NOTE This transform utilises the backwards compatibility of ITU-R BT.2100 HLG HDR with consumer electronic displays. Prior to display, the gamut may need to be limited to the range 0-1. The simplest method is to clip values but other gamut reduction techniques may provide better output images.
function simpleTransform(value, gamma) {
if (value < 0) {
return -1.0 * Math.pow(-1.0 * value, gamma);
} else {
return Math.pow(value, gamma);
}
}
function simpleInverseTransform(value, gamma) {
if (value < 0) {
return -1.0 * Math.pow(-1.0 * value, 1.0 / gamma);
} else {
return Math.pow(value, 1.0 / gamma);
}
}
function tonemapREC2100HLGtoSRGBdisplay(r, g, b) {
const displayGamma = 2.2;
const r1 = simpleTransform(r, displayGamma);
const g1 = simpleTransform(g, displayGamma);
const b1 = simpleTransform(b, displayGamma);
const [r2, g2, b2] = matrixXYZtoSRGB(matrixBT2020toXYZ(r1, g1, b1));
const srgbGamma = 2.2;
const r3 = simpleInverseTransform(r2, srgbGamma);
const g3 = simpleInverseTransform(g2, srgbGamma);
const b3 = simpleInverseTransform(b2, srgbGamma);
const [r4, g4, b4] = limitToSRGBGamut(r3, g3, b3);
return [r4, g4, b4];
}
This conversion method adjust the HLG pseudo-display nominal peak luminance such that the sRGB peak luminance maps to HDR reference white luminance. Using an sRGB peak luminance value of 80 cd/m² and the extended range gamma formula specified in BT.2100, Footnote 2, this results in an HLG nominal peak luminance Lw of 302.2 cd/m² and a system gamma of 1.001.
function convertSRGBtoREC2100HLG(r, g, b) {
/* Linearize using the sRGB EOTF */
const r1 = srgb_eotf(r);
const g1 = srgb_eotf(g);
const b1 = srgb_eotf(b);
/* convert color coordinates from sRGB to BT.2020 color space */
const [r2, g2, b2] = matrixXYZtoBT2020(matrixSRGBtoXYZ(r1, g1, b1));
/* Scale pixel values to match the HLG nominal peak luminance */
const linearLightScaler = 80/302.2;
const r3 = linearLightScaler * r2;
const g3 = linearLightScaler * g2;
const b3 = linearLightScaler * b2;
/* apply HLG Inverse OOTF to obtain scene light values */
const systemGamma = 1.001;
const [r4, g4, b4] = hlg_inverse_ootf(r3, g3, b3, systemGamma);
/* apply HLG OETF to obtain the non-linear HLG signal (see NOTE 1) */
const [r5, g5, b5] = hlg_oetf(r4, g4, b4);
return [r5, g5, b5]
}
NOTE 1: ITU-R BT.2408-4, 5.3 discusses negative transfer functions in format conversions.
See TTML 2, Annex Q.1, steps 1-8
with tts:luminanceGain = 203/80
.