File: color.i

package info (click to toggle)
yorick 1.5.08-1
  • links: PTS
  • area: main
  • in suites: woody
  • size: 7,508 kB
  • ctags: 7,937
  • sloc: ansic: 75,604; cpp: 1,282; lisp: 1,217; sh: 1,026; makefile: 616; fortran: 19
file content (146 lines) | stat: -rw-r--r-- 4,377 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
   COLOR.I
   Hue-Saturation-Value color representation routines and other
   color and palette construction tools.

   $Id$
 */
/*    Copyright (c) 1996.  The Regents of the University of California.
                    All rights reserved.  */

local palette_directory;
/* DOCUMENT palette_directory= "~/Gist/"
     holds the default directory for the dump_palette command.
     The directory name *must* end with "/"; the default is shown.
   SEE ALSO: dump_palette
 */
palette_directory= "~/Gist/";

func dump_palette(name)
/* DOCUMENT dump_palette, name
     dump the current palette under the NAME.  If NAME contains no
     slash characters, the palette_directory will be prepended to the
     name.  The name can be fed back to the palette command in order
     to reload the cumped palette.
   SEE ALSO: brighten, palette, palette_directory
 */
{
  if (!strmatch(name,"/")) name= palette_directory+name;
  local r, g, b;
  palette, query=1, r, g, b;
  f= create(name);
  write,f, format="%s\n", "ncolors= "+pr1(numberof(r));
  write,f, format="%s\n", "ntsc= 1";
  write,f, format="%s\n", "#  r   g   b";
  write,f, format="%4d%4d%4d\n", r, g, b;
}

func brighten(factor)
/* DOCUMENT brighten, factor
         or brighten
     brighten the current palette by the specified FACTOR.
     The FACTOR is the slope of the transfer function for the color value
     (see to_hsv for a description of the hsv color system); a value of
     1.0 always remains 1.0, but values near 0.0 change by FACTOR.
     FACTOR= 1.0 is a no-op.  The default factor is 4.0.
   SEE ALSO: dump_palette
 */
{
  if (is_void(factor)) factor= 4.0;
  local r, g, b;
  palette, query=1, r, g, b;
  hsv= to_hsv([r,g,b]);
  v= hsv(,3);
  /* this function is a symmetric parabolic mapping from [0,1] to [0,1] */
  fv= 0.5*(factor-1.0)*v;
  n= (2.*factor-fv)*v;
  d= 1.+fv+sqrt(max(1.+(factor^2-1.)*v,0.));
  hsv(,3)= n/d;
  /* here is an alternative which has the property that applying the
     function twice is the same as applying with the product of the
     two factors - however, this nice property is spoiled by the
     quantization of the byte scaling of the rgb values */
  /* hsv(,3)= 1.-(1.-v)^factor; */
  rgb= to_rgb(hsv);
  palette, rgb(,1),rgb(,2),rgb(,3);
}

func to_rgb(hsv)
/* DOCUMENT rgb= to_rgb(hsv)
         or rgb= to_rgb([h,s,v])
     return the RGB representation of the n-by-3 array of HSV colors
     rgb: red, green, blue from 0 to 255
     hsv: h= hue in degrees, red=0, green=120, blue=240
          s= saturation from 0 (gray) to 1 (full hue)
          v= value from 0 (black) to 1 (full intensity)
	  s= 1 - min(r,g,b)/max(r,g,b)
          v= max(r,g,b)/255
   SEE ALSO: to_hsv
 */
{
  hsv= double(hsv);
  h= hsv(*,1);
  s= hsv(*,2);
  v= hsv(*,3);

  /* normalize hue to lie in 0<=h<360 */
  h= h % 360.0;
  h+= (h<0.0)*360.0;

  /* divide hue into 60 degree sectors */
  i= long(h/60.0);
  f= h/60.0 - i;

  p= 1.0 - s;
  q= 1.0 - s*f;
  t= 1.0 - s*(1.-f);
  /* each hue sector will be represented by rgb values taken
   * from one of v, p, q, or t */
  r= ((i==0|i==5) + (i==2|i==3)*p + (i==1)*q + (i==4)*t) * v;
  g= ((i==1|i==2) + (i==4|i==5)*p + (i==3)*q + (i==0)*t) * v;
  b= ((i==3|i==4) + (i==0|i==1)*p + (i==5)*q + (i==2)*t) * v;

  /* return array same shape as input */
  rgb= hsv;
  rgb(*,1)= r;
  rgb(*,2)= g;
  rgb(*,3)= b;
  return bytscl(rgb,top=255,cmin=0.0,cmax=1.0);
}

func to_hsv(rgb)
/* DOCUMENT hsv= to_hsv(rgb)
         or hsv= to_hsv([r,g,b])
     return the HSV representation of the n-by-3 array of RGB colors
     rgb: red, green, blue from 0 to 255
     hsv: h= hue in degrees, red=0, green=120, blue=240
          s= saturation from 0 (gray) to 1 (full hue)
          v= value from 0 (black) to 1 (full intensity)
	  s= 1 - min(r,g,b)/max(r,g,b)
          v= max(r,g,b)
   SEE ALSO: to_rgb
 */
{
  rgb/= 255.0;
  hsv= rgb;
  rgb= rgb(*,);
  r= rgb(,1);
  g= rgb(,2);
  b= rgb(,3);

  /* compute and normalize hue angle */
  h= atan((g-b)*sqrt(0.75), r-0.5*(g+b)+1.e-30)/pi * 180.;
  h+= (h<0.0)*360.;

  /* any given hue is adjacent to one primary, opposite a second primary,
   * and neutral for the third
   * value is adjacent, which is always maximum
   * the ratio of opposite to adjacent is 1-saturation */
  v= max(r,g,b);
  s= 1.0 - (min(r,g,b)+1.e-30)/(v+1.e-30);

  hsv(*,1)= h;
  hsv(*,2)= s;
  hsv(*,3)= v;
  return hsv;
}