Panda3D
|
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 }