from __future__ import (absolute_import, division, print_function,
unicode_literals)
from operator import itemgetter
from .. import Color
[docs]def diff_rgb(a, b):
return [ch_b - ch_a for ch_a, ch_b in zip(a, b)]
[docs]def add_rgb(a, b):
return [ch_b + ch_a for ch_a, ch_b in zip(a, b)]
[docs]def manhattan_distance(a, b):
return sum(abs(b_el - a_el) for a_el, b_el in zip(a, b))
[docs]def closest(want_rgb, *available_rgb):
# This is about the slowest approach imaginable for this
distances = [(manhattan_distance(want_rgb, this_rgb), this_rgb)
for this_rgb in available_rgb]
distances.sort(key=itemgetter(0))
return distances[0][1]
[docs]def dithered_gradient(start_color, end_color, count):
"""
Make a dithering sequence which simulates a gradient between two colors
across ``count`` threads. Returns a list of length ``count`` where each
element is the color to be used for the corresponding thread.
"""
inc_rgb = [float(ch2 - ch1) for ch1, ch2 in
zip(start_color.rgb, end_color.rgb)]
error_rgb = 0.0, 0.0, 0.0
threads = []
for ii in range(count):
dist = (ii + 0.5) / count
ideal_rgb = [(inc_ch * dist) + start_ch for inc_ch, start_ch in
zip(inc_rgb, start_color.rgb)]
with_error_rgb = [ideal_ch + error_ch
for ideal_ch, error_ch in
zip(ideal_rgb, error_rgb)]
this_rgb = closest(with_error_rgb, start_color.rgb, end_color.rgb)
threads.append(Color(this_rgb))
error_rgb = add_rgb(error_rgb, diff_rgb(this_rgb, ideal_rgb))
return threads