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