refinery
RAW file processor
|
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 */