Coverage for models/rgb/transfer_functions/common.py: 62%
37 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-16 22:49 +1300
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-16 22:49 +1300
1"""
2Common Transfer Functions Utilities
3===================================
5Define various transfer functions common utilities.
6"""
8from __future__ import annotations
10import typing
12import numpy as np
14if typing.TYPE_CHECKING:
15 from colour.hints import ArrayLike, NDArrayReal
17from colour.utilities import as_float, as_float_array, as_int, as_int_array
19__author__ = "Colour Developers"
20__copyright__ = "Copyright 2013 Colour Developers"
21__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
22__maintainer__ = "Colour Developers"
23__email__ = "colour-developers@colour-science.org"
24__status__ = "Production"
26__all__ = [
27 "CV_range",
28 "legal_to_full",
29 "full_to_legal",
30]
33def CV_range(
34 bit_depth: int = 10, is_legal: bool = False, is_int: bool = False
35) -> NDArrayReal:
36 """
37 Return the code value :math:`CV` range for the specified bit-depth,
38 range legality and representation.
40 Parameters
41 ----------
42 bit_depth
43 Bit-depth of the code value :math:`CV` range.
44 is_legal
45 Whether the code value :math:`CV` range represents legal code values.
46 is_int
47 Whether the code value :math:`CV` range represents int code
48 values.
50 Returns
51 -------
52 :class:`numpy.ndarray`
53 Code value :math:`CV` range.
55 Examples
56 --------
57 >>> CV_range(8, True, True)
58 array([ 16, 235])
59 >>> CV_range(8, True, False) # doctest: +ELLIPSIS
60 array([ 0.0627451..., 0.9215686...])
61 >>> CV_range(10, False, False)
62 array([ 0., 1.])
63 """
65 if is_legal:
66 ranges = np.array([16, 235])
67 ranges *= 2 ** (bit_depth - 8)
68 else:
69 ranges = np.array([0, 2**bit_depth - 1])
71 if not is_int:
72 ranges = as_float_array(ranges) / (2**bit_depth - 1)
74 return ranges
77def legal_to_full(
78 CV: ArrayLike,
79 bit_depth: int = 10,
80 in_int: bool = False,
81 out_int: bool = False,
82) -> NDArrayReal:
83 """
84 Convert the specified code value :math:`CV` or float equivalent of a code
85 value at a specified bit-depth from *legal range* (studio swing) to
86 *full range* (full swing).
88 Parameters
89 ----------
90 CV
91 Legal range code value :math:`CV` or float equivalent of a code value
92 at a specified bit-depth.
93 bit_depth
94 Bit-depth used for conversion.
95 in_int
96 Whether to treat the input value as integer code value or floating
97 point equivalent of a code value at a specified bit-depth.
98 out_int
99 Whether to return value as integer code value or floating point
100 equivalent of a code value at a specified bit-depth.
102 Returns
103 -------
104 :class:`numpy.ndarray`
105 Full range code value :math:`CV` or float equivalent of a code value
106 at a specified bit-depth.
108 Examples
109 --------
110 >>> legal_to_full(64 / 1023)
111 0.0
112 >>> legal_to_full(940 / 1023)
113 1.0
114 >>> legal_to_full(64 / 1023, out_int=True)
115 0
116 >>> legal_to_full(940 / 1023, out_int=True)
117 1023
118 >>> legal_to_full(64, in_int=True)
119 0.0
120 >>> legal_to_full(940, in_int=True)
121 1.0
122 >>> legal_to_full(64, in_int=True, out_int=True)
123 0
124 >>> legal_to_full(940, in_int=True, out_int=True)
125 1023
126 """
128 CV = as_float_array(CV)
130 MV = 2**bit_depth - 1
132 CV_full = as_int_array(np.round(CV)) if in_int else CV * MV
134 B, W = CV_range(bit_depth, True, True)
136 CV_full = (CV_full - B) / (W - B)
138 if out_int:
139 return as_int(np.round(CV_full * MV))
141 return as_float(CV_full)
144def full_to_legal(
145 CV: ArrayLike,
146 bit_depth: int = 10,
147 in_int: bool = False,
148 out_int: bool = False,
149) -> NDArrayReal:
150 """
151 Convert the specified code value :math:`CV` or float equivalent of a
152 code value at a specified bit-depth from full range (full swing) to
153 legal range (studio swing).
155 Parameters
156 ----------
157 CV
158 Full range code value :math:`CV` or float equivalent of a code value
159 at a specified bit-depth.
160 bit_depth
161 Bit-depth used for conversion.
162 in_int
163 Whether to treat the input value as integer code value or floating
164 point equivalent of a code value at a specified bit-depth.
165 out_int
166 Whether to return value as integer code value or floating point
167 equivalent of a code value at a specified bit-depth.
169 Returns
170 -------
171 :class:`numpy.ndarray`
172 Legal range code value :math:`CV` or float equivalent of a code value
173 at a specified bit-depth.
175 Examples
176 --------
177 >>> full_to_legal(0.0) # doctest: +ELLIPSIS
178 0.0625610...
179 >>> full_to_legal(1.0) # doctest: +ELLIPSIS
180 0.9188660...
181 >>> full_to_legal(0.0, out_int=True)
182 64
183 >>> full_to_legal(1.0, out_int=True)
184 940
185 >>> full_to_legal(0, in_int=True) # doctest: +ELLIPSIS
186 0.0625610...
187 >>> full_to_legal(1023, in_int=True) # doctest: +ELLIPSIS
188 0.9188660...
189 >>> full_to_legal(0, in_int=True, out_int=True)
190 64
191 >>> full_to_legal(1023, in_int=True, out_int=True)
192 940
193 """
195 CV = as_float_array(CV)
197 MV = 2**bit_depth - 1
199 CV_legal = as_int_array(np.round(CV / MV)) if in_int else CV
201 B, W = CV_range(bit_depth, True, True)
203 CV_legal = (W - B) * CV_legal + B
205 if out_int:
206 return as_int(np.round(CV_legal))
208 return as_float(CV_legal / MV)