Repository navigation
Expand file tree
/
Copy pathOverview.bs
More file actions
2064 lines (1726 loc) · 78.5 KB
/
Copy pathOverview.bs
File metadata and controls
2064 lines (1726 loc) · 78.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<pre class='metadata'>
Title: CSS Color HDR Module Level 1
Shortname: css-color-hdr
Level: 1
Status: ED
Prepare for TR: no
Group: csswg
TR: https://www.w3.org/TR/css-color-hdr-1/
ED: https://drafts.csswg.org/css-color-hdr-1/
Work Status: exploring
Editor: Chris Lilley, W3C, https://svgees.us/, w3cid 1438
Abstract: This module defines additions to CSS Color 4 and 5 to enable High Dynamic Range (HDR).
WPT Path Prefix: css/css-color-hdr/
</pre>
<pre class="link-defaults">
spec:css-cascade-5; type:dfn; text:computed value
spec:css-color-4; type:dfn; text:color space
spec:css-color-4; type:dfn; text:gamut
spec:css-color-4; type:dfn; text:rectangular orthogonal color
spec:css-color-4; type:dfn; text:cylindrical polar color
spec:css-color-4; type:value; text:none
spec:css-color-4; type:value; text:srgb
spec:css-color-4; type:dfn; text:modern color syntax
spec:css-color-4; type:value; text:alpha-value
spec:css-color-5; type:type; text:<color>
spec:css-color-5; type:dfn; text:component keywords
spec:css-color-5; type:dfn; text:origin color
spec:css-color-5; type:dfn; text:conversion, if required
spec:css-color-5; type:function; text:color()
spec:css-color-adjust-1; type:value; text:light
spec:css-color-adjust-1; type:value; text:dark
spec:css-color-4; type:value; text:rec2020
spec:css-color-4; type:dfn; text:D65
</pre>
<pre class=biblio>
{
"ARIB_STD-B67":{
"href":"https://www.arib.or.jp/english/html/overview/doc/2-STD-B67v1_0.pdf",
"title":"Essential Parameter Values for the Extended Image Dynamic Range Television (EIDRTV) System for Programme Production",
"publisher":"ARIB",
"date":"3 July 2015"
},
"DisplayHDR":{
"title":"Summary of DisplayHDR Specs under CTS 1.2",
"href":"https://displayhdr.org/performance-criteria/",
"publisher":"VESA",
"date":"17 May 2024"
},
"Development_ITP":{
"authors":[
"F.Ebner",
"M.D.Fairchild"
],
"title":"Development and testing of a color space (IPT) with improved hue uniformity. In: Proceedings of The Sixth Color Imaging Conference, 8-13, 1998",
"date":"January 1998",
"href":"https://www.researchgate.net/publication/221677980_Development_and_Testing_of_a_Color_Space_IPT_with_Improved_Hue_Uniformity"
},
"ISO_21496-1":{
"title":"Gain map metadata for image conversion: Part 1: Dynamic Range Conversion",
"href":"https://www.iso.org/standard/86775.html",
"publisher":"ISO"
},
"Perrin":{
"authors":[
"Perrin, A-F.",
"Rerabek, M.",
"Husak, W.",
"Ebrahimi, T."
],
"href":"https://ieeexplore.ieee.org/document/8333011",
"title":"ICtCp Versus Y'CbCr: Evaluation of ICtCp Color Space and an Adaptive Reshaper for HDR and WCG",
"publisher":"IEEE Consumer Electronics Magazine",
"date":"May 2018"
},
"Rec_BT.814":{
"title":"Specifications of PLUGE test signals and alignment procedures for setting of brightness and contrast of displays",
"href":"https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.814-4-201807-I!!PDF-E.pdf",
"publisher":"ITU",
"date":"July 2018"
},
"Rec_BT.2100":{
"title":"ITU-R BT.2100-3 Image parameter values for high dynamic range television for use in production and international programme exchange",
"href":"https://www.itu.int/rec/recommendation.asp?lang=en&parent=R-REC-BT.2100-3-202502-I",
"publisher":"ITU",
"date":"February 2025"
},
"Rec_BT.2124":{
"title":"ITU-R BT.2124-0 Objective metric for the assessment of the potential visibility of colour differences in television",
"href":"https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2124-0-201901-I!!PDF-E.pdf",
"publisher":"ITU",
"date":"January 2019"
},
"Rec_BT.2390":{
"title":"High dynamic range television for production and international programme exchange",
"publisher":"ITU",
"date":"March 2025",
"href":"https://www.itu.int/pub/R-REP-BT.2390-12-2025"
},
"Rpt_BT.2408-9":{
"title":"Guidelines for operational practices in high dynamic range television production",
"publisher":"ITU",
"date":"March 2026",
"href":"https://www.itu.int/pub/R-REP-BT.2408-9-2026"
},
"Safdar-PUCS":{
"authors":[
"Safdar, Muhammad",
"Ciu, Guihua",
"Kim, Youn Jin",
"Luo, Ming Ronnier"
],
"href":"https://opg.optica.org/oe/fulltext.cfm?uri=oe-25-13-15131&id=368272",
"title":"Perceptually uniform color space for image signals including high dynamic range and wide gamut",
"publisher":"Optics Express, vol 24 no 13 pp. 15131-15151",
"date":"26 June 2017"
},
"SMPTE-ST-2084":{
"href":"https://pub.smpte.org/latest/st2084/st2084-2014.pdf",
"title":"ST 2084:2014 - SMPTE Standard - High Dynamic Range Electro-Optical Transfer Function of Mastering Reference Displays",
"publisher":"SMPTE",
"date":"29 August 2014",
"abstract":"This standard specifies an EOTF characterizing high-dynamic-range reference displays used primarily for mastering non-broadcast content. This standard also specifies an Inverse-EOTF derived from the EOTF.",
"isbn":"978-1-61482-829-7"
},
"SMPTE-ST-2094-50":{
"href":"https://github.com/SMPTE/st2094-50",
"title":"Dynamic Metadata for Color Volume Transform - Application #5 (Broadcast)",
"publisher":"SMPTE",
"date":"2025"
},
"What_is_ICtCp":{
"href":"https://professional.dolby.com/siteassets/pdfs/ictcp_dolbywhitepaper_v071.pdf",
"title":"What is ICtCp, v7.1",
"publisher":"Dolby"
}
}
</pre>
<link rel="stylesheet" href="style.css" />
Introduction {#intro}
=====================
<em>This section is not normative.</em>
CSS Color 4 adds Wide Color Gamut (WCG) color spaces to the Open Web Platform.
By design, these are all Standard Dynamic Range (SDR) color spaces.
This specification defines additions
to support High Dynamic Range (HDR).
<figure id="fig-eotf">
<p><img src="./images/lin-srgb-hlg-pq.png" alt="" width="839"></p>
<!-- alt text would be identical to figure caption -->
<figcaption>
The Electro-Optical Transfer Functions (EOTF)
of four color spaces:
extended sRGB and linear-light sRGB
(as defined in CSS Color 4) and
the Perceptual Quantizer (PQ) and Hybrid Log-Gamma (HLG)
as defined in this specification, from [[Rec_BT.2100]].
</figcaption>
</figure>
While WCG specifications have been broadly stable for some decades,
HDR standards are less mature
and have undergone frequent revision in the last decade.
Value Definitions {#values}
---------------------------
This specification follows the <a href="https://www.w3.org/TR/CSS2/about.html#property-defs">CSS property definition conventions</a> from [[!CSS2]]
using the <a href="https://www.w3.org/TR/css-values-3/#value-defs">value definition syntax</a> from [[!CSS-VALUES-3]].
Value types not defined in this specification are defined in CSS Values & Units [[!CSS-VALUES-3]].
Combination with other CSS modules may expand the definitions of these value types.
In addition to the property-specific values listed in their definitions,
all properties defined in this specification
also accept the <a>CSS-wide keywords</a> as their property value.
For readability they have not been repeated explicitly.
<!-- Big Text: terms
█████▌ █████▌ ████▌ █ █ ███▌
█▌ █▌ █▌ █▌ ██ ██ █▌ █▌
█▌ █▌ █▌ █▌ █▌█ █▐█ █▌
█▌ ████ ████▌ █▌ █ ▐█ ███▌
█▌ █▌ █▌▐█ █▌ ▐█ █▌
█▌ █▌ █▌ ▐█ █▌ ▐█ █▌ █▌
█▌ █████▌ █▌ █▌ █▌ ▐█ ███▌
-->
HDR Terminology {#terminology}
==========================
Defining Dynamic Range {#defining-dynamic-range}
------------------------------------------------
<dfn export>Peak luminance</dfn> is the [=luminance=]
of the brightest white that can be displayed.
It is a linear-light quantity,
measured in cd/m<sup>2</sup>, also called <em>nits</em>.
<dfn export>Deepest black</dfn> is the [=luminance=]
of the darkest black that can be displayed.
It is affected by viewing flare
(ambient light reflected off the screen),
and so the actual value depends on the viewing conditions.
<dfn export>Linear dynamic range</dfn> is the [=luminance=] ratio
between the <em>lightest</em> and the <em>darkest</em> colors
that can be displayed.
<dfn export>Dynamic range</dfn> is the base-2 logarithm of [=linear dynamic range=],
because our eyes percieve brightness on a logarithmic scale.
Dynamic range is measured in photographic <em>stops</em>.
One stop is a doubling of luminance.
<xmp class="lang-js" id="dynamic-range-function">
function DynamicRange (peak, deepest) {
return Math.log2(peak) - Math.log2(deepest);
}
</xmp>
<dfn export>HDR Reference White</dfn>,
also called media white or diffuse white,
is defined in [[Rpt_BT.2408-9]] section 2.1,
with a standard value of 203 cd/m<sup>2</sup>.
It is the color of a normal white background,
or of white text on a dark background.
It can be comfortably viewed, over the whole screen.
In <dfn export>Standard Dynamic Range</dfn> (SDR),
HDR Reference White is also
lightest possible color,
produced by full-intensity red, green, and blue.
<div class="example" id="ex-SDR-dynamic-range">
For example, in [=sRGB=],
under standard viewing conditions,
white is defined to have a luminance of 80 cd/m²
while black is defined to have a luminance of 0.2 cd/m².
Thus, the dynamic range is 8.6 stops.
</div>
It is common to adjust the overall brighness of the screen
to acommodate user preference or viewing conditions
which are different to the standard ones.
For SDR, making the screen brighter does not change the dynamic range,
because the darkest color also gets brighter.
<div class="example" id="ex-SDR-brighter-dynamic-range">
For example, an [=sRGB=] screen,
might be set so that white has a luminance of 160 cd/m²
so the deepest black now has a luminance of 0.4 cd/m².
The dynamic range is still 8.6 stops.
</div>
In <dfn export>High Dynamic Range</dfn> (HDR),
brighter colors than [=HDR Reference White=] can be displayed.
For example, if HDR Reference White on an HDR display is set to 203 cd/m²
it might be possible to display small highlights at 1000 cd/m².
Typically, the brightest colors can only be displayed
on a small part of the display,
and for a limited time.
This is because of energy usage and heating considerations.
<div class="example" id="ex-HDR-dynamic-range">
For example, on an HDR reference mastering display,
the small-area peak white might have a luminance of 1000 cd/m²
while the deepest black has a luminance of 0.05 cd/m².
Thus, the dynamic range is 14.3 stops.
</div>
For HDR, using a brighter screen increases the dynamic range,
while the luminance of HDR Reference White remains constant.
<div class="example" id="ex-HDR-PQ-dynamic-range">
For example, using the ''rec2100-pq'' colorspace
defined in [[Rec_BT.2100]],
the brightest peak white is defined to have a luminance of 10,000 cd/m²
while the deepest black has a luminance of 0.001 cd/m².
Thus, the encoded dynamic range is 23.3 stops.
</div>
Issue: add a diagram showing SDR and HDR dynamic ranges on a log scale
When [[#Compositing-SDR-HDR]],
and for color space conversion,
the HDR Reference White for SDR content
should be anchored at <strong>203 cd/m²</strong> [[!Rpt_BT.2408-9]]
so that that the HDR Reference White level
of the inputs to compositing
will end up at the HDR Reference White level
of the combined signal.
When displaying HDR (or mixed SDR and HDR) content,
for displays which are less capable than the reference mastering display,
and for viewing conditions different to the standard ones,
a <dfn export>color re-rendering</dfn> step ((OOTF) will be performed.
This may result in a HDR Reference White being displayed
at a value lower or higher than 203 cd/m².
<!-- Big Text: headroom
█▌ █▌ █████▌ ███▌ ████▌ ████▌ ███▌ ███▌ █ █
█▌ █▌ █▌ ▐█ ▐█ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ ██ ██
█▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌█ █▐█
█████▌ ████ █▌ █▌ █▌ █▌ ████▌ █▌ █▌ █▌ █▌ █▌ █ ▐█
█▌ █▌ █▌ █████▌ █▌ █▌ █▌▐█ █▌ █▌ █▌ █▌ █▌ ▐█
█▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ ▐█ █▌ █▌ █▌ █▌ █▌ ▐█
█▌ █▌ █████▌ █▌ █▌ ████▌ █▌ █▌ ███▌ ███▌ █▌ ▐█
-->
Introducing Headroom {#introducing-headroom}
--------------------------------------------
The [=peak luminance=] level
which an HDR display can produce
varies greatly.
The amount by which peak luminance is greater than [=HDR Reference White=]
is termed the <dfn export>linear HDR headroom</dfn>,
and the value depends on the level of HDR Reference White,
user preference,
and viewing conditions.
<div class="example" id="ex-linear-headroom">
For example, if a display
displays HDR Reference White at 160 cd/m<sup>2</sup>
and has a peak luminance of 1000 cd/m<sup>2</sup>
then it has a [=linear HDR headroom=]
of 1000 / 160 = 6.25 times.
</div>
<dfn export>HDR headroom</dfn> is the base 2 logarithm of [=linear HDR headroom=],
and like dynamic range
it is expressed in photographic <strong>stops</strong>.
<xmp class="lang-js" id="headroom-function">
function Headroom (peak, reference) {
return Math.log2(peak) - Math.log2(reference);
}
</xmp>
<div class="example" id="ex-stops-headroom">
For example, if a display
displays HDR Reference White at 160 cd/m<sup>2</sup>
and has a peak luminance of 1000 cd/m<sup>2</sup>
then it has an [=HDR headroom=]
of log<sub>2</sub>(1000) - log<sub>2</sub>(160) = 2.64 stops.
</div>
Thus, [=standard dynamic range=] (SDR)
by definition has an [=HDR headroom=] of 0 stops,
because the brightest white is the same as HDR Reference White.
<div class="example" id="ex-low-stops-headroom">
For example, a low-end HDR display
(which <em>just</em> meets the requirements of
<a href="https://displayhdr.org/">DisplayHDR 400</a>,
the lowest tier of Vesa Certified DisplayHDR conformance [[DisplayHDR]])
might display HDR Reference White at
up to 200 cd/m<sup>2</sup>
while the peak white is only
400 cd/m<sup>2</sup>
(at the brightest HDR Reference White, only one stop of HDR headroom).
</div>
<div class="example" id="ex-high-stops-headroom">
For example, a high-end HDR display
(which exceeds the requirements of
<a href="https://displayhdr.org/">DisplayHDR 1400</a>,
the current highest tier of Vesa Certified DisplayHDR conformance)
might display HDR Reference White at
up to 400 cd/m<sup>2</sup>
while it's peak white is
1600 cd/m<sup>2</sup>.
In dim viewing conditions,
with HDR Reference White set to 100 cd/m<sup>2</sup>,
this gives four stops of HDR headroom
(16x linear HDR headroom).
</div>
<p id="headroom-privacy">
The Web platform does not currently
directly expose the level of headroom of a display,
because it depends on viewing conditions
and real-time, unquantized headroom information
would be a tracking vector
(for example, detecting that a user moved outside
and that it is a sunny day).
</p>
<p id="constrained-headroom">
It is not always desirable
to use the maximum available level
of HDR headroom.
CSS provides a way to control,
in broad terms,
how much headroom is desired;
and this level can vary by element
and over time.
</p>
<div class="example" id="ex-photo-grid">
For example, consider a Web page displaying a grid of photographs.
Some of these are HDR, including some very high dynamic range images
such as a shot straight into the sun.
It would be tiring to view the set of photos together
at full dynamic range.
At the same time,
squashing everything to the SDR range
would not adequately represent
the character of individual photos.
The design goal is to show "enough" HDR
to allow meaningful evaluation of the group of photos.
</div>
Controlling Dynamic Range {#controlling-dynamic-range}
==========================
The 'dynamic-range-limit' property {#the-dynamic-range-limit-property}
-------------------------------
<pre class='propdef'>
Name: dynamic-range-limit
Value: standard | no-limit | constrained | <<dynamic-range-limit-mix()>>
Initial: no-limit
Applies to: all elements
Inherited: yes
Percentages: n/a
Computed value: see <a href="#computing-dynamic-range-limit">Computed Value for dynamic-range-limit</a>
Animation type: by ''dynamic-range-limit-mix()''
Canonical order: per grammar
</pre>
<wpt>
computed.html
inheritance.html
interpolation.html
parsing.html
</wpt>
<dl dfn-type="value" dfn-for="dynamic-range-limit">
<dt><dfn>standard</dfn>
<dd>
The highest luminance color
that is displayed is the same as
HDR Reference White, i.e. the CSS color ''white''.
</dd>
<dt><dfn>no-limit</dfn>
<dd>
The highest peak luminance
that is displayed is much greater than
HDR Reference White, i.e. the CSS color ''white'';
the precise level is not specified.
</dd>
<dt><dfn>constrained</dfn>
<dd>
The highest peak luminance
that is displayed is somewhat greater than
HDR Reference White, i.e. the CSS color ''white'',
such that a mix of SDR and HDR content
can be comfortably viewed together.
</dd>
</dl>
<div class="example" id="ex-hdr-limit-photogrid">
<pre class="lang-css">
body { dynamic-range-limit: standard; }
div.photogrid img { dynamic-range-limit: constrained }
</pre>
</div>
<!-- Big Text: d-r-l-m
████▌ ████▌ █▌ █ █
█▌ █▌ █▌ █▌ █▌ ██ ██
█▌ █▌ █▌ █▌ █▌ █▌█ █▐█
█▌ █▌ ████▌ ████▌ ████▌ █▌ ████▌ █▌ █ ▐█
█▌ █▌ █▌▐█ █▌ █▌ ▐█
█▌ █▌ █▌ ▐█ █▌ █▌ ▐█
████▌ █▌ █▌ █████ █▌ ▐█
-->
Mixing Dynamic Range Limits: the ''dynamic-range-limit-mix()'' function {#dynamic-range-limit-mix}
--------------------------------------------------------
This function takes one or more 'dynamic-range-limit' values,
converts them internally to a value in stops above HDR Reference White,
and alters the display to the result of mixing them
by the specified amount.
For privacy reasons, the actual calculated result is not exposed.
<pre class='prod'>
<dfn>dynamic-range-limit-mix()</dfn> = dynamic-range-limit-mix( [ <<'dynamic-range-limit'>> && <<percentage [0,100]>> ]# )
</pre>
<wpt>
computed.html
inheritance.html
interpolation.html
parsing.html
</wpt>
<!-- @@ handle the case of percentages summing to zero. Distribute equally?
https://github.com/w3c/csswg-drafts/issues/11678#issuecomment-2686103826
maybe link to
[=normalize mix percentages=]
-->
<h3 id="computing-dynamic-range-limit">
Computed Value for 'dynamic-range-limit'
</h3>
If the specified value is ''standard'', ''constrained'', or ''no-limit'', then the computed value is the specified value.
If the specified value is ''dynamic-range-limit-mix()'', then the computed value is determined by the following algorithm:
1. Let <var>v1</var>, ..., <var>vN</var> be the computed values for the parameters to be mixed.
2. Let <var>p1</var>, ..., <var>pN</var> be the mixing percentages, normalized to sum to 100%.
3. Define the contributing percentages as:
* Let <var>p1_standard</var>,...,<var>pN_standard</var> be the percentages for ''standard'' in <var>v1</var>,...,<var>vN</var>
* Let <var>p1_constrained_high</var>,...,<var>pN_constrained_high</var> be the percentages for ''constrained'' in <var>v1</var>,...,<var>vN</var>
* Let <var>p1_no_limit</var>,...,<var>pN_no_limit</var> be the percentages for ''no-limit'' in <var>v1</var>,...,<var>vN</var>
4. Compute the weighted sums as:
* <var>p_standard</var>=(<var>p1_standard</var>*<var>p1</var>+...+<var>pN_standard</var>*<var>pN</var>)/100.
* <var>p_constrained_high</var>=(<var>p1_constrained_high</var>*<var>p1</var>+...+<var>pN_constrained_high</var>*<var>pN</var>)/100.
* <var>p_no_limit</var>=(<var>p1_no_limit</var>*<var>p1</var>+...+<var>pN_no_limit</var>*<var>pN</var>)/100.
5. If <var>p_standard</var>, <var>p_constrained_high</var>, or <var>p_no_limit</var> equals 100%, then the computed value is ''standard'', ''constrained'', or ''no-limit'', respectively.
6. Otherwise, the computed value is ''dynamic-range-limit-mix()'', with parameters ''standard'', ''constrained'', and ''no-limit'', in that order, and percentages <var>p_standard</var>, <var>p_constrained_high</var>, and <var>p_no_limit</var>, omitting parameters with a percentage equal to 0%. If <em>all</em> parameters are thereby omitted, the computed value is the initial value.
<wpt>
computed.html
</wpt>
<div class="example" id="ex-hdr-limit-mix">
The computed value of
<pre class="lang-css">
dynamic-range-limit-mix(
high 10%,
dynamic-range-limit-mix(standard 25%, constrained 75%) 20%,
dynamic-range-limit-mix(constrained 10%, no-limit 30%) 20%)
</pre>
is
<pre class="lang-css">
dynamic-range-limit-mix(standard 10%, constrained 40%, no-limit 50%)
</pre>
</div>
<!-- Big Text: <color>
█▌ ███▌ ███▌ █▌ ███▌ ████▌ █▌
█▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌
█▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌
█▌ █▌ █▌ █▌ █▌ █▌ █▌ ████▌ █▌
█▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌▐█ █▌
█▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ ▐█ █▌
█▌ ███▌ ███▌ █████ ███▌ █▌ █▌ █▌
-->
<h2 id="color-syntax">The <<color>> syntax</h2>
This module extends the <<color-function>> type:
<pre class='prod'>
<dfn><color-function></dfn> = <<rgb()>> | <<rgba()>> |
<<hsl()>> | <<hsla()>> | <<hwb()>> |
<<lab()>> | <<lch()>> | <<oklab()>> | <<oklch()>> |
<<ictcp()>> | <<jzazbz()>> | <<jzczhz()>> |
<<alpha()>> |
<<color()>> |
<<hdr-color()>>
<dfn>ictcp()</dfn> = ictcp([from <<color>>]?
[<<percentage>> | <<number>> | none]
[<<percentage>> | <<number>> | none]
[<<percentage>> | <<number>> | none]
[ / [<<alpha-value>> | none] ]? )
<dfn>jzazbz()</dfn> = jzazbz([from <<color>>]?
[<<percentage>> | <<number>> | none]
[<<percentage>> | <<number>> | none]
[<<percentage>> | <<number>> | none]
[ / [<<alpha-value>> | none] ]? )
<dfn>jzczhz()</dfn> = jzczhz([from <<color>>]?
[<<percentage>> | <<number>> | none]
[<<percentage>> | <<number>> | none]
[<<hue>> | none]
[ / [<<alpha-value>> | none] ]? )
</pre>
<!-- Big Text: hdr-color()
█▌ █▌ ████▌ ████▌ ███▌ ███▌ █▌ ███▌ ████▌ ██ ██
█▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ ▐█
█▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ ▐█
█████▌ █▌ █▌ ████▌ ████▌ █▌ █▌ █▌ █▌ █▌ █▌ ████▌ █▌ ▐█
█▌ █▌ █▌ █▌ █▌▐█ █▌ █▌ █▌ █▌ █▌ █▌ █▌▐█ █▌ ▐█
█▌ █▌ █▌ █▌ █▌ ▐█ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ ▐█ █▌ ▐█
█▌ █▌ ████▌ █▌ █▌ ███▌ ███▌ █████ ███▌ █▌ █▌ ██ ██
-->
<h2 id="hdr-color-function">HDR colors parameterized by headroom: the ''hdr-color()'' function</h2>
The ''hdr-color()'' function allows a range of colors to be specified,
whose value is automatically calculated based on the [=HDR headroom=].
It does this by specifying two <<color>> values,
each with an associated level of HDR headroom.
(The two headroom values must not be the same).
The actual value is computed by interpolating between these two colors,
based on the current amount of HDR headroom,
as described in [[#headroom-interpolation]].
<div class="informative">
This is a similar mechanism to gain maps,
in raster images conforming to [[ISO_21496-1]],
or to adaptive gain curves,
in [[SMPTE-ST-2094-50]].
</div>
For privacy reasons, the actual calculated color is not exposed,
nor is the actual HDR headroom,
as this is a fingerprinting vector.
Its syntax is as follows:
<pre class='prod'>
<dfn>hdr-color()</dfn> = color-hdr([ <<color>> && <<number [0,infinity]>>? ]#{2})
</pre>
<div class="example" id="ex-hdr-color-simple">
Consider the color:
<pre class="lang-css">
color-hdr(
color(rec2100-linear 0.9 1.0 0.8) 0,
color(rec2100-linear 1.8 2.0 1.5) 2);
</pre>
On a display with [=HDR headroom=] <= 0,
in other words, an SDR display,
this color will display as
<pre class="lang-css">color(rec2100-linear 0.9 1.0 0.8)</pre>
On a display with [=HDR headroom=] >= 2,
this color will display as
<pre class="lang-css">color(rec2100-linear 1.8 2.0 1.5) 2);</pre>
For displays whose headroom lies between 0 and 2, the color is
interpolated. For <a href="#ex-hdr-interpolate">example</a>,
on a display with HDR headroom 1:
X = 243.664, Y = 275.713, Z = 244.000
</div>
Colors are interpolated in <dfn export>Absolute D65 CIE XYZ</dfn>.
This is derived from ''xyz-d65''
by multiplying each color component by 203 [[Rpt_BT.2408-9]]
to convert from relative units (Y of white is 1, regardless of actual brightness)
to absolute units of cd/m², also called "nits".
In the <a href="#color-conversion-code">sample code</a>,
this constant is denoted <var ignore=''>Yw</var>,
the luminance of HDR Reference White.
<div class="example" id="ex-rel-to-abs">
For example, the css color ''white'' is
<pre class="lang-css">color(xyz-d65 0.9505 1 1.089)</pre>
In absolute D65 XYX this is
[192.9426, 203, 221.0787]
</div>
<h3 id="headroom-interpolation">
Interpolating colors based on headroom
</h3>
To interpolate between a color <var>c1</var> at headroom <var>H1</var>
and a color <var>c2</var> at headroom <var>H2</var>,
giving result color <var>cxyz</var>,
when the target headroom is <var>H</var>:
1. Let <var>c1xyz</var> be <var>c1</var> converted to [=Absolute D65 CIE XYZ=]
2. Let <var>c2xyz</var> be <var>c2</var> converted to [=Absolute D65 CIE XYZ=]
3. Let <var> w1</var> = clamp((<var>H</var> - <var>H2</var>) / (<var>H1</var> - <var>H2</var>), 0, 1)
4. Let <var> w2</var> = clamp((<var>H</var> - <var>H1</var>) / (<var>H2</var> - <var>H1</var>), 0, 1)
Note that <var> w2</var> = 1 - <var> w1</var>
5. Let <var>eps</var> = 0.001
6. Let <var>cxyz</var> = Array(3)
7. For i from 0 to 2:
Let <var>cxyz</var>[i] = pow(<var>c1xyz</var>[i] + <var>eps</var>, <var>w1</var> ) * pow(<var>c2xyz</var>[i] + <var>eps</var>, <var>w2</var> ) - <var>eps</var>
Note: The factor <var>eps</var> is to prevent division by zero,
and is particularly important when interpolating with SDR colors near to black.
<div class="example" id="ex-hdr-interpolate">
For example, given c1 = color(rec2100-linear 0.9 1.0 0.8),
c2 = color(rec2100-linear 1.8 2.0 1.5),
H1 = 0, H2 = 2, and H = 1:
<pre class="lang-css">
c1xyz = [ 173.156, 195.260, 178.003 ]
c2xyz = [ 342.883, 389.315, 334.467 ]
w1 = 0.5
w2 = 0.5
cxyz = [ 243.664, 275.713, 244.000 ]
</pre>
</div>
<div class="example" id="ex-hdr-interpolate-2">
For example, given c1 = color(display-p3 1 1 0.33),
c2 = jzczhz(70% 0.14 100),
H1 = 0.5, H2 = 4, and H = 2;
<pre class="lang-css">
c1xyz = [ 156.285, 188.337, 28.015 ]
c2xyz = [ 3776.1434, 4362.407, 1577.913 ]
w1 = 0.571
w2 = 0.429
cxyz = [ 611.911, 724.180, 157.650 ]
</pre>
Note that c1 will be used unmodified at all headroom values <= 0.5,
and c2 will be used unmodified at all headroom values >= 4.
</div>
<div class="example" id="ex-hdr-interpolate-3">
For example, given c1 = ictcp(50% -0.3 0),
c2 = ictcp(85% -0.35 0.1),
H1 = 0, and H2 = 4.
This would be expressed in CSS as:
<pre class="lang-css">
color-hdr(
var(--c1) 0,
var(--c2) 4
)
</pre>
If H = 2.3
<pre class="lang-css">
c1xyz = [63.6, 96.53, 8.558]
c2xyz = [2521, 2508, 112.2]
w1 = 0.425
w2 = 0.575
cxyz = [527.68, 628.20, 37.59]
</pre>
</div>
<!-- Big Text: ICTCP Jaz
████ ███▌ █████▌ ███▌ ████▌ █▌ ███▌ █████▌
▐▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ ▐█ ▐█ ▐▌
▐▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ ▐▌
▐▌ █▌ █▌ █▌ ████▌ █▌ █▌ █▌ █▌
▐▌ █▌ █▌ █▌ █▌ █▌ █▌ █████▌ █
▐▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █▌ █
████ ███▌ █▌ ███▌ █▌ ███▌ █▌ █▌ █████▌
-->
<h2 id="DI-HDR">
Device-Independent HDR Colors
</h2>
In the same way that [[css-color-4#lab-colors]]
allows specifying device-independent SDR colors,
this specification allows specifying device-independent HDR colors.
<h3 id="ictcp-intro" class="informative">
Introducing ICtCp
</h3>
<em>This section is not normative.</em>
The IC<sub>T</sub>C<sub>P</sub> color space
has better perceptual uniformity than CIE Lab,
and is used as a part of the color image pipeline
in video and digital photography systems
for high dynamic range (HDR) and wide color gamut (WCG) imagery.
The T and P subscripts
refer to the Tritanope (yellowness-blueness)
and Protanope (redness-greenness)
opponent color axes in the human visual system.
To avoid pesky subscripts,
the simplification ICtCp is frequently used.
IC<sub>T</sub>C<sub>P</sub> was
originaly developed by Dolby Laboratories [[What_is_ICtCp]]
from the IPT color space by Ebner and Fairchild
[[Development_ITP]],
and is defined in [[!Rec_BT.2100]] as the
Constant Intensity IC<sub>T</sub>C<sub>P</sub> signal format.
It was intended to replace YCbCr [[Perrin]].
It is based on the human visual system LMS cone primaries;
the Hunt-Pointer-Estevez (HPE) XYZ to LMS transform
is used,
normalized to a [=D65=] whitepoint.
A 4% crosstalk matrix is then applied [[What_is_ICtCp]],
to reduce the gamut hull concavities of BT.2020 RGB,
thus reducing interpolation errors.
The crosstalk also provides improved lines of constant hue
and improved uniformity of Just Noticeable Difference (JND) MacAdam ellipses.
Unlike ''Lab'', which has primarily been tested with
lower-intensity <em>reflective</em> colors,
IC<sub>T</sub>C<sub>P</sub> has been tested with
high-chroma (wide color gamut),
self-luminous, and
high intensity (HDR) colors.
This makes it suitable for HDR color difference measurement
<a href="#deltaE">(deltaE ITP)</a>
and for gamut mapping of mixed SDR and HDR colors.
<div class="example" id="ex-DE-ITP">
For example, BT.2020 and BT.2100 use the same primaries and white point.
BT.2020 is SDR, while BT.2100 is HDR
and places HDR Reference White at a code value close to 0.58.
Here is a very wide gamut primary red in both color spaces:
<pre class="lang-css">
color(rec2100-pq 0.58 0 0) /* ictcp(44.6% -0.129 0.399) */
color(rec2020 1 0 0) /* ictcp(44.7% -0.130 0.399) */
</pre>
The two colors are clearly very close in ICTCP
and the deltaE ITP is 0.487,
meaning the colors are not visually different.
These colors are very different from sRGB "red":
<pre class="lang-css">
color(rec2100-pq 0.58 0 0) /* ictcp(44.6% -0.129 0.399) */
red /* ictcp(42.8% -0.116 0.279) */
</pre>
the deltaE ITP is 87.7,
meaning the colors are very visually different.
</div>
<h3 id="jaz-intro" class="informative">
Introducing Jzazbz and JzCzhz
</h3>
<em>This section is not normative.</em>
The J<sub>z</sub>a<sub>z</sub>b<sub>z</sub> color space [[!Safdar-PUCS]],
and its polar form J<sub>z</sub>C<sub>z</sub>h<sub>z</sub>,
were designed to be more perceptually uniform
for wide gamut colors such as BT.2020,
to accurately predict a wide-range of lightness,
including HDR colors,
and to have minimal inter-dependence
between the perceptual attributes (lightness, chroma, and hue).
In particular it has superior hue uniformity,
compared to CAM16-UCS [[!Safdar-PUCS]].
CIE Lab uses a lightness scale with a [0%, 100%] range,
relative to HDR Reference White;
similarly, Oklab uses a lightness scale with a [0, 1.0] range,
again with 1.0 referring to HDR Reference White.
In contrast, the J<sub>z</sub> axis in ''Jzazbz'',
which has a [0, 1.0] range,
uses an encoding <em>similar to</em> Perceptual Quantizer,
and can represent a dynamic range of more than 13 stops.
<dfn export>ICtCp</dfn> {#ICtCp}
-----------------
The ''ICtCp'' color space accepts three numeric parameters,
with I representing the Intensity
(similar to L in Lab, but covering a luminance range
up to 10,000 cd/m<sup>2</sup>)
while C<sub>T</sub> and C<sub>P</sub> represent the
yellowness-blueness (tritanope) and
redness-greenness (protanope)
opponent-color axes (similar to b and a, respectively, in Lab).
It has the following characteristics:
<table>
<thead><tr><td></td><td>x</td><td>y</td></tr></thead>
<tr><th>White chromaticity</th><td colspan="2">[=D65=]</td></tr>
<tr><th>Transfer function</th><td colspan="2">Perceptual Quantizer</td></tr>
<tr><th>White luminance</th><td colspan="2">203 cd/m²</td></tr>
<tr><th>Peak white luminance</th><td colspan="2">10,000 cd/m²</td></tr>
<tr><th>Black luminance</th><td colspan="2">0.001 cd/m²</td></tr>
<tr><th>Image state</th><td colspan="2">display-referred</td></tr>
<tr>
<th>Percentages</th>
<td colspan="2">Allowed for I, Ct and Cp</td>
</tr>
<tr>
<th>Percent reference range</th>
<td>for I: 0% = 0.0, 100% = 1.0<br>
for Ct and Cp: -100% = -0.5, 100% = 0.5</td>
</tr>
</table>
Although [[Rec_BT.2100]] defines IC<sub>T</sub>C<sub>P</sub>
by a conversion from linear-light BT.2100 RGB [[Rec_BT.2100]],
this conversion proceeds via LMS
and thus, any other color space can also be represented
by applying an XYZ to LMS transform
as shown in [[What_is_ICtCp]].
The <a href="#ictcp_code">sample code</a> uses this approach.
<div class="example">
This color represents the sRGB color "lime" in ''ICtCp''
<pre>
<span class="swatch" style="--color: lime"></span> ictcp(0.5393 -0.2643 -0.0625)
</pre>
</div>
<div class="example">
This color represents a comfortable "diffuse white"
This color can be displayed for long periods,
or used for subtitles,
on any sized area of the screen.
It is the same color as sRGB ''white''.
Diffuse white is 203 cd/m² [[!Rec_BT.2100]].
<pre>
<span class="swatch" style="--color: white"></span> ictcp(0.58069 0 0)
</pre>
</div>
Within a [=relative color=] syntax ''ictcp()'' function,
the allowed [=component keywords=] are:
* <dfn value for="ictcp()">i</dfn> is a <<number>>
that corresponds to the [=origin color's=] I (Lightness)
after [=conversion, if required=], to ictcp.
1.0 is equivalent to 100%.
* <dfn value for="ictcp()">ct</dfn> and <dfn value for="ictcp()">cp</dfn> are <<number>>s
that correspond to the [=origin color's=] ct and cp axes
after [=conversion, if required=], to ictcp.
0.5 is equivalent to 100%, while -0.5 is equivalent to -100%.
* <dfn value for="ictcp()">alpha</dfn> is a <<number>> that corresponds to the
[=origin color's=] alpha transparency. 1.0 is equivalent to 100%.
<dfn export>Jzazbz</dfn> {#Jzazbz}
-----------------
The ''Jzazbz'' color space accepts three numeric parameters,
with J<sub>z</sub> representing the Lightness (similar to L in Lab)
while a<sub>z</sub> and b<sub>z</sub> represent the
redness-greenness and yellowness-blueness
opponent-color axes (similar to a and b in Lab).
''Jzazbz'' has the following characteristics:
<table>
<thead><tr><td></td><td>x</td><td>y</td></tr></thead>
<tr><th>White chromaticity</th><td colspan="2">[=D65=]</td></tr>
<tr><th>Transfer function</th><td colspan="2">Perceptual Quantizer</td></tr>
<tr><th>Peak white luminance</th><td colspan="2">10,000 cd/m²</td></tr>
<tr><th>Black luminance</th><td colspan="2">0.001 cd/m²</td></tr>
<tr><th>Image state</th><td colspan="2">display-referred</td></tr>
<tr>
<th>Percentages</th>
<td colspan="2">Allowed for Jz, az and bz</td>
</tr>
<tr>
<th>Percent reference range</th>
<td>for Jz: 0% = 0.0, 100% = 1.0<br>
for az and bz: -100% = -0.21, 100% = 0.21</td>
</tr>
</table>
Note that unlike Lab, a [=D65=] whitepoint is used.
Thus, for most RGB spaces
(which also use a D65 whitepoint)
no chromatic adaptation step need be performed.
<a href="#jzazbz_code">Sample code</a>
for converting between XYZ-D65 and ''Jzazbz''
is provided.
<div class="example">
This color represents a comfortable "diffuse white"
This color can be displayed for long periods,
or used for subtitles,
on any sized area of the screen.
It is the same color as sRGB ''white''.
Diffuse white is 203 cd/m² [[Rec_BT.2100]].
<pre>
<span class="swatch" style="--color: white"></span> jzazbz(0.22207 -0.00016 -0.00012)
</pre>