Coverage for /usr/lib/python3/dist-packages/colorzero/attr.py: 48%

36 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-02-10 12:38 +0000

1# vim: set et sw=4 sts=4 fileencoding=utf-8: 

2# 

3# The colorzero color library 

4# Copyright (c) 2016-2018 Dave Jones <dave@waveform.org.uk> 

5# 

6# Redistribution and use in source and binary forms, with or without 

7# modification, are permitted provided that the following conditions are met: 

8# 

9# * Redistributions of source code must retain the above copyright 

10# notice, this list of conditions and the following disclaimer. 

11# * Redistributions in binary form must reproduce the above copyright 

12# notice, this list of conditions and the following disclaimer in the 

13# documentation and/or other materials provided with the distribution. 

14# * Neither the name of the copyright holder nor the 

15# names of its contributors may be used to endorse or promote products 

16# derived from this software without specific prior written permission. 

17# 

18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 

19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 

20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 

21# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 

22# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 

23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 

24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 

25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 

26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 

27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 

28# POSSIBILITY OF SUCH DAMAGE. 

29 

30""" 

31Defines the classes for manipulating the attributes of the :class:`Color` 

32class through the standard binary operators. 

33""" 

34 

35from __future__ import ( 

36 unicode_literals, 

37 print_function, 

38 division, 

39 absolute_import, 

40) 

41 

42from math import pi 

43 

44 

45class Red(float): 

46 """ 

47 Represents the red component of a :class:`Color` for use in 

48 transformations. Instances of this class can be constructed directly with a 

49 float value, or by querying the :attr:`Color.red` attribute. Addition, 

50 subtraction, and multiplication are supported with :class:`Color` 

51 instances. For example:: 

52 

53 >>> Color.from_rgb(0, 0, 0) + Red(0.5) 

54 <Color html='#800000' rgb=(0.5, 0, 0)> 

55 >>> Color('#f00') - Color('#900').red 

56 <Color html='#660000' rgb=(0.4, 0, 0)> 

57 >>> (Red(0.1) * Color('red')).red 

58 Red(0.1) 

59 """ 

60 

61 def __repr__(self): 

62 return "Red(%g)" % self 

63 

64 

65class Green(float): 

66 """ 

67 Represents the green component of a :class:`Color` for use in 

68 transformations. Instances of this class can be constructed directly with 

69 a float value, or by querying the :attr:`Color.green` attribute. Addition, 

70 subtraction, and multiplication are supported with :class:`Color` 

71 instances. For example:: 

72 

73 >>> Color(0, 0, 0) + Green(0.1) 

74 <Color html='#001a00' rgb=(0, 0.1, 0)> 

75 >>> Color.from_yuv(1, -0.4, -0.6) - Green(1) 

76 <Color html='#510030' rgb=(0.316098, 0, 0.187156)> 

77 >>> (Green(0.5) * Color('white')).rgb 

78 RGB(r=1.0, g=0.5, b=1.0) 

79 """ 

80 

81 def __repr__(self): 

82 return "Green(%g)" % self 

83 

84 

85class Blue(float): 

86 """ 

87 Represents the blue component of a :class:`Color` for use in 

88 transformations. Instances of this class can be constructed directly with 

89 a float value, or by querying the :attr:`Color.blue` attribute. Addition, 

90 subtraction, and multiplication are supported with :class:`Color` 

91 instances. For example:: 

92 

93 >>> Color(0, 0, 0) + Blue(0.2) 

94 <Color html='#000033' rgb=(0, 0, 0.2)> 

95 >>> Color.from_hls(0.5, 0.5, 1.0) - Blue(1) 

96 <Color html='#00ff00' rgb=(0, 1, 0)> 

97 >>> Blue(0.9) * Color('white') 

98 <Color html='#ffffe6' rgb=(1, 1, 0.9)> 

99 """ 

100 

101 def __repr__(self): 

102 return "Blue(%g)" % self 

103 

104 

105class Hue(float): 

