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
« 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.
30"""
31Defines the classes for manipulating the attributes of the :class:`Color`
32class through the standard binary operators.
33"""
35from __future__ import (
36 unicode_literals,
37 print_function,
38 division,
39 absolute_import,
40)
42from math import pi
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::
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 """
61 def __repr__(self):
62 return "Red(%g)" % self
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::
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 """
81 def __repr__(self):
82 return "Green(%g)" % self
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::
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 """
101 def __repr__(self):
102 return "Blue(%g)" % self
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).
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.
118 Addition, subtraction, and multiplication are supported with :class:`Color`
119 instances. For example::
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)
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::
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)
134 .. _HSL hue wheel: https://en.wikipedia.org/wiki/Hue
135 """
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')
147 def __repr__(self):
148 return "Hue(deg=%g)" % self.deg
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
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
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::
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 """
181 def __repr__(self):
182 return "Lightness(%g)" % self
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::
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 """
201 def __repr__(self):
202 return "Saturation(%g)" % self
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::
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 """
218 def __repr__(self):
219 return "Luma(%g)" % self