1 /*
2 * $Id: color.i,v 1.1 2005-09-18 22:05:54 dhmunro Exp $
3 * Hue-Saturation-Value color representation routines and other
4 * color and palette construction tools.
5 */
6 /* Copyright (c) 2005, The Regents of the University of California.
7 * All rights reserved.
8 * This file is part of yorick (http://yorick.sourceforge.net).
9 * Read the accompanying LICENSE file for details.
10 */
11
12 local palette_directory;
13 /* DOCUMENT palette_directory= "~/Gist/"
14 holds the default directory for the dump_palette command.
15 The directory name *must* end with "/"; the default is shown.
16 SEE ALSO: dump_palette
17 */
18 palette_directory= "~/Gist/";
19
dump_palette(name)20 func dump_palette(name)
21 /* DOCUMENT dump_palette, name
22 dump the current palette under the NAME. If NAME contains no
23 slash characters, the palette_directory will be prepended to the
24 name. The name can be fed back to the palette command in order
25 to reload the cumped palette.
26 SEE ALSO: brighten, palette, palette_directory
27 */
28 {
29 if (!strmatch(name,"/")) name= palette_directory+name;
30 local r, g, b;
31 palette, query=1, r, g, b;
32 f= create(name);
33 write,f, format="%s\n", "ncolors= "+pr1(numberof(r));
34 write,f, format="%s\n", "ntsc= 1";
35 write,f, format="%s\n", "# r g b";
36 write,f, format="%4d%4d%4d\n", r, g, b;
37 }
38
brighten(factor)39 func brighten(factor)
40 /* DOCUMENT brighten, factor
41 or brighten
42 brighten the current palette by the specified FACTOR.
43 The FACTOR is the slope of the transfer function for the color value
44 (see to_hsv for a description of the hsv color system); a value of
45 1.0 always remains 1.0, but values near 0.0 change by FACTOR.
46 FACTOR= 1.0 is a no-op. The default factor is 4.0.
47 SEE ALSO: dump_palette
48 */
49 {
50 if (is_void(factor)) factor= 4.0;
51 local r, g, b;
52 palette, query=1, r, g, b;
53 hsv= to_hsv([r,g,b]);
54 v= hsv(,3);
55 /* this function is a symmetric parabolic mapping from [0,1] to [0,1] */
56 fv= 0.5*(factor-1.0)*v;
57 n= (2.*factor-fv)*v;
58 d= 1.+fv+sqrt(max(1.+(factor^2-1.)*v,0.));
59 hsv(,3)= n/d;
60 /* here is an alternative which has the property that applying the
61 function twice is the same as applying with the product of the
62 two factors - however, this nice property is spoiled by the
63 quantization of the byte scaling of the rgb values */
64 /* hsv(,3)= 1.-(1.-v)^factor; */
65 rgb= to_rgb(hsv);
66 palette, rgb(,1),rgb(,2),rgb(,3);
67 }
68
to_rgb(hsv)69 func to_rgb(hsv)
70 /* DOCUMENT rgb= to_rgb(hsv)
71 or rgb= to_rgb([h,s,v])
72 return the RGB representation of the n-by-3 array of HSV colors
73 rgb: red, green, blue from 0 to 255
74 hsv: h= hue in degrees, red=0, green=120, blue=240
75 s= saturation from 0 (gray) to 1 (full hue)
76 v= value from 0 (black) to 1 (full intensity)
77 s= 1 - min(r,g,b)/max(r,g,b)
78 v= max(r,g,b)/255
79 SEE ALSO: to_hsv
80 */
81 {
82 hsv= double(hsv);
83 h= hsv(*,1);
84 s= hsv(*,2);
85 v= hsv(*,3);
86
87 /* normalize hue to lie in 0<=h<360 */
88 h= h % 360.0;
89 h+= (h<0.0)*360.0;
90
91 /* divide hue into 60 degree sectors */
92 i= long(h/60.0);
93 f= h/60.0 - i;
94
95 p= 1.0 - s;
96 q= 1.0 - s*f;
97 t= 1.0 - s*(1.-f);
98 /* each hue sector will be represented by rgb values taken
99 * from one of v, p, q, or t */
100 r= ((i==0|i==5) + (i==2|i==3)*p + (i==1)*q + (i==4)*t) * v;
101 g= ((i==1|i==2) + (i==4|i==5)*p + (i==3)*q + (i==0)*t) * v;
102 b= ((i==3|i==4) + (i==0|i==1)*p + (i==5)*q + (i==2)*t) * v;
103
104 /* return array same shape as input */
105 rgb= hsv;
106 rgb(*,1)= r;
107 rgb(*,2)= g;
108 rgb(*,3)= b;
109 return bytscl(rgb,top=255,cmin=0.0,cmax=1.0);
110 }
111
to_hsv(rgb)112 func to_hsv(rgb)
113 /* DOCUMENT hsv= to_hsv(rgb)
114 or hsv= to_hsv([r,g,b])
115 return the HSV representation of the n-by-3 array of RGB colors
116 rgb: red, green, blue from 0 to 255
117 hsv: h= hue in degrees, red=0, green=120, blue=240
118 s= saturation from 0 (gray) to 1 (full hue)
119 v= value from 0 (black) to 1 (full intensity)
120 s= 1 - min(r,g,b)/max(r,g,b)
121 v= max(r,g,b)
122 SEE ALSO: to_rgb
123 */
124 {
125 rgb/= 255.0;
126 hsv= rgb;
127 rgb= rgb(*,);
128 r= rgb(,1);
129 g= rgb(,2);
130 b= rgb(,3);
131
132 /* compute and normalize hue angle */
133 h= atan((g-b)*sqrt(0.75), r-0.5*(g+b)+1.e-30)/pi * 180.;
134 h+= (h<0.0)*360.;
135
136 /* any given hue is adjacent to one primary, opposite a second primary,
137 * and neutral for the third
138 * value is adjacent, which is always maximum
139 * the ratio of opposite to adjacent is 1-saturation */
140 v= max(r,g,b);
141 s= 1.0 - (min(r,g,b)+1.e-30)/(v+1.e-30);
142
143 hsv(*,1)= h;
144 hsv(*,2)= s;
145 hsv(*,3)= v;
146 return hsv;
147 }
148