106 """ 

107 Represents the hue of a :class:`Color` for use in transformations. 

108 Instances of this class can be constructed directly with a float value in 

109 the range [0.0, 1.0) representing an angle around the `HSL hue wheel`_. As 

110 this is a circular mapping, 0.0 and 1.0 effectively mean the same thing, 

111 i.e. out of range values will be normalized into the range [0.0, 1.0). 

112 

113 The class can also be constructed with the keyword arguments ``deg`` or 

114 ``rad`` if you wish to specify the hue value in degrees or radians instead, 

115 respectively. Instances can also be constructed by querying the 

116 :attr:`Color.hue` attribute. 

117 

118 Addition, subtraction, and multiplication are supported with :class:`Color` 

119 instances. For example:: 

120 

121 >>> Color(1, 0, 0).hls 

122 HLS(h=0.0, l=0.5, s=1.0) 

123 >>> (Color(1, 0, 0) + Hue(deg=180)).hls 

124 HLS(h=0.5, l=0.5, s=1.0) 

125 

126 Note that whilst multiplication by a :class:`Hue` doesn't make much sense, 

127 it is still supported. However, the circular nature of a hue value can lead 

128 to suprising effects. In particular, since 1.0 is equivalent to 0.0 the 

129 following may be observed:: 

130 

131 >>> (Hue(1.0) * Color.from_hls(0.5, 0.5, 1.0)).hls 

132 HLS(h=0.0, l=0.5, s=1.0) 

133 

134 .. _HSL hue wheel: https://en.wikipedia.org/wiki/Hue 

135 """ 

136 

137 def __new__(cls, n=None, deg=None, rad=None): 

138 if n is not None: 

139 return super(Hue, cls).__new__(cls, n % 1.0) 

140 elif deg is not None: 

141 return super(Hue, cls).__new__(cls, (deg / 360.0) % 1.0) 

142 elif rad is not None: 

143 return super(Hue, cls).__new__(cls, (rad / (2 * pi)) % 1.0) 

144 else: 

145 raise ValueError('You must specify a value, or deg or rad') 

146 

147 def __repr__(self): 

148 return "Hue(deg=%g)" % self.deg 

149 

150 @property 

151 def deg(self): 

152 """ 

153 Returns the hue as a value in degrees with the range 0.0 <= n < 360.0. 

154 """ 

155 return self * 360.0 

156 

157 @property 

158 def rad(self): 

159 """ 

160 Returns the hue as a value in radians with the range 0.0 <= n < 2π. 

161 """ 

162 return self * 2 * pi 

163 

164 

165class Lightness(float): 

166 """ 

167 Represents the lightness of a :class:`Color` for use in transformations. 

168 Instances of this class can be constructed directly with a float value, or 

169 by querying the :attr:`Color.lightness` attribute. Addition, subtraction, 

170 and multiplication are supported with :class:`Color` instances. For 

171 example:: 

172 

173 >>> Color(0, 0, 0) + Lightness(0.1) 

174 <Color html='#1a1a1a' rgb=(0.1, 0.1, 0.1)> 

175 >>> Color.from_rgb_bytes(0x80, 0x80, 0) - Lightness(0.2) 

176 <Color html='#1a1a00' rgb=(0.101961, 0.101961, 0)> 

177 >>> Lightness(0.9) * Color('wheat') 

178 <Color html='#f0ce8e' rgb=(0.94145, 0.806785, 0.555021)> 

179 """ 

180 

181 def __repr__(self): 

182 return "Lightness(%g)" % self 

183 

184 

185class Saturation(float): 

186 """ 

187 Represents the saturation of a :class:`Color` for use in transformations. 

188 Instances of this class can be constructed directly with a float value, or 

189 by querying the :attr:`Color.saturation` attribute. Addition, subtraction, 

190 and multiplication are supported with :class:`Color` instances. For 

191 example:: 

192 

193 >>> Color(0.9, 0.9, 0.6) + Saturation(0.1) 

194 <Color html='#ecec93' rgb=(0.925, 0.925, 0.575)> 

195 >>> Color('red') - Saturation(1) 

196 <Color html='#808080' rgb=(0.5, 0.5, 0.5)> 

197 >>> Saturation(0.5) * Color('wheat') 

198 <Color html='#e4d9c3' rgb=(0.896078, 0.85098, 0.766667)> 

199 """ 

200 

201 def __repr__(self): 

202 return "Saturation(%g)" % self 

203 

204 

205class Luma(float): 

206 """ 

207 Represents the luma of a :class:`Color` for use in transformations. 

208 Instances of this class can be constructed directly with a float value, or 

209 by querying the :attr:`Color.yuv.y` attribute. Addition, subtraction, and 

210 multiplication are supported with :class:`Color` instances. For example:: 

211 

212 >>> Color(0, 0, 0) + Luma(0.1) 

213 <Color html='#1a1a1a' rgb=(0.1, 0.1, 0.1)> 

214 >>> Color('red') * Luma(0.5) 

215 <Color html='#d90000' rgb=(0.8505, 0, 0)> 

216 """ 

217 

218 def __repr__(self): 

219 return "Luma(%g)" % self