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

1""" 

2Smits (1999) - Reflectance Recovery 

3=================================== 

4 

5Define objects for reflectance recovery using the *Smits (1999)* method. 

6 

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""" 

13 

14from __future__ import annotations 

15 

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 

25 

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" 

32 

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] 

41 

42PRIMARIES_SMITS1999: NDArrayFloat = RGB_COLOURSPACE_sRGB.primaries 

43"""*Smits (1999)* method implementation colourspace primaries.""" 

44 

45WHITEPOINT_NAME_SMITS1999 = "E" 

46"""*Smits (1999)* method implementation colourspace whitepoint name.""" 

47 

48CCS_WHITEPOINT_SMITS1999: NDArrayFloat = CCS_ILLUMINANTS[ 

49 "CIE 1931 2 Degree Standard Observer" 

50][WHITEPOINT_NAME_SMITS1999] 

51"""*Smits (1999)* method implementation colourspace whitepoint.""" 

52 

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. 

61 

62References 

63---------- 

64:cite:`Smits1999a`, 

65""" 

66 

67 

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. 

73 

74 Parameters 

75 ---------- 

76 XYZ 

77 *CIE XYZ* tristimulus values. 

78 

79 Returns 

80 ------- 

81 :class:`numpy.ndarray` 

82 *RGB* colour array. 

83 

84 Notes 

85 ----- 

86 +------------+-----------------------+---------------+ 

87 | **Domain** | **Scale - Reference** | **Scale - 1** | 

88 +============+=======================+===============+ 

89 | ``XYZ`` | 1 | 1 | 

90 +------------+-----------------------+---------------+ 

91 

92 +------------+-----------------------+---------------+ 

93 | **Range** | **Scale - Reference** | **Scale - 1** | 

94 +============+=======================+===============+ 

95 | ``RGB`` | 1 | 1 | 

96 +------------+-----------------------+---------------+ 

97 

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 """ 

105 

106 return XYZ_to_RGB(XYZ, RGB_COLOURSPACE_SMITS1999) 

107 

108 

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. 

113 

114 Parameters 

115 ---------- 

116 RGB 

117 *RGB* colourspace array to recover the spectral distribution from. 

118 

119 Returns 

120 ------- 

121 :class:`colour.SpectralDistribution` 

122 Recovered spectral distribution. 

123 

124 Notes 

125 ----- 

126 +------------+-----------------------+---------------+ 

127 | **Domain** | **Scale - Reference** | **Scale - 1** | 

128 +============+=======================+===============+ 

129 | ``RGB`` | 1 | 1 | 

130 +------------+-----------------------+---------------+ 

131 

132 References 

133 ---------- 

134 :cite:`Smits1999a` 

135 

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 """ 

170 

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() 

178 

179 R, G, B = to_domain_1(RGB) 

180 sd = sd_white.copy() * 0 

181 sd.name = f"Smits (1999) - {RGB!r}" 

182 

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) 

207 

208 return sd