Back to index

radiance  4R0+20100331
colrops.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: colrops.c,v 2.11 2003/07/30 10:11:06 schorsch Exp $";
00003 #endif
00004 /*
00005  * Integer operations on COLR scanlines
00006  */
00007 
00008 #include "copyright.h"
00009 
00010 #include <stdio.h>
00011 #include <math.h>
00012 
00013 #include "rtmisc.h"
00014 #include "color.h"
00015 
00016 
00017 #define MAXGSHIFT    31            /* maximum shift for gamma table */
00018 
00019 static BYTE   *g_mant = NULL, *g_nexp = NULL;
00020 
00021 static BYTE   (*g_bval)[256] = NULL;
00022 
00023 
00024 int
00025 setcolrcor(f, a2)           /* set brightness correction */
00026 double (*f)(double,double);
00027 double a2;
00028 {
00029        double mult;
00030        register int  i, j;
00031                                    /* allocate tables */
00032        if (g_bval == NULL && (g_bval =
00033                      (BYTE (*)[256])bmalloc((MAXGSHIFT+1)*256)) == NULL)
00034               return(-1);
00035                                    /* compute colr -> gamb mapping */
00036        mult = 1.0/256.0;
00037        for (i = 0; i <= MAXGSHIFT; i++) {
00038               for (j = 0; j < 256; j++)
00039                      g_bval[i][j] = 256.0 * (*f)((j+.5)*mult, a2);
00040               mult *= 0.5;
00041        }
00042        return(0);
00043 }
00044 
00045 
00046 int
00047 setcolrinv(f, a2)           /* set inverse brightness correction */
00048 double (*f)(double,double);
00049 double a2;
00050 {
00051        double mult;
00052        register int  i, j;
00053                                    /* allocate tables */
00054        if (g_mant == NULL && (g_mant = (BYTE *)bmalloc(256)) == NULL)
00055               return(-1);
00056        if (g_nexp == NULL && (g_nexp = (BYTE *)bmalloc(256)) == NULL)
00057               return(-1);
00058                                    /* compute gamb -> colr mapping */
00059        i = 0;
00060        mult = 256.0;
00061        for (j = 256; j--; ) {
00062               while ((g_mant[j] = mult * (*f)((j+.5)/256.0, a2)) < 128) {
00063                      i++;
00064                      mult *= 2.0;
00065               }
00066               g_nexp[j] = i;
00067        }
00068        return(0);
00069 }
00070 
00071 
00072 int
00073 setcolrgam(g)               /* set gamma conversion */
00074 double g;
00075 {
00076        if (setcolrcor(pow, 1.0/g) < 0)
00077               return(-1);
00078        return(setcolrinv(pow, g));
00079 }
00080 
00081 
00082 int
00083 colrs_gambs(scan, len)             /* convert scanline of colrs to gamma bytes */
00084 register COLR *scan;
00085 int    len;
00086 {
00087        register int  i, expo;
00088 
00089        if (g_bval == NULL)
00090               return(-1);
00091        while (len-- > 0) {
00092               expo = scan[0][EXP] - COLXS;
00093               if (expo < -MAXGSHIFT) {
00094                      if (expo < -MAXGSHIFT-8) {
00095                             scan[0][RED] =
00096                             scan[0][GRN] =
00097                             scan[0][BLU] = 0;
00098                      } else {
00099                             i = (-MAXGSHIFT-1) - expo;
00100                             scan[0][RED] = 
00101                             g_bval[MAXGSHIFT][((scan[0][RED]>>i)+1)>>1];
00102                             scan[0][GRN] =
00103                             g_bval[MAXGSHIFT][((scan[0][GRN]>>i)+1)>>1];
00104                             scan[0][BLU] =
00105                             g_bval[MAXGSHIFT][((scan[0][BLU]>>i)+1)>>1];
00106                      }
00107               } else if (expo > 0) {
00108                      if (expo > 8) {
00109                             scan[0][RED] =
00110                             scan[0][GRN] =
00111                             scan[0][BLU] = 255;
00112                      } else {
00113                             i = (scan[0][RED]<<1 | 1) << (expo-1);
00114                             scan[0][RED] = i > 255 ? 255 : g_bval[0][i];
00115                             i = (scan[0][GRN]<<1 | 1) << (expo-1);
00116                             scan[0][GRN] = i > 255 ? 255 : g_bval[0][i];
00117                             i = (scan[0][BLU]<<1 | 1) << (expo-1);
00118                             scan[0][BLU] = i > 255 ? 255 : g_bval[0][i];
00119                      }
00120               } else {
00121                      scan[0][RED] = g_bval[-expo][scan[0][RED]];
00122                      scan[0][GRN] = g_bval[-expo][scan[0][GRN]];
00123                      scan[0][BLU] = g_bval[-expo][scan[0][BLU]];
00124               }
00125               scan[0][EXP] = COLXS;
00126               scan++;
00127        }
00128        return(0);
00129 }
00130 
00131 
00132 int
00133 gambs_colrs(scan, len)             /* convert gamma bytes to colr scanline */
00134 register COLR *scan;
00135 int    len;
00136 {
00137        register int  nexpo;
00138 
00139        if ((g_mant == NULL) | (g_nexp == NULL))
00140               return(-1);
00141        while (len-- > 0) {
00142               nexpo = g_nexp[scan[0][RED]];
00143               if (g_nexp[scan[0][GRN]] < nexpo)
00144                      nexpo = g_nexp[scan[0][GRN]];
00145               if (g_nexp[scan[0][BLU]] < nexpo)
00146                      nexpo = g_nexp[scan[0][BLU]];
00147               if (nexpo < g_nexp[scan[0][RED]])
00148                      scan[0][RED] = g_mant[scan[0][RED]]
00149                                    >> (g_nexp[scan[0][RED]]-nexpo);
00150               else
00151                      scan[0][RED] = g_mant[scan[0][RED]];
00152               if (nexpo < g_nexp[scan[0][GRN]])
00153                      scan[0][GRN] = g_mant[scan[0][GRN]]
00154                                    >> (g_nexp[scan[0][GRN]]-nexpo);
00155               else
00156                      scan[0][GRN] = g_mant[scan[0][GRN]];
00157               if (nexpo < g_nexp[scan[0][BLU]])
00158                      scan[0][BLU] = g_mant[scan[0][BLU]]
00159                                    >> (g_nexp[scan[0][BLU]]-nexpo);
00160               else
00161                      scan[0][BLU] = g_mant[scan[0][BLU]];
00162               scan[0][EXP] = COLXS - nexpo;
00163               scan++;
00164        }
00165        return(0);
00166 }
00167 
00168 
00169 void
00170 shiftcolrs(scan, len, adjust)      /* shift a scanline of colors by 2^adjust */
00171 register COLR *scan;
00172 register int  len;
00173 register int  adjust;
00174 {
00175        int    minexp;
00176 
00177        if (adjust == 0)
00178               return;
00179        minexp = adjust < 0 ? -adjust : 0;
00180        while (len-- > 0) {
00181               if (scan[0][EXP] <= minexp)
00182                      scan[0][RED] = scan[0][GRN] = scan[0][BLU] =
00183                      scan[0][EXP] = 0;
00184               else
00185                      scan[0][EXP] += adjust;
00186               scan++;
00187        }
00188 }
00189 
00190 
00191 void
00192 normcolrs(scan, len, adjust)       /* normalize a scanline of colrs */
00193 register COLR  *scan;
00194 int  len;
00195 int  adjust;
00196 {
00197        register int  c;
00198        register int  shift;
00199 
00200        while (len-- > 0) {
00201               shift = scan[0][EXP] + adjust - COLXS;
00202               if (shift > 0) {
00203                      if (shift > 8) {
00204                             scan[0][RED] =
00205                             scan[0][GRN] =
00206                             scan[0][BLU] = 255;
00207                      } else {
00208                             shift--;
00209                             c = (scan[0][RED]<<1 | 1) << shift;
00210                             scan[0][RED] = c > 255 ? 255 : c;
00211                             c = (scan[0][GRN]<<1 | 1) << shift;
00212                             scan[0][GRN] = c > 255 ? 255 : c;
00213                             c = (scan[0][BLU]<<1 | 1) << shift;
00214                             scan[0][BLU] = c > 255 ? 255 : c;
00215                      }
00216               } else if (shift < 0) {
00217                      if (shift < -8) {
00218                             scan[0][RED] =
00219                             scan[0][GRN] =
00220                             scan[0][BLU] = 0;
00221                      } else {
00222                             shift = -1-shift;
00223                             scan[0][RED] = ((scan[0][RED]>>shift)+1)>>1;
00224                             scan[0][GRN] = ((scan[0][GRN]>>shift)+1)>>1;
00225                             scan[0][BLU] = ((scan[0][BLU]>>shift)+1)>>1;
00226                      }
00227               }
00228               scan[0][EXP] = COLXS - adjust;
00229               scan++;
00230        }
00231 }