Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
Data Structures | Macros | Functions | Variables
colorquant.c File Reference
#include <math.h>
#include <stdio.h>
#include "rle_config.h"
#include "colorquant.h"
Include dependency graph for colorquant.c:

Go to the source code of this file.

Data Structures

struct  Box
 

Macros

#define MAXCOLORS   256
 
#define FULLINTENSITY   255
 
#define MAX(x, y)   ((x) > (y) ? (x) : (y))
 
#define REDI   0
 
#define GREENI   1
 
#define BLUEI   2
 
#define TRUE   1
 
#define FALSE   0
 
#define INIT_HIST   1
 
#define USE_HIST   2
 
#define PROCESS_HIST   3
 

Functions

static void QuantHistogram ()
 
static void BoxStats ()
 
static void UpdateFrequencies ()
 
static void ComputeRGBMap ()
 
static void SetRGBmap ()
 
void inv_cmap ()
 
static int CutBoxes ()
 
static int CutBox ()
 
static int GreatestVariance ()
 
static int FindCutpoint ()
 
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)
 
static void QuantHistogram (unsigned char *r, unsigned char *g, unsigned char *b, Box *box, int quantize)
 
static int CutBoxes (Box *boxes, int colors)
 
static int GreatestVariance (Box *boxes, int n)
 
static void BoxStats (Box *box)
 
static int CutBox (Box *box, Box *newbox)
 
static int FindCutpoint (Box *box, int color, Box *newbox1, Box *newbox2)
 
static void UpdateFrequencies (Box *box1, Box *box2)
 
static void ComputeRGBMap (Box *boxes, int colors, unsigned char *rgbmap, int bits, colormap, int fast)
 
static void SetRGBmap (int boxnum, Box *box, unsigned char *rgbmap, int bits)
 

Variables

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 $"
 
static unsigned long * Histogram
 
static unsigned long NPixels
 
static unsigned long SumPixels
 
static unsigned int Bits
 
static unsigned int ColormaxI
 
static BoxBoxes
 

Macro Definition Documentation

#define BLUEI   2

Definition at line 164 of file colorquant.c.

#define FALSE   0

Definition at line 166 of file colorquant.c.

#define FULLINTENSITY   255

Definition at line 156 of file colorquant.c.

#define GREENI   1

Definition at line 163 of file colorquant.c.

#define INIT_HIST   1

Definition at line 238 of file colorquant.c.

#define MAX (   x,
  y 
)    ((x) > (y) ? (x) : (y))

Definition at line 157 of file colorquant.c.

#define MAXCOLORS   256

Definition at line 149 of file colorquant.c.

#define PROCESS_HIST   3

Definition at line 240 of file colorquant.c.

#define REDI   0

Definition at line 162 of file colorquant.c.

#define TRUE   1

Definition at line 165 of file colorquant.c.

#define USE_HIST   2

Definition at line 239 of file colorquant.c.

Function Documentation

static void BoxStats ( )
static
static void BoxStats ( Box box)
static

Definition at line 408 of file colorquant.c.

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 }
float mean[3]
Definition: colorquant.c:170
unsigned long freq[3][256]
Definition: colorquant.c:171
unsigned long weight
Definition: colorquant.c:171
static unsigned long SumPixels
Definition: colorquant.c:176
double weightedvar
Definition: colorquant.c:169
int i
Definition: rletorla.c:82
int high[3]
Definition: colorquant.c:173
static struct Requester freq
Definition: getami.c:192
int low[3]
Definition: colorquant.c:173
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 at line 242 of file colorquant.c.

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 }
#define FULLINTENSITY
Definition: colorquant.c:156
static void ComputeRGBMap()
static unsigned char blue[256]
Definition: rastorle.c:71
#define PROCESS_HIST
Definition: colorquant.c:240
unsigned long freq[3][256]
Definition: colorquant.c:171
static unsigned int ColormaxI
Definition: colorquant.c:179
#define CQ_FAST
Definition: colorquant.h:57
static unsigned long NPixels
Definition: colorquant.c:176
rle_map * colormap
Definition: rletoppm.c:56
#define BLUEI
Definition: colorquant.c:164
static unsigned int Bits
Definition: colorquant.c:179
static unsigned char green[256]
Definition: rastorle.c:71
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 unsigned long * Histogram
Definition: colorquant.c:176
#define CQ_NO_RGBMAP
Definition: colorquant.h:59
static void QuantHistogram()
#define GREENI
Definition: colorquant.c:163
void * malloc()
int i
Definition: rletorla.c:82
#define CQ_QUANTIZE
Definition: colorquant.h:58
static int CutBoxes()
static unsigned char red[256]
Definition: rastorle.c:71
static void ComputeRGBMap ( )
static
static void ComputeRGBMap ( Box boxes,
int  colors,
unsigned char *  rgbmap,
int  bits,
colormap  ,
int  fast 
)
static

