Source code for bibliopixel.colors.conversions

from .. import util
import colorsys


[docs]def hsv2rgb_raw(hsv): """ Converts an HSV tuple to RGB. Intended for internal use. You should use hsv2rgb_spectrum or hsv2rgb_rainbow instead. """ HSV_SECTION_3 = 0x40 h, s, v = hsv # The brightness floor is minimum number that all of # R, G, and B will be set to. invsat = 255 - s brightness_floor = (v * invsat) // 256 # The color amplitude is the maximum amount of R, G, and B # that will be added on top of the brightness_floor to # create the specific hue desired. color_amplitude = v - brightness_floor # figure out which section of the hue wheel we're in, # and how far offset we are within that section section = h // HSV_SECTION_3 # 0..2 offset = h % HSV_SECTION_3 # 0..63 rampup = offset rampdown = (HSV_SECTION_3 - 1) - offset # compute color-amplitude-scaled-down versions of rampup and rampdown rampup_amp_adj = (rampup * color_amplitude) // (256 // 4) rampdown_amp_adj = (rampdown * color_amplitude) // (256 // 4) # add brightness_floor offset to everything rampup_adj_with_floor = rampup_amp_adj + brightness_floor rampdown_adj_with_floor = rampdown_amp_adj + brightness_floor r, g, b = (0, 0, 0) if section: if section == 1: # section 1: 0x40..0x7F r = brightness_floor g = rampdown_adj_with_floor b = rampup_adj_with_floor else: # section 2; 0x80..0xBF r = rampup_adj_with_floor g = brightness_floor b = rampdown_adj_with_floor else: # section 0: 0x00..0x3F r = rampdown_adj_with_floor g = rampup_adj_with_floor b = brightness_floor return (r, g, b)
[docs]def hsv2rgb_spectrum(hsv): """Generates RGB values from HSV values in line with a typical light spectrum.""" h, s, v = hsv return hsv2rgb_raw(((h * 192) >> 8, s, v))
[docs]def hsv2rgb_rainbow(hsv): """Generates RGB values from HSV that have an even visual distribution. Be careful as this method is only have as fast as hsv2rgb_spectrum.""" def nscale8x3_video(r, g, b, scale): nonzeroscale = 0 if scale != 0: nonzeroscale = 1 if r != 0: r = ((r * scale) >> 8) + nonzeroscale if g != 0: g = ((g * scale) >> 8) + nonzeroscale if b != 0: b = ((b * scale) >> 8) + nonzeroscale return (r, g, b) def scale8_video_LEAVING_R1_DIRTY(i, scale): nonzeroscale = 0 if scale != 0: nonzeroscale = 1 if i != 0: i = ((i * scale) >> 8) + nonzeroscale return i h, s, v = hsv offset = h & 0x1F # 0..31 offset8 = offset * 8 third = (offset8 * (256 // 3)) >> 8 r, g, b = (0, 0, 0) if not (h & 0x80): if not (h & 0x40): if not (h & 0x20): r = 255 - third g = third b = 0 else: r = 171 g = 85 + third b = 0x00 else: if not (h & 0x20): twothirds = (third << 1) r = 171 - twothirds g = 171 + third b = 0 else: r = 0 g = 255 - third b = third else: if not (h & 0x40): if not (h & 0x20): r = 0x00 twothirds = (third << 1) g = 171 - twothirds b = 85 + twothirds else: r = third g = 0 b = 255 - third else: if not (h & 0x20): r = 85 + third g = 0 b = 171 - third else: r = 171 + third g = 0x00 b = 85 - third if s != 255: r, g, b = nscale8x3_video(r, g, b, s) desat = 255 - s desat = (desat * desat) >> 8 brightness_floor = desat r = r + brightness_floor g = g + brightness_floor b = b + brightness_floor if v != 255: v = scale8_video_LEAVING_R1_DIRTY(v, v) r, g, b = nscale8x3_video(r, g, b, v) return (r, g, b)
[docs]def hsv2rgb_360(hsv): """Python default hsv to rgb conversion for when hue values in the range 0-359 are preferred. Due to requiring float math, this method is slower than hsv2rgb_rainbow and hsv2rgb_spectrum.""" h, s, v = hsv r, g, b = colorsys.hsv_to_rgb(h / 360.0, s, v) return (int(r * 255.0), int(g * 255.0), int(b * 255.0))
# pre-generated spectra for the sake of speed HUE_RAW = [hsv2rgb_raw((hue, 255, 255)) for hue in range(256)] HUE_RAINBOW = [hsv2rgb_rainbow((hue, 255, 255)) for hue in range(256)] HUE_SPECTRUM = [hsv2rgb_spectrum((hue, 255, 255)) for hue in range(256)] HUE_360 = [hsv2rgb_360((hue, 1.0, 1.0)) for hue in range(360)]
[docs]def hue2rgb_raw(hue): if hue >= 0 or hue < 256: return HUE_RAW[int(hue)] else: raise ValueError("hue must be between 0 and 255")
[docs]def hue2rgb_rainbow(hue): if hue >= 0 or hue < 256: return HUE_RAINBOW[int(hue)] else: raise ValueError("hue must be between 0 and 255")
[docs]def hue2rgb_spectrum(hue): if hue >= 0 or hue < 256: return HUE_SPECTRUM[int(hue)] else: raise ValueError("hue must be between 0 and 255")
[docs]def hue2rgb_360(hue): if hue >= 0 or hue < 360: return HUE_360[int(hue)] else: raise ValueError("hue must be between 0 and 359")
hsv2rgb = hsv2rgb_rainbow hue2rgb = hue2rgb_rainbow
[docs]def hue_gradient(start, stop, steps): if not (0 <= start <= 255 and 0 <= stop <= 255): util.log.error( 'hue must be between 0 and 255; start=%s, stop=%s', start, stop) start = min(255, max(0, start)) stop = min(255, max(0, stop)) flip = False if start > stop: start, stop = stop, start flip = True stops = util.even_dist(start, stop, steps) if flip: stops = stops[::-1] return stops
[docs]def hue_helper(pos, length, cycle_step): return hue2rgb(((pos * 255 // length) + cycle_step) % 255)
[docs]def hue_helper360(pos, length, cycle_step): return hue2rgb_360(((pos * 360 // length) + cycle_step) % 360)
[docs]def rgb_to_hsv(pixel): return colorsys.rgb_to_hsv(*(p / 255 for p in pixel))
[docs]def color_cmp(a, b): """Order colors by hue, saturation and value, in that order. Returns -1 if a < b, 0 if a == b and 1 if a < b. """ if a == b: return 0 a, b = rgb_to_hsv(a), rgb_to_hsv(b) return -1 if a < b else 1