Coverage for colour/models/din99.py: 100%
53 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"""
2DIN99 Colourspace and DIN99b, DIN99c, DIN99d Refined Formulas
3=============================================================
5Define the *DIN99* colourspace and *DIN99b*, *DIN99c*, *DIN99d* refined
6formulas transformations.
8- :func:`colour.Lab_to_DIN99`
9- :func:`colour.DIN99_to_Lab`
10- :func:`colour.XYZ_to_DIN99`
11- :func:`colour.DIN99_to_XYZ`
13References
14----------
15- :cite:`ASTMInternational2007` : ASTM International. (2007). ASTM D2244-07 -
16 Standard Practice for Calculation of Color Tolerances and Color Differences
17 from Instrumentally Measured Color Coordinates: Vol. i (pp. 1-10).
18 doi:10.1520/D2244-16
19- :cite:`Cui2002` : Cui, G., Luo, M. R., Rigg, B., Roesler, G., & Witt, K.
20 (2002). Uniform colour spaces based on the DIN99 colour-difference formula.
21 Color Research & Application, 27(4), 282-290. doi:10.1002/col.10066
22"""
24from __future__ import annotations
26import typing
28import numpy as np
30from colour.algebra import spow
31from colour.colorimetry import CCS_ILLUMINANTS
33if typing.TYPE_CHECKING:
34 from colour.hints import Literal
36from colour.hints import ( # noqa: TC001
37 ArrayLike,
38 Domain1,
39 Domain100,
40 Range1,
41 Range100,
42)
43from colour.models import Lab_to_XYZ, XYZ_to_Lab
44from colour.utilities import (
45 CanonicalMapping,
46 from_range_100,
47 to_domain_100,
48 tsplit,
49 tstack,
50 validate_method,
51)
53__author__ = "Colour Developers"
54__copyright__ = "Copyright 2013 Colour Developers"
55__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
56__maintainer__ = "Colour Developers"
57__email__ = "colour-developers@colour-science.org"
58__status__ = "Production"
60__all__ = [
61 "DIN99_METHODS",
62 "Lab_to_DIN99",
63 "DIN99_to_Lab",
64 "XYZ_to_DIN99",
65 "DIN99_to_XYZ",
66]
68DIN99_METHODS: CanonicalMapping = CanonicalMapping(
69 {
70 "ASTMD2244-07": np.array(
71 [105.509, 0.0158, 16.0, 0.7, 1, 9 / 200, 0.0, 9 / 200]
72 ),
73 "DIN99": np.array([105.509, 0.0158, 16.0, 0.7, 1, 9 / 200, 0.0, 9 / 200]),
74 "DIN99b": np.array([303.67, 0.0039, 26.0, 0.83, 23.0, 0.075, 26.0, 1]),
75 "DIN99c": np.array([317.65, 0.0037, 0.0, 0.94, 23.0, 0.066, 0.0, 1]),
76 "DIN99d": np.array([325.22, 0.0036, 50.0, 1.14, 22.5, 0.06, 50.0, 1]),
77 }
78)
79"""
80Supported *DIN99* colourspace methods, i.e., the coefficients for the *DIN99b*,
81*DIN99c*, and *DIN99d* refined formulas according to *Cui et al. (2002)*.
83References
84----------
85:cite:`ASTMInternational2007`, :cite:`Cui2002`
86"""
89def Lab_to_DIN99(
90 Lab: Domain100,
91 k_E: float = 1,
92 k_CH: float = 1,
93 method: (
94 Literal["ASTMD2244-07", "DIN99", "DIN99b", "DIN99c", "DIN99d"] | str
95 ) = "DIN99",
96) -> Range100:
97 """
98 Convert from *CIE L\\*a\\*b\\** colourspace to *DIN99* colourspace or one
99 of the *DIN99b*, *DIN99c*, *DIN99d* refined formulas according to
100 *Cui et al. (2002)*.
102 Parameters
103 ----------
104 Lab
105 *CIE L\\*a\\*b\\** colourspace array.
106 k_E
107 Parametric factor :math:`K_E` used to compensate for texture and
108 other specimen presentation effects.
109 k_CH
110 Parametric factor :math:`K_{CH}` used to compensate for texture
111 and other specimen presentation effects.
112 method
113 Computation method.
115 Returns
116 -------
117 :class:`numpy.ndarray`
118 *DIN99* colourspace array.
120 Notes
121 -----
122 +------------+------------------------+--------------------+
123 | **Domain** | **Scale - Reference** | **Scale - 1** |
124 +============+========================+====================+
125 | ``Lab`` | 100 | 1 |
126 +------------+------------------------+--------------------+
128 +------------+------------------------+--------------------+
129 | **Range** | **Scale - Reference** | **Scale - 1** |
130 +============+========================+====================+
131 | ``Lab_99`` | 100 | 1 |
132 +------------+------------------------+--------------------+
134 References
135 ----------
136 :cite:`ASTMInternational2007`, :cite:`Cui2002`
138 Examples
139 --------
140 >>> import numpy as np
141 >>> Lab = np.array([41.52787529, 52.63858304, 26.92317922])
142 >>> Lab_to_DIN99(Lab) # doctest: +ELLIPSIS
143 array([ 53.2282198..., 28.4163465..., 3.8983955...])
144 """
146 c_1, c_2, c_3, c_4, c_5, c_6, c_7, c_8 = DIN99_METHODS[
147 validate_method(method, tuple(DIN99_METHODS))
148 ]
150 L, a, b = tsplit(to_domain_100(Lab))
152 cos_c = np.cos(np.radians(c_3))
153 sin_c = np.sin(np.radians(c_3))
155 e = cos_c * a + sin_c * b
156 f = c_4 * (-sin_c * a + cos_c * b)
157 G = spow(e**2 + f**2, 0.5)
158 h_ef = np.arctan2(f, e) + np.radians(c_7)
160 C_99 = c_5 * (np.log1p(c_6 * G)) / (c_8 * k_CH * k_E)
161 # Hue angle is unused currently.
162 # h_99 = np.degrees(h_ef)
163 a_99 = C_99 * np.cos(h_ef)
164 b_99 = C_99 * np.sin(h_ef)
165 L_99 = c_1 * (np.log1p(c_2 * L)) * k_E
167 Lab_99 = tstack([L_99, a_99, b_99])
169 return from_range_100(Lab_99)
172def DIN99_to_Lab(
173 Lab_99: Domain100,
174 k_E: float = 1,
175 k_CH: float = 1,
176 method: (
177 Literal["ASTMD2244-07", "DIN99", "DIN99b", "DIN99c", "DIN99d"] | str
178 ) = "DIN99",
179) -> Range100:
180 """
181 Convert from *DIN99* colourspace or one of the *DIN99b*, *DIN99c*, *DIN99d*
182 refined formulas according to *Cui et al. (2002)* to *CIE L\\*a\\*b\\**
183 colourspace.
185 Parameters
186 ----------
187 Lab_99
188 *DIN99* colourspace array.
189 k_E
190 Parametric factor :math:`K_E` used to compensate for texture
191 and other specimen presentation effects.
192 k_CH
193 Parametric factor :math:`K_{CH}` used to compensate for texture
194 and other specimen presentation effects.
195 method
196 Computation method.
198 Returns
199 -------
200 :class:`numpy.ndarray`
201 *CIE L\\*a\\*b\\** colourspace array.
203 Notes
204 -----
205 +------------+------------------------+--------------------+
206 | **Domain** | **Scale - Reference** | **Scale - 1** |
207 +============+========================+====================+
208 | ``Lab_99`` | 100 | 1 |
209 +------------+------------------------+--------------------+
211 +------------+------------------------+--------------------+
212 | **Range** | **Scale - Reference** | **Scale - 1** |
213 +============+========================+====================+
214 | ``Lab`` | 100 | 1 |
215 +------------+------------------------+--------------------+
217 References
218 ----------
219 :cite:`ASTMInternational2007`, :cite:`Cui2002`
221 Examples
222 --------
223 >>> import numpy as np
224 >>> Lab_99 = np.array([53.22821988, 28.41634656, 3.89839552])
225 >>> DIN99_to_Lab(Lab_99) # doctest: +ELLIPSIS
226 array([ 41.5278752..., 52.6385830..., 26.9231792...])
227 """
229 c_1, c_2, c_3, c_4, c_5, c_6, c_7, c_8 = DIN99_METHODS[
230 validate_method(method, tuple(DIN99_METHODS))
231 ]
233 L_99, a_99, b_99 = tsplit(to_domain_100(Lab_99))
235 cos = np.cos(np.radians(c_3))
236 sin = np.sin(np.radians(c_3))
238 h_99 = np.arctan2(b_99, a_99) - np.radians(c_7)
240 C_99 = np.hypot(a_99, b_99)
241 G = np.expm1((c_8 / c_5) * C_99 * k_CH * k_E) / c_6
243 e = G * np.cos(h_99)
244 f = G * np.sin(h_99)
246 a = e * cos - (f / c_4) * sin
247 b = e * sin + (f / c_4) * cos
248 L = np.expm1(L_99 * k_E / c_1) / c_2
250 Lab = tstack([L, a, b])
252 return from_range_100(Lab)
255def XYZ_to_DIN99(
256 XYZ: Domain1,
257 illuminant: ArrayLike = CCS_ILLUMINANTS["CIE 1931 2 Degree Standard Observer"][
258 "D65"
259 ],
260 k_E: float = 1,
261 k_CH: float = 1,
262 method: (
263 Literal["ASTMD2244-07", "DIN99", "DIN99b", "DIN99c", "DIN99d"] | str
264 ) = "DIN99",
265) -> Range100:
266 """
267 Convert from *CIE XYZ* tristimulus values to *DIN99* colourspace or one
268 of the *DIN99b*, *DIN99c*, *DIN99d* refined formulas according to
269 *Cui et al. (2002)*.
271 Parameters
272 ----------
273 XYZ
274 *CIE XYZ* tristimulus values.
275 illuminant
276 Reference *illuminant* *CIE xy* chromaticity coordinates or *CIE xyY*
277 colourspace array.
278 k_E
279 Parametric factor :math:`K_E` used to compensate for texture and
280 other specimen presentation effects.
281 k_CH
282 Parametric factor :math:`K_{CH}` used to compensate for texture and
283 other specimen presentation effects.
284 method
285 Computation method.
287 Returns
288 -------
289 :class:`numpy.ndarray`
290 *DIN99* colourspace array.
292 Notes
293 -----
294 +----------------+-----------------------+-----------------+
295 | **Domain** | **Scale - Reference** | **Scale - 1** |
296 +================+=======================+=================+
297 | ``XYZ`` | 1 | 1 |
298 +----------------+-----------------------+-----------------+
299 | ``illuminant`` | 1 | 1 |
300 +----------------+-----------------------+-----------------+
302 +------------+------------------------+--------------------+
303 | **Range** | **Scale - Reference** | **Scale - 1** |
304 +============+========================+====================+
305 | ``Lab_99`` | 100 | 1 |
306 +------------+------------------------+--------------------+
308 References
309 ----------
310 :cite:`ASTMInternational2007`
312 Examples
313 --------
314 >>> import numpy as np
315 >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952])
316 >>> XYZ_to_DIN99(XYZ) # doctest: +ELLIPSIS
317 array([ 53.2282198..., 28.4163465..., 3.8983955...])
318 """
320 Lab = XYZ_to_Lab(XYZ, illuminant)
322 return Lab_to_DIN99(Lab, k_E, k_CH, method)
325def DIN99_to_XYZ(
326 Lab_99: Domain100,
327 illuminant: ArrayLike = CCS_ILLUMINANTS["CIE 1931 2 Degree Standard Observer"][
328 "D65"
329 ],
330 k_E: float = 1,
331 k_CH: float = 1,
332 method: (
333 Literal["ASTMD2244-07", "DIN99", "DIN99b", "DIN99c", "DIN99d"] | str
334 ) = "DIN99",
335) -> Range1:
336 """
337 Convert from *DIN99* colourspace or one of the *DIN99b*, *DIN99c*,
338 *DIN99d* refined formulas according to *Cui et al. (2002)* to
339 *CIE XYZ* tristimulus values.
341 Parameters
342 ----------
343 Lab_99
344 *DIN99* colourspace array.
345 illuminant
346 Reference *illuminant* *CIE xy* chromaticity coordinates or *CIE xyY*
347 colourspace array.
348 k_E
349 Parametric factor :math:`K_E` used to compensate for texture
350 and other specimen presentation effects.
351 k_CH
352 Parametric factor :math:`K_{CH}` used to compensate for texture
353 and other specimen presentation effects.
354 method
355 Computation method.
357 Returns
358 -------
359 :class:`numpy.ndarray`
360 *CIE XYZ* tristimulus values.
362 Notes
363 -----
364 +----------------+------------------------+--------------------+
365 | **Domain** | **Scale - Reference** | **Scale - 1** |
366 +================+========================+====================+
367 | ``Lab_99`` | 100 | 1 |
368 +----------------+------------------------+--------------------+
369 | ``illuminant`` | 1 | 1 |
370 +----------------+------------------------+--------------------+
372 +----------------+-----------------------+---------------------+
373 | **Range** | **Scale - Reference** | **Scale - 1** |
374 +================+=======================+=====================+
375 | ``XYZ`` | 1 | 1 |
376 +----------------+-----------------------+---------------------+
378 References
379 ----------
380 :cite:`ASTMInternational2007`
382 Examples
383 --------
384 >>> import numpy as np
385 >>> Lab_99 = np.array([53.22821989, 28.41634656, 3.89839552])
386 >>> DIN99_to_XYZ(Lab_99) # doctest: +ELLIPSIS
387 array([ 0.2065400..., 0.1219722..., 0.0513695...])
388 """
390 Lab = DIN99_to_Lab(Lab_99, k_E, k_CH, method)
392 return Lab_to_XYZ(Lab, illuminant)