colors.py from gzz at Krugle
Show colors.py syntax highlighted
#
# Copyright (c) 2003, Janne Kujala and Tuomas J. Lukka
#
# This file is part of Gzz.
#
# Gzz is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Gzz is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
# Public License for more details.
#
# You should have received a copy of the GNU Lesser General
# Public License along with Gzz; if not, write to the Free
# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
#
from __future__ import nested_scopes
# Look at some colors...
import math
from math import sin,cos,pi,sqrt
import java
from java.lang import Math
# Get colorspace routines into this namespace
execfile("gfx/libcolor/spaces.py")
def interp(a, b, fact):
mfact = 1-fact
return [
fact*a[0] + mfact * b[0],
fact*a[1] + mfact * b[1],
fact*a[2] + mfact * b[2]
]
def HSBtoRGB(hsb):
angle = (hsb[0] - math.floor(hsb[0]))
# Now, the three colors use the same function; it's just
# offset around the circle at 120 degrees
def func(a):
a = a - round(a)
a = abs(a)
if a <= 1/6.0:
return hsb[2]
if a <= 2/6.0:
fract = (a-1/6.0)/(1/6.0)
return hsb[2] * ( 1 - hsb[1] * fract )
return hsb[2] * (1-hsb[1])
return (func(angle), func(angle + 1/3.0), func(angle + 2/3.0))
class ColorScene:
def __init__(self):
self.hsbhexes = {}
self.hslhexes = {}
def key(self, k):
pass
def hsbhex(self, b):
if not self.hsbhexes.has_key(b):
def pt(h, s):
color = HSBtoRGB((h,s,b))
angle = h * 2 * math.pi
x = s * math.sin(angle)
y = -s * math.cos(angle)
return """
Color %(color)s
Vertex %(vertex)s
""" % { "color": js(color),
"vertex": js((x,y)) }
str = "Begin TRIANGLE_FAN\n"
str += pt(0,0)
for hue in floats(0,1,18):
str += pt(hue, 1)
str += "End\n"
self.hsbhexes[b] = getDList(str)
return self.hsbhexes[b]
def hslhex(self, b):
# Bases:
# (1,1,1)
# (1,0,-1) / sqrt(2)
# (1,-2,1) / sqrt(6)
if not self.hslhexes.has_key(b):
def pt(h, s):
angle = h * 2 * math.pi
color = [-1]
mult = 1
x = y = 1
while len(filter((lambda x: x<-0.01 or x>1.01), color)) > 0:
mult *= 0.99
x = mult * s * math.sin(angle)
y = -mult * s * math.cos(angle)
color = (b + x + y,
b -2*y,
b - x + y)
return """
Color %(color)s
Vertex %(vertex)s
""" % { "color": js(color),
"vertex": js((2*x,2*y*math.sqrt(3))) }
str = ""
str += "Begin TRIANGLE_FAN\n"
str += pt(0, 0)
for hue in floats(0,1,43):
str += pt(hue, 1)
str += "End\n"
self.hslhexes[b] = getDList(str)
return self.hslhexes[b]
def scene(self, vs):
putnoc(vs, background((0.5,0.5,0.5)))
putnoc(vs, getDList("""
PushAttrib POLYGON_BIT ENABLE_BIT
Disable ALPHA_TEST
Disable DEPTH_TEST
Disable BLEND
Disable TEXTURE_2D
Color 1 0.1 1
"""))
dsiz = 200
for b in range(0,12):
fr = b / 11.0
vs.put(self.hsbhex(fr), "hsb"+str(b), 10, dsiz*(b/4), dsiz*(b%4), dsiz, dsiz)
vs.put(self.hslhex(fr), "hsl"+str(b), 10, 600 + dsiz*(b/4) , dsiz*(b%4), dsiz, dsiz)
putnoc(vs, getDList("""
PopAttrib
"""))
def readcolors():
file = open("/etc/X11/rgb.txt", "r")
lines = file.readlines()
file.close()
colors = [ line.split() for line in lines[1:] ]
hash = {}
for rgb in colors:
hash[" ".join(rgb[3:])] = (int(rgb[0])/255.,
int(rgb[1])/255.,
int(rgb[2])/255.)
return hash
class CIELABScene:
def __init__(self):
self.labhexes = {}
self.recolor()
def key(self, k):
if k == "v":
self.recolor()
if k == "c":
self.colors = readcolors().values()
def labhex(self, b):
# Bases:
# (1,1,1)
# (1,0,-1) / sqrt(2)
# (1,-2,1) / sqrt(6)
if not self.labhexes.has_key(b):
def pt(h, f0, f1):
angle = h * 2 * math.pi
color = [-1]
mult = 1
x = y = 1
while len(filter((lambda x: x<-0.001 or x>1.001), color)) > 0:
mult *= 0.99
x = mult * math.sin(angle)
y = -mult * math.cos(angle)
color = LABtoRGB([b*100, x*100, y*100])
return """
Color %(color0)s
Vertex %(vertex0)s
Color %(color1)s
Vertex %(vertex1)s
""" % { "color0": js(LABtoRGB([b*100, f0*x*100, f0*y*100])),
"vertex0": js((f0*x,f0*y)),
"color1": js(LABtoRGB([b*100, f1*x*100, f1*y*100])),
"vertex1": js((f1*x,f1*y)) }
str = ""
n=2
for i in range(0,n):
str += "Begin QUAD_STRIP\n"
for hue in floats(0,1,43):
str += pt(hue, (i+0.0)/n, (i+1.0)/n)
str += "End\n"
self.labhexes[b] = getDList(str)
return self.labhexes[b]
def recolor(self):
# Pick two different dark colors and
# two different light colors
cd = 50
ld = 15
rnd = java.util.Random()
while 1:
self.colors = [getRandomColor2(72,100-ld, rnd),
getRandomColor2(72,100-ld, rnd),
getRandomColor2(72+ld,100, rnd),
getRandomColor2(72+ld,100, rnd)]
if abdiff(self.colors[0], self.colors[1]) < cd: continue
if abdiff(self.colors[2], self.colors[3]) < cd: continue
if getL(self.colors[2])-getL(self.colors[0]) < ld: continue
if getL(self.colors[3])-getL(self.colors[1]) < ld: continue
break
self.dlt = """
PushMatrix
Translate -2.15 1.1 0
"""
for i in range(0,4):
self.dlt += """
Color %s
Begin QUAD_STRIP
Vertex 0 0
Vertex 0 1
Vertex 1 0
Vertex 1 1
End
Translate 1.1 0 0
""" % (js(self.colors[i]))
self.dlt += """
PopMatrix
"""
self.dlt += """
Begin QUAD_STRIP
"""
for x in floats(0,1,20):
vx = 2*x-1
c1 = js(interp(self.colors[0], self.colors[1], x))
c2 = js(interp(self.colors[2], self.colors[3], x))
self.dlt += """
Color %s
Vertex %s 1
Color %s
Vertex %s -1
""" % (c1, vx, c2, vx)
self.dlt += """
End
"""
def scene(self, vs):
putnoc(vs, background((1.0,1.0,1.0)))
putnoc(vs, getDList("""
PushAttrib POLYGON_BIT ENABLE_BIT
Disable ALPHA_TEST
Disable DEPTH_TEST
Disable BLEND
Disable TEXTURE_2D
Color 1 0.1 1
"""))
vs.put(getDList(self.dlt), "cp", 10, 100, 300, 200, 200);
dsiz = 200
for b in range(0,16):
l = 100 * (b+.5) / 16.0
#vs.put(self.labhex(fr), "lab"+str(b), 10, 600 + dsiz*(b/4) , dsiz*(b%4), dsiz, dsiz)
vs.put(GLRen.createLABSlice(0, l),
"labslice"+str(b),
10, 400 + dsiz*(b/4+.5) , dsiz*(b%4+.5), dsiz*.01, dsiz*.01)
i = 0
for col in self.colors:
lab = RGBtoLAB(col)
b = int(round(lab[0] * 16 / 100 - .5))
#print js(col)+"--->"+str(b)+" "+js(lab)
vs.put(getDList("""
PointSize 3
Begin POINTS
Color 0 0 0
Vertex %s
End
""" % (js([lab[1], lab[2]]))),
"color" + str(i),
10, 400 + dsiz*(b/4+.5) , dsiz*(b%4+.5), dsiz*.01, dsiz*.01)
i = i + 1
putnoc(vs, getDList("""
PopAttrib
"""))
class CIELABScene2:
def __init__(self):
self.angle = None
self.angle2 = 0
self.colors = None
self.map = None
self.dsiz = 4
def key(self, k):
a = self.angle or 0
if k == "Left": self.angle = a + 5
if k == "Right": self.angle = a - 5
if k == "Up": self.angle2 += 5
if k == "Down": self.angle2 -= 5
if k == "0": self.angle = None
if k == "c": self.colors = readcolors().values()
AbstractUpdateManager.setNoAnimation()
def mouse(self, ev):
global globalx, globaly
if ev.getID() == ev.MOUSE_CLICKED:
dsiz = 800
(a,b) = ((ev.getX() - 600.0) / self.dsiz,
(ev.getY() - 450.0) / self.dsiz)
print "A,B=", a,b
minr2 = 1E8
if not self.map: self.map = readcolors()
for name in self.map.keys():
lab = RGBtoLAB(self.map[name])
r2 = round((lab[1]-a)**2 + (lab[2]-b)**2, 2)
if r2 < minr2:
minr2 = r2
best = [name]
elif r2 == minr2:
best += [name]
print "Best matches:"
def round1(x): return round(x,1)
def round2(x): return round(100*x,1)
for name in best:
rgb = self.map[name]
print "%s: LAB=%s RGB=%s" % (name,
map(round1, RGBtoLAB(rgb)),
map(round2, rgb))
AbstractUpdateManager.setNoAnimation()
def scene(self, vs):
putnoc(vs, background((1.0,1.0,1.0)))
putnoc(vs, getDList("""
PushAttrib POLYGON_BIT ENABLE_BIT PopMatrix
Disable ALPHA_TEST
Disable DEPTH_TEST
Disable BLEND
Disable TEXTURE_2D
Color 1 0.1 1
"""))
n = 16
cs = vs.coords.affineCoordsys(0, 10, 600, 450,
self.dsiz, 0, 0, self.dsiz)
vs.matcher.add(cs, "foo")
if not self.colors:
for b in range(0,n):
l = 100 * (b+.5) /n
vs.map.put(GLRen.createLABSlice(0, l), cs)
vs.map.put(getDList("""
Color 1 1 1
Begin LINES
Vertex -100 0
Vertex +100 0
Vertex 0 -100
Vertex 0 +100
End
"""), cs)
i = 0
for rgb in self.colors or [
(1,0,0), (1,.5,0), (1,1,0), (.5,1,0),
(0,1,0), (0,1,.5), (0,1,1), (0,.5,1),
(0,0,1), (.5,0,1), (1,0,1), (1,0,.5) ]:
lab = RGBtoLAB(rgb)
if self.colors:
size = 8
else:
size = 10 - 5*i
rgb = (0,0,0)
vs.map.put(getDList("""
Color %s %s %s
PointSize %s
Begin POINTS
Vertex %s %s
End
""" % (rgb[0], rgb[1], rgb[2],
size, lab[1], lab[2])), cs)
i = 1 - i
if self.angle != None:
vs.map.put(getDList("""
PushMatrix
Rotate %s 0 0 1
Color 1 1 1
Begin QUADS
Vertex 0 -150
Vertex 0 +150
Vertex 200 +150
Vertex 200 -150
End
Rotate %s 0 0 1
Color 1 1 1
Begin QUADS
Vertex 0 -150
Vertex 0 +150
Vertex 200 +150
Vertex 200 -150
End
PopMatrix
""" % (self.angle, self.angle2)), cs)
putnoc(vs, getDList("""
PopAttrib
"""))
def lightcolor():
c = (0,0,0)
while reduce(lambda x,y:x+y, c) < 1.5:
c = [Math.random() for x in range(0,3)]
return c
class PaletteScene:
def __init__(self):
self.recolor()
def recolor(self):
self.colors = [lightcolor() for c in range(0,4)]
self.dlt = """
Begin QUAD_STRIP
"""
for x in floats(0,1,20):
vx = 2*x-1
c1 = js(interp(self.colors[0], self.colors[1], x))
c2 = js(interp(self.colors[2], self.colors[3], x))
self.dlt += """
Color %s
Vertex %s 1
Color %s
Vertex %s -1
""" % (c1, vx, c2, vx)
self.dlt += """
End
"""
def key(self, k):
if k == "v":
self.recolor()
def scene(self, vs):
putnoc(vs, background((0.5,0.5,0.5)))
putnoc(vs, getDList("""
PushAttrib POLYGON_BIT ENABLE_BIT
Disable ALPHA_TEST
Disable DEPTH_TEST
Disable BLEND
Disable TEXTURE_2D
Color 1 0.1 1
"""))
vs.put(getDList(self.dlt), "cp", 10, 300, 300, 200, 200);
putnoc(vs, getDList("""
PopAttrib
"""))
class HueScene:
def key(self, k):
pass
def scene(self, vs):
putnoc(vs, background((0.5,0.5,0.5)))
code = """
Translate 1 2 0
Scale .5 .5 .5
"""
for L in [5*r for r in range(10,20)]:
Y = LtoY(L)
r,g,b = YSTtoRGB((Y, 0, 0))
code += """
Begin TRIANGLE_FAN
Color %s %s %s
Vertex 0 0
""" % (r, g, b)
# Add orange color to the color circle
def getangle(f):
# 0 = red, 120 = green, 240 = blue
angles = [ 0, 30, 60, 120, 180, 240, 300, 360 ]
n = len(angles) - 1
f *= n / 360.0
while f < 0: f += n
index = int(f) % n
fract = f - int(f)
return (1 - fract) * angles[index] + fract * angles[index + 1]
for hue in [d * 5 for d in range(-18*2,18*2+1)]:
angle0 = hue / 180.0 * pi
angle = getangle(hue) / 180.0 * pi
r,g,b = clampSat( YSTtoRGB((Y, cos(angle), sin(angle))))
yst = RGBtoYST((r,g,b))
radius = sqrt(yst[1]**2 + yst[2]**2) * 1.5
x,y = radius * cos(angle0), radius * sin(angle0)
code += """
Color %s %s %s
Vertex %s %s
""" % (r, g, b, x, y)
code += """
End
Translate +2.2 0 0
"""
vs.put(getDList(code), "foobar", 10, 0, 0, 150, 150);
currentScene = CIELABScene()
def globalkey(k):
global currentScene
if k == "1":
currentScene = ColorScene()
AbstractUpdateManager.setNoAnimation()
elif k == "2":
currentScene = PaletteScene()
AbstractUpdateManager.setNoAnimation()
elif k == "3":
currentScene = CIELABScene()
#AbstractUpdateManager.setNoAnimation()
elif k == "4":
currentScene = CIELABScene2()
#AbstractUpdateManager.setNoAnimation()
elif k == "5":
currentScene = HueScene()
#AbstractUpdateManager.setNoAnimation()
See more files for this project here