Coverage for colour/recovery/smits1999.py: 100%
55 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"""
2Smits (1999) - Reflectance Recovery
3===================================
5Define objects for reflectance recovery using the *Smits (1999)* method.
7References
8----------
9- :cite:`Smits1999a` : Smits, B. (1999). An RGB-to-Spectrum Conversion for
10 Reflectances. Journal of Graphics Tools, 4(4), 11-22.
11 doi:10.1080/10867651.1999.10487511
12"""
14from __future__ import annotations
16from colour.colorimetry import CCS_ILLUMINANTS, SpectralDistribution
17from colour.hints import ( # noqa: TC001
18 Domain1,
19 NDArrayFloat,
20 Range1,
21)
22from colour.models import RGB_Colourspace, RGB_COLOURSPACE_sRGB, XYZ_to_RGB
23from colour.recovery import SDS_SMITS1999
24from colour.utilities import to_domain_1
26__author__ = "Colour Developers"
27__copyright__ = "Copyright 2013 Colour Developers"
28__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
29__maintainer__ = "Colour Developers"
30__email__ = "colour-developers@colour-science.org"
31__status__ = "Production"
33__all__ = [
34 "PRIMARIES_SMITS1999",
35 "WHITEPOINT_NAME_SMITS1999",
36 "CCS_WHITEPOINT_SMITS1999",
37 "RGB_COLOURSPACE_SMITS1999",
38 "XYZ_to_RGB_Smits1999",
39 "RGB_to_sd_Smits1999",
40]
42PRIMARIES_SMITS1999: NDArrayFloat = RGB_COLOURSPACE_sRGB.primaries
43"""*Smits (1999)* method implementation colourspace primaries."""
45WHITEPOINT_NAME_SMITS1999 = "E"
46"""*Smits (1999)* method implementation colourspace whitepoint name."""
48CCS_WHITEPOINT_SMITS1999: NDArrayFloat = CCS_ILLUMINANTS[
49 "CIE 1931 2 Degree Standard Observer"
50][WHITEPOINT_NAME_SMITS1999]
51"""*Smits (1999)* method implementation colourspace whitepoint."""
53RGB_COLOURSPACE_SMITS1999 = RGB_Colourspace(
54 "Smits 1999",
55 PRIMARIES_SMITS1999,
56 CCS_WHITEPOINT_SMITS1999,
57 WHITEPOINT_NAME_SMITS1999,
58)
59RGB_COLOURSPACE_sRGB.__doc__ = """
60*Smits (1999)* colourspace.
62References
63----------
64:cite:`Smits1999a`,
65"""
68def XYZ_to_RGB_Smits1999(XYZ: Domain1) -> Range1:
69 """
70 Convert from *CIE XYZ* tristimulus values to *RGB* colourspace using
71 the conditions required by the current *Smits (1999)* method
72 implementation.
74 Parameters
75 ----------
76 XYZ
77 *CIE XYZ* tristimulus values.
79 Returns
80 -------
81 :class:`numpy.ndarray`
82 *RGB* colour array.
84 Notes
85 -----
86 +------------+-----------------------+---------------+
87 | **Domain** | **Scale - Reference** | **Scale - 1** |
88 +============+=======================+===============+
89 | ``XYZ`` | 1 | 1 |
90 +------------+-----------------------+---------------+
92 +------------+-----------------------+---------------+
93 | **Range** | **Scale - Reference** | **Scale - 1** |
94 +============+=======================+===============+
95 | ``RGB`` | 1 | 1 |
96 +------------+-----------------------+---------------+
98 Examples
99 --------
100 >>> import numpy as np
101 >>> XYZ = np.array([0.21781186, 0.12541048, 0.04697113])
102 >>> XYZ_to_RGB_Smits1999(XYZ) # doctest: +ELLIPSIS
103 array([ 0.4063959..., 0.0275289..., 0.0398219...])
104 """
106 return XYZ_to_RGB(XYZ, RGB_COLOURSPACE_SMITS1999)
109def RGB_to_sd_Smits1999(RGB: Domain1) -> SpectralDistribution:
110 """
111 Recover the spectral distribution of the specified *RGB* colourspace array
112 using the *Smits (1999)* method.
114 Parameters
115 ----------
116 RGB
117 *RGB* colourspace array to recover the spectral distribution from.
119 Returns
120 -------
121 :class:`colour.SpectralDistribution`
122 Recovered spectral distribution.
124 Notes
125 -----
126 +------------+-----------------------+---------------+
127 | **Domain** | **Scale - Reference** | **Scale - 1** |
128 +============+=======================+===============+
129 | ``RGB`` | 1 | 1 |
130 +------------+-----------------------+---------------+
132 References
133 ----------
134 :cite:`Smits1999a`
136 Examples
137 --------
138 >>> import numpy as np
139 >>> from colour import MSDS_CMFS, SDS_ILLUMINANTS, SpectralShape
140 >>> from colour.colorimetry import sd_to_XYZ_integration
141 >>> from colour.utilities import numpy_print_options
142 >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952])
143 >>> RGB = XYZ_to_RGB_Smits1999(XYZ)
144 >>> cmfs = (
145 ... MSDS_CMFS["CIE 1931 2 Degree Standard Observer"]
146 ... .copy()
147 ... .align(SpectralShape(360, 780, 10))
148 ... )
149 >>> illuminant = SDS_ILLUMINANTS["E"].copy().align(cmfs.shape)
150 >>> sd = RGB_to_sd_Smits1999(RGB)
151 >>> with numpy_print_options(suppress=True):
152 ... sd # doctest: +ELLIPSIS
153 SpectralDistribution([[ 380. , 0.0787830...],
154 [ 417.7778 , 0.0622018...],
155 [ 455.5556 , 0.0446206...],
156 [ 493.3333 , 0.0352220...],
157 [ 531.1111 , 0.0324149...],
158 [ 568.8889 , 0.0330105...],
159 [ 606.6667 , 0.3207115...],
160 [ 644.4444 , 0.3836164...],
161 [ 682.2222 , 0.3836164...],
162 [ 720. , 0.3835649...]],
163 LinearInterpolator,
164 {},
165 Extrapolator,
166 {'method': 'Constant', 'left': None, 'right': None})
167 >>> sd_to_XYZ_integration(sd, cmfs, illuminant) / 100 # doctest: +ELLIPSIS
168 array([ 0.1894770..., 0.1126470..., 0.0474420...])
169 """
171 sd_white = SDS_SMITS1999["white"].copy()
172 sd_cyan = SDS_SMITS1999["cyan"].copy()
173 sd_magenta = SDS_SMITS1999["magenta"].copy()
174 sd_yellow = SDS_SMITS1999["yellow"].copy()
175 sd_red = SDS_SMITS1999["red"].copy()
176 sd_green = SDS_SMITS1999["green"].copy()
177 sd_blue = SDS_SMITS1999["blue"].copy()
179 R, G, B = to_domain_1(RGB)
180 sd = sd_white.copy() * 0
181 sd.name = f"Smits (1999) - {RGB!r}"
183 if R <= G and R <= B:
184 sd += sd_white * R
185 if G <= B:
186 sd += sd_cyan * (G - R)
187 sd += sd_blue * (B - G)
188 else:
189 sd += sd_cyan * (B - R)
190 sd += sd_green * (G - B)
191 elif G <= R and G <= B:
192 sd += sd_white * G
193 if R <= B:
194 sd += sd_magenta * (R - G)
195 sd += sd_blue * (B - R)
196 else:
197 sd += sd_magenta * (B - G)
198 sd += sd_red * (R - B)
199 else:
200 sd += sd_white * B
201 if R <= G:
202 sd += sd_yellow * (R - B)
203 sd += sd_green * (G - R)
204 else:
205 sd += sd_yellow * (G - B)
206 sd += sd_red * (R - G)
208 return sd