Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
colorquant.c
Go to the documentation of this file.
1 /*
2  * This software is copyrighted as noted below. It may be freely copied,
3  * modified, and redistributed, provided that the copyright notice is
4  * preserved on all copies.
5  *
6  * There is no warranty or other guarantee of fitness for this software,
7  * it is provided solely "as is". Bug reports or fixes may be sent
8  * to the author, who may or may not act on them as he desires.
9  *
10  * You may not include this software in a program or other software product
11  * without supplying the source, or without informing the end-user that the
12  * source is available for no extra charge.
13  *
14  * If you modify this software, you should include a notice giving the
15  * name of the person performing the modification, the date of modification,
16  * and the reason for such modification.
17  */
18 /*
19  * colorquant.c
20  *
21  * Perform variance-based color quantization on a "full color" image.
22  * Author: Craig Kolb
23  * Department of Mathematics
24  * Yale University
25  * kolb@yale.edu
26  * Date: Tue Aug 22 1989
27  * Copyright (C) 1989 Craig E. Kolb
28  * $Id: colorquant.c,v 3.0.1.4 1992/04/30 14:06:48 spencer Exp $
29  *
30  * $Log: colorquant.c,v $
31  * Revision 3.0.1.4 1992/04/30 14:06:48 spencer
32  * patch3: lint fixes.
33  *
34  * Revision 3.0.1.3 1991/02/06 16:46:47 spencer
35  * patch3: Fix round-off error in variance calculation that sometimes
36  * patch3: caused multiple boxes with the same center to be cut.
37  * patch3: Change 'fast' argument to 'flags' argument. Currently:
38  * patch3: CQ_FAST: same as old fast argument
39  * patch3: CQ_QUANTIZE: data is not prequantized to bits
40  * patch3: CQ_NO_RGBMAP: don't build rgbmap.
41  *
42  * Revision 3.0.1.2 90/11/29 15:18:04 spencer
43  * Remove a typo.
44  * 
45  *
46  * Revision 3.0.1.1 90/11/19 16:59:48 spencer
47  * Use inv_cmap instead of find_colors.
48  * Changes to process multiple files into one colormap (accum_hist arg).
49  * Delete 'otherimages' argument -- unnecessary with faster inv_cmap code.
50  *
51  *
52  * Revision 3.0 90/08/03 15:20:11 spencer
53  * Establish version 3.0 base.
54  *
55  * Revision 1.6 90/07/29 08:06:06 spencer
56  * If HUGE isn't defined, make it HUGE_VAL (for ansi).
57  *
58  * Revision 1.5 90/07/26 17:25:48 rgb
59  * Added a parameter to colorquant for rgbmap construction.
60  *
61  * Revision 1.4 90/07/13 14:53:31 spencer
62  * Get rid of ARB_ARG sh*t.
63  * Change a couple of vars to double so that HUGE won't cause problems.
64  *
65  * Revision 1.3 90/06/28 21:42:56 spencer
66  * Declare internal functions properly.
67  * Delete unused global variable.
68  *
69  * Revision 1.2 90/06/28 13:18:56 spencer
70  * Make internal functions static.
71  * Build entire RGB cube, not just those colors used by this image. This
72  * is so dithering will work.
73  *
74  * Revision 1.1 90/06/18 20:45:17 spencer
75  * Initial revision
76  *
77  * Revision 1.3 89/12/03 18:27:16 craig
78  * Removed bogus integer casts in distance calculation in makenearest().
79  *
80  * Revision 1.2 89/12/03 18:13:12 craig
81  * FindCutpoint now returns FALSE if the given box cannot be cut. This
82  * to avoid overflow problems in CutBox.
83  * "whichbox" in GreatestVariance() is now initialized to 0.
84  *
85  */
86 static char rcsid[] = "$Header: /l/spencer/src/urt/lib/RCS/colorquant.c,v 3.0.1.4 1992/04/30 14:06:48 spencer Exp $";
87 
88 #include <math.h>
89 #include <stdio.h>
90 #include "rle_config.h"
91 #include "colorquant.h"
92 
93 /* Ansi uses HUGE_VAL. */
94 #ifndef HUGE
95 #ifdef HUGE_VAL
96 #define HUGE HUGE_VAL
97 #else
98 #define HUGE MAXFLOAT
99 #endif
100 #endif
101 
102 static void QuantHistogram();
103 static void BoxStats();
104 static void UpdateFrequencies();
105 static void ComputeRGBMap();
106 static void SetRGBmap();
107 #ifdef slow_color_map
108 static void find_colors();
109 static int getneighbors();
110 static int makenearest();
111 #else
112 extern void inv_cmap();
113 #endif
114 static int CutBoxes();
115 static int CutBox();
116 static int GreatestVariance();
117 static int FindCutpoint();
118 
119 
120 
121 /*
122  * The colorquant() routine has been tested on an Iris 4D70 workstation,
123  * a Sun 3/60 workstation, and (to some extent), a Macintosh.
124  *
125  * Calls to bzero() may have to be replaced with the appropriate thing on
126  * your system. (bzero(ptr, len) writes 'len' 0-bytes starting at the location
127  * pointed to by ptr.)
128  *
129  * Although I've tried to avoid integer overflow problems where ever possible,
130  * it's likely I've missed a spot where an 'int' should really be a 'long'.
131  * (On the machine this was developed on, an int == long == 32 bits.)
132  *
133  * Note that it's quite easy to optimize this code for a given value for
134  * 'bits'. In addition, if you assume bits is small and
135  * that the total number of pixels is relatively small, there are several
136  * places that integer arithmetic may be substituted for floating-point.
137  * One such place is the loop in BoxStats -- mean and var need not necessary
138  * be floats.
139  *
140  * As things stand, the maximum number of colors to which an image may
141  * be quantized is 256. This limit may be overcome by changing rgbmap and
142  * colormap from pointers to characters to pointers to something larger.
143  */
144 
145 /*
146  * Maximum number of colormap entries. To make larger than 2^8, the rgbmap
147  * type will have to be changed from unsigned chars to something larger.
148  */
149 #define MAXCOLORS 256
150 /*
151  * Value corrersponding to full intensity in colormap. The values placed
152  * in the colormap are scaled to be between zero and this number. Note
153  * that anything larger than 255 is going to lead to problems, as the
154  * colormap is declared as an unsigned char.
155  */
156 #define FULLINTENSITY 255
157 #define MAX(x,y) ((x) > (y) ? (x) : (y))
158 
159 /*
160  * Readability constants.
161  */
162 #define REDI 0
163 #define GREENI 1
164 #define BLUEI 2
165 #define TRUE 1
166 #define FALSE 0
167 
168 typedef struct {
169  double weightedvar; /* weighted variance */
170  float mean[3]; /* centroid */
171  unsigned long weight, /* # of pixels in box */
172  freq[3][MAXCOLORS]; /* Projected frequencies */
173  int low[3], high[3]; /* Box extent */
174 } Box;
175 
176 static unsigned long *Histogram, /* image histogram */
177  NPixels, /* # of pixels in an image*/
178  SumPixels; /* total # of pixels */
179 static unsigned int Bits, /* # significant input bits */
180  ColormaxI; /* # of colors, 2^Bits */
181 static Box *Boxes; /* Array of color boxes. */
182 
183 /*
184  * Perform variance-based color quantization on a 24-bit image.
185  *
186  * Input consists of:
187  * red, green, blue Arrays of red, green and blue pixel
188  * intensities stored as unsigned characters.
189  * The color of the ith pixel is given
190  * by red[i] green[i] and blue[i]. 0 indicates
191  * zero intensity, 255 full intensity.
192  * pixels The length of the red, green and blue arrays
193  * in bytes, stored as an unsigned long int.
194  * colormap Points to the colormap. The colormap
195  * consists of red, green and blue arrays.
196  * The red/green/blue values of the ith
197  * colormap entry are given respectively by
198  * colormap[0][i], colormap[1][i] and
199  * colormap[2][i]. Each entry is an unsigned char.
200  * colors The number of colormap entries, stored
201  * as an integer.
202  * bits The number of significant bits in each entry
203  * of the red, greena and blue arrays. An integer.
204  * rgbmap An array of unsigned chars of size (2^bits)^3.
205  * This array is used to map from pixels to
206  * colormap entries. The 'prequantized' red,
207  * green and blue components of a pixel
208  * are used as an index into rgbmap to retrieve
209  * the index which should be used into the colormap
210  * to represent the pixel. In short:
211  * index = rgbmap[(((r << bits) | g) << bits) | b];
212  * flags A set of bit-flags:
213  * CQ_FAST If set, the rgbmap will be constructed
214  * quickly. If not set, the rgbmap will
215  * be built more slowly, but more
216  * accurately. In most cases, fast
217  * should be set, as the error introduced
218  * by the approximation is usually small.
219  * CQ_QUANTIZE: If set, the data in red, green, and
220  * blue is not pre-quantized, and will be
221  * quantized "on the fly". This slows
222  * the routine slightly. If not set, the
223  * data has been prequantized to 'bits'
224  * significant bits.
225  *
226  * accum_hist If non-zero the histogram will accumulate and
227  * reflect pixels from multiple images.
228  * when 1, the histogram will be initialized and
229  * summed, but not thrown away OR processed. when
230  * 2 the image RGB will be added to it. When 3
231  * Boxes are cut and a colormap and rgbmap
232  * are be returned, Histogram is freed too.
233  * When zero, all code is executed as per normal.
234  *
235  * colorquant returns the number of colors to which the image was
236  * quantized.
237  */
238 #define INIT_HIST 1
239 #define USE_HIST 2
240 #define PROCESS_HIST 3
241 int
243 unsigned char *red, *green, *blue;
244 unsigned long pixels;
245 unsigned char *colormap[3];
246 int colors, bits;
247 unsigned char *rgbmap;
248 int flags, accum_hist;
249 {
250  int i, /* Counter */
251  OutColors, /* # of entries computed */
252  Colormax; /* quantized full-intensity */
253  float Cfactor; /* Conversion factor */
254 
255  if (accum_hist < 0 || accum_hist > PROCESS_HIST)
256  fprintf(stderr, "colorquant: bad value for accum_hist\n");
257 
258  ColormaxI = 1 << bits; /* 2 ^ Bits */
259  Colormax = ColormaxI - 1;
260  Bits = bits;
261  NPixels = pixels;
262  Cfactor = (float)FULLINTENSITY / Colormax;
263 
264  if (! accum_hist || accum_hist == INIT_HIST) {
265  Histogram = (unsigned long *)calloc(ColormaxI*ColormaxI*ColormaxI,
266  sizeof(long));
267  Boxes = (Box *)malloc(colors * sizeof(Box));
268  /*
269  * Zero-out the projected frequency arrays of the largest box.
270  */
271  bzero(Boxes->freq[0], ColormaxI * sizeof(unsigned long));
272  bzero(Boxes->freq[1], ColormaxI * sizeof(unsigned long));
273  bzero(Boxes->freq[2], ColormaxI * sizeof(unsigned long));
274  SumPixels = 0;
275  }
276 
277  SumPixels += NPixels;
278 
279  if ( accum_hist != PROCESS_HIST )
280  QuantHistogram(red, green, blue, &Boxes[0], flags&CQ_QUANTIZE);
281 
282  if ( !accum_hist || accum_hist == PROCESS_HIST) {
283  OutColors = CutBoxes(Boxes, colors);
284 
285  /*
286  * We now know the set of representative colors. We now
287  * must fill in the colormap and convert the representatives
288  * from their 'prequantized' range to 0-FULLINTENSITY.
289  */
290  for (i = 0; i < OutColors; i++) {
291  colormap[0][i] =
292  (unsigned char)(Boxes[i].mean[REDI] * Cfactor + 0.5);
293  colormap[1][i] =
294  (unsigned char)(Boxes[i].mean[GREENI] * Cfactor + 0.5);
295  colormap[2][i] =
296  (unsigned char)(Boxes[i].mean[BLUEI] * Cfactor + 0.5);
297  }
298 
299  if ( !(flags & CQ_NO_RGBMAP) )
300  ComputeRGBMap(Boxes, OutColors, rgbmap, bits, colormap,
301  flags&CQ_FAST);
302 
303  free((char *)Histogram);
304  free((char *)Boxes);
305  return OutColors; /* Return # of colormap entries */
306  }
307  return 0;
308 }
309 
310 /*
311  * Compute the histogram of the image as well as the projected frequency
312  * arrays for the first world-encompassing box.
313  */
314 static void
316 register unsigned char *r, *g, *b;
317 Box *box;
318 int quantize;
319 {
320  register unsigned long *rf, *gf, *bf;
321  unsigned long i;
322 
323  rf = box->freq[0];
324  gf = box->freq[1];
325  bf = box->freq[2];
326 
327  /*
328  * We compute both the histogram and the proj. frequencies of
329  * the first box at the same time to save a pass through the
330  * entire image.
331  */
332 
333  if ( !quantize )
334  for (i = 0; i < NPixels; i++) {
335  rf[*r]++;
336  gf[*g]++;
337  bf[*b]++;
338  Histogram[((((*r++)<<Bits)|(*g++))<<Bits)|(*b++)]++;
339  }
340  else
341  {
342  unsigned char rr, gg, bb;
343  for (i = 0; i < NPixels; i++) {
344  rr = (*r++)>>(8-Bits);
345  gg = (*g++)>>(8-Bits);
346  bb = (*b++)>>(8-Bits);
347  rf[rr]++;
348  gf[gg]++;
349  bf[bb]++;
350  Histogram[(((rr<<Bits)|gg)<<Bits)|bb]++;
351  }
352  }
353 
354 }
355 
356 /*
357  * Interatively cut the boxes.
358  */
359 static int
361 Box *boxes;
362 int colors;
363 {
364  int curbox;
365 
366  boxes[0].low[REDI] = boxes[0].low[GREENI] = boxes[0].low[BLUEI] = 0;
367  boxes[0].high[REDI] = boxes[0].high[GREENI] =
368  boxes[0].high[BLUEI] = ColormaxI;
369  boxes[0].weight = SumPixels;
370 
371  BoxStats(&boxes[0]);
372 
373  for (curbox = 1; curbox < colors; curbox++) {
374  if (CutBox(&boxes[GreatestVariance(boxes, curbox)],
375  &boxes[curbox]) == FALSE)
376  break;
377  }
378 
379  return curbox;
380 }
381 
382 /*
383  * Return the number of the box in 'boxes' with the greatest variance.
384  * Restrict the search to those boxes with indices between 0 and n-1.
385  */
386 static int
388 Box *boxes;
389 int n;
390 {
391  register int i, whichbox = 0;
392  float max;
393 
394  max = -1;
395  for (i = 0; i < n; i++) {
396  if (boxes[i].weightedvar > max) {
397  max = boxes[i].weightedvar;
398  whichbox = i;
399  }
400  }
401  return whichbox;
402 }
403 
404 /*
405  * Compute mean and weighted variance of the given box.
406  */
407 static void
409 register Box *box;
410 {
411  register int i, color;
412  unsigned long *freq;
413  double mean, var;
414 
415  if(box->weight == 0) {
416  box->weightedvar = 0;
417  return;
418  }
419 
420  box->weightedvar = 0.;
421  for (color = 0; color < 3; color++) {
422  var = mean = 0;
423  i = box->low[color];
424  freq = &box->freq[color][i];
425  for (; i < box->high[color]; i++, freq++) {
426  mean += i * *freq;
427  var += i*i* *freq;
428  }
429  box->mean[color] = mean / (double)box->weight;
430  box->weightedvar += var - box->mean[color]*box->mean[color]*
431  (double)box->weight;
432  }
433  box->weightedvar /= SumPixels;
434 }
435 
436 /*
437  * Cut the given box. Returns TRUE if the box could be cut, FALSE otherwise.
438  */
439 static int
441 Box *box, *newbox;
442 {
443  int i;
444  double totalvar[3];
445  Box newboxes[3][2];
446 
447  if (box->weightedvar == 0. || box->weight == 0)
448  /*
449  * Can't cut this box.
450  */
451  return FALSE;
452 
453  /*
454  * Find 'optimal' cutpoint along each of the red, green and blue
455  * axes. Sum the variances of the two boxes which would result
456  * by making each cut and store the resultant boxes for
457  * (possible) later use.
458  */
459  for (i = 0; i < 3; i++) {
460  if (FindCutpoint(box, i, &newboxes[i][0], &newboxes[i][1]))
461  totalvar[i] = newboxes[i][0].weightedvar +
462  newboxes[i][1].weightedvar;
463  else
464  totalvar[i] = HUGE;
465  }
466 
467  /*
468  * Find which of the three cuts minimized the total variance
469  * and make that the 'real' cut.
470  */
471  if (totalvar[REDI] <= totalvar[GREENI] &&
472  totalvar[REDI] <= totalvar[BLUEI]) {
473  *box = newboxes[REDI][0];
474  *newbox = newboxes[REDI][1];
475  } else if (totalvar[GREENI] <= totalvar[REDI] &&
476  totalvar[GREENI] <= totalvar[BLUEI]) {
477  *box = newboxes[GREENI][0];
478  *newbox = newboxes[GREENI][1];
479  } else {
480  *box = newboxes[BLUEI][0];
481  *newbox = newboxes[BLUEI][1];
482  }
483 
484  return TRUE;
485 }
486 
487 /*
488  * Compute the 'optimal' cutpoint for the given box along the axis
489  * indcated by 'color'. Store the boxes which result from the cut
490  * in newbox1 and newbox2.
491  */
492 static int
494 Box *box, *newbox1, *newbox2;
495 int color;
496 {
497  float u, v, max;
498  int i, maxindex, minindex, cutpoint;
499  unsigned long optweight, curweight;
500 
501  if (box->low[color] + 1 == box->high[color])
502  return FALSE; /* Cannot be cut. */
503  minindex = (int)((box->low[color] + box->mean[color]) * 0.5);
504  maxindex = (int)((box->mean[color] + box->high[color]) * 0.5);
505 
506  cutpoint = minindex;
507  optweight = box->weight;
508 
509  curweight = 0;
510  for (i = box->low[color] ; i < minindex ; i++)
511  curweight += box->freq[color][i];
512  u = 0.;
513  max = -1;
514  for (i = minindex; i <= maxindex ; i++) {
515  curweight += box->freq[color][i];
516  if (curweight == box->weight)
517  break;
518  u += (float)(i * box->freq[color][i]) /
519  (float)box->weight;
520  v = ((float)curweight / (float)(box->weight-curweight)) *
521  (box->mean[color]-u)*(box->mean[color]-u);
522  if (v > max) {
523  max = v;
524  cutpoint = i;
525  optweight = curweight;
526  }
527  }
528  cutpoint++;
529  *newbox1 = *newbox2 = *box;
530  newbox1->weight = optweight;
531  newbox2->weight -= optweight;
532  newbox1->high[color] = cutpoint;
533  newbox2->low[color] = cutpoint;
534  UpdateFrequencies(newbox1, newbox2);
535  BoxStats(newbox1);
536  BoxStats(newbox2);
537 
538  return TRUE; /* Found cutpoint. */
539 }
540 
541 /*
542  * Update projected frequency arrays for two boxes which used to be
543  * a single box.
544  */
545 static void
547 register Box *box1, *box2;
548 {
549  register unsigned long myfreq, *h;
550  register int b, g, r;
551  int roff;
552 
553  bzero(box1->freq[0], ColormaxI * sizeof(unsigned long));
554  bzero(box1->freq[1], ColormaxI * sizeof(unsigned long));
555  bzero(box1->freq[2], ColormaxI * sizeof(unsigned long));
556 
557  for (r = box1->low[0]; r < box1->high[0]; r++) {
558  roff = r << Bits;
559  for (g = box1->low[1];g < box1->high[1]; g++) {
560  b = box1->low[2];
561  h = Histogram + (((roff | g) << Bits) | b);
562  for (; b < box1->high[2]; b++) {
563  if ((myfreq = *h++) == 0)
564  continue;
565  box1->freq[0][r] += myfreq;
566  box1->freq[1][g] += myfreq;
567  box1->freq[2][b] += myfreq;
568  box2->freq[0][r] -= myfreq;
569  box2->freq[1][g] -= myfreq;
570  box2->freq[2][b] -= myfreq;
571  }
572  }
573  }
574 }
575 
576 /*
577  * Compute RGB to colormap index map.
578  */
579 static void
581 Box *boxes;
582 int colors;
583 unsigned char *rgbmap, *colormap[3];
584 int bits, fast;
585 {
586  register int i;
587 
588  if (fast) {
589  /*
590  * The centroid of each box serves as the representative
591  * for each color in the box.
592  */
593  for (i = 0; i < colors; i++)
594  SetRGBmap(i, &boxes[i], rgbmap, bits);
595  } else
596  /*
597  * Find the 'nearest' representative for each
598  * pixel.
599  */
600 #ifdef slow_color_map
601  find_colors(boxes, colors, rgbmap, bits, colormap, 1);
602 #else
603  inv_cmap(colors, colormap, bits, Histogram, rgbmap);
604 #endif
605 }
606 
607 /*
608  * Make the centroid of "boxnum" serve as the representative for
609  * each color in the box.
610  */
611 static void
613 int boxnum;
614 Box *box;
615 unsigned char *rgbmap;
616 int bits;
617 {
618  register int r, g, b;
619 
620  for (r = box->low[REDI]; r < box->high[REDI]; r++) {
621  for (g = box->low[GREENI]; g < box->high[GREENI]; g++) {
622  for (b = box->low[BLUEI]; b < box->high[BLUEI]; b++) {
623  rgbmap[(((r<<bits)|g)<<bits)|b]=(char)boxnum;
624  }
625  }
626  }
627 }
628 
629 #ifdef slow_color_map
630 /*
631  * Form colormap and NearestColor arrays.
632  */
633 static void
634 find_colors(boxes, colors, rgbmap, bits, colormap, otherimages)
635 int colors;
636 Box *boxes;
637 unsigned char *rgbmap;
638 int bits;
639 unsigned char *colormap[3];
640 int otherimages;
641 {
642  register int i;
643  int num, *neighbors;
644 
645  neighbors = (int *)malloc(colors * sizeof(int));
646 
647  /*
648  * Form map of representative (nearest) colors.
649  */
650  for (i = 0; i < colors; i++) {
651  /*
652  * Create list of candidate neighbors and
653  * find closest representative for each
654  * color in the box.
655  */
656  num = getneighbors(boxes, i, neighbors, colors, colormap);
657  makenearest(boxes, i, num, neighbors, rgbmap, bits, colormap,
658  otherimages);
659  }
660  free((char *)neighbors);
661 }
662 
663 /*
664  * In order to minimize our search for 'best representative', we form the
665  * 'neighbors' array. This array contains the number of the boxes whose
666  * centroids *might* be used as a representative for some color in the
667  * current box. We need only consider those boxes whose centroids are closer
668  * to one or more of the current box's corners than is the centroid of the
669  * current box. 'Closeness' is measured by Euclidean distance.
670  */
671 static
672 getneighbors(boxes, num, neighbors, colors, colormap)
673 Box *boxes;
674 int num, colors, *neighbors;
675 unsigned char *colormap[3];
676 {
677  register int i, j;
678  Box *bp;
679  float dist, LowR, LowG, LowB, HighR, HighG, HighB, ldiff, hdiff;
680 
681  bp = &boxes[num];
682 
683  ldiff = bp->low[REDI] - bp->mean[REDI];
684  ldiff *= ldiff;
685  hdiff = bp->high[REDI] - bp->mean[REDI];
686  hdiff *= hdiff;
687  dist = MAX(ldiff, hdiff);
688 
689  ldiff = bp->low[GREENI] - bp->mean[GREENI];
690  ldiff *= ldiff;
691  hdiff = bp->high[GREENI] - bp->mean[GREENI];
692  hdiff *= hdiff;
693  dist += MAX(ldiff, hdiff);
694 
695  ldiff = bp->low[BLUEI] - bp->mean[BLUEI];
696  ldiff *= ldiff;
697  hdiff = bp->high[BLUEI] - bp->mean[BLUEI];
698  hdiff *= hdiff;
699  dist += MAX(ldiff, hdiff);
700 
701 #ifdef IRIS
702  dist = fsqrt(dist);
703 #else
704  dist = (float)sqrt((double)dist);
705 #endif
706 
707  /*
708  * Loop over all colors in the colormap, the ith entry of which
709  * corresponds to the ith box.
710  *
711  * If the centroid of a box is as close to any corner of the
712  * current box as is the centroid of the current box, add that
713  * box to the list of "neighbors" of the current box.
714  */
715  HighR = (float)bp->high[REDI] + dist;
716  HighG = (float)bp->high[GREENI] + dist;
717  HighB = (float)bp->high[BLUEI] + dist;
718  LowR = (float)bp->low[REDI] - dist;
719  LowG = (float)bp->low[GREENI] - dist;
720  LowB = (float)bp->low[BLUEI] - dist;
721  for (i = j = 0, bp = boxes; i < colors; i++, bp++) {
722  if (LowR <= bp->mean[REDI] && HighR >= bp->mean[REDI] &&
723  LowG <= bp->mean[GREENI] && HighG >= bp->mean[GREENI] &&
724  LowB <= bp->mean[BLUEI] && HighB >= bp->mean[BLUEI])
725  neighbors[j++] = i;
726  }
727 
728  return j; /* Return the number of neighbors found. */
729 }
730 
731 /*
732  * Assign representative colors to every pixel in a given box through
733  * the construction of the NearestColor array. For each color in the
734  * given box, we look at the list of neighbors passed to find the
735  * one whose centroid is closest to the current color.
736  */
737 static
738 makenearest(boxes, boxnum, nneighbors, neighbors, rgbmap, bits, colormap,
739  otherimages)
740 Box *boxes;
741 int boxnum;
742 int nneighbors, *neighbors, bits;
743 unsigned char *rgbmap, *colormap[3];
744 int otherimages;
745 {
746  register int n, b, g, r;
747  double rdist, gdist, bdist, dist, mindist;
748  int which, *np;
749  Box *box;
750 
751  box = &boxes[boxnum];
752 
753  for (r = box->low[REDI]; r < box->high[REDI]; r++) {
754  for (g = box->low[GREENI]; g < box->high[GREENI]; g++) {
755  for (b = box->low[BLUEI]; b < box->high[BLUEI]; b++) {
756 /*
757  * The following "if" is to avoid doing extra work when the RGBmap is
758  * not going to be used for other images.
759  */
760  if ((!otherimages) &&
761  (Histogram[(((r<<bits)|g)<<bits)|b] == 0))
762  continue;
763 
764  mindist = HUGE;
765  /*
766  * Find the colormap entry which is
767  * closest to the current color.
768  */
769  np = neighbors;
770  for (n = 0; n < nneighbors; n++, np++) {
771  rdist = r-boxes[*np].mean[REDI];
772  gdist = g-boxes[*np].mean[GREENI];
773  bdist = b-boxes[*np].mean[BLUEI];
774  dist = rdist*rdist + gdist*gdist + bdist*bdist;
775  if (dist < mindist) {
776  mindist = dist;
777  which = *np;
778  }
779  }
780  /*
781  * The colormap entry closest to this
782  * color is used as a representative.
783  */
784  rgbmap[(((r<<bits)|g)<<bits)|b] = which;
785  }
786  }
787  }
788 }
789 #endif /* slow_color_map */
static void ComputeRGBMap(Box *boxes, int colors, unsigned char *rgbmap, int bits, colormap, int fast)
Definition: colorquant.c:580
#define FULLINTENSITY
Definition: colorquant.c:156
float mean[3]
Definition: colorquant.c:170
#define PROCESS_HIST
Definition: colorquant.c:240
unsigned long freq[3][256]
Definition: colorquant.c:171
static void UpdateFrequencies(Box *box1, Box *box2)
Definition: colorquant.c:546
static char rcsid[]
Definition: colorquant.c:86
#define FALSE
Definition: giftorle.c:39
static void QuantHistogram(unsigned char *r, unsigned char *g, unsigned char *b, Box *box, int quantize)
Definition: colorquant.c:315
static unsigned int ColormaxI
Definition: colorquant.c:179
#define CQ_FAST
Definition: colorquant.h:57
static void BoxStats(Box *box)
Definition: colorquant.c:408
static unsigned long NPixels
Definition: colorquant.c:176
#define MAXCOLORS
Definition: colorquant.c:149
#define BLUEI
Definition: colorquant.c:164
unsigned long weight
Definition: colorquant.c:171
int colorquant(unsigned char *red, unsigned char *green, unsigned char *blue, unsigned long pixels, colormap, int colors, int bits, unsigned char *rgbmap, int flags, int accum_hist)
Definition: colorquant.c:242
static unsigned int Bits
Definition: colorquant.c:179
static Box * Boxes
Definition: colorquant.c:181
#define INIT_HIST
Definition: colorquant.c:238
#define REDI
Definition: colorquant.c:162
static unsigned long SumPixels
Definition: colorquant.c:176
static int CutBox(Box *box, Box *newbox)
Definition: colorquant.c:440
void inv_cmap(int colors, colormap, int bits, unsigned long *dist_buf,*rgbmap)
Definition: inv_cmap.c:214
#define TRUE
Definition: giftorle.c:38
static unsigned long * Histogram
Definition: colorquant.c:176
static int FindCutpoint(Box *box, int color, Box *newbox1, Box *newbox2)
Definition: colorquant.c:493
double weightedvar
Definition: colorquant.c:169
static int CutBoxes(Box *boxes, int colors)
Definition: colorquant.c:360
#define CQ_NO_RGBMAP
Definition: colorquant.h:59
#define GREENI
Definition: colorquant.c:163
int high[3]
Definition: colorquant.c:173
#define CQ_QUANTIZE
Definition: colorquant.h:58
static void SetRGBmap(int boxnum, Box *box, unsigned char *rgbmap, int bits)
Definition: colorquant.c:612
static int GreatestVariance(Box *boxes, int n)
Definition: colorquant.c:387
int low[3]
Definition: colorquant.c:173