Coverage for colour/models/rgb/transfer_functions/itur_bt_2100.py: 96%
160 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-15 19:01 +1300
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-15 19:01 +1300
1"""
2Recommendation ITU-R BT.2100
3============================
5Define the *Recommendation ITU-R BT.2100* opto-electrical transfer functions
6(OETF), opto-optical transfer functions (OOTF / OOCF) and electro-optical
7transfer functions (EOTF) and their inverse.
9- :func:`colour.models.oetf_BT2100_PQ`
10- :func:`colour.models.oetf_inverse_BT2100_PQ`
11- :func:`colour.models.eotf_BT2100_PQ`
12- :func:`colour.models.eotf_inverse_BT2100_PQ`
13- :func:`colour.models.ootf_BT2100_PQ`
14- :func:`colour.models.ootf_inverse_BT2100_PQ`
15- :func:`colour.models.oetf_BT2100_HLG`
16- :func:`colour.models.oetf_inverse_BT2100_HLG`
17- :func:`colour.models.eotf_BT2100_HLG_1`
18- :func:`colour.models.eotf_BT2100_HLG_2`
19- :attr:`colour.models.BT2100_HLG_EOTF_METHODS`
20- :func:`colour.models.eotf_BT2100_HLG`
21- :func:`colour.models.eotf_inverse_BT2100_HLG_1`
22- :func:`colour.models.eotf_inverse_BT2100_HLG_2`
23- :attr:`colour.models.BT2100_HLG_EOTF_INVERSE_METHODS`
24- :func:`colour.models.eotf_inverse_BT2100_HLG`
25- :func:`colour.models.ootf_BT2100_HLG`
26- :func:`colour.models.ootf_inverse_BT2100_HLG`
27- :func:`colour.models.ootf_BT2100_HLG_1`
28- :func:`colour.models.ootf_BT2100_HLG_2`
29- :attr:`colour.models.BT2100_HLG_OOTF_METHODS`
30- :func:`colour.models.ootf_BT2100_HLG`
31- :func:`colour.models.ootf_inverse_BT2100_HLG_1`
32- :func:`colour.models.ootf_inverse_BT2100_HLG_2`
33- :attr:`colour.models.BT2100_HLG_OOTF_INVERSE_METHODS`
34- :func:`colour.models.ootf_inverse_BT2100_HLG`
36References
37----------
38- :cite:`Borer2017a` : Borer, T. (2017). Private Discussion with Mansencal,
39 T. and Shaw, N.
40- :cite:`InternationalTelecommunicationUnion2017` : International
41 Telecommunication Union. (2017). Recommendation ITU-R BT.2100-1 - Image
42 parameter values for high dynamic range television for use in production
43 and international programme exchange.
44 https://www.itu.int/dms_pubrec/itu-r/rec/bt/\
45R-REC-BT.2100-1-201706-I!!PDF-E.pdf
46- :cite:`InternationalTelecommunicationUnion2018` : International
47 Telecommunication Union. (2018). Recommendation ITU-R BT.2100-2 - Image
48 parameter values for high dynamic range television for use in production
49 and international programme exchange.
50 https://www.itu.int/dms_pubrec/itu-r/rec/bt/\
51R-REC-BT.2100-2-201807-I!!PDF-E.pdf
52"""
54from __future__ import annotations
56import typing
58import numpy as np
60from colour.algebra import spow
62if typing.TYPE_CHECKING:
63 from colour.hints import Literal
65from colour.hints import ( # noqa: TC001
66 ArrayLike,
67 Domain1,
68 NDArrayFloat,
69 Range1,
70)
71from colour.models.rgb.transfer_functions import (
72 eotf_BT1886,
73 eotf_inverse_BT1886,
74 eotf_inverse_ST2084,
75 eotf_ST2084,
76 oetf_ARIBSTDB67,
77 oetf_BT709,
78 oetf_inverse_ARIBSTDB67,
79 oetf_inverse_BT709,
80)
81from colour.models.rgb.transfer_functions.arib_std_b67 import CONSTANTS_ARIBSTDB67
82from colour.utilities import (
83 CanonicalMapping,
84 Structure,
85 as_float,
86 as_float_array,
87 as_float_scalar,
88 domain_range_scale,
89 filter_kwargs,
90 from_range_1,
91 optional,
92 to_domain_1,
93 tsplit,
94 tstack,
95 usage_warning,
96 validate_method,
97)
99__author__ = "Colour Developers"
100__copyright__ = "Copyright 2013 Colour Developers"
101__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
102__maintainer__ = "Colour Developers"
103__email__ = "colour-developers@colour-science.org"
104__status__ = "Production"
106__all__ = [
107 "oetf_BT2100_PQ",
108 "oetf_inverse_BT2100_PQ",
109 "eotf_BT2100_PQ",
110 "eotf_inverse_BT2100_PQ",
111 "ootf_BT2100_PQ",
112 "ootf_inverse_BT2100_PQ",
113 "WEIGHTS_BT2100_HLG",
114 "CONSTANTS_BT2100_HLG",
115 "gamma_function_BT2100_HLG",
116 "oetf_BT2100_HLG",
117 "oetf_inverse_BT2100_HLG",
118 "black_level_lift_BT2100_HLG",
119 "eotf_BT2100_HLG_1",
120 "eotf_BT2100_HLG_2",
121 "BT2100_HLG_EOTF_METHODS",
122 "eotf_BT2100_HLG",
123 "eotf_inverse_BT2100_HLG_1",
124 "eotf_inverse_BT2100_HLG_2",
125 "BT2100_HLG_EOTF_INVERSE_METHODS",
126 "eotf_inverse_BT2100_HLG",
127 "ootf_BT2100_HLG_1",
128 "ootf_BT2100_HLG_2",
129 "BT2100_HLG_OOTF_METHODS",
130 "ootf_BT2100_HLG",
131 "ootf_inverse_BT2100_HLG_1",
132 "ootf_inverse_BT2100_HLG_2",
133 "BT2100_HLG_OOTF_INVERSE_METHODS",
134 "ootf_inverse_BT2100_HLG",
135]
138def oetf_BT2100_PQ(E: ArrayLike) -> NDArrayFloat:
139 """
140 Apply the *Recommendation ITU-R BT.2100* *Reference PQ* opto-electronic
141 transfer function (OETF).
143 Parameters
144 ----------
145 E
146 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the
147 signal determined by scene light and scaled by camera exposure.
149 Returns
150 -------
151 :class:`numpy.ndarray`
152 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`.
154 Notes
155 -----
156 +------------+-----------------------+---------------+
157 | **Domain** | **Scale - Reference** | **Scale - 1** |
158 +============+=======================+===============+
159 | ``E`` | ``UN`` | ``UN`` |
160 +------------+-----------------------+---------------+
162 +------------+-----------------------+---------------+
163 | **Range** | **Scale - Reference** | **Scale - 1** |
164 +============+=======================+===============+
165 | ``E_p`` | ``UN`` | ``UN`` |
166 +------------+-----------------------+---------------+
168 References
169 ----------
170 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`
172 Examples
173 --------
174 >>> oetf_BT2100_PQ(0.1) # doctest: +ELLIPSIS
175 0.7247698...
176 """
178 return eotf_inverse_ST2084(ootf_BT2100_PQ(E), 10000)
181def oetf_inverse_BT2100_PQ(E_p: ArrayLike) -> NDArrayFloat:
182 """
183 Apply the *Recommendation ITU-R BT.2100* *Reference PQ* inverse
184 opto-electrical transfer function (OETF).
186 Parameters
187 ----------
188 E_p
189 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`.
191 Returns
192 -------
193 :class:`numpy.ndarray`
194 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the
195 signal determined by scene light and scaled by camera exposure.
197 Notes
198 -----
199 +------------+-----------------------+---------------+
200 | **Domain** | **Scale - Reference** | **Scale - 1** |
201 +============+=======================+===============+
202 | ``E_p`` | ``UN`` | ``UN`` |
203 +------------+-----------------------+---------------+
205 +------------+-----------------------+---------------+
206 | **Range** | **Scale - Reference** | **Scale - 1** |
207 +============+=======================+===============+
208 | ``E`` | ``UN`` | ``UN`` |
209 +------------+-----------------------+---------------+
211 References
212 ----------
213 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`
215 Examples
216 --------
217 >>> oetf_inverse_BT2100_PQ(0.724769816665726) # doctest: +ELLIPSIS
218 0.0999999...
219 """
221 return ootf_inverse_BT2100_PQ(eotf_ST2084(E_p, 10000))
224def eotf_BT2100_PQ(E_p: ArrayLike) -> NDArrayFloat:
225 """
226 Apply the *Recommendation ITU-R BT.2100* *Reference PQ* electro-optical
227 transfer function (EOTF).
229 Parameters
230 ----------
231 E_p
232 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`.
234 Returns
235 -------
236 :class:`numpy.ndarray`
237 Luminance :math:`F_D` of a displayed linear component
238 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
239 :math:`cd/m^2`.
241 Notes
242 -----
243 +------------+-----------------------+---------------+
244 | **Domain** | **Scale - Reference** | **Scale - 1** |
245 +============+=======================+===============+
246 | ``E_p`` | ``UN`` | ``UN`` |
247 +------------+-----------------------+---------------+
249 +------------+-----------------------+---------------+
250 | **Range** | **Scale - Reference** | **Scale - 1** |
251 +============+=======================+===============+
252 | ``F_D`` | ``UN`` | ``UN`` |
253 +------------+-----------------------+---------------+
255 References
256 ----------
257 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`
259 Examples
260 --------
261 >>> eotf_BT2100_PQ(0.724769816665726) # doctest: +ELLIPSIS
262 779.9883608...
263 """
265 return eotf_ST2084(E_p, 10000)
268def eotf_inverse_BT2100_PQ(F_D: ArrayLike) -> NDArrayFloat:
269 """
270 Apply the *Recommendation ITU-R BT.2100* *Reference PQ* inverse
271 electro-optical transfer function (EOTF).
273 Parameters
274 ----------
275 F_D
276 Luminance :math:`F_D` of a displayed linear component
277 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
278 :math:`cd/m^2`.
280 Returns
281 -------
282 :class:`numpy.ndarray`
283 :math:`E'` denotes a non-linear colour value :math:`\\{R', G', B'\\}`
284 or :math:`\\{L', M', S'\\}`.
286 Notes
287 -----
288 +------------+-----------------------+---------------+
289 | **Domain** | **Scale - Reference** | **Scale - 1** |
290 +============+=======================+===============+
291 | ``F_D`` | ``UN`` | ``UN`` |
292 +------------+-----------------------+---------------+
294 +------------+-----------------------+---------------+
295 | **Range** | **Scale - Reference** | **Scale - 1** |
296 +============+=======================+===============+
297 | ``E_p`` | ``UN`` | ``UN`` |
298 +------------+-----------------------+---------------+
300 References
301 ----------
302 :cite:`Borer2017a`,
303 :cite:`InternationalTelecommunicationUnion2017`
305 Examples
306 --------
307 >>> eotf_inverse_BT2100_PQ(779.988360834085370) # doctest: +ELLIPSIS
308 0.7247698...
309 """
311 return eotf_inverse_ST2084(F_D, 10000)
314def ootf_BT2100_PQ(E: ArrayLike) -> NDArrayFloat:
315 """
316 Apply the *Recommendation ITU-R BT.2100* *Reference PQ* opto-optical
317 transfer function (OOTF).
319 Parameters
320 ----------
321 E
322 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the
323 signal determined by scene light and scaled by camera exposure.
325 Returns
326 -------
327 :class:`numpy.ndarray`
328 Luminance :math:`F_D` of a displayed linear component
329 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
330 :math:`cd/m^2`.
332 Notes
333 -----
334 +------------+-----------------------+---------------+
335 | **Domain** | **Scale - Reference** | **Scale - 1** |
336 +============+=======================+===============+
337 | ``E`` | ``UN`` | ``UN`` |
338 +------------+-----------------------+---------------+
340 +------------+-----------------------+---------------+
341 | **Range** | **Scale - Reference** | **Scale - 1** |
342 +============+=======================+===============+
343 | ``F_D`` | ``UN`` | ``UN`` |
344 +------------+-----------------------+---------------+
346 References
347 ----------
348 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`
350 Examples
351 --------
352 >>> ootf_BT2100_PQ(0.1) # doctest: +ELLIPSIS
353 779.9883608...
354 """
356 E = as_float_array(E)
358 with domain_range_scale("ignore"):
359 return 100 * eotf_BT1886(oetf_BT709(59.5208 * E))
362def ootf_inverse_BT2100_PQ(F_D: ArrayLike) -> NDArrayFloat:
363 """
364 Apply the *Recommendation ITU-R BT.2100* *Reference PQ* inverse
365 opto-optical transfer function (OOTF).
367 Parameters
368 ----------
369 F_D
370 Luminance :math:`F_D` of a displayed linear component
371 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
372 :math:`cd/m^2`.
374 Returns
375 -------
376 :class:`numpy.ndarray`
377 :math:`E = \\{R_S, G_S, B_S; Y_S; or I_S\\}` denotes the signal
378 determined by scene light and scaled by camera exposure.
380 Notes
381 -----
382 +------------+-----------------------+---------------+
383 | **Domain** | **Scale - Reference** | **Scale - 1** |
384 +============+=======================+===============+
385 | ``F_D`` | ``UN`` | ``UN`` |
386 +------------+-----------------------+---------------+
388 +------------+-----------------------+---------------+
389 | **Range** | **Scale - Reference** | **Scale - 1** |
390 +============+=======================+===============+
391 | ``E`` | ``UN`` | ``UN`` |
392 +------------+-----------------------+---------------+
394 References
395 ----------
396 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`
398 Examples
399 --------
400 >>> ootf_inverse_BT2100_PQ(779.988360834115840) # doctest: +ELLIPSIS
401 0.1000000...
402 """
404 F_D = as_float_array(F_D)
406 with domain_range_scale("ignore"):
407 return oetf_inverse_BT709(eotf_inverse_BT1886(F_D / 100)) / 59.5208
410WEIGHTS_BT2100_HLG: NDArrayFloat = np.array([0.2627, 0.6780, 0.0593])
411"""Luminance weights for *Recommendation ITU-R BT.2100* *Reference HLG*."""
413CONSTANTS_BT2100_HLG: Structure = Structure(
414 a=CONSTANTS_ARIBSTDB67.a,
415 b=1 - 4 * CONSTANTS_ARIBSTDB67.a,
416 c=0.5 - CONSTANTS_ARIBSTDB67.a * np.log(4 * CONSTANTS_ARIBSTDB67.a),
417)
418"""
419*Recommendation ITU-R BT.2100* *Reference HLG* constants expressed in their
420analytical form in contrast to the *ARIB STD-B67 (Hybrid Log-Gamma)* numerical
421reference.
423References
424----------
425:cite:`InternationalTelecommunicationUnion2017`
426"""
429def gamma_function_BT2100_HLG(L_W: float = 1000) -> float:
430 """
431 Compute the *Reference HLG* system gamma value for the specified display
432 nominal peak luminance.
434 Parameters
435 ----------
436 L_W
437 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for
438 achromatic pixels.
440 Returns
441 -------
442 :class:`float`
443 *Reference HLG* system gamma value.
445 Examples
446 --------
447 >>> gamma_function_BT2100_HLG()
448 1.2
449 >>> gamma_function_BT2100_HLG(2000) # doctest: +ELLIPSIS
450 1.3264325...
451 >>> gamma_function_BT2100_HLG(4000) # doctest: +ELLIPSIS
452 1.4528651...
453 """
455 gamma = 1.2 + 0.42 * np.log10(L_W / 1000)
457 return as_float_scalar(gamma)
460def oetf_BT2100_HLG(E: Domain1, constants: Structure | None = None) -> Range1:
461 """
462 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* opto-electrical
463 transfer function (OETF).
465 The OETF maps relative scene linear light into the non-linear *HLG* signal
467 Parameters
468 ----------
469 E
470 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the
471 signal determined by scene light and scaled by camera exposure.
472 constants
473 *Recommendation ITU-R BT.2100* *Reference HLG* constants.
475 Returns
476 -------
477 :class:`numpy.ndarray`
478 :math:`E'` is the resulting non-linear signal :math:`\\{R', G', B'\\}`.
480 Notes
481 -----
482 +------------+-----------------------+---------------+
483 | **Domain** | **Scale - Reference** | **Scale - 1** |
484 +============+=======================+===============+
485 | ``E`` | 1 | 1 |
486 +------------+-----------------------+---------------+
488 +------------+-----------------------+---------------+
489 | **Range** | **Scale - Reference** | **Scale - 1** |
490 +============+=======================+===============+
491 | ``E_p`` | 1 | 1 |
492 +------------+-----------------------+---------------+
494 References
495 ----------
496 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`
498 Examples
499 --------
500 >>> oetf_BT2100_HLG(0.18 / 12) # doctest: +ELLIPSIS
501 0.2121320...
502 """
504 E = as_float_array(E)
505 constants = optional(constants, CONSTANTS_BT2100_HLG)
507 return oetf_ARIBSTDB67(12 * E, constants=constants)
510def oetf_inverse_BT2100_HLG(E_p: Domain1, constants: Structure | None = None) -> Range1:
511 """
512 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* inverse
513 opto-electrical transfer function (OETF).
515 Parameters
516 ----------
517 E_p
518 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`.
519 constants
520 *Recommendation ITU-R BT.2100* *Reference HLG* constants.
522 Returns
523 -------
524 :class:`numpy.ndarray`
525 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the
526 signal determined by scene light and scaled by camera exposure.
528 Notes
529 -----
530 +------------+-----------------------+---------------+
531 | **Domain** | **Scale - Reference** | **Scale - 1** |
532 +============+=======================+===============+
533 | ``E_p`` | 1 | 1 |
534 +------------+-----------------------+---------------+
536 +------------+-----------------------+---------------+
537 | **Range** | **Scale - Reference** | **Scale - 1** |
538 +============+=======================+===============+
539 | ``E`` | 1 | 1 |
540 +------------+-----------------------+---------------+
542 References
543 ----------
544 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`
546 Examples
547 --------
548 >>> oetf_inverse_BT2100_HLG(0.212132034355964) # doctest: +ELLIPSIS
549 0.0149999...
550 """
552 constants = optional(constants, CONSTANTS_BT2100_HLG)
554 return oetf_inverse_ARIBSTDB67(E_p, constants=constants) / 12
557def black_level_lift_BT2100_HLG(
558 L_B: float = 0, L_W: float = 1000, gamma: float | None = None
559) -> float:
560 """
561 Compute the *Reference HLG* black level lift :math:`\\beta` for the
562 specified display luminance for black, nominal peak luminance, and system
563 gamma value.
565 Parameters
566 ----------
567 L_B
568 Display luminance for black :math:`L_B` in :math:`cd/m^2`.
569 L_W
570 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for
571 achromatic pixels.
572 gamma
573 System gamma value, defaults to 1.2 at the nominal display peak
574 luminance of :math:`1000 cd/m^2`.
576 Returns
577 -------
578 :class:`float`
579 *Reference HLG* black level lift :math:`\\beta`.
581 Examples
582 --------
583 >>> black_level_lift_BT2100_HLG()
584 0.0
585 >>> black_level_lift_BT2100_HLG(0.01) # doctest: +ELLIPSIS
586 0.0142964...
587 >>> black_level_lift_BT2100_HLG(0.001, 2000) # doctest: +ELLIPSIS
588 0.0073009...
589 >>> black_level_lift_BT2100_HLG(0.01, gamma=1.4) # doctest: +ELLIPSIS
590 0.0283691...
591 """
593 gamma = optional(gamma, gamma_function_BT2100_HLG(L_W))
595 beta = np.sqrt(3 * spow((L_B / L_W), 1 / gamma))
597 return as_float_scalar(beta)
600def eotf_BT2100_HLG_1(
601 E_p: Domain1,
602 L_B: float = 0,
603 L_W: float = 1000,
604 gamma: float | None = None,
605 constants: Structure | None = None,
606) -> Range1:
607 """
608 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* electro-optical
609 transfer function (EOTF) as specified in *ITU-R BT.2100-1*.
611 Parameters
612 ----------
613 E_p
614 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`.
615 L_B
616 Display luminance for black :math:`L_B` in :math:`cd/m^2`.
617 L_W
618 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for
619 achromatic pixels.
620 gamma
621 System gamma value, defaults to 1.2 at the nominal display peak
622 luminance of :math:`1000 cd/m^2`.
623 constants
624 *Recommendation ITU-R BT.2100* *Reference HLG* constants.
626 Returns
627 -------
628 :class:`numpy.ndarray`
629 Luminance :math:`F_D` of a displayed linear component
630 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
631 :math:`cd/m^2`.
633 Notes
634 -----
635 +------------+-----------------------+---------------+
636 | **Domain** | **Scale - Reference** | **Scale - 1** |
637 +============+=======================+===============+
638 | ``E_p`` | 1 | 1 |
639 +------------+-----------------------+---------------+
641 +------------+-----------------------+---------------+
642 | **Range** | **Scale - Reference** | **Scale - 1** |
643 +============+=======================+===============+
644 | ``F_D`` | 1 | 1 |
645 +------------+-----------------------+---------------+
647 References
648 ----------
649 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`
651 Examples
652 --------
653 >>> eotf_BT2100_HLG_1(0.212132034355964) # doctest: +ELLIPSIS
654 6.4760398...
655 >>> eotf_BT2100_HLG_1(0.212132034355964, 0.01) # doctest: +ELLIPSIS
656 6.4859750...
657 """
659 constants = optional(constants, CONSTANTS_BT2100_HLG)
661 return ootf_BT2100_HLG_1(
662 oetf_inverse_ARIBSTDB67(E_p, constants=constants) / 12, L_B, L_W, gamma
663 )
666def eotf_BT2100_HLG_2(
667 E_p: Domain1,
668 L_B: float = 0,
669 L_W: float = 1000,
670 gamma: float | None = None,
671 constants: Structure | None = None,
672) -> Range1:
673 """
674 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* electro-optical
675 transfer function (EOTF) as specified in *ITU-R BT.2100-2* with
676 modified black level behaviour.
678 Parameters
679 ----------
680 E_p
681 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`.
682 L_B
683 Display luminance for black :math:`L_B` in :math:`cd/m^2`.
684 L_W
685 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for
686 achromatic pixels.
687 gamma
688 System gamma value, defaults to 1.2 at the nominal display peak
689 luminance of :math:`1000 cd/m^2`.
690 constants
691 *Recommendation ITU-R BT.2100* *Reference HLG* constants.
693 Returns
694 -------
695 :class:`numpy.ndarray`
696 Luminance :math:`F_D` of a displayed linear component
697 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
698 :math:`cd/m^2`.
700 Notes
701 -----
702 +------------+-----------------------+---------------+
703 | **Domain** | **Scale - Reference** | **Scale - 1** |
704 +============+=======================+===============+
705 | ``E_p`` | 1 | 1 |
706 +------------+-----------------------+---------------+
708 +------------+-----------------------+---------------+
709 | **Range** | **Scale - Reference** | **Scale - 1** |
710 +============+=======================+===============+
711 | ``F_D`` | 1 | 1 |
712 +------------+-----------------------+---------------+
714 References
715 ----------
716 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2018`
718 Examples
719 --------
720 >>> eotf_BT2100_HLG_2(0.212132034355964) # doctest: +ELLIPSIS
721 6.4760398...
722 >>> eotf_BT2100_HLG_2(0.212132034355964, 0.01) # doctest: +ELLIPSIS
723 7.3321975...
724 """
726 E_p = as_float_array(E_p)
727 constants = optional(constants, CONSTANTS_BT2100_HLG)
729 beta = black_level_lift_BT2100_HLG(L_B, L_W, gamma)
731 return ootf_BT2100_HLG_2(
732 oetf_inverse_ARIBSTDB67((1 - beta) * E_p + beta, constants=constants) / 12,
733 L_W,
734 gamma,
735 )
738BT2100_HLG_EOTF_METHODS: CanonicalMapping = CanonicalMapping(
739 {
740 "ITU-R BT.2100-1": eotf_BT2100_HLG_1,
741 "ITU-R BT.2100-2": eotf_BT2100_HLG_2,
742 }
743)
744BT2100_HLG_EOTF_METHODS.__doc__ = """
745Define supported *ITU-R BT.2100* *Reference HLG* electro-optical transfer
746function (EOTF) methods.
748References
749----------
750:cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`,
751:cite:`InternationalTelecommunicationUnion2018`
752"""
755def eotf_BT2100_HLG(
756 E_p: Domain1,
757 L_B: float = 0,
758 L_W: float = 1000,
759 gamma: float | None = None,
760 constants: Structure | None = None,
761 method: (Literal["ITU-R BT.2100-1", "ITU-R BT.2100-2"] | str) = "ITU-R BT.2100-2",
762) -> Range1:
763 """
764 Apply the *Recommendation ITU-R BT.2100* *Reference HLG*
765 electro-optical transfer function (EOTF).
767 Parameters
768 ----------
769 E_p
770 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`.
771 L_B
772 Display luminance for black :math:`L_B` in :math:`cd/m^2`.
773 L_W
774 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for
775 achromatic pixels.
776 gamma
777 System gamma value, defaults to 1.2 at the nominal display peak
778 luminance of :math:`1000 cd/m^2`.
779 constants
780 *Recommendation ITU-R BT.2100* *Reference HLG* constants.
781 method
782 Computation method.
784 Returns
785 -------
786 :class:`numpy.ndarray`
787 Luminance :math:`F_D` of a displayed linear component
788 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
789 :math:`cd/m^2`.
791 Notes
792 -----
793 +------------+-----------------------+---------------+
794 | **Domain** | **Scale - Reference** | **Scale - 1** |
795 +============+=======================+===============+
796 | ``E_p`` | 1 | 1 |
797 +------------+-----------------------+---------------+
799 +------------+-----------------------+---------------+
800 | **Range** | **Scale - Reference** | **Scale - 1** |
801 +============+=======================+===============+
802 | ``F_D`` | 1 | 1 |
803 +------------+-----------------------+---------------+
805 References
806 ----------
807 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`,
808 :cite:`InternationalTelecommunicationUnion2018`
810 Examples
811 --------
812 >>> eotf_BT2100_HLG(0.212132034355964) # doctest: +ELLIPSIS
813 6.4760398...
814 >>> eotf_BT2100_HLG(0.212132034355964, method="ITU-R BT.2100-1")
815 ... # doctest: +ELLIPSIS
816 6.4760398...
817 >>> eotf_BT2100_HLG(0.212132034355964, 0.01)
818 ... # doctest: +ELLIPSIS
819 7.3321975...
820 """
822 constants = optional(constants, CONSTANTS_BT2100_HLG)
823 method = validate_method(method, tuple(BT2100_HLG_EOTF_METHODS))
825 return BT2100_HLG_EOTF_METHODS[method](E_p, L_B, L_W, gamma, constants)
828def eotf_inverse_BT2100_HLG_1(
829 F_D: Domain1,
830 L_B: float = 0,
831 L_W: float = 1000,
832 gamma: float | None = None,
833 constants: Structure | None = None,
834) -> Range1:
835 """
836 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* inverse
837 electro-optical transfer function (EOTF) as specified in
838 *ITU-R BT.2100-1*.
840 Parameters
841 ----------
842 F_D
843 Luminance :math:`F_D` of a displayed linear component
844 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
845 :math:`cd/m^2`.
846 L_B
847 Display luminance for black :math:`L_B` in :math:`cd/m^2`.
848 L_W
849 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for
850 achromatic pixels.
851 gamma
852 System gamma value, defaults to 1.2 at the nominal display peak
853 luminance of :math:`1000 cd/m^2`.
854 constants
855 *Recommendation ITU-R BT.2100* *Reference HLG* constants.
857 Returns
858 -------
859 :class:`numpy.ndarray`
860 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`.
862 Notes
863 -----
864 +------------+-----------------------+---------------+
865 | **Domain** | **Scale - Reference** | **Scale - 1** |
866 +============+=======================+===============+
867 | ``F_D`` | 1 | 1 |
868 +------------+-----------------------+---------------+
870 +------------+-----------------------+---------------+
871 | **Range** | **Scale - Reference** | **Scale - 1** |
872 +============+=======================+===============+
873 | ``E_p`` | 1 | 1 |
874 +------------+-----------------------+---------------+
876 References
877 ----------
878 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`
880 Examples
881 --------
882 >>> eotf_inverse_BT2100_HLG_1(6.476039825649814) # doctest: +ELLIPSIS
883 0.2121320...
884 >>> eotf_inverse_BT2100_HLG_1(6.485975065251558, 0.01)
885 ... # doctest: +ELLIPSIS
886 0.2121320...
887 """
889 constants = optional(constants, CONSTANTS_BT2100_HLG)
891 return oetf_ARIBSTDB67(
892 ootf_inverse_BT2100_HLG_1(F_D, L_B, L_W, gamma) * 12,
893 constants=constants,
894 )
897def eotf_inverse_BT2100_HLG_2(
898 F_D: Domain1,
899 L_B: float = 0,
900 L_W: float = 1000,
901 gamma: float | None = None,
902 constants: Structure | None = None,
903) -> Range1:
904 """
905 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* inverse
906 electro-optical transfer function (EOTF) as specified in *ITU-R BT.2100-2*
907 with modified black level behaviour.
909 Parameters
910 ----------
911 F_D
912 Luminance :math:`F_D` of a displayed linear component
913 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
914 :math:`cd/m^2`.
915 L_B
916 Display luminance for black :math:`L_B` in :math:`cd/m^2`.
917 L_W
918 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for
919 achromatic pixels.
920 gamma
921 System gamma value, defaults to 1.2 at the nominal display peak
922 luminance of :math:`1000 cd/m^2`.
923 constants
924 *Recommendation ITU-R BT.2100* *Reference HLG* constants.
926 Returns
927 -------
928 :class:`numpy.ndarray`
929 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`.
931 Notes
932 -----
933 +------------+-----------------------+---------------+
934 | **Domain** | **Scale - Reference** | **Scale - 1** |
935 +============+=======================+===============+
936 | ``F_D`` | 1 | 1 |
937 +------------+-----------------------+---------------+
939 +------------+-----------------------+---------------+
940 | **Range** | **Scale - Reference** | **Scale - 1** |
941 +============+=======================+===============+
942 | ``E_p`` | 1 | 1 |
943 +------------+-----------------------+---------------+
945 References
946 ----------
947 :cite:`Borer2017a`,
948 :cite:`InternationalTelecommunicationUnion2018`
950 Examples
951 --------
952 >>> eotf_inverse_BT2100_HLG_2(6.476039825649814) # doctest: +ELLIPSIS
953 0.2121320...
954 >>> eotf_inverse_BT2100_HLG_2(7.332197528353875, 0.01)
955 ... # doctest: +ELLIPSIS
956 0.2121320...
957 """
959 constants = optional(constants, CONSTANTS_BT2100_HLG)
961 beta = black_level_lift_BT2100_HLG(L_B, L_W, gamma)
963 return (
964 oetf_ARIBSTDB67(
965 ootf_inverse_BT2100_HLG_2(F_D, L_W, gamma) * 12,
966 constants=constants,
967 )
968 - beta
969 ) / (1 - beta)
972BT2100_HLG_EOTF_INVERSE_METHODS: CanonicalMapping = CanonicalMapping(
973 {
974 "ITU-R BT.2100-1": eotf_inverse_BT2100_HLG_1,
975 "ITU-R BT.2100-2": eotf_inverse_BT2100_HLG_2,
976 }
977)
978BT2100_HLG_EOTF_INVERSE_METHODS.__doc__ = """
979Define the supported *ITU-R BT.2100* *Reference HLG* inverse
980electro-optical transfer function (EOTF) methods.
982References
983----------
984:cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`,
985:cite:`InternationalTelecommunicationUnion2018`
986"""
989def eotf_inverse_BT2100_HLG(
990 F_D: Domain1,
991 L_B: float = 0,
992 L_W: float = 1000,
993 gamma: float | None = None,
994 constants: Structure | None = None,
995 method: (Literal["ITU-R BT.2100-1", "ITU-R BT.2100-2"] | str) = "ITU-R BT.2100-2",
996) -> Range1:
997 """
998 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* inverse
999 electro-optical transfer function (EOTF).
1001 Parameters
1002 ----------
1003 F_D
1004 Luminance :math:`F_D` of a displayed linear component
1005 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
1006 :math:`cd/m^2`.
1007 L_B
1008 Display luminance for black :math:`L_B` in :math:`cd/m^2`.
1009 L_W
1010 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for
1011 achromatic pixels.
1012 gamma
1013 System gamma value, defaults to 1.2 at the nominal display peak
1014 luminance of :math:`1000 cd/m^2`.
1015 constants
1016 *Recommendation ITU-R BT.2100* *Reference HLG* constants.
1017 method
1018 Computation method.
1020 Returns
1021 -------
1022 :class:`numpy.ndarray`
1023 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`.
1025 Notes
1026 -----
1027 +------------+-----------------------+---------------+
1028 | **Domain** | **Scale - Reference** | **Scale - 1** |
1029 +============+=======================+===============+
1030 | ``F_D`` | 1 | 1 |
1031 +------------+-----------------------+---------------+
1033 +------------+-----------------------+---------------+
1034 | **Range** | **Scale - Reference** | **Scale - 1** |
1035 +============+=======================+===============+
1036 | ``E_p`` | 1 | 1 |
1037 +------------+-----------------------+---------------+
1039 References
1040 ----------
1041 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`,
1042 :cite:`InternationalTelecommunicationUnion2018`
1044 Examples
1045 --------
1046 >>> eotf_inverse_BT2100_HLG(6.476039825649814) # doctest: +ELLIPSIS
1047 0.2121320...
1048 >>> eotf_inverse_BT2100_HLG(6.476039825649814, method="ITU-R BT.2100-1")
1049 ... # doctest: +ELLIPSIS
1050 0.2121320...
1051 >>> eotf_inverse_BT2100_HLG(7.332197528353875, 0.01) # doctest: +ELLIPSIS
1052 0.2121320...
1053 """
1055 constants = optional(constants, CONSTANTS_BT2100_HLG)
1056 method = validate_method(method, tuple(BT2100_HLG_EOTF_INVERSE_METHODS))
1058 return BT2100_HLG_EOTF_INVERSE_METHODS[method](F_D, L_B, L_W, gamma, constants)
1061def ootf_BT2100_HLG_1(
1062 E: Domain1,
1063 L_B: float = 0,
1064 L_W: float = 1000,
1065 gamma: float | None = None,
1066) -> Range1:
1067 """
1068 Apply the *Recommendation ITU-R BT.2100* *Reference HLG*
1070 opto-optical transfer function
1071 (OOTF) as specified in *ITU-R BT.2100-1*.
1073 The OOTF maps relative scene linear light to display linear light.
1075 Parameters
1076 ----------
1077 E
1078 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the
1079 signal determined by scene light and scaled by camera exposure.
1080 L_B
1081 Display luminance for black :math:`L_B` in :math:`cd/m^2`.
1082 L_W
1083 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for
1084 achromatic pixels.
1085 gamma
1086 System gamma value, defaults to 1.2 at the nominal display peak
1087 luminance of :math:`1000 cd/m^2`.
1089 Returns
1090 -------
1091 :class:`numpy.ndarray`
1092 Luminance :math:`F_D` of a displayed linear component
1093 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
1094 :math:`cd/m^2`.
1096 Notes
1097 -----
1098 +------------+-----------------------+---------------+
1099 | **Domain** | **Scale - Reference** | **Scale - 1** |
1100 +============+=======================+===============+
1101 | ``E`` | 1 | 1 |
1102 +------------+-----------------------+---------------+
1104 +------------+-----------------------+---------------+
1105 | **Range** | **Scale - Reference** | **Scale - 1** |
1106 +============+=======================+===============+
1107 | ``F_D`` | 1 | 1 |
1108 +------------+-----------------------+---------------+
1110 References
1111 ----------
1112 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`
1114 Examples
1115 --------
1116 >>> ootf_BT2100_HLG_1(0.1) # doctest: +ELLIPSIS
1117 63.0957344...
1118 >>> ootf_BT2100_HLG_1(0.1, 0.01)
1119 ... # doctest: +ELLIPSIS
1120 63.1051034...
1121 """
1123 E = to_domain_1(E)
1125 is_single_channel = np.atleast_1d(E).shape[-1] != 3
1127 if is_single_channel:
1128 usage_warning(
1129 '"Recommendation ITU-R BT.2100" "Reference HLG OOTF" uses '
1130 "RGB Luminance in computations and expects a vector input, thus "
1131 "the specified input array will be stacked to compose a vector for "
1132 "internal computations but a single component will be output."
1133 )
1134 R_S = G_S = B_S = E
1135 else:
1136 R_S, G_S, B_S = tsplit(E)
1138 alpha = L_W - L_B
1139 beta = L_B
1141 Y_S = np.sum(WEIGHTS_BT2100_HLG * tstack([R_S, G_S, B_S]), axis=-1)
1143 gamma = optional(gamma, gamma_function_BT2100_HLG(L_W))
1145 R_D = alpha * R_S * np.abs(Y_S) ** (gamma - 1) + beta
1146 G_D = alpha * G_S * np.abs(Y_S) ** (gamma - 1) + beta
1147 B_D = alpha * B_S * np.abs(Y_S) ** (gamma - 1) + beta
1149 if is_single_channel:
1150 return as_float(from_range_1(R_D))
1152 RGB_D = tstack([R_D, G_D, B_D])
1154 return from_range_1(RGB_D)
1157def ootf_BT2100_HLG_2(
1158 E: Domain1,
1159 L_W: float = 1000,
1160 gamma: float | None = None,
1161) -> Range1:
1162 """
1163 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* opto-optical
1164 transfer function (OOTF) as specified in *ITU-R BT.2100-2*.
1166 The OOTF maps relative scene linear light to display linear light.
1168 Parameters
1169 ----------
1170 E
1171 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the
1172 signal determined by scene light and scaled by camera exposure.
1173 L_W
1174 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for
1175 achromatic pixels.
1176 gamma
1177 System gamma value, defaults to 1.2 at the nominal display peak
1178 luminance of :math:`1000 cd/m^2`.
1180 Returns
1181 -------
1182 :class:`numpy.ndarray`
1183 Luminance :math:`F_D` of a displayed linear component
1184 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
1185 :math:`cd/m^2`.
1187 Notes
1188 -----
1189 +------------+-----------------------+---------------+
1190 | **Domain** | **Scale - Reference** | **Scale - 1** |
1191 +============+=======================+===============+
1192 | ``E`` | 1 | 1 |
1193 +------------+-----------------------+---------------+
1195 +------------+-----------------------+---------------+
1196 | **Range** | **Scale - Reference** | **Scale - 1** |
1197 +============+=======================+===============+
1198 | ``F_D`` | 1 | 1 |
1199 +------------+-----------------------+---------------+
1201 References
1202 ----------
1203 :cite:`InternationalTelecommunicationUnion2018`
1205 Examples
1206 --------
1207 >>> ootf_BT2100_HLG_2(0.1) # doctest: +ELLIPSIS
1208 63.0957344...
1209 """
1211 E = to_domain_1(E)
1213 is_single_channel = np.atleast_1d(E).shape[-1] != 3
1215 if is_single_channel:
1216 usage_warning(
1217 '"Recommendation ITU-R BT.2100" "Reference HLG OOTF" uses '
1218 "RGB Luminance in computations and expects a vector input, thus "
1219 "the specified input array will be stacked to compose a vector for "
1220 "internal computations but a single component will be output."
1221 )
1222 R_S = G_S = B_S = E
1223 else:
1224 R_S, G_S, B_S = tsplit(E)
1226 alpha = L_W
1228 Y_S = np.sum(WEIGHTS_BT2100_HLG * tstack([R_S, G_S, B_S]), axis=-1)
1230 gamma = optional(gamma, gamma_function_BT2100_HLG(L_W))
1232 R_D = alpha * R_S * np.abs(Y_S) ** (gamma - 1)
1233 G_D = alpha * G_S * np.abs(Y_S) ** (gamma - 1)
1234 B_D = alpha * B_S * np.abs(Y_S) ** (gamma - 1)
1236 if is_single_channel:
1237 return as_float(from_range_1(R_D))
1239 RGB_D = tstack([R_D, G_D, B_D])
1241 return from_range_1(RGB_D)
1244BT2100_HLG_OOTF_METHODS: CanonicalMapping = CanonicalMapping(
1245 {
1246 "ITU-R BT.2100-1": ootf_BT2100_HLG_1,
1247 "ITU-R BT.2100-2": ootf_BT2100_HLG_2,
1248 }
1249)
1250BT2100_HLG_OOTF_METHODS.__doc__ = """
1251Map *Recommendation ITU-R BT.2100* *Reference HLG* opto-optical transfer
1252function (OOTF) methods.
1254References
1255----------
1256:cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`,
1257:cite:`InternationalTelecommunicationUnion2018`
1258"""
1261def ootf_BT2100_HLG(
1262 E: Domain1,
1263 L_B: float = 0,
1264 L_W: float = 1000,
1265 gamma: float | None = None,
1266 method: (Literal["ITU-R BT.2100-1", "ITU-R BT.2100-2"] | str) = "ITU-R BT.2100-2",
1267) -> Range1:
1268 """
1269 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* opto-optical
1270 transfer function (OOTF).
1272 The OOTF maps relative scene linear light to display linear light.
1274 Parameters
1275 ----------
1276 E
1277 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the
1278 signal determined by scene light and scaled by camera exposure.
1279 L_B
1280 Display luminance for black :math:`L_B` in :math:`cd/m^2`.
1281 L_W
1282 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2`
1283 for achromatic pixels.
1284 gamma
1285 System gamma value, defaults to 1.2 at the nominal display peak
1286 luminance of :math:`1000 cd/m^2`.
1288 Returns
1289 -------
1290 :class:`numpy.ndarray`
1291 Luminance :math:`F_D` of a displayed linear component
1292 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
1293 :math:`cd/m^2`.
1295 Notes
1296 -----
1297 +------------+-----------------------+---------------+
1298 | **Domain** | **Scale - Reference** | **Scale - 1** |
1299 +============+=======================+===============+
1300 | ``E`` | 1 | 1 |
1301 +------------+-----------------------+---------------+
1303 +------------+-----------------------+---------------+
1304 | **Range** | **Scale - Reference** | **Scale - 1** |
1305 +============+=======================+===============+
1306 | ``F_D`` | 1 | 1 |
1307 +------------+-----------------------+---------------+
1309 References
1310 ----------
1311 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`
1313 Examples
1314 --------
1315 >>> ootf_BT2100_HLG(0.1) # doctest: +ELLIPSIS
1316 63.0957344...
1317 >>> ootf_BT2100_HLG(0.1, 0.01, method="ITU-R BT.2100-1")
1318 ... # doctest: +ELLIPSIS
1319 63.1051034...
1320 """
1322 method = validate_method(method, tuple(BT2100_HLG_OOTF_METHODS))
1324 function = BT2100_HLG_OOTF_METHODS[method]
1326 return function(
1327 E,
1328 **filter_kwargs(function, L_B=L_B, L_W=L_W, gamma=gamma),
1329 )
1332def ootf_inverse_BT2100_HLG_1(
1333 F_D: Domain1,
1334 L_B: float = 0,
1335 L_W: float = 1000,
1336 gamma: float | None = None,
1337) -> Range1:
1338 """
1339 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* inverse
1340 opto-optical transfer function (OOTF) as defined in *ITU-R BT.2100-1*.
1342 The inverse OOTF maps display linear light to relative scene linear light.
1344 Parameters
1345 ----------
1346 F_D
1347 Luminance :math:`F_D` of a displayed linear component
1348 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
1349 :math:`cd/m^2`.
1350 L_B
1351 Display luminance for black :math:`L_B` in :math:`cd/m^2`.
1352 L_W
1353 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for
1354 achromatic pixels.
1355 gamma
1356 System gamma value, defaults to 1.2 at the nominal display peak
1357 luminance of :math:`1000 cd/m^2`.
1359 Returns
1360 -------
1361 :class:`numpy.ndarray`
1362 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the
1363 signal determined by scene light and scaled by camera exposure.
1365 Notes
1366 -----
1367 +------------+-----------------------+---------------+
1368 | **Domain** | **Scale - Reference** | **Scale - 1** |
1369 +============+=======================+===============+
1370 | ``F_D`` | 1 | 1 |
1371 +------------+-----------------------+---------------+
1373 +------------+-----------------------+---------------+
1374 | **Range** | **Scale - Reference** | **Scale - 1** |
1375 +============+=======================+===============+
1376 | ``E`` | 1 | 1 |
1377 +------------+-----------------------+---------------+
1379 References
1380 ----------
1381 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`
1383 Examples
1384 --------
1385 >>> ootf_inverse_BT2100_HLG_1(63.095734448019336) # doctest: +ELLIPSIS
1386 0.1000000...
1387 >>> ootf_inverse_BT2100_HLG_1(63.105103490674857, 0.01)
1388 ... # doctest: +ELLIPSIS
1389 0.0999999...
1390 """
1392 F_D = to_domain_1(F_D)
1394 is_single_channel = np.atleast_1d(F_D).shape[-1] != 3
1396 if is_single_channel:
1397 usage_warning(
1398 '"Recommendation ITU-R BT.2100" "Reference HLG OOTF" uses '
1399 "RGB Luminance in computations and expects a vector input, thus "
1400 "the specified input array will be stacked to compose a vector for "
1401 "internal computations but a single component will be output."
1402 )
1403 R_D = G_D = B_D = F_D
1404 else:
1405 R_D, G_D, B_D = tsplit(F_D)
1407 Y_D = np.sum(WEIGHTS_BT2100_HLG * tstack([R_D, G_D, B_D]), axis=-1)
1409 alpha = L_W - L_B
1410 beta = L_B
1412 gamma = optional(gamma, gamma_function_BT2100_HLG(L_W))
1414 Y_D_beta = np.abs((Y_D - beta) / alpha) ** ((1 - gamma) / gamma)
1416 R_S = np.where(
1417 beta == Y_D,
1418 0.0,
1419 Y_D_beta * (R_D - beta) / alpha,
1420 )
1421 G_S = np.where(
1422 beta == Y_D,
1423 0.0,
1424 Y_D_beta * (G_D - beta) / alpha,
1425 )
1426 B_S = np.where(
1427 beta == Y_D,
1428 0.0,
1429 Y_D_beta * (B_D - beta) / alpha,
1430 )
1432 if is_single_channel:
1433 return as_float(from_range_1(R_S))
1435 RGB_S = tstack([R_S, G_S, B_S])
1437 return from_range_1(RGB_S)
1440def ootf_inverse_BT2100_HLG_2(
1441 F_D: Domain1,
1442 L_W: float = 1000,
1443 gamma: float | None = None,
1444) -> Range1:
1445 """
1446 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* inverse
1447 opto-optical transfer function (OOTF) according to *ITU-R BT.2100-2*.
1449 The inverse OOTF maps display linear light to relative scene linear light.
1451 Parameters
1452 ----------
1453 F_D
1454 Luminance :math:`F_D` of a displayed linear component
1455 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
1456 :math:`cd/m^2`.
1457 L_W
1458 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for
1459 achromatic pixels.
1460 gamma
1461 System gamma value, defaults to 1.2 at the nominal display peak
1462 luminance of :math:`1000 cd/m^2`.
1464 Returns
1465 -------
1466 :class:`numpy.ndarray`
1467 :math:`E` denotes the signal for each colour component
1468 :math:`\\{R_S, G_S, B_S\\}` proportional to scene linear light and
1469 scaled by camera exposure.
1471 Notes
1472 -----
1473 +------------+-----------------------+---------------+
1474 | **Domain** | **Scale - Reference** | **Scale - 1** |
1475 +============+=======================+===============+
1476 | ``F_D`` | 1 | 1 |
1477 +------------+-----------------------+---------------+
1479 +------------+-----------------------+---------------+
1480 | **Range** | **Scale - Reference** | **Scale - 1** |
1481 +============+=======================+===============+
1482 | ``E`` | 1 | 1 |
1483 +------------+-----------------------+---------------+
1485 References
1486 ----------
1487 :cite:`InternationalTelecommunicationUnion2018`
1489 Examples
1490 --------
1491 >>> ootf_inverse_BT2100_HLG_2(63.095734448019336) # doctest: +ELLIPSIS
1492 0.1000000...
1493 """
1495 F_D = to_domain_1(F_D)
1497 is_single_channel = np.atleast_1d(F_D).shape[-1] != 3
1499 if is_single_channel:
1500 usage_warning(
1501 '"Recommendation ITU-R BT.2100" "Reference HLG OOTF" uses '
1502 "RGB Luminance in computations and expects a vector input, thus "
1503 "the specified input array will be stacked to compose a vector for "
1504 "internal computations but a single component will be output."
1505 )
1506 R_D = G_D = B_D = F_D
1507 else:
1508 R_D, G_D, B_D = tsplit(F_D)
1510 Y_D = np.sum(WEIGHTS_BT2100_HLG * tstack([R_D, G_D, B_D]), axis=-1)
1512 alpha = L_W
1514 gamma = optional(gamma, gamma_function_BT2100_HLG(L_W))
1516 Y_D_alpha = np.abs(Y_D / alpha) ** ((1 - gamma) / gamma)
1518 R_S = np.where(
1519 Y_D == 0,
1520 0.0,
1521 Y_D_alpha * R_D / alpha,
1522 )
1523 G_S = np.where(
1524 Y_D == 0,
1525 0.0,
1526 Y_D_alpha * G_D / alpha,
1527 )
1528 B_S = np.where(
1529 Y_D == 0,
1530 0.0,
1531 Y_D_alpha * B_D / alpha,
1532 )
1534 if is_single_channel:
1535 return as_float(from_range_1(R_S))
1537 RGB_S = tstack([R_S, G_S, B_S])
1539 return from_range_1(RGB_S)
1542BT2100_HLG_OOTF_INVERSE_METHODS: CanonicalMapping = CanonicalMapping(
1543 {
1544 "ITU-R BT.2100-1": ootf_inverse_BT2100_HLG_1,
1545 "ITU-R BT.2100-2": ootf_inverse_BT2100_HLG_2,
1546 }
1547)
1548BT2100_HLG_OOTF_INVERSE_METHODS.__doc__ = """
1549Support methods for the *ITU-R BT.2100* *Reference HLG* inverse
1550opto-optical transfer function (OOTF).
1552References
1553----------
1554:cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`,
1555:cite:`InternationalTelecommunicationUnion2018`
1556"""
1559def ootf_inverse_BT2100_HLG(
1560 F_D: Domain1,
1561 L_B: float = 0,
1562 L_W: float = 1000,
1563 gamma: float | None = None,
1564 method: (Literal["ITU-R BT.2100-1", "ITU-R BT.2100-2"] | str) = "ITU-R BT.2100-2",
1565) -> Range1:
1566 """
1567 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* inverse
1568 opto-optical transfer function (OOTF).
1570 The inverse OOTF maps display linear light to relative scene linear light.
1572 Parameters
1573 ----------
1574 F_D
1575 Luminance :math:`F_D` of a displayed linear component
1576 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in
1577 :math:`cd/m^2`.
1578 L_B
1579 Display luminance for black :math:`L_B` in :math:`cd/m^2`.
1580 L_W
1581 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for
1582 achromatic pixels.
1583 gamma
1584 System gamma value, defaults to 1.2 at the nominal display peak
1585 luminance of :math:`1000 cd/m^2`.
1586 method
1587 Computation method.
1589 Returns
1590 -------
1591 :class:`numpy.ndarray`
1592 :math:`E` denotes the signal for each colour component
1593 :math:`\\{R_S, G_S, B_S\\}` proportional to scene linear light and
1594 scaled by camera exposure.
1596 Notes
1597 -----
1598 +------------+-----------------------+---------------+
1599 | **Domain** | **Scale - Reference** | **Scale - 1** |
1600 +============+=======================+===============+
1601 | ``F_D`` | 1 | 1 |
1602 +------------+-----------------------+---------------+
1604 +------------+-----------------------+---------------+
1605 | **Range** | **Scale - Reference** | **Scale - 1** |
1606 +============+=======================+===============+
1607 | ``E`` | 1 | 1 |
1608 +------------+-----------------------+---------------+
1610 References
1611 ----------
1612 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`,
1613 :cite:`InternationalTelecommunicationUnion2018`
1615 Examples
1616 --------
1617 >>> ootf_inverse_BT2100_HLG(63.095734448019336) # doctest: +ELLIPSIS
1618 0.1000000...
1619 >>> ootf_inverse_BT2100_HLG(63.105103490674857, 0.01, method="ITU-R BT.2100-1")
1620 ... # doctest: +ELLIPSIS
1621 0.0999999...
1622 """
1624 method = validate_method(method, tuple(BT2100_HLG_OOTF_INVERSE_METHODS))
1626 function = BT2100_HLG_OOTF_INVERSE_METHODS[method]
1628 return function(
1629 F_D,
1630 **filter_kwargs(function, L_B=L_B, L_W=L_W, gamma=gamma),
1631 )