From 47a0a3f433f820fc78d180884f6ca376fba97b73 Mon Sep 17 00:00:00 2001 From: Vasil Zlatanov Date: Sun, 12 Apr 2015 13:05:47 +0200 Subject: Tidy up everything :) --- tools/py/color_detect.py | 108 +++++++++++++++++++++++++++++++++++++++++++++++ tools/py/colorz.py | 71 +++++++++++++++++++++++++++++++ tools/py/colorz.pyc | Bin 0 -> 3064 bytes 3 files changed, 179 insertions(+) create mode 100644 tools/py/color_detect.py create mode 100644 tools/py/colorz.py create mode 100644 tools/py/colorz.pyc (limited to 'tools/py') diff --git a/tools/py/color_detect.py b/tools/py/color_detect.py new file mode 100644 index 0000000..30661f8 --- /dev/null +++ b/tools/py/color_detect.py @@ -0,0 +1,108 @@ +import sys +import colorsys +from colorz import colorz +from math import sqrt + +try: + import Image +except ImportError: + from PIL import Image + +if len(sys.argv) < 2: + print "Usage: {0} FILENAME [num_colors]".format(sys.argv[0]) + sys.exit() + + +print sys.argv[1] + +WALLPAPER = sys.argv[1] +filename = WALLPAPER.split('/').pop() +COLORS = ".{0}.colors".format(filename) +XRESOURCES = ".{0}.Xres".format(filename) +SAMPLE = ".{0}.sample.png".format(filename) + +cols = '' +xres = '' + +def torgb(hexv): + hexv = hexv[1:] + r, g, b = ( + int(hexv[0:2], 16) / 256.0, + int(hexv[2:4], 16) / 256.0, + int(hexv[4:6], 16) / 256.0, + ) + return r, g, b + +def normalize(hexv, minv=128, maxv=256): + r, g, b = torgb(hexv) + h, s, v = colorsys.rgb_to_hsv(r, g, b) + minv = minv / 256.0 + maxv = maxv / 256.0 + if v < minv: + v = minv + if v > maxv: + v = maxv + r, g, b = colorsys.hsv_to_rgb(h, s, v) + return '#{:02x}{:02x}{:02x}'.format(int(r * 256), int(g * 256), int(b * 256)) + +def darkness(hexv): + r, g, b = torgb(hexv) + darkness = sqrt((255 - r) ** 2 + (255 - g) ** 2 + (255 - b) ** 2) + return darkness + +def to_hsv(c): + r, g, b = torgb(c) + h, s, v = colorsys.rgb_to_hsv(r, g, b) + return h, s, v + +def hex_color_to_rgb(color): + color = color[1:] if color[0]=="#" else color + return ( + int(color[:2], 16), + int(color[2:4], 16), + int(color[4:], 16) + ) + +def create_sample(f, colors): + im = Image.new("RGB", (1000, 100), "white") + pix = im.load() + + width_sample = im.size[0]/len(colors) + + for i, c in enumerate(colors): + for j in range(width_sample*i, width_sample*i+width_sample): + for k in range(0, 100): + pix[j, k] = hex_color_to_rgb(c) + + im.save(f) + +if __name__ == '__main__': + if len(sys.argv) == 2: + n = 16 + else: + n = int(sys.argv[2]) + + + i = 0 + # sort by value, saturation, then hue + colors = colorz(WALLPAPER, n=n) + colors.sort(key=lambda x:darkness(x), reverse=True) + for c in colors: + if i == 0: + c = normalize(c, minv=0, maxv=32) + elif i == 8: + c = normalize(c, minv=128, maxv=192) + elif i < 8: + c = normalize(c, minv=160, maxv=224) + else: + c = normalize(c, minv=200, maxv=256) + c = normalize(c, minv=32, maxv=224) + xres += """*color{}: {}\n""".format(i, c) + cols += """export COLOR{}="{}"\n""".format(i, c) + i += 1 + + create_sample(SAMPLE, colors) + with open(XRESOURCES, 'w') as f: + f.write(xres) + with open(COLORS, 'w') as f: + f.write(cols) diff --git a/tools/py/colorz.py b/tools/py/colorz.py new file mode 100644 index 0000000..8c00f0c --- /dev/null +++ b/tools/py/colorz.py @@ -0,0 +1,71 @@ +from collections import namedtuple +from math import sqrt +import random +try: + import Image +except ImportError: + from PIL import Image + +Point = namedtuple('Point', ('coords', 'n', 'ct')) +Cluster = namedtuple('Cluster', ('points', 'center', 'n')) + +def get_points(img): + points = [] + w, h = img.size + for count, color in img.getcolors(w * h): + points.append(Point(color, 3, count)) + return points + +rtoh = lambda rgb: '#%s' % ''.join(('%02x' % p for p in rgb)) + +def colorz(filename, n=3): + img = Image.open(filename) + img.thumbnail((200, 200)) + w, h = img.size + + points = get_points(img) + clusters = kmeans(points, n, 1) + rgbs = [map(int, c.center.coords) for c in clusters] + return map(rtoh, rgbs) + +def euclidean(p1, p2): + return sqrt(sum([ + (p1.coords[i] - p2.coords[i]) ** 2 for i in range(p1.n) + ])) + +def calculate_center(points, n): + vals = [0.0 for i in range(n)] + plen = 0 + for p in points: + plen += p.ct + for i in range(n): + vals[i] += (p.coords[i] * p.ct) + return Point([(v / plen) for v in vals], n, 1) + +def kmeans(points, k, min_diff): + clusters = [Cluster([p], p, p.n) for p in random.sample(points, k)] + + while 1: + plists = [[] for i in range(k)] + + for p in points: + smallest_distance = float('Inf') + for i in range(k): + distance = euclidean(p, clusters[i].center) + if distance < smallest_distance: + smallest_distance = distance + idx = i + plists[idx].append(p) + + diff = 0 + for i in range(k): + old = clusters[i] + center = calculate_center(plists[i], old.n) + new = Cluster(plists[i], center, old.n) + clusters[i] = new + diff = max(diff, euclidean(old.center, new.center)) + + if diff < min_diff: + break + + return clusters diff --git a/tools/py/colorz.pyc b/tools/py/colorz.pyc new file mode 100644 index 0000000..c31b558 Binary files /dev/null and b/tools/py/colorz.pyc differ -- cgit v1.2.3-54-g00ecf