ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/cut.c
Revision: 1.2
Committed: Thu Feb 2 14:10:36 1989 UTC (35 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.1: +3 -1 lines
Log Message:
Fixed SCCSid

File Contents

# Content
1 /* Copyright 1988 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 CUT - Median bisection (k-d tree) algorithm for color image quantization
9
10 flaw: doesn't always create as many colors as requested
11 because the binary subdivision is always done in a balanced tree and when a box
12 contains only one color it's unsplittable
13
14 Paul Heckbert
15 */
16
17 #include "ciq.h"
18
19 struct index {short *o; int freq;};
20 /* offset and pixel count for a box */
21
22 struct pail {struct plum *first; int freak;};
23 /* each pail is a bucket containing plums */
24
25 struct plum {struct plum *next; int code;};
26 /* a color in a pail's linked list */
27
28 static short off[len];
29 /* color codes: offsets of colors in hist array */
30
31
32 makecm(nw,na) /* subdivide colorspace to generate a colormap*/
33 int nw,*na; /* number of colors wanted, actual */
34 {
35 int i,m,n,freq,weight,sr,sg,sb;
36 short *o;
37 struct index index[257]; /* pointers into off */
38 /* index[i].o is pointer to code for first color in box i */
39
40 for (o=off, *na=i=0; i<len; i++)
41 if (hist[i]) {
42 (*na)++;
43 *o++ = i; /* initialize offsets */
44 }
45 index[0].o = off; /* start with one big box which contains all *na colors */
46 index[0].freq = xmax*ymax; /* and (sum of hist[i]) pixels */
47 index[1].o = off+*na;
48
49 /* breadth-first binary subdivision: try to make nw boxes */
50 for (m=1; m<nw; m<<=1) {
51 /*printf("%d ",m);*/
52 index[m<<1].o = index[m].o;
53 for (i=m-1; i>=0; --i) splitbox(index+i,index+(i<<1));
54 }
55 for (n=i=0; i<m && n<nw; i++) if (index[i+1].o>index[i].o) {
56 sr = sg = sb = (freq = index[i].freq)>>1;
57 for (o=index[i].o; o<index[i+1].o; o++) {
58 weight = hist[*o];
59 /* find weighted average of colors in box i */
60 sr += red(*o)*weight;
61 sg += gre(*o)*weight;
62 sb += blu(*o)*weight;
63 }
64 color[0][n] = sr/freq;
65 color[1][n] = sg/freq;
66 color[2][n] = sb/freq;
67 /* printf("color[%d]=(%3d,%3d,%3d) freq=%d\n",
68 n,color[0][n],color[1][n],color[2][n],freq); */
69 n++;
70 }
71 /*printf("[%d empty boxes] from %d to %d colors\n",nw-n,*na,n);*/
72 return n;
73 }
74
75 splitbox(ii,io) /* split a box in two: half of the pixels from */
76 struct index *ii,*io; /* box ii will go into io, the other half into io+1 */
77 {
78 register short *o,*o1,*o2;
79 register int shift,count,k,freq,r,g,b,r1,g1,b1,r2,g2,b2;
80 struct pail pail[32],*p,*q; /* buckets for sorting colors */
81 struct plum plum[len],*pl=plum,*u; /* colors */
82
83 o1 = ii[0].o;
84 o2 = ii[1].o;
85 freq = ii[0].freq; /* number of pixels with color in this box */
86 r1 = g1 = b1 = 256; r2 = g2 = b2 = -1;
87 for (o=o1; o<o2; o++) {
88 r = red(*o);
89 g = gre(*o);
90 b = blu(*o);
91 if (r<r1) r1 = r; if (r>r2) r2 = r; /* find min&max r, g, and b */
92 if (g<g1) g1 = g; if (g>g2) g2 = g;
93 if (b<b1) b1 = b; if (b>b2) b2 = b;
94 }
95
96 /* adaptive partitioning: find dominant dimension */
97 shift = r2-r1>g2-g1?r2-r1>=b2-b1?10:0:g2-g1>=b2-b1?5:0;
98 /* printf("splitbox %3d-%3d %3dx%3dx%3d %c ",
99 o1-off,o2-off,r2-r1,g2-g1,b2-b1,shift==10?'R':shift==5?'G':'B'); */
100
101 for (p=pail, k=0; k<32; k++, p++) { /* start with empty pails */
102 p->first = 0;
103 p->freak = 0;
104 }
105 for (o=o1; o<o2; o++) {
106 p = pail+(*o>>shift&31); /* find appropriate pail */
107 pl->code = *o;
108 pl->next = p->first;
109 p->first = pl++; /* add new plum to pail */
110 p->freak += hist[*o];
111 }
112
113 /* find median along dominant dimension */
114 for (count=freq>>1, p=pail; count>0; p++) count -= p->freak;
115
116 if (p>pail && count+(p-1)->freak<-count) /* back up one? */
117 count += (--p)->freak;
118
119 io[1].o = o1; /* in case of empty box */
120 for (o=o1, q=pail; o<o2;) { /* dump the pails to reorder colors in box */
121 for (u=q->first; u; u=u->next) *o++ = u->code;
122 if (++q==p) io[1].o = o; /* place partition at offset o */
123 }
124 io[0].o = o1;
125 io[0].freq = (freq>>1)-count;
126 io[1].freq = (freq+1>>1)+count;
127 /* printf(" at %3d %d=%d+%d\n",io[1].o-off,freq,io[0].freq,io[1].freq); */
128 }