Definition at line 580 of file colorquant.c.

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 }
static void SetRGBmap()
void inv_cmap()
rle_map * colormap
Definition: rletoppm.c:56
static unsigned long * Histogram
Definition: colorquant.c:176
int i
Definition: rletorla.c:82
static int CutBox ( )
static
static int CutBox ( Box box,
Box newbox 
)
static

Definition at line 440 of file colorquant.c.

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 }
#define BLUEI
Definition: colorquant.c:164
unsigned long weight
Definition: colorquant.c:171
#define REDI
Definition: colorquant.c:162
#define FALSE
Definition: colorquant.c:166
#define TRUE
Definition: colorquant.c:165
double weightedvar
Definition: colorquant.c:169
#define GREENI
Definition: colorquant.c:163
int i
Definition: rletorla.c:82
static int FindCutpoint()
static int CutBoxes ( )
static
static int CutBoxes ( Box boxes,
int  colors 
)
static

Definition at line 360 of file colorquant.c.

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 }
static unsigned int ColormaxI
Definition: colorquant.c:179
#define BLUEI
Definition: colorquant.c:164
unsigned long weight
Definition: colorquant.c:171
#define REDI
Definition: colorquant.c:162
static unsigned long SumPixels
Definition: colorquant.c:176
static void BoxStats()
#define FALSE
Definition: colorquant.c:166
#define GREENI
Definition: colorquant.c:163
int high[3]
Definition: colorquant.c:173
static int CutBox()
static int GreatestVariance()
int low[3]
Definition: colorquant.c:173
static int FindCutpoint ( )
static
static int FindCutpoint ( Box box,
int  color,
Box newbox1,
Box newbox2 
)
static

Definition at line 493 of file colorquant.c.

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 }
float mean[3]
Definition: colorquant.c:170
unsigned long freq[3][256]
Definition: colorquant.c:171
static void UpdateFrequencies()
unsigned long weight
Definition: colorquant.c:171
static void BoxStats()
#define FALSE
Definition: colorquant.c:166
int
Definition: getami.c:848
#define TRUE
Definition: colorquant.c:165
int i
Definition: rletorla.c:82
int high[3]
Definition: colorquant.c:173
int low[3]
Definition: colorquant.c:173
static int GreatestVariance ( )
static
static int GreatestVariance ( Box boxes,
int  n 
)
static

Definition at line 387 of file colorquant.c.

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 }
double weightedvar
Definition: colorquant.c:169
int i
Definition: rletorla.c:82
void inv_cmap ( )
static void QuantHistogram ( )
static
static void QuantHistogram ( unsigned char *  r,
unsigned char *  g,
unsigned char *  b,
Box box,
int  quantize 
)
static

Definition at line 315 of file colorquant.c.

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 }
static unsigned char g
Definition: getami.c:692
unsigned long freq[3][256]
Definition: colorquant.c:171
static unsigned char r
Definition: getami.c:692
static unsigned long NPixels
Definition: colorquant.c:176
static unsigned char b
Definition: getami.c:692
static unsigned int Bits
Definition: colorquant.c:179
static unsigned long * Histogram
Definition: colorquant.c:176
int i
Definition: rletorla.c:82
static void SetRGBmap ( )
static
static void SetRGBmap ( int  boxnum,
Box box,
unsigned char *  rgbmap,
int  bits 
)
static

Definition at line 612 of file colorquant.c.

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 }
static unsigned char g
Definition: getami.c:692
static unsigned char r
Definition: getami.c:692
#define BLUEI
Definition: colorquant.c:164
static unsigned char b
Definition: getami.c:692
#define REDI
Definition: colorquant.c:162
#define GREENI
Definition: colorquant.c:163
int low[3]
Definition: colorquant.c:173
static void UpdateFrequencies ( )
static
static void UpdateFrequencies ( Box box1,
Box box2 
)
static

Definition at line 546 of file colorquant.c.

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 }
static unsigned char g
Definition: getami.c:692
unsigned long freq[3][256]
Definition: colorquant.c:171
static unsigned char r
Definition: getami.c:692
static unsigned int ColormaxI
Definition: colorquant.c:179
static unsigned char b
Definition: getami.c:692
static unsigned int Bits
Definition: colorquant.c:179
static unsigned long * Histogram
Definition: colorquant.c:176
int high[3]
Definition: colorquant.c:173
int low[3]
Definition: colorquant.c:173

Variable Documentation

unsigned int Bits
static

Definition at line 179 of file colorquant.c.

Box* Boxes
static

Definition at line 181 of file colorquant.c.

unsigned int ColormaxI
static

Definition at line 179 of file colorquant.c.

unsigned long* Histogram
static

Definition at line 176 of file colorquant.c.

unsigned long NPixels
static

Definition at line 176 of file colorquant.c.

char rcsid[] = "$Header: /l/spencer/src/urt/lib/RCS/colorquant.c,v 3.0.1.4 1992/04/30 14:06:48 spencer Exp $"
static

Definition at line 86 of file colorquant.c.

unsigned long SumPixels
static

Definition at line 176 of file colorquant.c.