Coverage for colour/notation/hexadecimal.py: 100%

33 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-15 19:01 +1300

1""" 

2Hexadecimal Notation 

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

4 

5Define objects for converting between RGB colour values and hexadecimal 

6notation. 

7 

8- :func:`colour.notation.RGB_to_HEX` 

9- :func:`colour.notation.HEX_to_RGB` 

10""" 

11 

12from __future__ import annotations 

13 

14import typing 

15 

16import numpy as np 

17 

18from colour.algebra import normalise_maximum 

19 

20if typing.TYPE_CHECKING: 

21 from colour.hints import NDArrayStr 

22 

23from colour.hints import ( # noqa: TC001 

24 ArrayLike, 

25 Domain1, 

26 Range1, 

27) 

28from colour.models import eotf_inverse_sRGB, eotf_sRGB 

29from colour.utilities import ( 

30 as_float_array, 

31 as_int_array, 

32 from_range_1, 

33 to_domain_1, 

34 usage_warning, 

35) 

36 

37__author__ = "Colour Developers" 

38__copyright__ = "Copyright 2013 Colour Developers" 

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

40__maintainer__ = "Colour Developers" 

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

42__status__ = "Production" 

43 

44__all__ = [ 

45 "RGB_to_HEX", 

46 "HEX_to_RGB", 

47] 

48 

49 

50def RGB_to_HEX(RGB: Domain1) -> NDArrayStr: 

51 """ 

52 Convert from *RGB* colourspace to hexadecimal representation. 

53 

54 Parameters 

55 ---------- 

56 RGB 

57 *RGB* colourspace array with values typically normalised to [0, 1]. 

58 

59 Returns 

60 ------- 

61 :class:`str` or :class:`numpy.array` 

62 Hexadecimal representation as a string in the format '#RRGGBB'. 

63 

64 Notes 

65 ----- 

66 +------------+-----------------------+---------------+ 

67 | **Domain** | **Scale - Reference** | **Scale - 1** | 

68 +============+=======================+===============+ 

69 | ``RGB`` | 1 | 1 | 

70 +------------+-----------------------+---------------+ 

71 

72 Examples 

73 -------- 

74 >>> RGB = np.array([0.66666667, 0.86666667, 1.00000000]) 

75 >>> RGB_to_HEX(RGB) 

76 '#aaddff' 

77 """ 

78 

79 RGB = to_domain_1(RGB) 

80 

81 if np.any(RGB < 0): 

82 usage_warning( 

83 '"RGB" array contains negative values, those will be clipped, ' 

84 "unpredictable results may occur!" 

85 ) 

86 

87 RGB = as_float_array(np.clip(RGB, 0, np.inf)) 

88 

89 if np.any(RGB > 1): 

90 usage_warning( 

91 '"RGB" array contains values over 1 and will be normalised, ' 

92 "unpredictable results may occur!" 

93 ) 

94 

95 RGB = eotf_inverse_sRGB(normalise_maximum(eotf_sRGB(RGB))) 

96 

97 to_HEX = np.vectorize("{:02x}".format) 

98 

99 HEX = to_HEX(as_int_array(RGB * 255, dtype=np.uint8)).astype(object) 

100 

101 return np.asarray("#") + HEX[..., 0] + HEX[..., 1] + HEX[..., 2] 

102 

103 

104def HEX_to_RGB(HEX: ArrayLike) -> Range1: 

105 """ 

106 Convert from hexadecimal representation to *RGB* colourspace. 

107 

108 Parameters 

109 ---------- 

110 HEX 

111 Hexadecimal representation as a string in the format '#RRGGBB'. 

112 

113 Returns 

114 ------- 

115 :class:`numpy.array` 

116 *RGB* colourspace array with values typically normalised to [0, 1]. 

117 

118 Notes 

119 ----- 

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

121 | **Range** | **Scale - Reference** | **Scale - 1** | 

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

123 | ``RGB`` | 1 | 1 | 

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

125 

126 Examples 

127 -------- 

128 >>> HEX = "#aaddff" 

129 >>> HEX_to_RGB(HEX) # doctest: +ELLIPSIS 

130 array([ 0.6666666..., 0.8666666..., 1. ]) 

131 """ 

132 

133 HEX = np.char.lstrip(HEX, "#") # pyright: ignore 

134 

135 def to_RGB(x: list) -> list: 

136 """Convert specified hexadecimal representation to *RGB*.""" 

137 

138 l_x = len(x) 

139 

140 return [ 

141 int(x[i : i + l_x // 3], 16) # pyright: ignore 

142 for i in range(0, l_x, l_x // 3) 

143 ] 

144 

145 to_RGB_v = np.vectorize(to_RGB, otypes=[np.ndarray]) 

146 

147 RGB = as_float_array(to_RGB_v(HEX).tolist()) / 255 

148 

149 return from_range_1(RGB)