Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
inv_cmap.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  * inv_cmap.c - Compute an inverse colormap.
20  *
21  * Author: Spencer W. Thomas
22  * EECS Dept.
23  * University of Michigan
24  * Date: Thu Sep 20 1990
25  * Copyright (c) 1990, University of Michigan
26  *
27  * $Id: inv_cmap.c,v 3.0.1.3 1992/04/30 14:07:28 spencer Exp $
28  */
29 
30 #include <math.h>
31 #include <stdio.h>
32 
33 #ifndef NO_INV_CMAP_TRACKING
34 
35 #ifdef DEBUG
36 static int cred, cgreen, cblue;
37 static int red, green;
38 static unsigned char *zrgbp;
39 #endif
40 static int bcenter, gcenter, rcenter;
41 static long gdist, rdist, cdist;
42 static long cbinc, cginc, crinc;
43 static unsigned long *gdp, *rdp, *cdp;
44 static unsigned char *grgbp, *rrgbp, *crgbp;
45 static long gstride, rstride;
46 static long x, xsqr, colormax;
47 static int cindex;
48 #ifdef INSTRUMENT_IT
49 static long outercount = 0, innercount = 0;
50 #endif
51 
52 #ifdef USE_PROTOTYPES
53 static void maxfill( unsigned long *, long );
54 static int redloop( void );
55 static int greenloop( int );
56 static int blueloop( int );
57 #else
58 static void maxfill();
59 static int redloop();
60 static int greenloop();
61 static int blueloop();
62 #endif
63 
64 
65 /*****************************************************************
66  * TAG( inv_cmap )
67  *
68  * Compute an inverse colormap efficiently.
69  * Inputs:
70  * colors: Number of colors in the forward colormap.
71  * colormap: The forward colormap.
72  * bits: Number of quantization bits. The inverse
73  * colormap will have (2^bits)^3 entries.
74  * dist_buf: An array of (2^bits)^3 long integers to be
75  * used as scratch space.
76  * Outputs:
77  * rgbmap: The output inverse colormap. The entry
78  * rgbmap[(r<<(2*bits)) + (g<<bits) + b]
79  * is the colormap entry that is closest to the
80  * (quantized) color (r,g,b).
81  * Assumptions:
82  * Quantization is performed by right shift (low order bits are
83  * truncated). Thus, the distance to a quantized color is
84  * actually measured to the color at the center of the cell
85  * (i.e., to r+.5, g+.5, b+.5, if (r,g,b) is a quantized color).
86  * Algorithm:
87  * Uses a "distance buffer" algorithm:
88  * The distance from each representative in the forward color map
89  * to each point in the rgb space is computed. If it is less
90  * than the distance currently stored in dist_buf, then the
91  * corresponding entry in rgbmap is replaced with the current
92  * representative (and the dist_buf entry is replaced with the
93  * new distance).
94  *
95  * The distance computation uses an efficient incremental formulation.
96  *
97  * Distances are computed "outward" from each color. If the
98  * colors are evenly distributed in color space, the expected
99  * number of cells visited for color I is N^3/I.
100  * Thus, the complexity of the algorithm is O(log(K) N^3),
101  * where K = colors, and N = 2^bits.
102  */
103 
104 /*
105  * Here's the idea: scan from the "center" of each cell "out"
106  * until we hit the "edge" of the cell -- that is, the point
107  * at which some other color is closer -- and stop. In 1-D,
108  * this is simple:
109  * for i := here to max do
110  * if closer then buffer[i] = this color
111  * else break
112  * repeat above loop with i := here-1 to min by -1
113  *
114  * In 2-D, it's trickier, because along a "scan-line", the
115  * region might start "after" the "center" point. A picture
116  * might clarify:
117  * | ...
118  * | ... .
119  * ... .
120  * ... | .
121  * . + .
122  * . .
123  * . .
124  * .........
125  *
126  * The + marks the "center" of the above region. On the top 2
127  * lines, the region "begins" to the right of the "center".
128  *
129  * Thus, we need a loop like this:
130  * detect := false
131  * for i := here to max do
132  * if closer then
133  * buffer[..., i] := this color
134  * if !detect then
135  * here = i
136  * detect = true
137  * else
138  * if detect then
139  * break
140  *
141  * Repeat the above loop with i := here-1 to min by -1. Note that
142  * the "detect" value should not be reinitialized. If it was
143  * "true", and center is not inside the cell, then none of the
144  * cell lies to the left and this loop should exit
145  * immediately.
146  *
147  * The outer loops are similar, except that the "closer" test
148  * is replaced by a call to the "next in" loop; its "detect"
149  * value serves as the test. (No assignment to the buffer is
150  * done, either.)
151  *
152  * Each time an outer loop starts, the "here", "min", and
153  * "max" values of the next inner loop should be
154  * re-initialized to the center of the cell, 0, and cube size,
155  * respectively. Otherwise, these values will carry over from
156  * one "call" to the inner loop to the next. This tracks the
157  * edges of the cell and minimizes the number of
158  * "unproductive" comparisons that must be made.
159  *
160  * Finally, the inner-most loop can have the "if !detect"
161  * optimized out of it by splitting it into two loops: one
162  * that finds the first color value on the scan line that is
163  * in this cell, and a second that fills the cell until
164  * another one is closer:
165  * if !detect then {needed for "down" loop}
166  * for i := here to max do
167  * if closer then
168  * buffer[..., i] := this color
169  * detect := true
170  * break
171  * for i := i+1 to max do
172  * if closer then
173  * buffer[..., i] := this color
174  * else
175  * break
176  *
177  * In this implementation, each level will require the
178  * following variables. Variables labelled (l) are local to each
179  * procedure. The ? should be replaced with r, g, or b:
180  * cdist: The distance at the starting point.
181  * ?center: The value of this component of the color
182  * c?inc: The initial increment at the ?center position.
183  * ?stride: The amount to add to the buffer
184  * pointers (dp and rgbp) to get to the
185  * "next row".
186  * min(l): The "low edge" of the cell, init to 0
187  * max(l): The "high edge" of the cell, init to
188  * colormax-1
189  * detect(l): True if this row has changed some
190  * buffer entries.
191  * i(l): The index for this row.
192  * ?xx: The accumulated increment value.
193  *
194  * here(l): The starting index for this color. The
195  * following variables are associated with here,
196  * in the sense that they must be updated if here
197  * is changed.
198  * ?dist: The current distance for this level. The
199  * value of dist from the previous level (g or r,
200  * for level b or g) initializes dist on this
201  * level. Thus gdist is associated with here(b)).
202  * ?inc: The initial increment for the row.
203  * ?dp: Pointer into the distance buffer. The value
204  * from the previous level initializes this level.
205  * ?rgbp: Pointer into the rgb buffer. The value
206  * from the previous level initializes this level.
207  *
208  * The blue and green levels modify 'here-associated' variables (dp,
209  * rgbp, dist) on the green and red levels, respectively, when here is
210  * changed.
211  */
212 
213 void
215 int colors, bits;
216 unsigned char *colormap[3], *rgbmap;
217 unsigned long *dist_buf;
218 {
219  int nbits = 8 - bits;
220 
221  colormax = 1 << bits;
222  x = 1 << nbits;
223  xsqr = 1 << (2 * nbits);
224 
225  /* Compute "strides" for accessing the arrays. */
226  gstride = colormax;
228 
229 #ifdef INSTRUMENT_IT
230  outercount = 0;
231  innercount = 0;
232 #endif
233  maxfill( dist_buf, colormax );
234 
235  for ( cindex = 0; cindex < colors; cindex++ )
236  {
237  /*
238  * Distance formula is
239  * (red - map[0])^2 + (green - map[1])^2 + (blue - map[2])^2
240  *
241  * Because of quantization, we will measure from the center of
242  * each quantized "cube", so blue distance is
243  * (blue + x/2 - map[2])^2,
244  * where x = 2^(8 - bits).
245  * The step size is x, so the blue increment is
246  * 2*x*blue - 2*x*map[2] + 2*x^2
247  *
248  * Now, b in the code below is actually blue/x, so our
249  * increment will be 2*(b*x^2 + x^2 - x*map[2]). For
250  * efficiency, we will maintain this quantity in a separate variable
251  * that will be updated incrementally by adding 2*x^2 each time.
252  */
253  /* The initial position is the cell containing the colormap
254  * entry. We get this by quantizing the colormap values.
255  */
256  rcenter = colormap[0][cindex] >> nbits;
257  gcenter = colormap[1][cindex] >> nbits;
258  bcenter = colormap[2][cindex] >> nbits;
259 #ifdef DEBUG
260  cred = colormap[0][cindex];
261  cgreen = colormap[1][cindex];
262  cblue = colormap[2][cindex];
263  fprintf( stderr, "---Starting %d: %d,%d,%d -> %d,%d,%d\n",
264  cindex, cred, cgreen, cblue,
265  rcenter, gcenter, bcenter );
266  zrgbp = rgbmap;
267 #endif
268 
269  rdist = colormap[0][cindex] - (rcenter * x + x/2);
270  gdist = colormap[1][cindex] - (gcenter * x + x/2);
271  cdist = colormap[2][cindex] - (bcenter * x + x/2);
273 
274  crinc = 2 * ((rcenter + 1) * xsqr - (colormap[0][cindex] * x));
275  cginc = 2 * ((gcenter + 1) * xsqr - (colormap[1][cindex] * x));
276  cbinc = 2 * ((bcenter + 1) * xsqr - (colormap[2][cindex] * x));
277 
278  /* Array starting points. */
279  cdp = dist_buf + rcenter * rstride + gcenter * gstride + bcenter;
280  crgbp = rgbmap + rcenter * rstride + gcenter * gstride + bcenter;
281 
282  (void)redloop();
283  }
284 #ifdef INSTRUMENT_IT
285  fprintf( stderr, "K = %d, N = %d, outer count = %ld, inner count = %ld\n",
286  colors, colormax, outercount, innercount );
287 #endif
288 }
289 
290 /* redloop -- loop up and down from red center. */
291 static int
293 {
294  int detect;
295  int r;
296  int first;
297  long txsqr = xsqr + xsqr;
298  static long rxx;
299 
300  detect = 0;
301 
302  /* Basic loop up. */
303  for ( r = rcenter, rdist = cdist, rxx = crinc,
304  rdp = cdp, rrgbp = crgbp, first = 1;
305  r < colormax;
306  r++, rdp += rstride, rrgbp += rstride,
307  rdist += rxx, rxx += txsqr, first = 0 )
308  {
309 #ifdef DEBUG
310  red = r;
311 #endif
312  if ( greenloop( first ) )
313  detect = 1;
314  else if ( detect )
315  break;
316  }
317 
318  /* Basic loop down. */
319  for ( r = rcenter - 1, rxx = crinc - txsqr, rdist = cdist - rxx,
320  rdp = cdp - rstride, rrgbp = crgbp - rstride, first = 1;
321  r >= 0;
322  r--, rdp -= rstride, rrgbp -= rstride,
323  rxx -= txsqr, rdist -= rxx, first = 0 )
324  {
325 #ifdef DEBUG
326  red = r;
327 #endif
328  if ( greenloop( first ) )
329  detect = 1;
330  else if ( detect )
331  break;
332  }
333 
334  return detect;
335 }
336 
337 /* greenloop -- loop up and down from green center. */
338 static int
340 int restart;
341 {
342  int detect;
343  int g;
344  int first;
345  long txsqr = xsqr + xsqr;
346  static int here, min, max;
347 #ifdef MINMAX_TRACK
348  static int prevmax, prevmin;
349  int thismax, thismin;
350 #endif
351  static long ginc, gxx, gcdist; /* "gc" variables maintain correct */
352  static unsigned long *gcdp; /* values for bcenter position, */
353  static unsigned char *gcrgbp; /* despite modifications by blueloop */
354  /* to gdist, gdp, grgbp. */
355 
356  if ( restart )
357  {
358  here = gcenter;
359  min = 0;
360  max = colormax - 1;
361  ginc = cginc;
362 #ifdef MINMAX_TRACK
363  prevmax = 0;
364  prevmin = colormax;
365 #endif
366  }
367 
368 #ifdef MINMAX_TRACK
369  thismin = min;
370  thismax = max;
371 #endif
372  detect = 0;
373 
374  /* Basic loop up. */
375  for ( g = here, gcdist = gdist = rdist, gxx = ginc,
376  gcdp = gdp = rdp, gcrgbp = grgbp = rrgbp, first = 1;
377  g <= max;
378  g++, gdp += gstride, gcdp += gstride, grgbp += gstride, gcrgbp += gstride,
379  gdist += gxx, gcdist += gxx, gxx += txsqr, first = 0 )
380  {
381 #ifdef DEBUG
382  green = g;
383 #endif
384  if ( blueloop( first ) )
385  {
386  if ( !detect )
387  {
388  /* Remember here and associated data! */
389  if ( g > here )
390  {
391  here = g;
392  rdp = gcdp;
393  rrgbp = gcrgbp;
394  rdist = gcdist;
395  ginc = gxx;
396 #ifdef MINMAX_TRACK
397  thismin = here;
398 #endif
399 #ifdef DEBUG
400  fprintf( stderr, "===Adjusting green here up at %d,%d\n",
401  red, here );
402 #endif
403  }
404  detect = 1;
405  }
406  }
407  else if ( detect )
408  {
409 #ifdef MINMAX_TRACK
410  thismax = g - 1;
411 #endif
412  break;
413  }
414  }
415 
416  /* Basic loop down. */
417  for ( g = here - 1, gxx = ginc - txsqr, gcdist = gdist = rdist - gxx,
418  gcdp = gdp = rdp - gstride, gcrgbp = grgbp = rrgbp - gstride,
419  first = 1;
420  g >= min;
421  g--, gdp -= gstride, gcdp -= gstride, grgbp -= gstride, gcrgbp -= gstride,
422  gxx -= txsqr, gdist -= gxx, gcdist -= gxx, first = 0 )
423  {
424 #ifdef DEBUG
425  green = g;
426 #endif
427  if ( blueloop( first ) )
428  {
429  if ( !detect )
430  {
431  /* Remember here! */
432  here = g;
433  rdp = gcdp;
434  rrgbp = gcrgbp;
435  rdist = gcdist;
436  ginc = gxx;
437 #ifdef MINMAX_TRACK
438  thismax = here;
439 #endif
440 #ifdef DEBUG
441  fprintf( stderr, "===Adjusting green here down at %d,%d\n",
442  red, here );
443 #endif
444  detect = 1;
445  }
446  }
447  else if ( detect )
448  {
449 #ifdef MINMAX_TRACK
450  thismin = g + 1;
451 #endif
452  break;
453  }
454  }
455 
456 #ifdef MINMAX_TRACK
457  /* If we saw something, update the edge trackers. For now, only
458  * tracks edges that are "shrinking" (min increasing, max
459  * decreasing.
460  */
461  if ( detect )
462  {
463  if ( thismax < prevmax )
464  max = thismax;
465 
466  prevmax = thismax;
467 
468  if ( thismin > prevmin )
469  min = thismin;
470 
471  prevmin = thismin;
472  }
473 #endif
474 
475  return detect;
476 }
477 
478 /* blueloop -- loop up and down from blue center. */
479 static int
481 int restart;
482 {
483  int detect;
484  register unsigned long *dp;
485  register unsigned char *rgbp;
486  register long bdist, bxx;
487  register int b, i = cindex;
488  register long txsqr = xsqr + xsqr;
489  register int lim;
490  static int here, min, max;
491 #ifdef MINMAX_TRACK
492  static int prevmin, prevmax;
493  int thismin, thismax;
494 #ifdef DMIN_DMAX_TRACK
495  static int dmin, dmax;
496 #endif /* DMIN_DMAX_TRACK */
497 #endif /* MINMAX_TRACK */
498  static long binc;
499 #ifdef DEBUG
500  long dist, tdist;
501 #endif
502 
503  if ( restart )
504  {
505  here = bcenter;
506  min = 0;
507  max = colormax - 1;
508  binc = cbinc;
509 #ifdef MINMAX_TRACK
510  prevmin = colormax;
511  prevmax = 0;
512 #ifdef DMIN_DMAX_TRACK
513  dmin = 0;
514  dmax = 0;
515 #endif /* DMIN_DMAX_TRACK */
516 #endif /* MINMAX_TRACK */
517  }
518 
519  detect = 0;
520 #ifdef MINMAX_TRACK
521  thismin = min;
522  thismax = max;
523 #endif
524 #ifdef DEBUG
525  tdist = cred - red * x - x/2;
526  dist = tdist*tdist;
527  tdist = cgreen - green * x - x/2;
528  dist += tdist*tdist;
529  tdist = cblue - here * x - x/2;
530  dist += tdist*tdist;
531  if ( gdist != dist )
532  fprintf( stderr, "*** At %d,%d,%d; dist = %ld != gdist = %ld\n",
533  red, green, here, dist, gdist );
534  if ( grgbp != zrgbp + red*rstride + green*gstride + here )
535  fprintf( stderr, "*** At %d,%d,%d: buffer pointer is at %d,%d,%d\n",
536  red, green, here,
537  (grgbp - zrgbp) / rstride,
538  ((grgbp - zrgbp) % rstride) / gstride,
539  (grgbp - zrgbp) % gstride );
540 #endif /* DEBUG */
541 
542  /* Basic loop up. */
543  /* First loop just finds first applicable cell. */
544  for ( b = here, bdist = gdist, bxx = binc, dp = gdp, rgbp = grgbp, lim = max;
545  b <= lim;
546  b++, dp++, rgbp++,
547  bdist += bxx, bxx += txsqr )
548  {
549 #ifdef INSTRUMENT_IT
550  outercount++;
551 #endif
552  if ( *dp > bdist )
553  {
554  /* Remember new 'here' and associated data! */
555  if ( b > here )
556  {
557  here = b;
558  gdp = dp;
559  grgbp = rgbp;
560  gdist = bdist;
561  binc = bxx;
562 #ifdef MINMAX_TRACK
563  thismin = here;
564 #endif
565 #ifdef DEBUG
566  fprintf( stderr, "===Adjusting blue here up at %d,%d,%d\n",
567  red, green, here );
568 
569  tdist = cred - red * x - x/2;
570  dist = tdist*tdist;
571  tdist = cgreen - green * x - x/2;
572  dist += tdist*tdist;
573  tdist = cblue - here * x - x/2;
574  dist += tdist*tdist;
575  if ( gdist != dist )
576  fprintf( stderr,
577  "*** Adjusting here up at %d,%d,%d; dist = %ld != gdist = %ld\n",
578  red, green, here, dist, gdist );
579 #endif /* DEBUG */
580  }
581  detect = 1;
582 #ifdef INSTRUMENT_IT
583  outercount--;
584 #endif
585  break;
586  }
587  }
588  /* Second loop fills in a run of closer cells. */
589  for ( ;
590  b <= lim;
591  b++, dp++, rgbp++,
592  bdist += bxx, bxx += txsqr )
593  {
594 #ifdef INSTRUMENT_IT
595  outercount++;
596 #endif
597  if ( *dp > bdist )
598  {
599 #ifdef INSTRUMENT_IT
600  innercount++;
601 #endif
602  *dp = bdist;
603  *rgbp = i;
604  }
605  else
606  {
607 #ifdef MINMAX_TRACK
608  thismax = b - 1;
609 #endif
610  break;
611  }
612  }
613 #ifdef DEBUG
614  tdist = cred - red * x - x/2;
615  dist = tdist*tdist;
616  tdist = cgreen - green * x - x/2;
617  dist += tdist*tdist;
618  tdist = cblue - b * x - x/2;
619  dist += tdist*tdist;
620  if ( bdist != dist )
621  fprintf( stderr,
622  "*** After up loop at %d,%d,%d; dist = %ld != bdist = %ld\n",
623  red, green, b, dist, bdist );
624 #endif /* DEBUG */
625 
626  /* Basic loop down. */
627  /* Do initializations here, since the 'find' loop might not get
628  * executed.
629  */
630  lim = min;
631  b = here - 1;
632  bxx = binc - txsqr;
633  bdist = gdist - bxx;
634  dp = gdp - 1;
635  rgbp = grgbp - 1;
636  /* The 'find' loop is executed only if we didn't already find
637  * something.
638  */
639  if ( !detect )
640  for ( ;
641  b >= lim;
642  b--, dp--, rgbp--,
643  bxx -= txsqr, bdist -= bxx )
644  {
645 #ifdef INSTRUMENT_IT
646  outercount++;
647 #endif
648  if ( *dp > bdist )
649  {
650  /* Remember here! */
651  /* No test for b against here necessary because b <
652  * here by definition.
653  */
654  here = b;
655  gdp = dp;
656  grgbp = rgbp;
657  gdist = bdist;
658  binc = bxx;
659 #ifdef MINMAX_TRACK
660  thismax = here;
661 #endif
662  detect = 1;
663 #ifdef DEBUG
664  fprintf( stderr, "===Adjusting blue here down at %d,%d,%d\n",
665  red, green, here );
666  tdist = cred - red * x - x/2;
667  dist = tdist*tdist;
668  tdist = cgreen - green * x - x/2;
669  dist += tdist*tdist;
670  tdist = cblue - here * x - x/2;
671  dist += tdist*tdist;
672  if ( gdist != dist )
673  fprintf( stderr,
674  "*** Adjusting here down at %d,%d,%d; dist = %ld != gdist = %ld\n",
675  red, green, here, dist, gdist );
676 #endif /* DEBUG */
677 #ifdef INSTRUMENT_IT
678  outercount--;
679 #endif
680  break;
681  }
682  }
683  /* The 'update' loop. */
684  for ( ;
685  b >= lim;
686  b--, dp--, rgbp--,
687  bxx -= txsqr, bdist -= bxx )
688  {
689 #ifdef INSTRUMENT_IT
690  outercount++;
691 #endif
692  if ( *dp > bdist )
693  {
694 #ifdef INSTRUMENT_IT
695  innercount++;
696 #endif
697  *dp = bdist;
698  *rgbp = i;
699  }
700  else
701  {
702 #ifdef MINMAX_TRACK
703  thismin = b + 1;
704 #endif
705  break;
706  }
707  }
708 
709 #ifdef DEBUG
710  tdist = cred - red * x - x/2;
711  dist = tdist*tdist;
712  tdist = cgreen - green * x - x/2;
713  dist += tdist*tdist;
714  tdist = cblue - b * x - x/2;
715  dist += tdist*tdist;
716  if ( bdist != dist )
717  fprintf( stderr,
718  "*** After down loop at %d,%d,%d; dist = %ld != bdist = %ld\n",
719  red, green, b, dist, bdist );
720 #endif /* DEBUG */
721 
722  /* If we saw something, update the edge trackers. */
723 #ifdef MINMAX_TRACK
724  if ( detect )
725  {
726 #ifdef DMIN_DMAX_TRACK
727  /* Predictively track. Not clear this is a win. */
728  /* If there was a previous line, update the dmin/dmax values. */
729  if ( prevmax >= prevmin )
730  {
731  if ( thismin > 0 )
732  dmin = thismin - prevmin - 1;
733  else
734  dmin = 0;
735  if ( thismax < colormax - 1 )
736  dmax = thismax - prevmax + 1;
737  else
738  dmax = 0;
739  /* Update the min and max values by the differences. */
740  max = thismax + dmax;
741  if ( max >= colormax )
742  max = colormax - 1;
743  min = thismin + dmin;
744  if ( min < 0 )
745  min = 0;
746  }
747 #else /* !DMIN_DMAX_TRACK */
748  /* Only tracks edges that are "shrinking" (min increasing, max
749  * decreasing.
750  */
751  if ( thismax < prevmax )
752  max = thismax;
753 
754  if ( thismin > prevmin )
755  min = thismin;
756 #endif /* DMIN_DMAX_TRACK */
757 
758  /* Remember the min and max values. */
759  prevmax = thismax;
760  prevmin = thismin;
761  }
762 #endif /* MINMAX_TRACK */
763 
764  return detect;
765 }
766 
767 static void
769 unsigned long *buffer;
770 long side;
771 {
772  register unsigned long maxv = ~0L;
773  register long i;
774  register unsigned long *bp;
775 
776  for ( i = colormax * colormax * colormax, bp = buffer;
777  i > 0;
778  i--, bp++ )
779  *bp = maxv;
780 }
781 
782 #else /* !NO_INV_CMAP_TRACKING */
783 /*****************************************************************
784  * TAG( inv_cmap )
785  *
786  * Compute an inverse colormap efficiently.
787  * Inputs:
788  * colors: Number of colors in the forward colormap.
789  * colormap: The forward colormap.
790  * bits: Number of quantization bits. The inverse
791  * colormap will have (2^bits)^3 entries.
792  * dist_buf: An array of (2^bits)^3 long integers to be
793  * used as scratch space.
794  * Outputs:
795  * rgbmap: The output inverse colormap. The entry
796  * rgbmap[(r<<(2*bits)) + (g<<bits) + b]
797  * is the colormap entry that is closest to the
798  * (quantized) color (r,g,b).
799  * Assumptions:
800  * Quantization is performed by right shift (low order bits are
801  * truncated). Thus, the distance to a quantized color is
802  * actually measured to the color at the center of the cell
803  * (i.e., to r+.5, g+.5, b+.5, if (r,g,b) is a quantized color).
804  * Algorithm:
805  * Uses a "distance buffer" algorithm:
806  * The distance from each representative in the forward color map
807  * to each point in the rgb space is computed. If it is less
808  * than the distance currently stored in dist_buf, then the
809  * corresponding entry in rgbmap is replaced with the current
810  * representative (and the dist_buf entry is replaced with the
811  * new distance).
812  *
813  * The distance computation uses an efficient incremental formulation.
814  *
815  * Right now, distances are computed for all entries in the rgb
816  * space. Thus, the complexity of the algorithm is O(K N^3),
817  * where K = colors, and N = 2^bits.
818  */
819 void
820 inv_cmap( colors, colormap, bits, dist_buf, rgbmap )
821 int colors, bits;
822 unsigned char *colormap[3], *rgbmap;
823 unsigned long *dist_buf;
824 {
825  register unsigned long *dp;
826  register unsigned char *rgbp;
827  register long bdist, bxx;
828  register int b, i;
829  int nbits = 8 - bits;
830  register int colormax = 1 << bits;
831  register long xsqr = 1 << (2 * nbits);
832  int x = 1 << nbits;
833  int rinc, ginc, binc, r, g;
834  long rdist, gdist, rxx, gxx;
835 #ifdef INSTRUMENT_IT
836  long outercount = 0, innercount = 0;
837 #endif
838 
839  for ( i = 0; i < colors; i++ )
840  {
841  /*
842  * Distance formula is
843  * (red - map[0])^2 + (green - map[1])^2 + (blue - map[2])^2
844  *
845  * Because of quantization, we will measure from the center of
846  * each quantized "cube", so blue distance is
847  * (blue + x/2 - map[2])^2,
848  * where x = 2^(8 - bits).
849  * The step size is x, so the blue increment is
850  * 2*x*blue - 2*x*map[2] + 2*x^2
851  *
852  * Now, b in the code below is actually blue/x, so our
853  * increment will be 2*x*x*b + (2*x^2 - 2*x*map[2]). For
854  * efficiency, we will maintain this quantity in a separate variable
855  * that will be updated incrementally by adding 2*x^2 each time.
856  */
857  rdist = colormap[0][i] - x/2;
858  gdist = colormap[1][i] - x/2;
859  bdist = colormap[2][i] - x/2;
860  rdist = rdist*rdist + gdist*gdist + bdist*bdist;
861 
862  rinc = 2 * (xsqr - (colormap[0][i] << nbits));
863  ginc = 2 * (xsqr - (colormap[1][i] << nbits));
864  binc = 2 * (xsqr - (colormap[2][i] << nbits));
865  dp = dist_buf;
866  rgbp = rgbmap;
867  for ( r = 0, rxx = rinc;
868  r < colormax;
869  rdist += rxx, r++, rxx += xsqr + xsqr )
870  for ( g = 0, gdist = rdist, gxx = ginc;
871  g < colormax;
872  gdist += gxx, g++, gxx += xsqr + xsqr )
873  for ( b = 0, bdist = gdist, bxx = binc;
874  b < colormax;
875  bdist += bxx, b++, dp++, rgbp++,
876  bxx += xsqr + xsqr )
877  {
878 #ifdef INSTRUMENT_IT
879  outercount++;
880 #endif
881  if ( i == 0 || *dp > bdist )
882  {
883 #ifdef INSTRUMENT_IT
884  innercount++;
885 #endif
886  *dp = bdist;
887  *rgbp = i;
888  }
889  }
890  }
891 #ifdef INSTRUMENT_IT
892  fprintf( stderr, "K = %d, N = %d, outer count = %ld, inner count = %ld\n",
893  colors, colormax, outercount, innercount );
894 #endif
895 }
896 
897 #endif /* NO_INV_CMAP_TRACKING */
static int greenloop(int restart)
Definition: inv_cmap.c:339
static int bcenter
Definition: inv_cmap.c:40
static long cbinc
Definition: inv_cmap.c:42
static long crinc
Definition: inv_cmap.c:42
static long x
Definition: inv_cmap.c:46
static int rcenter
Definition: inv_cmap.c:40
static unsigned char * rrgbp
Definition: inv_cmap.c:44
static unsigned long * gdp
Definition: inv_cmap.c:43
static void maxfill(unsigned long *buffer, long side)
Definition: inv_cmap.c:768
static long cdist
Definition: inv_cmap.c:41
static long gdist
Definition: inv_cmap.c:41
static long rdist
Definition: inv_cmap.c:41
static int gcenter
Definition: inv_cmap.c:40
static int redloop()
Definition: inv_cmap.c:292
static long rstride
Definition: inv_cmap.c:45
static long colormax
Definition: inv_cmap.c:46
static unsigned char * grgbp
Definition: inv_cmap.c:44
static long cginc
Definition: inv_cmap.c:42
void inv_cmap(int colors, colormap, int bits, unsigned long *dist_buf,*rgbmap)
Definition: inv_cmap.c:214
static unsigned long * cdp
Definition: inv_cmap.c:43
static int cindex
Definition: inv_cmap.c:47
static int blueloop(int restart)
Definition: inv_cmap.c:480
static unsigned long * rdp
Definition: inv_cmap.c:43
static long gstride
Definition: inv_cmap.c:45
static long xsqr
Definition: inv_cmap.c:46
static unsigned char * crgbp
Definition: inv_cmap.c:44