ResponseTransform.h

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00024 #ifndef _PHOTOMETRIC_VIGNETTING_CORRECTION_H
00025 #define _PHOTOMETRIC_VIGNETTING_CORRECTION_H
00026 
00027 #include <vector>
00028 #include <functional>
00029 #include "hugin_config.h"
00030 #ifdef HAVE_CXX11
00031 #include <random>
00032 #define RANDOMGENERATOR std::mt19937
00033 #else
00034 #include <boost/version.hpp>
00035 #if BOOST_VERSION>104700
00036 #include <boost/random/taus88.hpp>
00037 #define RANDOMGENERATOR boost::random::taus88
00038 #else
00039 #include <boost/random/mersenne_twister.hpp>
00040 #define RANDOMGENERATOR boost::mt19937
00041 #endif
00042 #endif
00043 
00044 #include <vigra/stdimage.hxx>
00045 #include <vigra/numerictraits.hxx>
00046 #include <vigra/array_vector.hxx>
00047 
00048 #include <hugin_math/hugin_math.h>
00049 #include <vigra_ext/lut.h>
00050 #include <vigra_ext/utils.h>
00051 #include <panodata/SrcPanoImage.h>
00052 
00053 
00054 namespace HuginBase { namespace Photometric {
00055     
00056 
00062 template <class VTIn>
00063 class ResponseTransform
00064 {
00065         
00066     public:
00068         typedef typename vigra_ext::ValueTypeTraits<VTIn>::value_type VT1;
00069         
00071         typedef std::vector<double> LUT;
00072 
00073         
00074     public:
00076         ResponseTransform();
00077         
00079         ResponseTransform(const HuginBase::SrcPanoImage & src);
00080         
00082         virtual ~ResponseTransform() {};
00083         
00084     private:
00086         void initWithSrcImg(const HuginBase::SrcPanoImage & src);
00087         
00088         
00089     public:
00091         void setFlatfield(const vigra::FImage * flat)
00092         { m_flatfield = flat; }
00093 
00095         double calcVigFactor(hugin_utils::FDiff2D d) const;
00096 
00097                 void enforceMonotonicity()
00098                 {
00099                         vigra_ext::enforceMonotonicity(m_lutR);
00100                 }
00101 
00103         typename vigra::NumericTraits<VT1>::RealPromote
00104             apply(VT1 v, const hugin_utils::FDiff2D & pos, vigra::VigraTrueType) const;
00105         
00107         typename vigra::NumericTraits<VT1>::RealPromote
00108             apply(VT1 v, const hugin_utils::FDiff2D & pos) const;
00109 
00111         typename vigra::NumericTraits<vigra::RGBValue<VT1> >::RealPromote
00112             apply(vigra::RGBValue<VT1> v, const hugin_utils::FDiff2D & pos, vigra::VigraFalseType) const;
00113         
00115         typename vigra::NumericTraits<vigra::RGBValue<VT1> >::RealPromote
00116             apply(vigra::RGBValue<VT1> v, const hugin_utils::FDiff2D & pos) const;
00117         
00118         
00120         template <class T>
00121         typename vigra::NumericTraits<T>::RealPromote
00122             operator()(T v, const hugin_utils::FDiff2D & pos) const { return apply(v, pos); }
00123 
00124         
00125         
00126     public:
00127             
00128         LUT m_lutR;
00129         double m_radiusScale;
00130         vigra_ext::LUTFunctor<VT1, LUT> m_lutRFunc;
00131         const vigra::FImage * m_flatfield;
00132         double m_srcExposure;
00133         std::vector<double> m_RadialVigCorrCoeff;
00134         hugin_utils::FDiff2D m_RadialVigCorrCenter;
00135         int m_VigCorrMode;
00136         double m_WhiteBalanceRed;
00137         double m_WhiteBalanceBlue;
00138 
00139         HuginBase::SrcPanoImage m_src;
00140 };
00141 
00142 
00148 template <class VTIn, class VTOut>
00149 class InvResponseTransform : public ResponseTransform<VTIn>
00150 {
00151 
00152         typedef ResponseTransform<VTIn> Base;
00153      
00154     public:
00155         typedef typename vigra_ext::ValueTypeTraits<VTIn>::value_type VT1;
00156         typedef typename vigra::NumericTraits<VT1>::RealPromote VTInCompReal;
00157         typedef typename vigra_ext::ValueTypeTraits<VTOut>::value_type dest_type;
00158 
00159         typedef std::vector<double> LUT;
00160         typedef std::vector<dest_type> LUTD;
00161 
00162 
00163     public:
00165         InvResponseTransform();
00166 
00168         InvResponseTransform(const HuginBase::SrcPanoImage & src);
00169         
00171         virtual ~InvResponseTransform() {};
00172         
00173     private:
00175         void init(const HuginBase::SrcPanoImage & src);
00176 
00177         
00178     public:
00180         void setHDROutput(bool hdrMode, double destExposure);
00181         
00183         void setOutput(double destExposure, const LUTD & destLut, double scale);
00184         
00185                 void enforceMonotonicity()
00186                 {
00187                     if (Base::m_lutR.size()) {
00188                                 vigra_ext::enforceMonotonicity(Base::m_lutR);
00189                         // todo: invert lut, instead of using this functor?
00190                         m_lutRInvFunc = vigra_ext::InvLUTFunctor<VT1, LUT>(Base::m_lutR);
00191                         }
00192                 }
00193 
00200         double dither(const double &v) const;
00201         
00203         typename vigra::NumericTraits<dest_type>::RealPromote
00204             apply(VT1 v, const hugin_utils::FDiff2D & pos, vigra::VigraTrueType) const;
00205         
00207         typename vigra::NumericTraits<dest_type>::RealPromote
00208             apply(VT1 v, const hugin_utils::FDiff2D & pos) const;
00209         
00211         typename vigra::NumericTraits<vigra::RGBValue<VT1> >::RealPromote
00212             apply(vigra::RGBValue<VT1> v, const hugin_utils::FDiff2D & pos, vigra::VigraFalseType) const;
00213         
00215         typename vigra::NumericTraits<vigra::RGBValue<VT1> >::RealPromote
00216             apply(vigra::RGBValue<VT1> v, const hugin_utils::FDiff2D & pos) const;
00217         
00218         
00220         template <class T>
00221         typename vigra::NumericTraits<T>::RealPromote 
00222             operator()(T v, const hugin_utils::FDiff2D & pos) const
00223         {
00224             return apply(v, pos);
00225         }
00226         
00228         template <class T, class A>
00229         A hdrWeight(T v, A a) const
00230         {
00231             if (m_hdrMode && a > 0) {
00232                 return vigra::NumericTraits<A>::fromRealPromote(vigra_ext::getMaxComponent(v)/(double)vigra_ext::LUTTraits<T>::max()*vigra_ext::LUTTraits<A>::max());
00233             } else {
00234                 return a;
00235             }
00236         }
00237         
00238         void emitGLSL(std::ostringstream& oss, std::vector<double>& invLut, std::vector<double>& destLut) const;
00239 
00240     protected: // needs be public?
00241         //LUT m_lutRInv;
00242         vigra_ext::InvLUTFunctor<VT1, LUT> m_lutRInvFunc;
00243         LUTD m_destLut;
00244         vigra_ext::LUTFunctor<VTInCompReal, LUTD> m_destLutFunc;
00245         double m_destExposure;
00246         bool m_hdrMode;
00247         double m_intScale;
00248         
00249     private:
00250         RANDOMGENERATOR Twister;
00251 };
00252 
00253 
00254 }} // namespace
00255 
00256 
00257 
00258 
00259 // templated implementation ----------------------------------------------------
00260 
00261 
00262 namespace HuginBase { namespace Photometric {
00263 
00264 
00265 template <class VTIn>
00266 ResponseTransform<VTIn>::ResponseTransform()
00267 {
00268     m_radiusScale=0;
00269     m_flatfield = 0;
00270 }
00271 
00272 template <class VTIn>
00273 ResponseTransform<VTIn>::ResponseTransform(const HuginBase::SrcPanoImage & src)
00274 {
00275     initWithSrcImg(src);
00276 }
00277 
00278 
00279 template <class VTIn>
00280 void ResponseTransform<VTIn>::initWithSrcImg(const HuginBase::SrcPanoImage & src)
00281 {
00282 //        DEBUG_DEBUG(" " << src.getFilename() << ": resp type:" <<   src.getResponseType() << " expo: " << src.getExposure());
00283     m_flatfield = 0;
00284     m_src = src;
00285     m_radiusScale = 1.0/sqrt(m_src.getSize().x/2.0*m_src.getSize().x/2.0 + m_src.getSize().y/2.0*m_src.getSize().y/2.0);
00286     m_srcExposure = m_src.getExposure();
00287     //save some variables, direct access is slower since merging of layout mode
00288     m_RadialVigCorrCoeff = m_src.getRadialVigCorrCoeff();
00289     m_RadialVigCorrCenter = m_src.getRadialVigCorrCenter();
00290     m_VigCorrMode = m_src.getVigCorrMode();
00291     m_WhiteBalanceRed = m_src.getWhiteBalanceRed();
00292     m_WhiteBalanceBlue = m_src.getWhiteBalanceBlue();
00293 
00294     // build response function lookup table, if required
00295     if (m_src.getResponseType() != HuginBase::SrcPanoImage::RESPONSE_LINEAR) {
00296         // scale lut to right byte size..
00297         double lutLenD = vigra_ext::LUTTraits<VT1>::max();
00298         // maximum lut size: 10 bits. Should be enought for most purposes.
00299         // and fit into the L1 cache.
00300         size_t lutLen=0;
00301         if (lutLenD == 1.0 || (lutLenD > ((1<<10)-1))) {
00302             lutLen = (1<<10);
00303         } else {
00304             lutLen = size_t(lutLenD) + 1;
00305         }
00306         switch (m_src.getResponseType()) 
00307         {
00308             case HuginBase::SrcPanoImage::RESPONSE_EMOR:
00309                 {
00310                 if (lutLen == 1<<10) {
00311                     vigra_ext::EMoR::createEMoRLUT(m_src.getEMoRParams(), m_lutR);
00312                 } else {
00313                     // resize lut, if size doesn't fit
00314                     LUT tmp;
00315                     vigra_ext::EMoR::createEMoRLUT(m_src.getEMoRParams(), tmp);
00316                     m_lutR.resize(lutLen);
00317                     vigra_ext::resizeLUT(tmp, m_lutR);
00318                 }
00319                 }
00320                 break;
00321             case HuginBase::SrcPanoImage::RESPONSE_GAMMA:
00322                 m_lutR.resize(lutLen);
00323                 vigra_ext::createGammaLUT(m_src.getGamma(), m_lutR);
00324                 break;
00325             default:
00326                 // response curve is stored in src image
00327                 vigra_fail("ResponseTransform: unknown response function type");
00328                 break;
00329         }
00330         m_lutRFunc = vigra_ext::LUTFunctor<VT1, LUT>(m_lutR);
00331     }
00332 }
00333 
00334 
00335 template <class VTIn>
00336 double ResponseTransform<VTIn>::calcVigFactor(hugin_utils::FDiff2D d) const
00337 {
00338     if (m_VigCorrMode & HuginBase::SrcPanoImage::VIGCORR_RADIAL) {
00339         d = d - m_RadialVigCorrCenter;
00340         // scale according to 
00341         d *= m_radiusScale;
00342         double vig = m_RadialVigCorrCoeff[0];
00343         double r2 = d.x*d.x + d.y*d.y;
00344         double r = r2;
00345         for (unsigned int i = 1; i < 4; i++) {
00346             vig += m_RadialVigCorrCoeff[i] * r;
00347             r *= r2;
00348         }
00349         return vig;
00350     } else if (m_VigCorrMode & HuginBase::SrcPanoImage::VIGCORR_FLATFIELD) {
00351         // TODO: implement flatfield
00352         if (m_flatfield) {
00353             int x = std::min(std::max(hugin_utils::roundi(d.x),0), static_cast<int>(m_flatfield->width()-1));
00354             int y = std::min(std::max(hugin_utils::roundi(d.y),0), static_cast<int>(m_flatfield->height()-1));
00355             return (*m_flatfield)(x,y);
00356         } else {
00357             return 1;
00358         }
00359     } else {
00360         return 1;
00361     }
00362 }
00363 
00364 
00365 template <class VTIn>
00366 typename vigra::NumericTraits<typename ResponseTransform<VTIn>::VT1>::RealPromote
00367 ResponseTransform<VTIn>::apply(typename ResponseTransform<VTIn>::VT1 v, const hugin_utils::FDiff2D & pos, vigra::VigraTrueType) const
00368 {
00369     typename vigra::NumericTraits<VT1>::RealPromote ret = v;
00370     // first, apply vignetting
00371 
00372     ret = ret*calcVigFactor(pos)*m_srcExposure;
00373     if (m_lutR.size()) {
00374         return m_lutRFunc(ret);
00375     } else {
00376         return ret;
00377     }
00378 }
00379 
00380 template <class VTIn>
00381 typename vigra::NumericTraits<vigra::RGBValue<typename ResponseTransform<VTIn>::VT1> >::RealPromote
00382 ResponseTransform<VTIn>::apply(vigra::RGBValue<typename ResponseTransform<VTIn>::VT1> v, const hugin_utils::FDiff2D & pos, vigra::VigraFalseType) const
00383 {
00384     typename vigra::NumericTraits<vigra::RGBValue<VT1> >::RealPromote ret = v;
00385     // first, apply vignetting
00386     double common = calcVigFactor(pos)*m_srcExposure;
00387     ret = ret*common;
00388     // apply white balance factors
00389     ret.red() = ret.red() * m_WhiteBalanceRed;
00390     ret.blue() = ret.blue() * m_WhiteBalanceBlue;
00391     // apply response curve
00392     if (m_lutR.size()) {
00393         return m_lutRFunc(ret);
00394     } else {
00395         return ret;
00396     }
00397 }
00398 
00399 template <class VTIn>
00400 typename vigra::NumericTraits<typename ResponseTransform<VTIn>::VT1>::RealPromote
00401 ResponseTransform<VTIn>::apply(typename ResponseTransform<VTIn>::VT1 v, const hugin_utils::FDiff2D & pos) const
00402 {
00403     typedef typename vigra::NumericTraits<VT1>::isScalar is_scalar;
00404     return apply(v, pos, is_scalar());
00405 }
00406 
00407 template <class VTIn>
00408 typename vigra::NumericTraits<vigra::RGBValue<typename ResponseTransform<VTIn>::VT1> >::RealPromote
00409 ResponseTransform<VTIn>::apply(vigra::RGBValue<typename ResponseTransform<VTIn>::VT1> v, const hugin_utils::FDiff2D & pos) const
00410 {
00411     typedef typename vigra::NumericTraits<vigra::RGBValue<VT1> >::isScalar is_scalar;
00412     return apply(v, pos, is_scalar());
00413 }
00414 
00415 template <class VTIn, class VTOut>
00416 InvResponseTransform<VTIn,VTOut>::InvResponseTransform()
00417 {
00418     m_destExposure = 1.0;
00419     m_hdrMode = false;
00420     m_intScale = 1;
00421 }
00422 
00423 template <class VTIn, class VTOut>
00424 InvResponseTransform<VTIn,VTOut>::InvResponseTransform(const HuginBase::SrcPanoImage & src)
00425 : Base(src), m_hdrMode(false)
00426 {
00427     m_destExposure = 1.0;
00428     m_intScale = 1;
00429     if (Base::m_lutR.size()) {
00430         // todo: invert lut, instead of using this functor?
00431         m_lutRInvFunc = vigra_ext::InvLUTFunctor<VT1, LUT>(Base::m_lutR);
00432     }
00433 }
00434 
00435 template <class VTIn, class VTOut>
00436 void InvResponseTransform<VTIn,VTOut>::init(const HuginBase::SrcPanoImage & src)
00437 {
00438     m_destExposure = 1.0;
00439     m_intScale = 1;
00440     Base::init(src);
00441     if (Base::m_lutR.size()) {
00442         // todo: invert lut, instead of using this functor?
00443         m_lutRInvFunc = vigra_ext::InvLUTFunctor<VT1, LUT>(Base::m_lutR);
00444     }
00445 }
00446 
00447 template <class VTIn, class VTOut>
00448 void InvResponseTransform<VTIn,VTOut>::setHDROutput(bool hdrMode, double destExposure)
00449 {
00450     m_hdrMode = hdrMode;
00451     m_intScale = 1;
00452     m_destExposure = destExposure;
00453     m_destLut.clear();
00454 }
00455 
00456 template <class VTIn, class VTOut>
00457 void InvResponseTransform<VTIn,VTOut>::setOutput(double destExposure, const LUTD & destLut, double scale)
00458 {
00459     m_hdrMode = false;
00460     m_destLut = destLut;
00461     if (m_destLut.size() > 0) {
00462         m_destLutFunc = vigra_ext::LUTFunctor<VTInCompReal, LUTD>(m_destLut);
00463     }
00464     m_destExposure = destExposure;
00465     m_intScale = scale;
00466 }
00467 
00468 
00469 template <class VTIn, class VTOut>
00470 double InvResponseTransform<VTIn,VTOut>::dither(const double &v) const
00471 {
00472     RANDOMGENERATOR &mt = const_cast<RANDOMGENERATOR &>(Twister);
00473     double vFraction = v - floor(v);
00474     // Only dither values within a certain range of the rounding cutoff point.
00475     if (vFraction > 0.25 && vFraction <= 0.75) {
00476         // Generate a random number between 0 and 0.5.
00477         double random = 0.5 * (double)mt() / UINT_MAX;
00478         if ((vFraction - 0.25) >= random) {
00479             return ceil(v);
00480         } else {
00481             return floor(v);
00482         }
00483     } else {
00484         return v;
00485     }
00486 }
00487 
00488 
00489 template <class VTIn, class VTOut>
00490 typename vigra::NumericTraits<typename InvResponseTransform<VTIn,VTOut>::dest_type>::RealPromote
00491 InvResponseTransform<VTIn,VTOut>::apply(VT1 v, const hugin_utils::FDiff2D & pos, vigra::VigraTrueType) const
00492 {
00493     // inverse response
00494     typename vigra::NumericTraits<VT1>::RealPromote ret(v);
00495     if (Base::m_lutR.size()) {
00496         ret = m_lutRInvFunc(v);
00497     } else {
00498         ret /= vigra_ext::LUTTraits<VT1>::max();
00499     }
00500     // inverse vignetting and exposure
00501     ret *= m_destExposure / (Base::calcVigFactor(pos) * Base::m_srcExposure);
00502     // apply output transform if required
00503     if (m_destLut.size() > 0) {
00504         ret = m_destLutFunc(ret);
00505     }
00506     // dither all integer images
00507     if ( m_intScale > 1) {
00508         return dither(ret * m_intScale);
00509     }
00510     return ret;
00511 }
00512 
00513 
00514 template <class VTIn, class VTOut>
00515 typename vigra::NumericTraits<vigra::RGBValue<typename InvResponseTransform<VTIn,VTOut>::VT1> >::RealPromote
00516 InvResponseTransform<VTIn,VTOut>::apply(vigra::RGBValue<VT1> v, const hugin_utils::FDiff2D & pos, vigra::VigraFalseType) const
00517 {
00518     typename vigra::NumericTraits<vigra::RGBValue<VT1> >::RealPromote ret(v);
00519     if (Base::m_lutR.size()) {
00520         ret = m_lutRInvFunc(v);
00521     } else {
00522         ret /= vigra_ext::LUTTraits<VT1>::max();
00523     }
00524 
00525     // inverse vignetting and exposure
00526     ret *= m_destExposure/(Base::calcVigFactor(pos)*Base::m_srcExposure);
00527     ret.red() /= Base::m_WhiteBalanceRed;
00528     ret.blue() /= Base::m_WhiteBalanceBlue;
00529     // apply output transform if required
00530     if (m_destLut.size() > 0) {
00531         ret = m_destLutFunc(ret);
00532     }
00533     // dither 8 bit images.
00534     if (m_intScale > 1) {
00535         for (size_t i=0; i < 3; i++) {
00536             ret[i] = dither(ret[i] * m_intScale);
00537         }
00538     }
00539     return ret;
00540 }
00541 
00542 
00543 template <class VTIn, class VTOut>
00544 typename vigra::NumericTraits<typename InvResponseTransform<VTIn,VTOut>::dest_type>::RealPromote
00545 InvResponseTransform<VTIn,VTOut>::apply(VT1 v, const hugin_utils::FDiff2D & pos) const
00546 {
00547     typedef typename vigra::NumericTraits<VT1>::isScalar is_scalar;
00548     return apply(v, pos, is_scalar());
00549 }
00550 
00551 template <class VTIn, class VTOut>
00552 typename vigra::NumericTraits<vigra::RGBValue<typename InvResponseTransform<VTIn,VTOut>::VT1> >::RealPromote
00553 InvResponseTransform<VTIn,VTOut>::apply(vigra::RGBValue<VT1> v, const hugin_utils::FDiff2D & pos) const
00554 {
00555     typedef typename vigra::NumericTraits<vigra::RGBValue<VT1> >::isScalar is_scalar;
00556     return apply(v, pos, is_scalar());
00557 }
00558 
00559 template <class VTIn, class VTOut>
00560 void
00561 InvResponseTransform<VTIn,VTOut>::emitGLSL(std::ostringstream& oss, std::vector<double>& invLut, std::vector<double>& destLut) const
00562 {
00563     invLut.clear();
00564     invLut.reserve(Base::m_lutR.size());
00565 
00566     for (int i = 0; i < Base::m_lutR.size(); i++) {
00567         double f = static_cast<double>(i) / (Base::m_lutR.size() - 1);
00568         double v = m_lutRInvFunc(f);
00569         invLut.push_back(v);
00570     }
00571         
00572     destLut.clear();
00573     destLut.reserve(m_destLut.size());
00574 
00575     for (typename LUTD::const_iterator lutI = m_destLut.begin(); lutI != m_destLut.end(); ++lutI) {
00576         typename LUTD::value_type entry = *lutI;
00577         destLut.push_back(entry);
00578     }
00579 
00580     double invLutSize = Base::m_lutR.size();
00581     double pixelMax = vigra_ext::LUTTraits<VT1>::max();
00582     double destLutSize = m_destLut.size();
00583 
00584     oss << "    // invLutSize = " << invLutSize << endl
00585         << "    // pixelMax = " << pixelMax << endl
00586         << "    // destLutSize = " << destLutSize << endl
00587         << "    // destExposure = " << m_destExposure << endl
00588         << "    // srcExposure = " << Base::m_srcExposure << endl
00589         << "    // whiteBalanceRed = " << Base::m_src.getWhiteBalanceRed() << endl
00590         << "    // whiteBalanceBlue = " << Base::m_src.getWhiteBalanceBlue() << endl;
00591 
00592     if (Base::m_lutR.size() > 0) {
00593         oss << "    p.rgb = p.rgb * " << (invLutSize - 1.0) << ";" << endl
00594             << "    vec2 invR = texture2DRect(InvLutTexture, vec2(p.r, 0.0)).sq;" << endl
00595             << "    vec2 invG = texture2DRect(InvLutTexture, vec2(p.g, 0.0)).sq;" << endl
00596             << "    vec2 invB = texture2DRect(InvLutTexture, vec2(p.b, 0.0)).sq;" << endl
00597             << "    vec3 invX = vec3(invR.x, invG.x, invB.x);" << endl
00598             << "    vec3 invY = vec3(invR.y, invG.y, invB.y);" << endl
00599             << "    vec3 invA = fract(p.rgb);" << endl
00600             << "    p.rgb = mix(invX, invY, invA);" << endl;
00601     }
00602 
00603     if (Base::m_src.getVigCorrMode() & HuginBase::SrcPanoImage::VIGCORR_RADIAL) {
00604         oss << "    // VigCorrMode=VIGCORR_RADIAL" << endl
00605             << "    float vig = 1.0;" << endl
00606             << "    {" << endl
00607             << "        vec2 vigCorrCenter = vec2(" << Base::m_src.getRadialVigCorrCenter().x << ", "
00608             << Base::m_src.getRadialVigCorrCenter().y << ");" << endl
00609             << "        float radiusScale=" << Base::m_radiusScale << ";" << endl
00610             << "        float radialVigCorrCoeff0 = " << Base::m_src.getRadialVigCorrCoeff()[0] << ";" << endl
00611             << "        float radialVigCorrCoeff1 = " << Base::m_src.getRadialVigCorrCoeff()[1] << ";" << endl
00612             << "        float radialVigCorrCoeff2 = " << Base::m_src.getRadialVigCorrCoeff()[2] << ";" << endl
00613             << "        float radialVigCorrCoeff3 = " << Base::m_src.getRadialVigCorrCoeff()[3] << ";" << endl
00614             << "        vec2 src = texture2DRect(CoordTexture, gl_TexCoord[0].st).sq;" << endl
00615             << "        vec2 d = src - vigCorrCenter;" << endl
00616             << "        d *= radiusScale;" << endl
00617             << "        vig = radialVigCorrCoeff0;" << endl
00618             << "        float r2 = dot(d, d);" << endl
00619             << "        float r = r2;" << endl
00620             << "        vig += radialVigCorrCoeff1 * r;" << endl
00621             << "        r *= r2;" << endl
00622             << "        vig += radialVigCorrCoeff2 * r;" << endl
00623             << "        r *= r2;" << endl
00624             << "        vig += radialVigCorrCoeff3 * r;" << endl
00625             << "    }" << endl;
00626     } else if (Base::m_src.getVigCorrMode() & HuginBase::SrcPanoImage::VIGCORR_FLATFIELD) {
00627         oss << "    // VigCorrMode=VIGCORR_FLATFIELD" << endl
00628             << "    float vig = 1.0;" << endl;
00629     } else {
00630         oss << "    // VigCorrMode=none" << endl
00631             << "    float vig = 1.0;" << endl;
00632     }
00633 
00634     oss << "    vec3 exposure_whitebalance = vec3("
00635         << (m_destExposure / (Base::m_srcExposure * Base::m_src.getWhiteBalanceRed())) << ", "
00636         << (m_destExposure / (Base::m_srcExposure)) << ", "
00637         << (m_destExposure / (Base::m_srcExposure * Base::m_src.getWhiteBalanceBlue())) << ");" << endl
00638         << "    p.rgb = (p.rgb * exposure_whitebalance) / vig;" << endl;
00639 
00640     if (m_destLut.size() > 0) {
00641         oss << "    p.rgb = p.rgb * " << (destLutSize - 1.0) << ";" << endl
00642             << "    vec2 destR = texture2DRect(DestLutTexture, vec2(p.r, 0.0)).sq;" << endl
00643             << "    vec2 destG = texture2DRect(DestLutTexture, vec2(p.g, 0.0)).sq;" << endl
00644             << "    vec2 destB = texture2DRect(DestLutTexture, vec2(p.b, 0.0)).sq;" << endl
00645             << "    vec3 destX = vec3(destR.x, destG.x, destB.x);" << endl
00646             << "    vec3 destY = vec3(destR.y, destG.y, destB.y);" << endl
00647             << "    vec3 destA = fract(p.rgb);" << endl
00648             << "    p.rgb = mix(destX, destY, destA);" << endl;
00649     }
00650 
00651     // alpha hdrWeight
00652     if (m_hdrMode) {
00653         oss << "    p.a = max(p.r, max(p.g, p.b));" << endl;
00654     }
00655 }
00656 
00657 }} // namespace
00658 
00659 #endif // _H

Generated on 31 Jul 2015 for Hugintrunk by  doxygen 1.4.7