ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ciq.c
Revision: 2.3
Committed: Tue May 13 17:58:33 2003 UTC (20 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.2: +2 -2 lines
Log Message:
Changed (char *) casts for memory copies to (void *) and other fixes

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.2 static const char RCSid[] = "$Id$";
3 greg 1.1 #endif
4 greg 1.2 /*
5 greg 1.1 CIQ - main program for color image quantization
6     options for Floyd-Steinberg dithering by minimization of accumulated error
7     or undithered quantization
8    
9     Paul Heckbert 16 April 82, cleaned up 8 June 86
10     Greg Ward 1 March 88, modified for arbitrary picture sizes
11     */
12    
13 greg 1.6 #include "standard.h"
14 greg 1.1 #include "ciq.h"
15    
16     #define table(m,r,g,b) hist[m[0][r]|m[1][g]|m[2][b]] /* histogram/pvtable */
17    
18     int hist[len]; /* list of frequencies or pixelvalues for coded color */
19    
20     colormap color; /* quantization colormap */
21     int n; /* number of colors in it */
22    
23 ph 1.4 #define ERRMAX 20 /* maximum allowed propagated error,
24     if >=255 then no clamping */
25    
26 greg 1.1 /*----------------------------------------------------------------------*/
27    
28     ciq(dith,nw,synth,cm)
29     int dith; /* is dithering desired? 0=no, 1=yes */
30     int nw; /* number of colors wanted in output image */
31     int synth; /* synthesize colormap? 0=no, 1=yes */
32     colormap cm; /* quantization colormap */
33     /* read if synth=0; always written */
34     {
35     int na,i;
36     colormap ocm;
37    
38     picreadcm(ocm); /* read original picture's colormap (usually identity)*/
39     sample(ocm); /* find histogram */
40    
41     if (synth)
42     n = makecm(nw,&na); /* analyze histogram and synthesize colormap */
43     else {
44 greg 2.3 bcopy((void *)cm,(void *)color,sizeof color);
45 greg 1.1 n = nw;
46     na = 0;
47     for (i=0; i<len; i++) if (hist[i]) na++;
48     /*printf("from %d to %d colors\n",na,n);*/
49     }
50     picwritecm(color);
51    
52 ph 1.4 initializeclosest();
53 greg 1.1 if (dith)
54     draw_dith(ocm);
55     else {
56     for (i=0; i<len; i++)
57     if (hist[i]) hist[i] = closest(red(i),gre(i),blu(i));
58     draw_nodith(ocm);
59     }
60    
61 greg 2.3 bcopy((void *)color,(void *)cm,sizeof color);
62 greg 1.1 /*endclosest();*/
63     }
64    
65     /*----------------------------------------------------------------------*/
66    
67     sample(ocm) /* make color frequency table (histogram) */
68     colormap ocm;
69     {
70     register int x,y;
71     register rgbpixel *lp;
72     rgbpixel *line;
73     colormap map;
74    
75 greg 1.3 for (x = 0; x < len; x++) /* clear histogram */
76     hist[x] = 0;
77    
78 greg 1.1 line = line3alloc(xmax);
79     convertmap(ocm,map);
80    
81     for (y=0; y<ymax; y++) {
82     picreadline3(y,line);
83     for (lp=line, x=0; x<xmax; x++, lp++)
84     table(map,lp->r,lp->g,lp->b)++;
85     }
86 greg 2.2 free((void *)line);
87 greg 1.1 }
88    
89     convertmap(in,out) /* convert to shifted color map */
90     register colormap in,out;
91     {
92     register int j;
93    
94     for (j=0; j<256; j++) {
95     out[0][j] = (in[0][j]&0xf8)<<7;
96     out[1][j] = (in[1][j]&0xf8)<<2;
97     out[2][j] = (in[2][j]&0xf8)>>3;
98     }
99     }
100    
101     draw_nodith(ocm) /* quantize without dithering */
102     colormap ocm; /* colormap for orig */
103     {
104     register int x,y;
105     register rgbpixel *lp;
106     rgbpixel *iline;
107     pixel *oline;
108     colormap map;
109    
110     iline = line3alloc(xmax);
111     oline = linealloc(xmax);
112     convertmap(ocm,map);
113    
114     for (y=0; y<ymax; y++) {
115     picreadline3(y,iline);
116     for (lp=iline, x=0; x<xmax; x++, lp++)
117     oline[x] = table(map,lp->r,lp->g,lp->b);
118     picwriteline(y,oline);
119     }
120 greg 2.2 free((void *)iline);
121     free((void *)oline);
122 greg 1.1 }
123    
124     draw_dith(ocm) /* quantize with dithering */
125     colormap ocm; /* colormap for orig */
126     {
127     register int *p,*q,rr,gg,bb,v,x,y,*P,*Q,*R;
128     int *buf;
129     rgbpixel *iline; /* input scanline */
130     pixel *oline; /* output scanline */
131    
132     buf = (int *)ecalloc(2,3*sizeof(int)*(xmax+1));
133     iline = line3alloc(xmax);
134     oline = linealloc(xmax);
135     /* reuse hist array as quantization table */
136     for (v=0; v<len; v++) hist[v] = -1;
137    
138     P = &buf[0];
139     Q = &buf[3*(xmax+1)];
140     for (y=0; y<ymax; y++, R=P, P=Q, Q=R) {
141     Q[0] = Q[1] = Q[2] = 0;
142     picreadline3(y,iline);
143     for (p=P, q=Q, x=0; x<xmax; x++, p+=3, q+=3) {
144 ph 1.4 rr = p[0];
145     if (rr<-ERRMAX) rr = -ERRMAX; else if (rr>ERRMAX) rr = ERRMAX;
146     gg = p[1];
147     if (gg<-ERRMAX) gg = -ERRMAX; else if (gg>ERRMAX) gg = ERRMAX;
148     bb = p[2];
149     if (bb<-ERRMAX) bb = -ERRMAX; else if (bb>ERRMAX) bb = ERRMAX;
150     /* now rr,gg,bb is propagated color */
151     rr += ocm[0][iline[x].r];
152     gg += ocm[1][iline[x].g]; /* ideal */
153     bb += ocm[2][iline[x].b];
154 greg 1.1 if (rr<0) rr = 0; else if (rr>255) rr = 255;
155     if (gg<0) gg = 0; else if (gg>255) gg = 255;
156     if (bb<0) bb = 0; else if (bb>255) bb = 255;
157     v = (rr&0xf8)<<7 | (gg&0xf8)<<2 | (bb&0xf8)>>3;
158     if (hist[v]<0)
159     hist[v] = closest(rr,gg,bb); /* nearest to ideal */
160     oline[x] = v = hist[v];
161     rr -= color[0][v];
162     gg -= color[1][v]; /* error */
163     bb -= color[2][v];
164     v = rr*3>>3; p[3] += v; q[0] += v; q[3] = rr-(v<<1);
165     v = gg*3>>3; p[4] += v; q[1] += v; q[4] = gg-(v<<1);
166     v = bb*3>>3; p[5] += v; q[2] += v; q[5] = bb-(v<<1);
167     }
168     picwriteline(y,oline);
169     }
170 greg 2.2 free((void *)iline);
171     free((void *)oline);
172     free((void *)buf);
173 greg 1.1 }