00001
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
00035
00036
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
00043
00044
00045
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
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
00075 oLUT[oIdx] = iLUT[iIdx];
00076 } else if (iIdx+1 <= iLUT.size()){
00077
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
00125
00126 typedef typename LUT::value_type lut_type;
00127
00130
00131
00132 LUTFunctor()
00133 {
00134
00135 }
00136
00138 LUTFunctor(LUT & lut)
00139 : m_lut(lut)
00140 {
00141
00142
00143
00144
00145
00146
00147 }
00148
00149 lut_type applyLutInteger(VT1 v) const
00150 {
00151
00152 assert(m_lut.size() > 0);
00153 if (m_lut.size() == LUTTraits<VT1>::max()) {
00154 return m_lut[v];
00155 } else {
00156
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
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
00178 x = x-i;
00179 if ( i+1 < m_lut.size()) {
00180
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
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
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
00209 lut_type applyScalar(VT1 v, vigra::VigraFalseType) const
00210 {
00211 return applyLutFloat(v);
00212 }
00213
00214
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
00257
00258 typedef typename LUT::value_type lut_type;
00259
00262
00263
00264 InvLUTFunctor()
00265 {
00266 }
00267
00269 InvLUTFunctor(LUT & lut)
00270 : m_lut(lut)
00271 {
00272 }
00273
00274
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
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
00288
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
00298
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
00314
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
00336 template <class T>
00337 lut_type applyScalar(T v, vigra::VigraFalseType) const
00338 {
00339 return applyLutFloat(v);
00340 }
00341
00342
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 }
00396
00397 #endif // _H