refinery
RAW file processor

include/refinery/gamma.h

00001 #ifndef _REFINERY_GAMMA_H
00002 #define _REFINERY_GAMMA_H
00003 
00004 #include <cmath>
00005 #include <limits>
00006 #include <vector>
00007 
00008 namespace refinery {
00009 
00019 template<typename T>
00020 class GammaCurve {
00021 public:
00022   typedef std::vector<T> CurveType; 
00024 private:
00025   CurveType mCurve;
00026 
00027   void init(double pwr, double ts, T max)
00028   {
00029     double g[6] = { 0, 0, 0, 0, 0, 0 };
00030     const T limit = std::numeric_limits<T>::max();
00031     const unsigned int curveSize = static_cast<unsigned int>(limit) + 1;
00032     g[0] = pwr;
00033     g[1] = ts;
00034 
00035     double bnd[2] = { 0, 1 };
00036 
00037     for (int i = 0; i < 48; i++) {
00038       g[2] = (bnd[0] + bnd[1]) / 2;
00039 
00040       double t = std::pow(g[2]/g[1],-g[0]) - 1;
00041       bnd[t/g[0] - 1/g[2] > -1] = g[2];
00042     }
00043 
00044     g[3] = g[2] / g[1];
00045     g[4] = g[2] * (1/g[0] - 1);
00046     g[5] = 1 / (
00047         g[1] * g[3] * g[3] / 2
00048         + 1 - g[2] - g[3]
00049         - g[2] * g[3] * (std::log(g[3]) - 1)
00050         ) - 1;
00051 
00052     mCurve.reserve(curveSize);
00053 
00054     for (unsigned int i = 0; i < curveSize; i++) {
00055       double r = static_cast<double>(i) / max;
00056       T val;
00057       if (r < 1.0) {
00058         val = curveSize * (
00059             r < g[3]
00060             ? r * g[1]
00061             : (std::pow(r, g[0]) * (1 + g[4]) - g[4])
00062             );
00063       } else {
00064         val = limit;
00065       }
00066       mCurve.push_back(val);
00067     }
00068   }
00069 
00070 public:
00078   GammaCurve(double pwr, double ts, T max)
00079   {
00080     this->init(pwr, ts, max);
00081   }
00095   template<typename HistogramType> GammaCurve(const HistogramType& histogram)
00096   {
00097     typedef typename HistogramType::ColorType ColorType;
00098     typedef typename HistogramType::ValueType ValueType;
00099 
00100     // Output image will be 1% white
00101     unsigned int perc = histogram.nPixels() * 0.01;
00102     unsigned int white = 0;
00103 
00104     for (ColorType c = 0; c < HistogramType::NColors; c++) {
00105       unsigned int total = 0;
00106       unsigned int val = 0x1fff;
00107       while (val > 32) {
00108         total += histogram.count(c, val);
00109         if (total > perc) break;
00110         val--;
00111       }
00112       if (white < val) white = val;
00113     }
00114 
00115     this->init(0.45, 4.5, white << HistogramType::Coarseness);
00116   }
00122   GammaCurve(const GammaCurve& rhs) : mCurve(rhs.mCurve) {}
00123 
00127   inline const T& at(const T& in) const { return mCurve.at(in); }
00128 };
00129 
00130 } // namespace refinery
00131 
00132 #endif /* _REFINERY_GAMMA_H */
 All Classes Functions Variables Typedefs Enumerations Enumerator