class CachedColorParser(ColorParser): check = check_file_regex('^colors\.yaml$') def read(self): with open(self.data) as fh: self.colors = yaml.load(fh) return self.colors
class KmeansColorParser(ColorParser): check = check_file_regex('\.(jpg|png|jpeg)$') def __init__(self, wallpaper, config, logger, k=16, bg='#0e0e0e', fg='#ffffff'): self.wallpaper = wallpaper self.config = config self.logger = logger self.bg = bg self.fg = fg self.k = k def _get_points_from_image(self, img): points = [] w, h = img.size for count, color in img.getcolors(w * h): points.append((color, count)) return points def rgb_to_hex(self, rgb): return '#{}'.format(''.join(('%02x' % int(p) for p in rgb))) def hex_to_rgb(self, h): h = h.lstrip('#') return tuple( map(lambda n: int(n, 16), [h[i:i + 2] for i in range(0, 6, 2)])) def get_dominant_colors(self): img = Image.open(self.wallpaper) img.thumbnail((300, 300)) # Resize to speed up python loop. width, height = img.size points = self._get_points_from_image(img) rgbs = kmeans.kmeans(points, self.k) #rgbs = [map(int, c.center.coords) for c in clusters] return [self.rgb_to_hex(rgb) for rgb in rgbs] def normalize(self, hexv, minv=128, maxv=256): r, g, b = self.hex_to_rgb(hexv) h, s, v = colorsys.rgb_to_hsv(r / 256.0, g / 256.0, b / 256.0) minv = minv / 256.0 maxv = maxv / 256.0 if v < minv: v = minv if v > maxv: v = maxv rgb = colorsys.hsv_to_rgb(h, s, v) return self.rgb_to_hex(map(lambda i: i * 256, rgb)) def read(self): colors = self.get_dominant_colors() color_dict = {'background': self.bg, 'foreground': self.fg} for i, color in enumerate(itertools.cycle(colors)): if i == 0: color = self.normalize(color, minv=0, maxv=32) elif i == 8: color = self.normalize(color, minv=128, maxv=192) elif i < 8: color = self.normalize(color, minv=160, maxv=224) else: color = self.normalize(color, minv=200, maxv=256) color_dict['color%d' % i] = color if i == 15: break mapping = self.mapping() translated = {} for k, v in color_dict.items(): translated[mapping[k]] = v return translated
class VimColorParser(ColorParser): check = check_file_regex('\.vim$') vimGroups = [ 'Normal', 'Visual', 'VertSplit', 'Identifier', 'Statement', 'PreProc', 'Type', 'Function', 'String', 'Conditional', 'Repeat', 'Label', 'Operator', 'Keyword', 'Exception', 'Character', 'Number', 'Boolean', 'Float', 'Comment', 'Special', 'Error', 'Todo' ] vimGroups.reverse() mapping = { 'bg': ['background', 'black', 'alt_black'], 'fg': ['foreground', 'white'], 'rest': [ 'red', 'alt_red', 'green', 'alt_green', 'yellow', 'alt_yellow', 'blue', 'alt_blue', 'magenta', 'alt_magenta', 'cyan', 'alt_cyan', 'alt_white' ] } def mapVimColorNames(self, name): #TODO handle unknown names for o in vimColorsMapping: if o['name'] == name: return o['hex'] def read(self): normalBg, normalFg = '', '' self.colors = [] output = {} groupRegex = re.compile(r'hi\s(\w*)\s') guibgRegex = re.compile(r'guibg\=(\S*)\s') guifgRegex = re.compile(r'guifg\=(\S*)\s') with open(self.data) as fh: for line in fh: guifg = guifgRegex.findall(line) guibg = guibgRegex.findall(line) group = groupRegex.findall(line) if (group and (guifg or guibg)): currentLine = { "group": group[0] if group else '', "fg": guifg[0] if guifg else '', "bg": guibg[0] if guibg else '' } # normalize each line currentLine.update( (x, y.strip().lower()) for x, y in currentLine.items()) # store the basic colors ('normal' colors) without any special hi gourps if (currentLine["group"] == "normal"): normalFg = currentLine["fg"] normalBg = currentLine["bg"] self.colors.append(currentLine) # convert vim color name to hex for entry in self.colors: if (entry['fg'].find('#')): entry['fg'] = self.mapVimColorNames(entry['fg']) if (entry['bg'].find('#')): entry['bg'] = self.mapVimColorNames(entry['bg']) # walk through self colors, check for vim groups of interest - use those for fg,bg, pop through the rest for fgtype in self.mapping['fg']: output.update({fgtype: normalFg}) for bgtype in self.mapping['bg']: output.update({bgtype: normalBg}) for el in self.colors: for group in self.vimGroups: if (len(self.mapping['rest']) > 0 and el['group'] == group.lower()): output.update({self.mapping['rest'].pop(): el['fg']}) return output