Back to index

radiance  4R0+20100331
Defines | Functions | Variables
clrtab.c File Reference
#include "copyright.h"
#include <string.h>
#include "standard.h"
#include "color.h"
#include "clrtab.h"

Go to the source code of this file.

Defines

#define NRED   36
#define NGRN   48
#define NBLU   24
#define HMAX   NGRN
#define MINSAMP   7
#define set_branch(p, c)   ((c)<<2|(p))
#define part(cn)   ((cn)>>2)
#define prim(cn)   ((cn)&3)
#define cndx(c)   histo[((c)[RED]*NRED)>>8][((c)[GRN]*NGRN)>>8][((c)[BLU]*NBLU)>>8]
#define MAXERR   20
#define CLOSEST   1 /* this step takes a little longer */
#define c0   r
#define NBSIZ   32
#define i   r

Functions

static void closest (int n)
static void setclosest (BYTE *nl[], int r, int g, int b)
static void addneigh (BYTE *nl[], int i, int j)
static unsigned int dist (BYTE col[3], int r, int g, int b)
static void cut (int box[3][2], int c0, int c1)
static int split (int box[3][2])
static void mktabent (int p, int box[3][2])
int new_histo (int n)
void cnt_pixel (register BYTE col[])
void cnt_colrs (register COLR *cs, register int n)
int new_clrtab (int ncolors)
int map_pixel (register BYTE col[])
void map_colrs (register BYTE *bs, register COLR *cs, register int n)
void dith_colrs (register BYTE *bs, register COLR *cs, int n)
static void cut (register int box[3][2], int c0, int c1)
static int split (register int box[3][2])
static void mktabent (int p, register int box[3][2])
static void addneigh (register BYTE *nl[], register int i, int j)
static unsigned int dist (register BYTE col[3], int r, int g, int b)

Variables

static const char RCSid [] = "$Id: clrtab.c,v 2.18 2005/09/19 02:23:58 greg Exp $"
BYTE clrtab [256][3]
static unsigned histo [NRED][NGRN][NBLU]
static int CLRCUBE [3][2] = {{0,NRED},{0,NGRN},{0,NBLU}}

Define Documentation

#define c0   r
#define CLOSEST   1 /* this step takes a little longer */

Definition at line 38 of file clrtab.c.

#define cndx (   c)    histo[((c)[RED]*NRED)>>8][((c)[GRN]*NGRN)>>8][((c)[BLU]*NBLU)>>8]

Definition at line 31 of file clrtab.c.

#define HMAX   NGRN

Definition at line 20 of file clrtab.c.

#define i   r
#define MAXERR   20

Definition at line 35 of file clrtab.c.

#define MINSAMP   7

Definition at line 22 of file clrtab.c.

#define NBLU   24

Definition at line 19 of file clrtab.c.

#define NBSIZ   32

Definition at line 308 of file clrtab.c.

#define NGRN   48

Definition at line 18 of file clrtab.c.

#define NRED   36

Definition at line 17 of file clrtab.c.

#define part (   cn)    ((cn)>>2)

Definition at line 25 of file clrtab.c.

#define prim (   cn)    ((cn)&3)

Definition at line 26 of file clrtab.c.

#define set_branch (   p,
  c 
)    ((c)<<2|(p))

Definition at line 24 of file clrtab.c.


Function Documentation

static void addneigh ( BYTE nl[],
int  i,
int  j 
) [static]

Here is the caller graph for this function:

static void addneigh ( register BYTE nl[],
register int  i,
int  j 
) [static]

Definition at line 350 of file clrtab.c.

{
       int    nc;
       char   *nnl;
       register int  t;
       
       for (nc = 0; nc < 2; nc++) {              /* do both neighbors */
              for (t = 0; nl[i][t] != i; t++)
                     if (nl[i][t] == j)
                            break;        /* in list already */
              if (nl[i][t] == i) {        /* add to list */
                     nl[i][t++] = j;
                     if (t % NBSIZ == 0) {       /* enlarge list */
                            if ((nnl = realloc((void *)nl[i],
                                          t+NBSIZ)) == NULL)
                                   t--;
                            else
                                   nl[i] = (BYTE *)nnl;
                     }
                     nl[i][t] = i;        /* terminator */
              }
              t = i; i = j; j = t;        /* swap and do it again */
       }
}
static void closest ( int  n) [static]

Definition at line 310 of file clrtab.c.

