Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages
hugin_base/vigra_ext/lut.h
Go to the documentation of this file.00001 // -*- c-basic-offset: 4 -*- 00024 #ifndef _VIGRA_EXT_LUT_H 00025 #define _VIGRA_EXT_LUT_H 00026 00027 #include <vector> 00028 #include <functional> 00029 00030 #include <hugin_math/hugin_math.h> 00031 00032 #include <vigra/stdimage.hxx> 00033 #include <vigra/numerictraits.hxx> 00034 //#include <vigra/transformimage.hxx> 00035 //#include <vigra/combineimages.hxx> 00036 //#include <vigra/functorexpression.hxx> 00037 #include <vigra/array_vector.hxx> 00038 00039 #include <vigra_ext/utils.h> 00040 #include <vigra_ext/HDRUtils.h> 00041 #include <vigra_ext/emor.h> 00042 //#include <boost/random/mersenne_twister.hpp> 00043 00044 00045 //#define DEBUG_WRITE_FILES 00046 00047 namespace vigra_ext{ 00048 00049 template <class VECTOR> 00050 inline void createGammaLUT(double gamma, VECTOR & lut) 00051 { 00052 typedef typename VECTOR::value_type VT; 00053 VT s = vigra_ext::LUTTraits<VT>::max(); 00054 00055 // lookup tables 00056 for (size_t i=0; i<lut.size(); ++i) { 00057 double x = i*1.0/(lut.size() -1); 00058 lut[i] = vigra::NumericTraits<VT>::fromRealPromote(pow(x, gamma)*s); 00059 } 00060 } 00061 00062 00063 template <class VEC, class VEC2> 00064 void resizeLUT(const VEC & iLUT, VEC2 & oLUT) 00065 { 00066 assert(iLUT.size()); 00067 assert(oLUT.size()); 00068 00069 for(size_t oIdx = 0; oIdx < oLUT.size(); oIdx++) { 00070 double ix = oIdx/(oLUT.size()-1.0) * (iLUT.size()-1); 00071 unsigned iIdx = unsigned(ix); 00072 double deltaix = ix-iIdx; 00073 if (deltaix == 0.0) { 00074 // no interpolation required. 00075 oLUT[oIdx] = iLUT[iIdx]; 00076 } else if (iIdx+1 <= iLUT.size()){ 00077 // linear interpolation 00078 oLUT[oIdx] = (1-deltaix) * iLUT[iIdx] + deltaix * iLUT[iIdx+1]; 00079 } else { 00080 oLUT[oIdx] = iLUT.back(); 00081 } 00082 } 00083 } 00084 00086 template <class LUT> 00087 void enforceMonotonicity(LUT & lut) 00088 { 00089 typedef typename LUT::value_type lut_type; 00090 int lutsize = lut.size(); 00091 00092 if (lutsize) { 00093 lut_type max = lut.back(); 00094 for (int j=0; j < lutsize-1; j++) 00095 { 00096 if (lut[j+1] > max) { 00097 lut[j+1] = max; 00098 } else if (lut[j+1] < lut[j]) { 00099 lut[j+1] = lut[j]; 00100 } 00101 } 00102 } 00103 } 00104 00117 template <class VTIn, class LUT> 00118 struct LUTFunctor 00119 { 00120 typedef typename vigra_ext::ValueTypeTraits<VTIn>::value_type VT1; 00121 00124 //typedef VT1 first_argument_type; 00125 00126 typedef typename LUT::value_type lut_type; 00127 00130 //typedef typename vigra::NumericTraits<VT1>::RealPromote result_type; 00131 00132 LUTFunctor() 00133 { 00134 00135 } 00136 00138 LUTFunctor(LUT & lut) 00139 : m_lut(lut) 00140 { 00141 /* 00142 if (sizeof(VT1) ==1) 00143 assert(m_lut.size() >= 256); 00144 else 00145 assert(m_lut.size() >= 1<<10); 00146 */ 00147 } 00148 00149 lut_type applyLutInteger(VT1 v) const 00150 { 00151 // lut type. 00152 assert(m_lut.size() > 0); 00153 if (m_lut.size() == LUTTraits<VT1>::max()) { 00154 return m_lut[v]; 00155 } else { 00156 // calculate new index 00157 double m = LUTTraits<VT1>::max(); 00158 double x=v/m*(m_lut.size()-1); 00159 unsigned i = unsigned(x); 00160 x = x-i; 00161 if ( x != 0 && i+1 < m_lut.size()) { 00162 // linear interpolation 00163 return ((1-x)*m_lut[i]+x*m_lut[i+1]); 00164 } else { 00165 return m_lut[i]; 00166 } 00167 } 00168 } 00169 00170 lut_type applyLutFloat(double v) const 00171 { 00172 assert(m_lut.size() > 0); 00173 if (v > 1) return m_lut.back(); 00174 if (v < 0) return 0; 00175 double x=v*(m_lut.size()-1); 00176 unsigned i = unsigned(x); 00177 // interpolate 00178 x = x-i; 00179 if ( i+1 < m_lut.size()) { 00180 // linear interpolation 00181 return vigra::NumericTraits<lut_type>::fromRealPromote((1-x)*m_lut[i]+x*m_lut[i+1]); 00182 } else { 00183 return m_lut[i]; 00184 } 00185 } 00186 00187 // lookup on floating point values, interpolate if nessecary 00188 vigra::RGBValue<lut_type> applyVector( vigra::RGBValue<VT1> v, vigra::VigraFalseType) const 00189 { 00190 vigra::RGBValue<VT1> ret; 00191 for (size_t i=0; i < v.size(); i++) { 00192 ret[i] = applyLutFloat((v[i])); 00193 } 00194 return ret; 00195 } 00196 00197 // lookup vector types (the lut needs to be long enought!) 00198 vigra::RGBValue<lut_type> applyVector(vigra::RGBValue<VT1> v, vigra::VigraTrueType) const 00199 { 00200 assert(m_lut.size() > 0); 00201 vigra::RGBValue<lut_type> ret; 00202 for (size_t i=0; i < v.size(); i++) { 00203 ret[i] = applyLutInteger(v[i]); 00204 } 00205 return ret; 00206 } 00207 00208 // lookup floating point types 00209 lut_type applyScalar(VT1 v, vigra::VigraFalseType) const 00210 { 00211 return applyLutFloat(v); 00212 } 00213 00214 // lookup scalar types 00215 lut_type applyScalar(VT1 v, vigra::VigraTrueType) const 00216 { 00217 return applyLutInteger(v); 00218 } 00219 00220 lut_type apply(VT1 v, vigra::VigraTrueType) const 00221 { 00222 typedef typename vigra::NumericTraits<VT1>::isIntegral isIntegral; 00223 return applyScalar(v, isIntegral()); 00224 } 00225 00226 vigra::RGBValue<lut_type> apply(vigra::RGBValue<VT1> v, vigra::VigraFalseType) const 00227 { 00228 typedef typename vigra::NumericTraits<VT1>::isIntegral isIntegral; 00229 return applyVector(v, isIntegral()); 00230 } 00231 00232 template <class T> 00233 typename vigra::NumericTraits<T>::RealPromote operator()(T v) const 00234 { 00235 typedef typename vigra::NumericTraits<T>::isScalar is_scalar; 00236 return apply(v, is_scalar()); 00237 } 00238 00239 LUT m_lut; 00240 }; 00241 00251 template <class VT1, class LUT> 00252 struct InvLUTFunctor 00253 { 00256 //typedef VT1 first_argument_type; 00257 00258 typedef typename LUT::value_type lut_type; 00259 00262 //typedef typename vigra::NumericTraits<VT1>::RealPromote result_type; 00263 00264 InvLUTFunctor() 00265 { 00266 } 00267 00269 InvLUTFunctor(LUT & lut) 00270 : m_lut(lut) 00271 { 00272 } 00273 00274 // assume float is scaled 0..1 00275 lut_type applyLutFloat(lut_type v) const 00276 { 00277 assert(m_lut.size() > 0); 00278 if (v >= m_lut.back()) return m_lut.back(); 00279 if (v < m_lut[0]) return 0; 00280 00281 // find the lower bound, p will point to the first *p >= v 00282 typename LUT::const_iterator p = lower_bound(m_lut.begin(), m_lut.end(), v); 00283 00284 00285 int x = p-m_lut.begin(); 00286 #ifdef DEBUG 00287 // just for usage in the debugger 00288 //const lut_type *plut = &(*(m_lut.begin())); 00289 #endif 00290 if (v == 1) { 00291 return 1; 00292 } else if (x == 0) { 00293 return 0; 00294 } else if (v == *p) { 00295 return x/(m_lut.size()-1.0); 00296 } else { 00297 // interpolate position. 00298 // p points to the first element > v 00299 double lower = *(p-1); 00300 double upper = *(p); 00301 lut_type delta = (v - lower) / (upper - lower); 00302 return (x-1 + delta) / (m_lut.size()-1.0); 00303 } 00304 00305 } 00306 00307 template <class T> 00308 lut_type applyLutInteger(T i) const 00309 { 00310 return applyLutFloat(i / lut_type(vigra::NumericTraits<T>::max())); 00311 } 00312 00313 // lookup on floating point values. convert to 16 bit 00314 // and use lookup table there. 00315 template <class T> 00316 vigra::RGBValue<lut_type> applyVector( vigra::RGBValue<T> v, vigra::VigraFalseType) const 00317 { 00318 vigra::RGBValue<VT1> ret; 00319 for (size_t i=0; i < v.size(); i++) { 00320 ret[i] = applyLutFloat((v[i])); 00321 } 00322 return ret; 00323 } 00324 00325 template <class T> 00326 vigra::RGBValue<lut_type> applyVector(vigra::RGBValue<T> v, vigra::VigraTrueType) const 00327 { 00328 vigra::RGBValue<lut_type> ret; 00329 for (size_t i=0; i < v.size(); i++) { 00330 ret[i] = applyLutInteger(v[i]); 00331 } 00332 return ret; 00333 } 00334 00335 // lookup integers, 00336 template <class T> 00337 lut_type applyScalar(T v, vigra::VigraFalseType) const 00338 { 00339 return applyLutFloat(v); 00340 } 00341 00342 // lookup scalar types (the lut needs to be long enought!) 00343 template <class T> 00344 lut_type applyScalar(T v, vigra::VigraTrueType) const 00345 { 00346 return applyLutInteger(v); 00347 } 00348 00349 template <class T> 00350 lut_type apply(T v, vigra::VigraTrueType) const 00351 { 00352 typedef typename vigra::NumericTraits<T>::isIntegral isIntegral; 00353 return applyScalar(v, isIntegral()); 00354 } 00355 00356 template <class T> 00357 vigra::RGBValue<lut_type> apply(vigra::RGBValue<T> v, vigra::VigraFalseType) const 00358 { 00359 typedef typename vigra::NumericTraits<T>::isIntegral isIntegral; 00360 return applyVector(v, isIntegral()); 00361 } 00362 00363 template <class T> 00364 typename vigra::NumericTraits<T>::RealPromote operator()(T v) const 00365 { 00366 typedef typename vigra::NumericTraits<T>::isScalar is_scalar; 00367 return apply(v, is_scalar()); 00368 } 00369 00370 LUT m_lut; 00371 }; 00372 00375 template <class OP> 00376 struct ExposureResponseFunctor 00377 { 00378 ExposureResponseFunctor(double exposure, OP & operation) 00379 : op(operation), e(exposure) 00380 { 00381 e=exposure; 00382 op = operation; 00383 } 00384 OP op; 00385 double e; 00386 00387 template <class VT> 00388 typename vigra::NumericTraits<VT>::RealPromote 00389 operator()(VT v) 00390 { 00391 return op(v*e); 00392 } 00393 }; 00394 00395 } // namespace 00396 00397 #endif // _H
1.3.9.1