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