def get_values(self): b = [float(x) for x in self.begin.split(',')] e = [float(x) for x in self.end.split(',')] b_hsv = rgb2hsv(b) e_hsv = rgb2hsv(e) size_fact = 1.0 / (float(self.size) - 1.0) # Ignore the undefined hues if b_hsv[0] is None: b_hsv[0] = e_hsv[0] elif e_hsv[0] is None: e_hsv[0] = b_hsv[0] if b_hsv[0] is None: # There is no hue at all! b_hsv[0] = e_hsv[0] = 0.0 # unused value hue_step = 0.0 else: # Compute hue # Because the hue is an angle, there is two ways to interpolate it; # choose the shorter path diff1 = e_hsv[0] - b_hsv[0] diff2 = e_hsv[0] - b_hsv[0] + 360.0 if diff2 >= 360.0: diff2 -= 360.0 assert 0.0 <= diff2 < 360.0 if abs(diff1) < abs(diff2): hue_step = diff1 else: hue_step = diff2 colors = [] for i in xrange(self.size): u = i * size_fact hue = b_hsv[0] + u * hue_step if hue < 0.0: hue += 360.0 elif hue > 360.0: hue -= 360.0 colors.append(Color.to_string(*hsv2rgb(( hue, b_hsv[1] + u * (e_hsv[1] - b_hsv[1]), b_hsv[2] + u * (e_hsv[2] - b_hsv[2]) )))) return colors
def test_hsv_interpolation(self): tests = [((120.0, 0.8, 0.2), (170.0, 0.5, 0.2), [(120.0, 0.8, 0.2), (130.0, 0.74, 0.2), (140.0, 0.68, 0.2), (150.0, 0.62, 0.2), (160.0, 0.56, 0.2), (170.0, 0.5, 0.2)]), ((260.0, 0.2, 0.7), (40.0, 0.8, 0.1), [(260.0, 0.2, 0.7), (288.0, 0.32, 0.58), (316.0, 0.44, 0.46), (344.0, 0.56, 0.34), (12.0, 0.68, 0.22), (40.0, 0.8, 0.1)])] for b, e, expected in tests: b = hsv2rgb(b) e = hsv2rgb(e) interp = HSVColorInterpolator(','.join(str(c) for c in b), ','.join(str(c) for c in e), 6) for i, color in enumerate(interp.get_values()): color = [float(e) for e in color.split(',')] color = rgb2hsv(color) self.assertAlmostEqual(color[0], expected[i][0], delta=0.2) self.assertAlmostEqual(color[1], expected[i][1], delta=0.005) self.assertAlmostEqual(color[2], expected[i][2], delta=0.005)