aboutsummaryrefslogtreecommitdiff
path: root/ratpoison/py
diff options
context:
space:
mode:
Diffstat (limited to 'ratpoison/py')
-rw-r--r--ratpoison/py/color_detect.py108
-rw-r--r--ratpoison/py/colorz.py71
2 files changed, 179 insertions, 0 deletions
diff --git a/ratpoison/py/color_detect.py b/ratpoison/py/color_detect.py
new file mode 100644
index 0000000..30661f8
--- /dev/null
+++ b/ratpoison/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/ratpoison/py/colorz.py b/ratpoison/py/colorz.py
new file mode 100644
index 0000000..8c00f0c
--- /dev/null
+++ b/ratpoison/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