Coverage for models/rgb/prismatic.py: 52%

29 statements  

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

1""" 

2Prismatic Colourspace 

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

4 

5Define transformations for the *Prismatic* colourspace, a perceptually-based 

6colour representation that separates lightness from chromaticity components. 

7 

8- :func:`colour.RGB_to_Prismatic` 

9- :func:`colour.Prismatic_to_RGB` 

10 

11References 

12---------- 

13- :cite:`Shirley2015a` : Shirley, P., & Hart, D. (2015). The prismatic color 

14 space for rgb computations (pp. 2-7). 

15""" 

16 

17from __future__ import annotations 

18 

19import numpy as np 

20 

21from colour.algebra import sdiv, sdiv_mode 

22from colour.hints import ( # noqa: TC001 

23 Domain1, 

24 Range1, 

25) 

26from colour.utilities import from_range_1, to_domain_1, tsplit, tstack 

27 

28__author__ = "Colour Developers" 

29__copyright__ = "Copyright 2013 Colour Developers" 

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

31__maintainer__ = "Colour Developers" 

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

33__status__ = "Production" 

34 

35__all__ = [ 

36 "RGB_to_Prismatic", 

37 "Prismatic_to_RGB", 

38] 

39 

40 

41def RGB_to_Prismatic(RGB: Domain1) -> Range1: 

42 """ 

43 Convert from *RGB* colourspace to *Prismatic* :math:`L\\rho\\gamma\\beta` 

44 colourspace array. 

45 

46 Parameters 

47 ---------- 

48 RGB 

49 *RGB* colourspace array. 

50 

51 Returns 

52 ------- 

53 :class:`numpy.ndarray` 

54 *Prismatic* :math:`L\\rho\\gamma\\beta` colourspace array. 

55 

56 Notes 

57 ----- 

58 +------------+-----------------------+---------------+ 

59 | **Domain** | **Scale - Reference** | **Scale - 1** | 

60 +============+=======================+===============+ 

61 | ``RGB`` | 1 | 1 | 

62 +------------+-----------------------+---------------+ 

63 

64 +------------+-----------------------+---------------+ 

65 | **Range** | **Scale - Reference** | **Scale - 1** | 

66 +============+=======================+===============+ 

67 | ``Lrgb`` | 1 | 1 | 

68 +------------+-----------------------+---------------+ 

69 

70 References 

71 ---------- 

72 :cite:`Shirley2015a` 

73 

74 Examples 

75 -------- 

76 >>> RGB = np.array([0.25, 0.50, 0.75]) 

77 >>> RGB_to_Prismatic(RGB) # doctest: +ELLIPSIS 

78 array([ 0.75... , 0.1666666..., 0.3333333..., 0.5... ]) 

79 

80 Adjusting saturation of the specified *RGB* colourspace array: 

81 >>> saturation = 0.5 

82 >>> Lrgb = RGB_to_Prismatic(RGB) 

83 >>> Lrgb[..., 1:] = 1 / 3 + saturation * (Lrgb[..., 1:] - 1 / 3) 

84 >>> Prismatic_to_RGB(Lrgb) # doctest: +ELLIPSIS 

85 array([ 0.45..., 0.6..., 0.75...]) 

86 """ 

87 

88 RGB = to_domain_1(RGB) 

89 

90 L = np.max(RGB, axis=-1) 

91 s = np.sum(RGB, axis=-1) 

92 

93 with sdiv_mode(): 

94 one_s = sdiv(1, s[..., None]) 

95 

96 r, g, b = tsplit(one_s * RGB) 

97 

98 Lrgb = tstack([L, r, g, b]) 

99 

100 return from_range_1(Lrgb) 

101 

102 

103def Prismatic_to_RGB(Lrgb: Domain1) -> Range1: 

104 """ 

105 Convert from *Prismatic* :math:`L\\rho\\gamma\\beta` colourspace array to 

106 *RGB* colourspace. 

107 

108 Parameters 

109 ---------- 

110 Lrgb 

111 *Prismatic* :math:`L\\rho\\gamma\\beta` colourspace array. 

112 

113 Returns 

114 ------- 

115 :class:`numpy.ndarray` 

116 *RGB* colourspace array. 

117 

118 Notes 

119 ----- 

120 +------------+-----------------------+---------------+ 

121 | **Domain** | **Scale - Reference** | **Scale - 1** | 

122 +============+=======================+===============+ 

123 | ``Lrgb`` | 1 | 1 | 

124 +------------+-----------------------+---------------+ 

125 

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

127 | **Range** | **Scale - Reference** | **Scale - 1** | 

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

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

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

131 

132 References 

133 ---------- 

134 :cite:`Shirley2015a` 

135 

136 Examples 

137 -------- 

138 >>> Lrgb = np.array([0.75000000, 0.16666667, 0.33333333, 0.50000000]) 

139 >>> Prismatic_to_RGB(Lrgb) # doctest: +ELLIPSIS 

140 array([ 0.25... , 0.4999999..., 0.75... ]) 

141 """ 

142 

143 Lrgb = to_domain_1(Lrgb) 

144 

145 rgb = Lrgb[..., 1:] 

146 m = np.max(rgb, axis=-1) 

147 

148 with sdiv_mode(): 

149 RGB = sdiv(Lrgb[..., 0][..., None], m[..., None]) 

150 

151 RGB = RGB * rgb 

152 

153 return from_range_1(RGB)