{
       BYTE   *neigh[256];
       register int  r, g, b;
#define i r
                                   /* get space for neighbor lists */
       for (i = 0; i < n; i++) {
              if ((neigh[i] = (BYTE *)malloc(NBSIZ)) == NULL) {
                     while (i--)
                            free(neigh[i]);
                     return;                     /* ENOMEM -- abandon effort */
              }
              neigh[i][0] = i;            /* identity is terminator */
       }
                                   /* make neighbor lists */
       for (r = 0; r < NRED; r++)
           for (g = 0; g < NGRN; g++)
              for (b = 0; b < NBLU; b++) {
                  if (r < NRED-1 && histo[r][g][b] != histo[r+1][g][b])
                     addneigh(neigh, histo[r][g][b], histo[r+1][g][b]);
                  if (g < NGRN-1 && histo[r][g][b] != histo[r][g+1][b])
                     addneigh(neigh, histo[r][g][b], histo[r][g+1][b]);
                  if (b < NBLU-1 && histo[r][g][b] != histo[r][g][b+1])
                     addneigh(neigh, histo[r][g][b], histo[r][g][b+1]);
              }
                                   /* assign closest values */
       for (r = 0; r < NRED; r++)
           for (g = 0; g < NGRN; g++)
              for (b = 0; b < NBLU; b++)
                  setclosest(neigh, r, g, b);
                                   /* free neighbor lists */
       for (i = 0; i < n; i++)
              free(neigh[i]);
#undef i
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cnt_colrs ( register COLR cs,
register int  n 
)

Definition at line 73 of file clrtab.c.

{
       while (n-- > 0) {
              cndx(cs[0])++;
              cs++;
       }
}

Here is the caller graph for this function:

void cnt_pixel ( register BYTE  col[])

Definition at line 64 of file clrtab.c.

{
       cndx(col)++;
}
static void cut ( int  box[3][2],
int  c0,
int  c1 
) [static]
static void cut ( register int  box[3][2],
int  c0,
int  c1 
) [static]

Definition at line 180 of file clrtab.c.

{
       register int  branch;
       int    kb[3][2];
       
       if (c1-c0 <= 1) {           /* assign pixel */
              mktabent(c0, box);
              return;
       }
                                   /* split box */
       branch = split(box);
       memcpy((void *)kb, (void *)box, sizeof(kb));
                                          /* do left (lesser) branch */
       kb[prim(branch)][1] = part(branch);
       cut(kb, c0, (c0+c1)>>1);
                                          /* do right branch */
       kb[prim(branch)][0] = part(branch);
       kb[prim(branch)][1] = box[prim(branch)][1];
       cut(kb, (c0+c1)>>1, c1);
}

Here is the call graph for this function:

static unsigned int dist ( BYTE  col[3],
int  r,
int  g,
int  b 
) [static]

Here is the caller graph for this function:

static unsigned int dist ( register BYTE  col[3],
int  r,
int  g,
int  b 
) [static]

Definition at line 381 of file clrtab.c.

{
       register int  tmp;
       register unsigned    sum;
       
       tmp = col[RED]*NRED/256 - r;
       sum = tmp*tmp;
       tmp = col[GRN]*NGRN/256 - g;
       sum += tmp*tmp;
       tmp = col[BLU]*NBLU/256 - b;
       sum += tmp*tmp;
       return(sum);
}
void dith_colrs ( register BYTE bs,
register COLR cs,
int  n 
)

Definition at line 130 of file clrtab.c.

{
       static short  (*cerr)[3] = NULL;
       static int    N = 0;
       int    err[3], errp[3];
       register int  x, i;

       if (n != N) {        /* get error propogation array */
              if (N) {
                     free((void *)cerr);
                     cerr = NULL;
              }
              if (n)
                     cerr = (short (*)[3])malloc(3*n*sizeof(short));
              if (cerr == NULL) {
                     N = 0;
                     map_colrs(bs, cs, n);
                     return;
              }
              N = n;
              memset((void *)cerr, '\0', 3*N*sizeof(short));
       }
       err[0] = err[1] = err[2] = 0;
       for (x = 0; x < n; x++) {
              for (i = 0; i < 3; i++) {   /* dither value */
                     errp[i] = err[i];
                     err[i] += cerr[x][i];
#ifdef MAXERR
                     if (err[i] > MAXERR) err[i] = MAXERR;
                     else if (err[i] < -MAXERR) err[i] = -MAXERR;
#endif
                     err[i] += cs[x][i];
                     if (err[i] < 0) err[i] = 0;
                     else if (err[i] > 255) err[i] = 255;
              }
              bs[x] = cndx(err);
              for (i = 0; i < 3; i++) {   /* propagate error */
                     err[i] -= clrtab[bs[x]][i];
                     err[i] /= 3;
                     cerr[x][i] = err[i] + errp[i];
              }
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void map_colrs ( register BYTE bs,
register COLR cs,
register int  n 
)

Definition at line 116 of file clrtab.c.

{
       while (n-- > 0) {
              *bs++ = cndx(cs[0]);
              cs++;
       }
}

Here is the caller graph for this function:

int map_pixel ( register BYTE  col[])

Definition at line 107 of file clrtab.c.

{
    return(cndx(col));
}

Here is the caller graph for this function:

static void mktabent ( int  p,
int  box[3][2] 
) [static]

Here is the caller graph for this function:

static void mktabent ( int  p,
register int  box[3][2] 
) [static]

Definition at line 266 of file clrtab.c.

{
       unsigned long sum[3];
       unsigned      r, g;
       unsigned long n;
       register unsigned    b, c;
                                          /* sum pixels in box */
       n = 0;
       sum[RED] = sum[GRN] = sum[BLU] = 0;
       for (r = box[RED][0]; r < box[RED][1]; r++)
           for (g = box[GRN][0]; g < box[GRN][1]; g++)
              for (b = box[BLU][0]; b < box[BLU][1]; b++) {
                  if ( (c = histo[r][g][b]) ) {
                     n += c;
                     sum[RED] += (long)c*r;
                     sum[GRN] += (long)c*g;
                     sum[BLU] += (long)c*b;
                  }
                  histo[r][g][b] = p;            /* assign pixel */
              }
       if (n >= (1L<<23)/HMAX) {          /* avoid overflow */
              sum[RED] /= n;
              sum[GRN] /= n;
              sum[BLU] /= n;
              n = 1;
       }
       if (n) {                           /* compute average */
              clrtab[p][RED] = sum[RED]*256/NRED/n;
              clrtab[p][GRN] = sum[GRN]*256/NGRN/n;
              clrtab[p][BLU] = sum[BLU]*256/NBLU/n;
       } else {                           /* empty box -- use midpoint */
              clrtab[p][RED] = (box[RED][0]+box[RED][1])*256/NRED/2;
              clrtab[p][GRN] = (box[GRN][0]+box[GRN][1])*256/NGRN/2;
              clrtab[p][BLU] = (box[BLU][0]+box[BLU][1])*256/NBLU/2;
       }
}
int new_clrtab ( int  ncolors)

Definition at line 86 of file clrtab.c.

{
       if (ncolors < 1)
              return(0);
       if (ncolors > 256)
              ncolors = 256;
                            /* partition color space */
       cut(CLRCUBE, 0, ncolors);
#ifdef CLOSEST
       closest(ncolors);    /* ensure colors picked are closest */
#endif
                            /* reset dithering function */
       dith_colrs((BYTE *)NULL, (COLR *)NULL, 0);
                            /* return new color table size */
       return(ncolors);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int new_histo ( int  n)

Definition at line 54 of file clrtab.c.

{
       memset((void *)histo, '\0', sizeof(histo));
       return(0);
}

Here is the caller graph for this function:

static void setclosest ( BYTE nl[],
int  r,
int  g,
int  b 
) [static]

Definition at line 402 of file clrtab.c.

{
       int    ident;
       unsigned      min;
       register unsigned    d;
       register BYTE *p;
                                   /* get starting value */
       min = dist(clrtab[ident=histo[r][g][b]], r, g, b);
                                   /* find minimum */
       for (p = nl[ident]; *p != ident; p++)
              if ((d = dist(clrtab[*p], r, g, b)) < min) {
                     min = d;
                     histo[r][g][b] = *p;
              }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int split ( int  box[3][2]) [static]
static int split ( register int  box[3][2]) [static]

Definition at line 207 of file clrtab.c.

{
#define c0    r
       register int  r, g, b;
       int    pri;
       long   t[HMAX], med;
                                   /* find dominant axis */
       pri = RED;
       if (box[GRN][1]-box[GRN][0] > box[pri][1]-box[pri][0])
              pri = GRN;
       if (box[BLU][1]-box[BLU][0] > box[pri][1]-box[pri][0])
              pri = BLU;
                                   /* sum histogram over box */
       med = 0;
       switch (pri) {
       case RED:
              for (r = box[RED][0]; r < box[RED][1]; r++) {
                     t[r] = 0;
                     for (g = box[GRN][0]; g < box[GRN][1]; g++)
                            for (b = box[BLU][0]; b < box[BLU][1]; b++)
                                   t[r] += histo[r][g][b];
                     med += t[r];
              }
              break;
       case GRN:
              for (g = box[GRN][0]; g < box[GRN][1]; g++) {
                     t[g] = 0;
                     for (b = box[BLU][0]; b < box[BLU][1]; b++)
                            for (r = box[RED][0]; r < box[RED][1]; r++)
                                   t[g] += histo[r][g][b];
                     med += t[g];
              }
              break;
       case BLU:
              for (b = box[BLU][0]; b < box[BLU][1]; b++) {
                     t[b] = 0;
                     for (r = box[RED][0]; r < box[RED][1]; r++)
                            for (g = box[GRN][0]; g < box[GRN][1]; g++)
                                   t[b] += histo[r][g][b];
                     med += t[b];
              }
              break;
       }
       if (med < MINSAMP)          /* if too sparse, split at midpoint */
              return(set_branch(pri,(box[pri][0]+box[pri][1])>>1));
                                   /* find median position */
       med >>= 1;
       for (c0 = box[pri][0]; med > 0; c0++)
              med -= t[c0];
       if (c0 > (box[pri][0]+box[pri][1])>>1)    /* if past the midpoint */
              c0--;                       /* part left of median */
       return(set_branch(pri,c0));
#undef c0
}

Variable Documentation

int CLRCUBE[3][2] = {{0,NRED},{0,NGRN},{0,NBLU}} [static]

Definition at line 33 of file clrtab.c.

BYTE clrtab[256][3]

Definition at line 26 of file ra_gif.c.

unsigned histo[NRED][NGRN][NBLU] [static]

Definition at line 30 of file clrtab.c.

const char RCSid[] = "$Id: clrtab.c,v 2.18 2005/09/19 02:23:58 greg Exp $" [static]

Definition at line 2 of file clrtab.c.