ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/closest.c
Revision: 1.3
Committed: Fri Apr 7 16:36:15 1989 UTC (35 years, 1 month ago) by ph
Content type: text/plain
Branch: MAIN
Changes since 1.2: +10 -7 lines
Log Message:
ciq() now calls initializeclosest() fixing a bug, also error clamping

File Contents

# User Rev Content
1 greg 1.2 /* Copyright 1988 Regents of the University of California */
2 greg 1.1
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6 greg 1.2
7     /*
8 greg 1.1 CLOSEST - nearest-color lookup by locally ordered search
9     we use distance in rgb space as color metric
10    
11     fillbucket subroutine makes trimmed, sorted lists of
12     possible closest colors to speed the closest searching.
13     About 6 times faster than exhaustive.
14    
15     Paul Heckbert
16     */
17    
18     #include "ciq.h"
19    
20     #define inf 3*256*256
21 ph 1.3 #define key(r,g,b) (((r)&0xe0)<<1|((g)&0xe0)>>2|((b)&0xe0)>>5)
22     /* 9-bit hash key: rrrgggbbb */
23 greg 1.1
24 ph 1.3 static struct thing {int mindist,pv;} space[512*257],*next,*bucket[512];
25 greg 1.1 /* sorted lists of colors */
26    
27 ph 1.3 static int nfill,tests,calls;
28 greg 1.1 static char filled[512]; /* has bucket[key] been filled yet? */
29     static int sq[511];
30    
31 ph 1.3 initializeclosest() { /* reset the buckets */
32 greg 1.1 int k;
33     nfill = tests = calls = 0;
34     for (k=0; k<512; k++) filled[k] = 0;
35     next = space;
36     }
37    
38     closest(r,g,b) /* find pv of colormap color closest to (r,g,b) */
39     int r,g,b;
40     {
41     register struct thing *p;
42 ph 1.3 register int *rsq,*gsq,*bsq,dist,min;
43     int best,k;
44 greg 1.1 struct thing *p0;
45    
46 ph 1.3 k = key(r,g,b);
47     if (!filled[k]) fillbucket(k);
48 greg 1.1 min = inf;
49     rsq = sq+255-r;
50     gsq = sq+255-g;
51     bsq = sq+255-b;
52    
53     /* stop looking when best is closer than next could be */
54 ph 1.3 for (p0=p=bucket[k]; min>p->mindist; p++) {
55 greg 1.1 dist = rsq[color[0][p->pv]] + gsq[color[1][p->pv]] +
56     bsq[color[2][p->pv]];
57     if (dist<min) {
58     best = p->pv;
59     min = dist;
60     }
61     }
62     tests += p-p0;
63     calls++;
64     return best;
65     }
66    
67     #define H 16 /* half-width of a bucket */
68    
69     compare(a,b)
70     register struct thing *a,*b;
71     {
72     return a->mindist-b->mindist;
73     }
74    
75     fillbucket(k) /* make list of colormap colors which could be closest */
76     int k; /* matches for colors in bucket #k */
77     {
78     register int r,g,b,j,dist,*rsq,*gsq,*bsq,min,best;
79     struct thing *p,*q;
80    
81     if (!sq[0]) for (j= -255; j<256; j++) sq[j+255] = j*j;
82    
83     r = k>>1&0xe0|H; /* center of 32x32x32 cubical bucket */
84     g = k<<2&0xe0|H;
85     b = k<<5&0xe0|H;
86     rsq = sq+255-r;
87     gsq = sq+255-g;
88     bsq = sq+255-b;
89     bucket[k] = p = next;
90     min = inf;
91    
92     for (j=0; j<n; j++, p++) {
93     p->pv = j;
94     dist = 0; /* compute distance from cube surface */
95     if (color[0][j]< r-H) dist += rsq[color[0][j]+H];
96     else if (color[0][j]>=r+H) dist += rsq[color[0][j]-H+1];
97     if (color[1][j]< g-H) dist += gsq[color[1][j]+H];
98     else if (color[1][j]>=g+H) dist += gsq[color[1][j]-H+1];
99     if (color[2][j]< b-H) dist += bsq[color[2][j]+H];
100     else if (color[2][j]>=b+H) dist += bsq[color[2][j]-H+1];
101     p->mindist = dist; /* for termination test in closest */
102     dist = rsq[color[0][j]]+gsq[color[1][j]]+bsq[color[2][j]];
103     if (dist<min) { /* find color closest to cube center */
104     best = j;
105     min = dist;
106     }
107     }
108    
109     dist = rsq[color[0][best]+(color[0][best]<r?1-H:H)] +
110     gsq[color[1][best]+(color[1][best]<g?1-H:H)] +
111     bsq[color[2][best]+(color[2][best]<b?1-H:H)];
112     /* dist is an upper bound on mindist: maximum possible distance */
113     /* between a color in the bucket and its nearest neighbor */
114    
115     /* eliminate colors which couldn't be closest */
116     for (p=q=next, j=0; j<n; j++, p++)
117     if (p->mindist<dist) {
118     q->mindist = p->mindist;
119     q->pv = p->pv;
120     q++;
121     }
122     if (q<=next) fprintf(stderr,"ERROR: empty bucket!\n");
123    
124     /* and sort the list by mindist */
125     qsort(next,q-next,sizeof(struct thing),compare);
126     q->mindist = inf; /* list terminator */
127     next = q+1;
128     filled[k] = 1;
129     nfill++;
130     }
131    
132     /*endclosest() {
133     printf("filled %d buckets, averaging %d colors per list, %d of which were tested\n",
134     nfill,(next-space-nfill)/nfill,tests/calls);
135     }*/