|
Blender
V2.59
|
00001 /* 00002 * Jitter offset table 00003 * 00004 * $Id: gammaCorrectionTables.c 35233 2011-02-27 19:31:27Z jesterking $ 00005 * 00006 * ***** BEGIN GPL LICENSE BLOCK ***** 00007 * 00008 * This program is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU General Public License 00010 * as published by the Free Software Foundation; either version 2 00011 * of the License, or (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software Foundation, 00020 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00021 * 00022 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00023 * All rights reserved. 00024 * 00025 * The Original Code is: all of this file. 00026 * 00027 * Contributor(s): none yet. 00028 * 00029 * ***** END GPL LICENSE BLOCK ***** 00030 */ 00031 00037 #include "gammaCorrectionTables.h" 00038 #include <stdlib.h> 00039 #include <math.h> 00040 00041 /* WARNING; optimized, cannot be used to do gamma(invgamma()) and expect */ 00042 /* result remain identical (ton) */ 00043 00044 /* gamma is only used here for correcting adding colors or alpha */ 00045 #define RE_DEFAULT_GAMMA 2.0 00046 00047 /* This 400 is sort of based on the number of intensity levels needed for */ 00048 /* the typical dynamic range of a medium, in this case CRTs. (Foley) */ 00049 /* (Actually, it says the number should be between 400 and 535.) */ 00050 #define RE_GAMMA_TABLE_SIZE 400 00051 00052 /* These indicate the status of the gamma lookup table --------------------- */ 00053 00054 static float gamma_range_table[RE_GAMMA_TABLE_SIZE + 1]; 00055 static float gamfactor_table[RE_GAMMA_TABLE_SIZE]; 00056 static float inv_gamma_range_table[RE_GAMMA_TABLE_SIZE + 1]; 00057 static float inv_gamfactor_table[RE_GAMMA_TABLE_SIZE]; 00058 static float color_domain_table[RE_GAMMA_TABLE_SIZE + 1]; 00059 static float color_step; 00060 static float inv_color_step; 00061 static float valid_gamma; 00062 static float valid_inv_gamma; 00063 00064 /* ------------------------------------------------------------------------- */ 00065 00066 float gammaCorrect(float c) 00067 { 00068 int i; 00069 float res = 0.0; 00070 00071 i = floor(c * inv_color_step); 00072 /* Clip to range [0,1]: outside, just do the complete calculation. */ 00073 /* We may have some performance problems here. Stretching up the LUT */ 00074 /* may help solve that, by exchanging LUT size for the interpolation. */ 00075 /* Negative colors are explicitly handled. */ 00076 if (i < 0) res = -pow(abs(c), valid_gamma); 00077 else if (i >= RE_GAMMA_TABLE_SIZE ) res = pow(c, valid_gamma); 00078 else res = gamma_range_table[i] + 00079 ( (c - color_domain_table[i]) * gamfactor_table[i]); 00080 00081 return res; 00082 } /* end of float gammaCorrect(float col) */ 00083 00084 /* ------------------------------------------------------------------------- */ 00085 00086 float invGammaCorrect(float col) 00087 { 00088 int i; 00089 float res = 0.0; 00090 00091 i = floor(col*inv_color_step); 00092 /* Negative colors are explicitly handled. */ 00093 if (i < 0) res = -pow(abs(col), valid_inv_gamma); 00094 else if (i >= RE_GAMMA_TABLE_SIZE) res = pow(col, valid_inv_gamma); 00095 else res = inv_gamma_range_table[i] + 00096 ( (col - color_domain_table[i]) * inv_gamfactor_table[i]); 00097 00098 return res; 00099 } /* end of float invGammaCorrect(float col) */ 00100 00101 00102 /* ------------------------------------------------------------------------- */ 00103 00104 void makeGammaTables(float gamma) 00105 { 00106 /* we need two tables: one forward, one backward */ 00107 int i; 00108 00109 valid_gamma = gamma; 00110 valid_inv_gamma = 1.0 / gamma; 00111 color_step = 1.0 / RE_GAMMA_TABLE_SIZE; 00112 inv_color_step = (float) RE_GAMMA_TABLE_SIZE; 00113 00114 /* We could squeeze out the two range tables to gain some memory. */ 00115 for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) { 00116 color_domain_table[i] = i * color_step; 00117 gamma_range_table[i] = pow(color_domain_table[i], 00118 valid_gamma); 00119 inv_gamma_range_table[i] = pow(color_domain_table[i], 00120 valid_inv_gamma); 00121 } 00122 00123 /* The end of the table should match 1.0 carefully. In order to avoid */ 00124 /* rounding errors, we just set this explicitly. The last segment may */ 00125 /* have a different length than the other segments, but our */ 00126 /* interpolation is insensitive to that. */ 00127 color_domain_table[RE_GAMMA_TABLE_SIZE] = 1.0; 00128 gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0; 00129 inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0; 00130 00131 /* To speed up calculations, we make these calc factor tables. They are */ 00132 /* multiplication factors used in scaling the interpolation. */ 00133 for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++ ) { 00134 gamfactor_table[i] = inv_color_step 00135 * (gamma_range_table[i + 1] - gamma_range_table[i]) ; 00136 inv_gamfactor_table[i] = inv_color_step 00137 * (inv_gamma_range_table[i + 1] - inv_gamma_range_table[i]) ; 00138 } 00139 00140 } /* end of void makeGammaTables(float gamma) */ 00141 00142 00143 00144 /* ------------------------------------------------------------------------- */ 00145 00146 /* eof */