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

Generated on 30 May 2016 for Hugintrunk by  doxygen 1.4.7