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

Generated on Mon Jul 28 01:25:41 2014 for Hugintrunk by  doxygen 1.3.9.1