[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gzz-commits] gzz ./TODO Documentation/Manuscripts/Paper/pape...
From: |
Janne V. Kujala |
Subject: |
[Gzz-commits] gzz ./TODO Documentation/Manuscripts/Paper/pape... |
Date: |
Mon, 14 Oct 2002 13:49:30 -0400 |
CVSROOT: /cvsroot/gzz
Module name: gzz
Changes by: Janne V. Kujala <address@hidden> 02/10/14 13:49:30
Modified files:
. : TODO
Documentation/Manuscripts/Paper: paper.tex
gfx/demo : paperbasis.py
gfx/demo/color : colors.py
gfx/libcolor : spaces.py
gfx/libpaper : colors.py
Log message:
Use a linear color space with configurable lightness weigths of RGB
primaries in libpaper; uses the same luminance nonlinearity as CIELAB; results
in slightly different saturations and interpolated hues between the color
circle sample points compared to the old code
CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/gzz/gzz/TODO.diff?tr1=1.289&tr2=1.290&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gzz/gzz/Documentation/Manuscripts/Paper/paper.tex.diff?tr1=1.17&tr2=1.18&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gzz/gzz/gfx/demo/paperbasis.py.diff?tr1=1.12&tr2=1.13&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gzz/gzz/gfx/demo/color/colors.py.diff?tr1=1.8&tr2=1.9&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gzz/gzz/gfx/libcolor/spaces.py.diff?tr1=1.9&tr2=1.10&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gzz/gzz/gfx/libpaper/colors.py.diff?tr1=1.14&tr2=1.15&r1=text&r2=text
Patches:
Index: gzz/Documentation/Manuscripts/Paper/paper.tex
diff -c gzz/Documentation/Manuscripts/Paper/paper.tex:1.17
gzz/Documentation/Manuscripts/Paper/paper.tex:1.18
*** gzz/Documentation/Manuscripts/Paper/paper.tex:1.17 Sat Oct 5 09:04:11 2002
--- gzz/Documentation/Manuscripts/Paper/paper.tex Mon Oct 14 13:49:29 2002
***************
*** 84,91 ****
--- 84,95 ----
\subsection{Colors}
Readability
+
Different palettes
+
Enough different colors for recognition
+
+ Color spaces: perceptually uniform
{\bf jvk}
Index: gzz/TODO
diff -c gzz/TODO:1.289 gzz/TODO:1.290
*** gzz/TODO:1.289 Mon Oct 14 09:59:32 2002
--- gzz/TODO Mon Oct 14 13:49:29 2002
***************
*** 16,22 ****
needed for palettes and color textures.
Maybe just a wrapper class? Talk to Tjl
[jvk: wrapper class added]
- + [GI03] simplify libpaper color space
+ [GI03] think about modeling textures
+ [GI03] libpaper NV2x combined passes
jvk,tjl,marke:
--- 16,21 ----
Index: gzz/gfx/demo/color/colors.py
diff -c gzz/gfx/demo/color/colors.py:1.8 gzz/gfx/demo/color/colors.py:1.9
*** gzz/gfx/demo/color/colors.py:1.8 Mon Sep 30 06:18:54 2002
--- gzz/gfx/demo/color/colors.py Mon Oct 14 13:49:30 2002
***************
*** 461,467 ****
putnoc(vs, background((0.5,0.5,0.5)))
code = """
! Translate 5 1 0
"""
for L in [5*r for r in range(10,20)]:
--- 461,468 ----
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)]:
***************
*** 472,478 ****
Vertex 0 0
""" % (r, g, b)
! for hue in [d * 10 for d in range(-18,18+1)]:
angle0 = (hue / 180.0) * pi
angle = getangle((hue + 360) % 360 / 360.0)
--- 473,479 ----
Vertex 0 0
""" % (r, g, b)
! for hue in [d * 5 for d in range(-18*2,18*2+1)]:
angle0 = (hue / 180.0) * pi
angle = getangle((hue + 360) % 360 / 360.0)
***************
*** 491,497 ****
code += """
End
! #Translate +2.2 0 0
"""
vs.put(getDList(code), "foobar", 10, 0, 0, 150, 150);
--- 492,498 ----
code += """
End
! Translate +2.2 0 0
"""
vs.put(getDList(code), "foobar", 10, 0, 0, 150, 150);
Index: gzz/gfx/demo/paperbasis.py
diff -c gzz/gfx/demo/paperbasis.py:1.12 gzz/gfx/demo/paperbasis.py:1.13
*** gzz/gfx/demo/paperbasis.py:1.12 Tue Oct 8 05:51:07 2002
--- gzz/gfx/demo/paperbasis.py Mon Oct 14 13:49:29 2002
***************
*** 261,267 ****
ActiveTexture TEXTURE0
""")
! texid = gfx.libpaper.textures.ptextures["RGB2"][3].getTexId();
constcode = """
ActiveTexture TEXTURE0
--- 261,267 ----
ActiveTexture TEXTURE0
""")
! texid = gfx.libpaper.textures.ptextures["RGB2"][9].getTexId();
constcode = """
ActiveTexture TEXTURE0
Index: gzz/gfx/libcolor/spaces.py
diff -c gzz/gfx/libcolor/spaces.py:1.9 gzz/gfx/libcolor/spaces.py:1.10
*** gzz/gfx/libcolor/spaces.py:1.9 Mon Sep 30 06:18:54 2002
--- gzz/gfx/libcolor/spaces.py Mon Oct 14 13:49:30 2002
***************
*** 107,119 ****
return LABclamp(rgb)
def LABclamp(rgb):
"""Clamp a RGB color into [0,1]^3 towards the CIELAB L-axis
rgb: the color in RGB709
returns: the clamped color in RGB709
"""
! if len(filter((lambda x: x<0 or x>1), rgb)) == 0:
return rgb
(L,a,b) = RGBtoLAB(rgb)
--- 107,124 ----
return LABclamp(rgb)
+ def inUnit(vec):
+ """Tests whether the vector is inside the unit cube [0,1]^n"""
+ return len(filter((lambda x: x<0 or x>1), vec)) == 0
+
+
def LABclamp(rgb):
"""Clamp a RGB color into [0,1]^3 towards the CIELAB L-axis
rgb: the color in RGB709
returns: the clamped color in RGB709
"""
! if inUnit(rgb):
return rgb
(L,a,b) = RGBtoLAB(rgb)
***************
*** 122,129 ****
bit = .5
for iter in range(0,10):
rgb = LABtoRGB([L,(r+bit)*a,(r+bit)*b])
! if len(filter((lambda x: x<0 or x>1), rgb)) == 0:
r = r + bit
bit = bit * .5
return LABtoRGB([L,r*a,r*b])
--- 127,221 ----
bit = .5
for iter in range(0,10):
rgb = LABtoRGB([L,(r+bit)*a,(r+bit)*b])
! if inUnit(rgb):
r = r + bit
bit = bit * .5
return LABtoRGB([L,r*a,r*b])
+
+
+ # The YST color space below is a linear color space with
+ # a lightness component and a color plane vector whose angle and
+ # radius specify the hue and saturation, respectively.
+ # Opposite colors are 180 degrees apart.
+ #
+ # The Y component is the CIE Y lightness (but the weights can be changed) and
+ # the ST-plane has the RGB primaries 120 (R = 0, G = 120, B = 240) degrees
apart
+ # at radius 1.
+ #
+ # Lightness weights of the RGB primaries used in YST color space functions
+ Wr = 0.212671
+ Wg = 0.715160
+ Wb = 0.072169
+
+ def YSTtoRGB(v):
+ n = 1.0 / (Wr+Wg+Wb)
+ mat = [ [n, n*(Wg+Wb), n*(Wb - Wg) / math.sqrt(3) ],
+ [n, n*(-Wr), n*(2*Wb + Wr) / math.sqrt(3) ],
+ [n, n*(-Wr), n*-(2*Wg + Wr) / math.sqrt(3) ] ]
+
+ return [ mat[0][0] * v[0] + mat[0][1] * v[1] + mat[0][2] * v[2],
+ mat[1][0] * v[0] + mat[1][1] * v[1] + mat[1][2] * v[2],
+ mat[2][0] * v[0] + mat[2][1] * v[1] + mat[2][2] * v[2] ]
+
+ def RGBtoYST(v):
+ mat = [[ Wr, Wg, Wb ],
+ [ 1, -.5, -.5],
+ [ 0, .5*math.sqrt(3), -.5*math.sqrt(3) ]]
+
+ return [ mat[0][0] * v[0] + mat[0][1] * v[1] + mat[0][2] * v[2],
+ mat[1][0] * v[0] + mat[1][1] * v[1] + mat[1][2] * v[2],
+ mat[2][0] * v[0] + mat[2][1] * v[1] + mat[2][2] * v[2] ]
+
+ def maxYSTsat(YST):
+ """Return the maximum saturation factor in RGB cube of the given color"""
+
+ # Split into "lightness" and "color" components
+ Y = YSTtoRGB((YST[0],0,0))
+ vec = YSTtoRGB((0,YST[1],YST[2]))
+
+ assert 0 <= Y[0] == Y[1] == Y[2] <= 1
+
+ return min( ((vec[0] > 0) - Y[0]) / vec[0],
+ ((vec[1] > 0) - Y[1]) / vec[1],
+ ((vec[2] > 0) - Y[2]) / vec[2] )
+
+ def clampSat(rgb):
+ """Clamp an RGB color keeping hue and lightness constant"""
+
+ if inUnit(rgb):
+ return rgb
+
+ (Y,S,T) = RGBtoYST(rgb)
+
+ r = maxYSTsat((Y,S,T))
+
+ return YSTtoRGB((Y,r*S,r*T))
+
+
+
+ def YSThue(RGB):
+ YST = RGBtoYST(RGB)
+ return math.atan2(YST[2],YST[1])
+
+
+
+
+ """
+ # Kluge: Emulate LAB color space using YST hues
+ angles = map(YSThue, colors)
+ angles = map(lambda a: a + (a < 0) * 2 * math.pi, angles)
+ angles.sort()
+ angles += [angles[0] + 2 * math.pi]
+
+ LABclamp = clampSat
+ LABtoRGB = lambda lab: YSTtoRGB((lab[0]*.01,lab[1]*.01,lab[2]*.01))
+
+ def RGBtoLAB(rgb):
+ yst = RGBtoYST(rgb)
+ return [ -16 + 116 * pow(yst[0], 1./3), 100 * yst[1], 100 * yst[2] ]
+
+ def LABtoRGB(lab):
+ yst = [ pow((lab[0] + 16.0) / 116, 3), lab[1] / 100.0, lab[2] / 100.0 ]
+ return YSTtoRGB(yst)
+ """
Index: gzz/gfx/libpaper/colors.py
diff -c gzz/gfx/libpaper/colors.py:1.14 gzz/gfx/libpaper/colors.py:1.15
*** gzz/gfx/libpaper/colors.py:1.14 Fri Oct 11 08:17:47 2002
--- gzz/gfx/libpaper/colors.py Mon Oct 14 13:49:30 2002
***************
*** 1,6 ****
# Choosing colors and 3-dotproduct factors for papers.
! from gfx.libcolor.spaces import
getRandomColor,getRandomColor2,RGBtoLAB,LABtoRGB,LABclamp,getangle
from math import sin,cos,atan2,pi,log
from random import Random,shuffle
--- 1,7 ----
# Choosing colors and 3-dotproduct factors for papers.
! from gfx.libcolor.spaces import
getRandomColor,getRandomColor2,YSTtoRGB,clampSat
! from gfx.libcolor.spaces import RGBtoLAB,LABtoRGB,LABclamp
from math import sin,cos,atan2,pi,log
from random import Random,shuffle
***************
*** 18,47 ****
colors = 8
minlum = 80
- #huerange = (45 + rnd.nextGaussian() * 45)
huerange = rnd.nextGaussian() * 90
# Note: This color sampling scheme only produces
# palettes with similar colors.
# It could be nice to have other schemes
# with, e.g., complementary colors.
! # (Note: color complementing should be done in RGB space)
# Sample hues uniformly from the range shifted to a random angle
! if 0:
! huerange *= pi / 180
! hue0 = rnd.nextDouble() * 2*pi
! hues = ([hue0, hue0 + huerange] +
! [hue0 + rnd.nextDouble() * huerange for i in
range(2,colors)])
! shuffle(hues, rnd.nextDouble)
! else:
! huerange /= 360
! hue0 = rnd.nextDouble()
! hues = ([hue0, hue0 + huerange] +
! [hue0 + rnd.nextDouble() * huerange for i in
range(2,colors)])
! hues = map(getangle, hues)
! shuffle(hues, rnd.nextDouble)
!
# Take one half dark colors and one half light colors
lumrange = 100 - minlum
--- 19,47 ----
colors = 8
minlum = 80
huerange = rnd.nextGaussian() * 90
# Note: This color sampling scheme only produces
# palettes with similar colors.
# It could be nice to have other schemes
# with, e.g., complementary colors.
!
! # 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
! index = int(f) % n
! fract = f - int(f)
! return (1 - fract) * angles[index] + fract * angles[index + 1]
# Sample hues uniformly from the range shifted to a random angle
! hue0 = rnd.nextDouble() * 360
! hues = ([hue0, hue0 + huerange] +
! [hue0 + rnd.nextDouble() * huerange for i in range(2,colors)])
! hues = map(getangle, hues)
! shuffle(hues, rnd.nextDouble)
# Take one half dark colors and one half light colors
lumrange = 100 - minlum
***************
*** 54,67 ****
# Sample saturation:
# - take the most saturated color 2/3 of the time
# and a dull color 1/3 of the time
! sats = [100 * (1 - (1 - (1 - rnd.nextDouble())**2) *
(rnd.nextDouble() < .333))
for i in range(0, colors)]
! # Construct colors and clamp towards the CIELAB L-axis
! # (keeping hue and luminance) to fit into the RGB cube
! lab = [(lums[i], sats[i] * cos(hues[i]), sats[i] * sin(hues[i]))
! for i in range(0,colors)]
! col = [LABclamp(LABtoRGB(c)) for c in lab]
shuffle(col, rnd.nextDouble)
if dbg:
--- 54,69 ----
# Sample saturation:
# - take the most saturated color 2/3 of the time
# and a dull color 1/3 of the time
! sats = [(1 - (1 - (1 - rnd.nextDouble())**2) * (rnd.nextDouble() <
.333))
for i in range(0, colors)]
! # Construct colors and clamp to RGB cube keeping hue and luminance
constant
! yst = [(pow((lums[i] + 16.0) / 116, 3),
! sats[i] * cos(hues[i]*pi/180),
! sats[i] * sin(hues[i]*pi/180))
! for i in range(0,colors)]
!
! col = [clampSat(YSTtoRGB(c)) for c in yst]
shuffle(col, rnd.nextDouble)
if dbg: