ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ciq.c
Revision: 1.1
Committed: Thu Feb 2 10:49:08 1989 UTC (35 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

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