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

Generated on 28 Nov 2014 for Hugintrunk by  doxygen 1.4.7