Coverage for colour/models/rgb/transfer_functions/itur_bt_1361.py: 100%
23 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.1361
3============================
5Define the *Recommendation ITU-R BT.1361* opto-electrical transfer function
6(OETF) and its inverse.
8- :func:`colour.models.oetf_BT1361`
9- :func:`colour.models.oetf_inverse_BT1361`
11References
12----------
13- :cite:`InternationalTelecommunicationUnion1998` : International
14 Telecommunication Union. (1998). Recommendation ITU-R BT.1361 - Worldwide
15 unified colorimetry and related characteristics of future television and
16 imaging systems (pp. 1-32). https://www.itu.int/dms_pubrec/itu-r/rec/bt/\
17R-REC-BT.1361-0-199802-W!!PDF-E.pdf
18"""
20from __future__ import annotations
22import numpy as np
24from colour.algebra import spow
25from colour.hints import ( # noqa: TC001
26 Domain1,
27 Range1,
28)
29from colour.models.rgb.transfer_functions import oetf_BT709, oetf_inverse_BT709
30from colour.utilities import as_float, domain_range_scale, from_range_1, to_domain_1
32__author__ = "Colour Developers"
33__copyright__ = "Copyright 2013 Colour Developers"
34__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
35__maintainer__ = "Colour Developers"
36__email__ = "colour-developers@colour-science.org"
37__status__ = "Production"
39__all__ = [
40 "oetf_BT1361",
41 "oetf_inverse_BT1361",
42]
45def oetf_BT1361(L: Domain1) -> Range1:
46 """
47 Apply the *Recommendation ITU-R BT.1361* extended colour gamut system
48 opto-electronic transfer function (OETF).
50 Parameters
51 ----------
52 L
53 Scene *Luminance* :math:`L`.
55 Returns
56 -------
57 :class:`numpy.ndarray`
58 Non-linear primary signal :math:`E'`.
60 Notes
61 -----
62 +------------+-----------------------+---------------+
63 | **Domain** | **Scale - Reference** | **Scale - 1** |
64 +============+=======================+===============+
65 | ``L`` | 1 | 1 |
66 +------------+-----------------------+---------------+
68 +------------+-----------------------+---------------+
69 | **Range** | **Scale - Reference** | **Scale - 1** |
70 +============+=======================+===============+
71 | ``E_p'`` | 1 | 1 |
72 +------------+-----------------------+---------------+
74 References
75 ----------
76 :cite:`InternationalTelecommunicationUnion1998`
78 Examples
79 --------
80 >>> oetf_BT1361(0.18) # doctest: +ELLIPSIS
81 0.4090077288641...
82 >>> oetf_BT1361(-0.25) # doctest: +ELLIPSIS
83 -0.25
84 >>> oetf_BT1361(1.33) # doctest: +ELLIPSIS
85 1.1504846663972...
86 """
88 L = to_domain_1(L)
90 with domain_range_scale("ignore"):
91 E_p = np.where(
92 L >= 0,
93 oetf_BT709(L),
94 np.where(
95 L <= -0.0045,
96 # L in [-0.25, -0.0045] range
97 -(1.099 * spow(-4 * L, 0.45) - 0.099) / 4,
98 # L in [-0.0045, 0] range
99 4.500 * L,
100 ),
101 )
103 return as_float(from_range_1(E_p))
106def oetf_inverse_BT1361(E_p: Domain1) -> Range1:
107 """
108 Apply the *Recommendation ITU-R BT.1361* extended colour gamut system
109 inverse opto-electronic transfer function (OETF).
111 Parameters
112 ----------
113 E_p
114 Non-linear primary signal :math:`E'`.
116 Returns
117 -------
118 :class:`numpy.ndarray`
119 Scene *Luminance* :math:`L`.
121 Notes
122 -----
123 +------------+-----------------------+---------------+
124 | **Domain** | **Scale - Reference** | **Scale - 1** |
125 +============+=======================+===============+
126 | ``E_p`` | 1 | 1 |
127 +------------+-----------------------+---------------+
129 +------------+-----------------------+---------------+
130 | **Range** | **Scale - Reference** | **Scale - 1** |
131 +============+=======================+===============+
132 | ``L`` | 1 | 1 |
133 +------------+-----------------------+---------------+
135 References
136 ----------
137 :cite:`InternationalTelecommunicationUnion1998`
139 Examples
140 --------
141 >>> oetf_inverse_BT1361(0.4090077288641) # doctest: +ELLIPSIS
142 0.1799999...
143 >>> oetf_inverse_BT1361(-0.25) # doctest: +ELLIPSIS
144 -0.25
145 >>> oetf_inverse_BT1361(1.1504846663972) # doctest: +ELLIPSIS
146 1.3299999...
147 """
149 E_p = to_domain_1(E_p)
151 with domain_range_scale("ignore"):
152 L = np.where(
153 E_p >= 0,
154 oetf_inverse_BT709(E_p),
155 np.where(
156 E_p <= 4.500 * -0.0045,
157 # L in [-0.25, -0.0045] range
158 -spow((-4 * E_p + 0.099) / 1.099, 1 / 0.45) / 4,
159 # L in [-0.0045, 0] range
160 E_p / 4.500,
161 ),
162 )
164 return as_float(from_range_1(L))