Coverage for models/cie_lab.py: 59%
34 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"""
2CIE L*a*b* Colourspace
3======================
5Define the *CIE L\\*a\\*b\\** colourspace transformations.
7- :func:`colour.XYZ_to_Lab`
8- :func:`colour.Lab_to_XYZ`
10References
11----------
12- :cite:`CIETC1-482004m` : CIE TC 1-48. (2004). CIE 1976 uniform colour
13 spaces. In CIE 015:2004 Colorimetry, 3rd Edition (p. 24).
14 ISBN:978-3-901906-33-6
15"""
17from __future__ import annotations
19from colour.colorimetry import (
20 CCS_ILLUMINANTS,
21 intermediate_lightness_function_CIE1976,
22 intermediate_luminance_function_CIE1976,
23)
24from colour.hints import ( # noqa: TC001
25 ArrayLike,
26 Domain1,
27 Domain100,
28 Range1,
29 Range100,
30)
31from colour.models import xy_to_xyY, xyY_to_XYZ
32from colour.utilities import (
33 from_range_1,
34 from_range_100,
35 to_domain_1,
36 to_domain_100,
37 tsplit,
38 tstack,
39)
41__author__ = "Colour Developers"
42__copyright__ = "Copyright 2013 Colour Developers"
43__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
44__maintainer__ = "Colour Developers"
45__email__ = "colour-developers@colour-science.org"
46__status__ = "Production"
48__all__ = [
49 "XYZ_to_Lab",
50 "Lab_to_XYZ",
51]
54def XYZ_to_Lab(
55 XYZ: Domain1,
56 illuminant: ArrayLike = CCS_ILLUMINANTS["CIE 1931 2 Degree Standard Observer"][
57 "D65"
58 ],
59) -> Range100:
60 """
61 Convert from *CIE XYZ* tristimulus values to *CIE L\\*a\\*b\\**
62 colourspace.
64 Parameters
65 ----------
66 XYZ
67 *CIE XYZ* tristimulus values.
68 illuminant
69 Reference *illuminant* *CIE xy* chromaticity coordinates or *CIE xyY*
70 colourspace array.
72 Returns
73 -------
74 :class:`numpy.ndarray`
75 *CIE L\\*a\\*b\\** colourspace array.
77 Notes
78 -----
79 +----------------+-----------------------+-----------------+
80 | **Domain** | **Scale - Reference** | **Scale - 1** |
81 +================+=======================+=================+
82 | ``XYZ`` | 1 | 1 |
83 +----------------+-----------------------+-----------------+
84 | ``illuminant`` | 1 | 1 |
85 +----------------+-----------------------+-----------------+
87 +----------------+-----------------------+-----------------+
88 | **Range** | **Scale - Reference** | **Scale - 1** |
89 +================+=======================+=================+
90 | ``Lab`` | 100 | 1 |
91 +----------------+-----------------------+-----------------+
93 References
94 ----------
95 :cite:`CIETC1-482004m`
97 Examples
98 --------
99 >>> import numpy as np
100 >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952])
101 >>> XYZ_to_Lab(XYZ) # doctest: +ELLIPSIS
102 array([ 41.5278752..., 52.6385830..., 26.9231792...])
103 """
105 X, Y, Z = tsplit(to_domain_1(XYZ))
106 X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant)))
108 f_X_X_n = intermediate_lightness_function_CIE1976(X, X_n)
109 f_Y_Y_n = intermediate_lightness_function_CIE1976(Y, Y_n)
110 f_Z_Z_n = intermediate_lightness_function_CIE1976(Z, Z_n)
112 L = 116 * f_Y_Y_n - 16
113 a = 500 * (f_X_X_n - f_Y_Y_n)
114 b = 200 * (f_Y_Y_n - f_Z_Z_n)
116 Lab = tstack([L, a, b])
118 return from_range_100(Lab)
121def Lab_to_XYZ(
122 Lab: Domain100,
123 illuminant: ArrayLike = CCS_ILLUMINANTS["CIE 1931 2 Degree Standard Observer"][
124 "D65"
125 ],
126) -> Range1:
127 """
128 Convert from *CIE L\\*a\\*b\\** colourspace to *CIE XYZ* tristimulus
129 values.
131 Parameters
132 ----------
133 Lab
134 *CIE L\\*a\\*b\\** colourspace array.
135 illuminant
136 Reference *illuminant* *CIE xy* chromaticity coordinates or *CIE xyY*
137 colourspace array.
139 Returns
140 -------
141 :class:`numpy.ndarray`
142 *CIE XYZ* tristimulus values.
144 Notes
145 -----
146 +----------------+-----------------------+-----------------+
147 | **Domain** | **Scale - Reference** | **Scale - 1** |
148 +================+=======================+=================+
149 | ``Lab`` | 100 | 1 |
150 +----------------+-----------------------+-----------------+
151 | ``illuminant`` | 1 | 1 |
152 +----------------+-----------------------+-----------------+
154 +----------------+-----------------------+-----------------+
155 | **Range** | **Scale - Reference** | **Scale - 1** |
156 +================+=======================+=================+
157 | ``XYZ`` | 1 | 1 |
158 +----------------+-----------------------+-----------------+
160 References
161 ----------
162 :cite:`CIETC1-482004m`
164 Examples
165 --------
166 >>> import numpy as np
167 >>> Lab = np.array([41.52787529, 52.63858304, 26.92317922])
168 >>> Lab_to_XYZ(Lab) # doctest: +ELLIPSIS
169 array([ 0.2065400..., 0.1219722..., 0.0513695...])
170 """
172 L, a, b = tsplit(to_domain_100(Lab))
174 X_n, Y_n, Z_n = tsplit(xyY_to_XYZ(xy_to_xyY(illuminant)))
176 f_Y_Y_n = (L + 16) / 116
177 f_X_X_n = a / 500 + f_Y_Y_n
178 f_Z_Z_n = f_Y_Y_n - b / 200
180 X = intermediate_luminance_function_CIE1976(f_X_X_n, X_n)
181 Y = intermediate_luminance_function_CIE1976(f_Y_Y_n, Y_n)
182 Z = intermediate_luminance_function_CIE1976(f_Z_Z_n, Z_n)
184 XYZ = tstack([X, Y, Z])
186 return from_range_1(XYZ)