Coverage for models/igpgtg.py: 21%

28 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-16 22:49 +1300

1""" 

2:math:`I_GP_GT_G` Colourspace 

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

4 

5Define the :math:`I_GP_GT_G` colourspace transformations. 

6 

7- :func:`colour.XYZ_to_IgPgTg` 

8- :func:`colour.IgPgTg_to_XYZ` 

9 

10References 

11---------- 

12- :cite:`Hellwig2020` : Hellwig, L., & Fairchild, M. D. (2020). Using 

13 Gaussian Spectra to Derive a Hue-linear Color Space. Journal of Perceptual 

14 Imaging. doi:10.2352/J.Percept.Imaging.2020.3.2.020401 

15""" 

16 

17from __future__ import annotations 

18 

19import numpy as np 

20 

21from colour.algebra import spow 

22from colour.hints import ( # noqa: TC001 

23 ArrayLike, 

24 Domain1, 

25 NDArrayFloat, 

26 Range1, 

27) 

28from colour.models import Iab_to_XYZ, XYZ_to_Iab 

29 

30__author__ = "Colour Developers" 

31__copyright__ = "Copyright 2013 Colour Developers" 

32__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause" 

33__maintainer__ = "Colour Developers" 

34__email__ = "colour-developers@colour-science.org" 

35__status__ = "Production" 

36 

37__all__ = [ 

38 "MATRIX_IGPGTG_XYZ_TO_LMS", 

39 "MATRIX_IGPGTG_LMS_TO_XYZ", 

40 "MATRIX_IGPGTG_LMS_P_TO_IGPGTG", 

41 "MATRIX_IGPGTG_IGPGTG_TO_LMS_P", 

42 "XYZ_to_IgPgTg", 

43 "IgPgTg_to_XYZ", 

44] 

45 

46MATRIX_IGPGTG_XYZ_TO_LMS: NDArrayFloat = np.array( 

47 [ 

48 [2.968, 2.741, -0.649], 

49 [1.237, 5.969, -0.173], 

50 [-0.318, 0.387, 2.311], 

51 ] 

52) 

53"""*CIE XYZ* tristimulus values to normalised cone responses matrix.""" 

54 

55MATRIX_IGPGTG_LMS_TO_XYZ: NDArrayFloat = np.linalg.inv(MATRIX_IGPGTG_XYZ_TO_LMS) 

56"""Normalised cone responses to *CIE XYZ* tristimulus values matrix.""" 

57 

58MATRIX_IGPGTG_LMS_P_TO_IGPGTG: NDArrayFloat = np.array( 

59 [ 

60 [0.117, 1.464, 0.130], 

61 [8.285, -8.361, 21.400], 

62 [-1.208, 2.412, -36.530], 

63 ] 

64) 

65"""Normalised non-linear cone responses to :math:`I_GP_GT_G` colourspace matrix.""" 

66 

67MATRIX_IGPGTG_IGPGTG_TO_LMS_P: NDArrayFloat = np.linalg.inv( 

68 MATRIX_IGPGTG_LMS_P_TO_IGPGTG 

69) 

70""":math:`I_GP_GT_G` colourspace to normalised non-linear cone responses matrix.""" 

71 

72 

73def XYZ_to_IgPgTg(XYZ: Domain1) -> Range1: 

74 """ 

75 Convert from *CIE XYZ* tristimulus values to :math:`I_GP_GT_G` 

76 colourspace. 

77 

78 Parameters 

79 ---------- 

80 XYZ 

81 *CIE XYZ* tristimulus values. 

82 

83 Returns 

84 ------- 

85 :class:`numpy.ndarray` 

86 :math:`I_GP_GT_G` colourspace array. 

87 

88 Notes 

89 ----- 

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

91 | **Domain** | **Scale - Reference** | **Scale - 1** | 

92 +============+=======================+=================+ 

93 | ``XYZ`` | 1 | 1 | 

94 +------------+-----------------------+-----------------+ 

95 

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

97 | **Range** | **Scale - Reference** | **Scale - 1** | 

98 +============+=======================+=================+ 

99 | ``IgPgTg`` | 1 | 1 | 

100 +------------+-----------------------+-----------------+ 

101 

102 - Input *CIE XYZ* tristimulus values must be adapted to 

103 *CIE Standard Illuminant D Series* *D65*. 

104 

105 References 

106 ---------- 

107 :cite:`Hellwig2020` 

108 

109 Examples 

110 -------- 

111 >>> XYZ = np.array([0.20654008, 0.12197225, 0.05136952]) 

112 >>> XYZ_to_IgPgTg(XYZ) # doctest: +ELLIPSIS 

113 array([ 0.4242125..., 0.1863249..., 0.1068922...]) 

114 """ 

115 

116 def LMS_to_LMS_p_callable(LMS: ArrayLike) -> NDArrayFloat: 

117 """ 

118 Callable applying the forward non-linearity to the :math:`LMS` 

119 colourspace array. 

120 """ 

121 

122 return spow(LMS / np.array([18.36, 21.46, 19435]), 0.427) 

123 

124 return XYZ_to_Iab( 

125 XYZ, 

126 LMS_to_LMS_p_callable, 

127 MATRIX_IGPGTG_XYZ_TO_LMS, 

128 MATRIX_IGPGTG_LMS_P_TO_IGPGTG, 

129 ) 

130 

131 

132def IgPgTg_to_XYZ(IgPgTg: Domain1) -> Range1: 

133 """ 

134 Convert from :math:`I_GP_GT_G` colourspace to *CIE XYZ* tristimulus 

135 values. 

136 

137 Parameters 

138 ---------- 

139 IgPgTg 

140 :math:`I_GP_GT_G` colourspace array. 

141 

142 Returns 

143 ------- 

144 :class:`numpy.ndarray` 

145 *CIE XYZ* tristimulus values. 

146 

147 Notes 

148 ----- 

149 +------------+-----------------------+-----------------+ 

150 | **Domain** | **Scale - Reference** | **Scale - 1** | 

151 +============+=======================+=================+ 

152 | ``IgPgTg`` | 1 | 1 | 

153 +------------+-----------------------+-----------------+ 

154 

155 +------------+-----------------------+-----------------+ 

156 | **Range** | **Scale - Reference** | **Scale - 1** | 

157 +============+=======================+=================+ 

158 | ``XYZ`` | 1 | 1 | 

159 +------------+-----------------------+-----------------+ 

160 

161 - Output *CIE XYZ* tristimulus values are adapted to 

162 *CIE Standard Illuminant D Series* *D65*. 

163 

164 References 

165 ---------- 

166 :cite:`Hellwig2020` 

167 

168 Examples 

169 -------- 

170 >>> IgPgTg = np.array([0.42421258, 0.18632491, 0.10689223]) 

171 >>> IgPgTg_to_XYZ(IgPgTg) # doctest: +ELLIPSIS 

172 array([ 0.2065400..., 0.1219722..., 0.0513695...]) 

173 """ 

174 

175 def LMS_p_to_LMS_callable(LMS_p: ArrayLike) -> NDArrayFloat: 

176 """ 

177 Callable applying the reverse non-linearity to the :math:`LMS_p` 

178 colourspace array. 

179 """ 

180 

181 return spow(LMS_p, 1 / 0.427) * np.array([18.36, 21.46, 19435]) 

182 

183 return Iab_to_XYZ( 

184 IgPgTg, 

185 LMS_p_to_LMS_callable, 

186 MATRIX_IGPGTG_IGPGTG_TO_LMS_P, 

187 MATRIX_IGPGTG_LMS_TO_XYZ, 

188 )