Skip to content

Commit

Permalink
rewrote Color() to reduce complexity and added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
prdx23 committed Sep 11, 2021
1 parent 2e4e315 commit 615e4a4
Show file tree
Hide file tree
Showing 9 changed files with 303 additions and 575 deletions.
462 changes: 62 additions & 400 deletions acrylic/Color.py

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions acrylic/Converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ def rgb_to_hsv(rgb):
norm = [x / m[1] for x, m in zip(rgb, rgb_format)]
h, s, v = colorsys.rgb_to_hsv(*norm)

hsl = [round(x * m[1], PRECISION) for x, m in zip([h, s, v], hsv_format)]
return SCHEMAS['hsl'].output_type(*hsl)
hsv = [round(x * m[1], PRECISION) for x, m in zip([h, s, v], hsv_format)]
return SCHEMAS['hsv'].output_type(*hsv)


def rgb_to_hex(rgb):
return f'#{"".join(f"{x:02X}" for x in rgb)}'.upper()
return SCHEMAS['hex'].output_type(''.join(f'{x:02X}' for x in rgb))


def rgb_to_name(rgb):
Expand All @@ -44,7 +44,6 @@ def rgb_to_ryb(rgb):
rgb_r, rgb_g, rgb_b = [x - white for x in (rgb_r, rgb_g, rgb_b)]

yellow = min(rgb_r, rgb_g)
print(yellow, rgb_r, rgb_g)
ryb_r = rgb_r - yellow
ryb_y = (yellow + rgb_g) / 2
ryb_b = (rgb_b + rgb_g - yellow) / 2
Expand Down
7 changes: 5 additions & 2 deletions acrylic/Defaults.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import re
from random import randint, uniform, choice
from collections import namedtuple
from random import randint, uniform, choice

from acrylic.color_names import color_names

Expand All @@ -10,10 +10,13 @@
Hsv = namedtuple('Hsv', 'h s v')
Ryb = namedtuple('Ryb', 'r y b')


Schema = namedtuple(
'Schema', 'format names length rng input_type output_type validation_type'
'Schema',
'format names length rng input_type output_type validation_type'
)


RANDOM = -1
PRECISION = 2

Expand Down
77 changes: 77 additions & 0 deletions acrylic/Schemes.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
from random import uniform, randint

from acrylic.Defaults import RANDOM, SCHEMAS
from acrylic.Validators import in_range, check_datatype


ANALOGOUS = 1
COMPLEMENTARY = 2
Expand All @@ -11,3 +16,75 @@
NEAR_COMPLEMENTARY = 10
COMPLEMENTARY_TRIADIC = 11
MODIFIED_TRIADIC = 12


def scheme(self, name, in_rgb=False, fuzzy=-1):
'''
Returns a list of `Color` according to the given color scheme
Args:
name(int):
a variable from `acrylic.Schemes`
example: Schemes.COMPLEMENTARY
in_rgb(bool, optional):
False: use the RYB color wheel for calculations
True: use the RGB color wheel for calculations
Default: False
fuzzy(int, optional):
adds a random value between -fuzzy and +fuzzy to
the generated hue. Can be set to `RANDOM` to use
the recommended value.
Default: 0
Returns:
list of Color
'''
Color = type(self)

colors, (a, b) = list(), SCHEMAS['hsl'].format.h
if fuzzy == RANDOM:
fuzzy = uniform(b / 20, b / 5) if randint(0, 5) else 0
else:
fuzzy = check_datatype(float, fuzzy, 'fuzzy')
fuzzy = in_range(fuzzy, a, b, 'fuzzy')

deltas = {
ANALOGOUS: [b / 24, -(b / 24), b / 12, -(b / 12)],
COMPLEMENTARY: [b / 2],
TRIADIC: [b / 3, -(b / 3)],
SQUARE: [b / 4, -(b / 4), b / 2],
SPLIT_COMPLEMENTARY: [(b / 2) - (b / 12), (b / 2) + (b / 12)],
ACCENTED_ANALOGOUS: [b / 12, -(b / 12), b / 2],
RECTANGLE: [b / 2, (b / 2) - (b / 8), b / 8],
NEAR_COMPLEMENTARY: [(b / 2) - (b / 12)],
COMPLEMENTARY_TRIADIC: [b / 2, b / 4],
MODIFIED_TRIADIC: [b / 12, b / 6],
}

if name == MONOCHROMATIC:
m = (SCHEMAS['hsv'].format.s[1] / (SCHEMAS['hsv'].format.s[1] / 30))
if self.hsv.s > m:
s = [self.hsv.s, self.hsv.s - m, self.hsv.s, self.hsv.s - m]
else:
s = [self.hsv.s, self.hsv.s + m, self.hsv.s, self.hsv.s + m]
v = [SCHEMAS['hsv'].format.v[1] / 5, SCHEMAS['hsv'].format.v[1]]
for i in range(4):
colors.append(Color(hsv=(self.hsl.h, s[i], v)))
return colors

elif name == SHADES:
v = [SCHEMAS['hsv'].format.v[1] / 5, SCHEMAS['hsv'].format.v[1]]
for i in range(4):
colors.append(Color(hsv=(self.hsl.h, self.hsv.s, v)))
return colors

elif name not in deltas:
raise ValueError(f'{name!r} is not a valid color scheme')

for angle in deltas[name]:
h = (self.hsl.h + angle + uniform(-fuzzy, +fuzzy)) % b
if not in_rgb:
colors.append(Color(hsv=(h, self.hsv.s, self.hsv.v))._in_ryb())
else:
colors.append(Color(hsv=(h, self.hsv.s, self.hsv.v)))
return colors
2 changes: 1 addition & 1 deletion acrylic/Validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def check_datatype(datatype, value, param):
try:
return datatype(value)
except ValueError:
msg = f'cannot convert value {value!r} given for {param!r}'
msg = f'cannot convert value {value!r} given for {param!r} '
msg += f'to {datatype.__name__}'
raise ValueError(msg) from None
except TypeError:
Expand Down
4 changes: 3 additions & 1 deletion changelog
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ v0.3.0
- optimized the validation code to remove inefficient parts
- added option to select colors by name, using any valid CSS3 color name
- added more detailed tests for validation and conversion
- changed conversion to lazily evaluate when needed
- rewrote most of Color() class to reduce complexity


v0.2.4 & older
- changelog not maintained here
- changelog not maintained
151 changes: 0 additions & 151 deletions tests.py

This file was deleted.

Loading

0 comments on commit 615e4a4

Please sign in to comment.