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 $";
107 #ifdef slow_color_map
108 static void find_colors();
109 static int getneighbors();
110 static int makenearest();
149 #define MAXCOLORS 256
156 #define FULLINTENSITY 255
157 #define MAX(x,y) ((x) > (y) ? (x) : (y))
240 #define PROCESS_HIST 3
243 unsigned char *red, *green, *blue;
244 unsigned long pixels;
245 unsigned char *colormap[3];
247 unsigned char *rgbmap;
248 int flags, accum_hist;
256 fprintf(stderr,
"colorquant: bad value for accum_hist\n");
264 if (! accum_hist || accum_hist ==
INIT_HIST) {
267 Boxes = (Box *)malloc(colors *
sizeof(Box));
290 for (i = 0; i < OutColors; i++) {
316 register unsigned char *r, *g, *b;
320 register unsigned long *rf, *gf, *bf;
334 for (i = 0; i <
NPixels; i++) {
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);
373 for (curbox = 1; curbox < colors; curbox++) {
391 register int i, whichbox = 0;
395 for (i = 0; i < n; i++) {
411 register int i, color;
421 for (color = 0; color < 3; color++) {
424 freq = &box
->freq[color][i];
425 for (; i < box
->high[color]; i++, freq++) {
459 for (i = 0; i < 3; i++) {
473 *box = newboxes[
REDI][0];
474 *newbox = newboxes[
REDI][1];
475 }
else if (totalvar[
GREENI] <= totalvar[
REDI] &&
477 *box = newboxes[
GREENI][0];
478 *newbox = newboxes[
GREENI][1];
480 *box = newboxes[
BLUEI][0];
481 *newbox = newboxes[
BLUEI][1];
498 int i, maxindex, minindex, cutpoint;
499 unsigned long optweight, curweight;
503 minindex = (
int)((box
->low[color] + box
->mean[color]) * 0.5);
504 maxindex = (
int)((box
->mean[color] + box
->high[color]) * 0.5);
510 for (i = box
->low[color] ; i < minindex ; i++)
511 curweight += box
->freq[color][i];
514 for (i = minindex; i <= maxindex ; i++) {
515 curweight += box
->freq[color][i];
518 u += (
float)(i * box
->freq[color][i]) /
520 v = ((
float)curweight / (
float)(box
->weight-curweight)) *
525 optweight = curweight;
529 *newbox1 = *newbox2 = *box;
532 newbox1
->high[color] = cutpoint;
533 newbox2
->low[color] = cutpoint;
547 register Box *box1, *box2;
549 register unsigned long myfreq, *h;
550 register int b, g, r;
562 for (; b < box1
->high[2]; b++) {
563 if ((myfreq = *h++) == 0)
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;
583 unsigned char *rgbmap, *
colormap[3];
593 for (i = 0; i < colors; i++)
600 #ifdef slow_color_map
601 find_colors(boxes, colors, rgbmap, bits, colormap, 1);
615 unsigned char *rgbmap;
618 register int r, g, b;
623 rgbmap[(((r<<bits)|g)<<bits)|b]=(
char)boxnum;
629 #ifdef slow_color_map
634 find_colors(boxes, colors, rgbmap, bits, colormap, otherimages)
637 unsigned char *rgbmap;
639 unsigned char *colormap[3];
645 neighbors = (
int *)malloc(colors *
sizeof(
int));
650 for (i = 0; i < colors; i++) {
656 num = getneighbors(boxes, i, neighbors, colors, colormap);
657 makenearest(boxes, i, num, neighbors, rgbmap, bits, colormap,
660 free((
char *)neighbors);
672 getneighbors(boxes, num, neighbors, colors, colormap)
674 int num, colors, *neighbors;
675 unsigned char *colormap[3];
679 float dist, LowR, LowG, LowB, HighR, HighG, HighB, ldiff, hdiff;
683 ldiff = bp->low[REDI] - bp->mean[REDI];
685 hdiff = bp->high[REDI] - bp->mean[REDI];
687 dist = MAX(ldiff, hdiff);
689 ldiff = bp->low[GREENI] - bp->mean[GREENI];
691 hdiff = bp->high[GREENI] - bp->mean[GREENI];
693 dist += MAX(ldiff, hdiff);
695 ldiff = bp->low[BLUEI] - bp->mean[BLUEI];
697 hdiff = bp->high[BLUEI] - bp->mean[BLUEI];
699 dist += MAX(ldiff, hdiff);
704 dist = (
float)sqrt((
double)dist);
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])
738 makenearest(boxes, boxnum, nneighbors, neighbors, rgbmap, bits, colormap,
742 int nneighbors, *neighbors, bits;
743 unsigned char *rgbmap, *colormap[3];
746 register int n, b, g, r;
747 double rdist, gdist, bdist, dist, mindist;
751 box = &boxes[boxnum];
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++) {
760 if ((!otherimages) &&
761 (Histogram[(((r<<bits)|g)<<bits)|b] == 0))
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) {
784 rgbmap[(((r<<bits)|g)<<bits)|b] = which;
static void ComputeRGBMap(Box *boxes, int colors, unsigned char *rgbmap, int bits, colormap, int fast)
unsigned long freq[3][256]
static void UpdateFrequencies(Box *box1, Box *box2)
static void QuantHistogram(unsigned char *r, unsigned char *g, unsigned char *b, Box *box, int quantize)
static unsigned int ColormaxI
static void BoxStats(Box *box)
static unsigned long NPixels
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 unsigned long SumPixels
static int CutBox(Box *box, Box *newbox)
void inv_cmap(int colors, colormap, int bits, unsigned long *dist_buf,*rgbmap)
static unsigned long * Histogram
static int FindCutpoint(Box *box, int color, Box *newbox1, Box *newbox2)
static int CutBoxes(Box *boxes, int colors)
static void SetRGBmap(int boxnum, Box *box, unsigned char *rgbmap, int bits)
static int GreatestVariance(Box *boxes, int n)