// // Tonemapper.hpp // AwesomeAttractorND // // Created by Joshua Moerman on 10/28/11. // Copyright 2011 Vadovas. All rights reserved. // #ifndef AwesomeAttractorND_Tonemapper_hpp #define AwesomeAttractorND_Tonemapper_hpp #include #include #include #include namespace Tonemappers { struct Normalizer { Normalizer() : max(0) {} template void analyse(C const & canvas){ max = *std::max_element(canvas.begin(), canvas.end()); } template void process(C const & canvas, I & image) const { for (typename C::const_iterator it = canvas.begin(); it != canvas.end(); ++it) { const double grayscale = get_value(*it); image << typename I::pixel(grayscale, grayscale, grayscale); } } template double get_value(T const & n) const { return (double) n / (double) max; } protected: unsigned int max; }; struct GammaCorrector : public Normalizer { GammaCorrector(double gamma = 1.0) : gamma(gamma) {} template void analyse(C const & canvas){ Normalizer::analyse(canvas); const unsigned int sum = std::accumulate(canvas.begin(), canvas.end(), 0); const double average = sum / (double) canvas.size(); power = -2.5/std::log(average/max); } template void process(C const & canvas, I & image) const { for (typename C::const_iterator it = canvas.begin(); it != canvas.end(); ++it) { const double grayscale = get_value(*it); image << typename I::pixel(grayscale, grayscale, grayscale); } } template double get_value(T const & n, double factor = 1.0) const { return std::pow(Normalizer::get_value(n), factor * power / gamma); } protected: double power; double gamma; }; struct Colorizer { Colorizer(size_t n_planes) : gamma_correctors(n_planes) , gammas() { gammas[0].push_back(1.3); gammas[1].push_back(2.0); gammas[2].push_back(3.0); gammas[0].push_back(3.0); gammas[1].push_back(1.0); gammas[2].push_back(1.0); colors[0].push_back(1.5); colors[1].push_back(2.0); colors[2].push_back(1.0); colors[0].push_back(-1.0); colors[1].push_back(-0.5); colors[2].push_back(0.7); } template void analyse(C const & canvas){ for (size_t i = 0; i < gamma_correctors.size(); ++i) { gamma_correctors[i].analyse(canvas[i]); } } template typename std::enable_if::type process(C & canvas, I & image) const { for (unsigned int r = 0; r < canvas.template size<1>(); ++r){ for (unsigned int c = 0; c < canvas.template size<0>(); ++c){ auto const c1 = canvas[0][r][c]; auto const c2 = canvas[1][r][c]; std::array const a = {{c1, c2}}; image << typename I::pixel(get_value(a, 0), get_value(a, 1), get_value(a, 2)); } } } protected: template double get_value(T const & n, size_t color) const { double ret = 0.0; for (size_t i = 0; i < n.size(); ++i){ ret += gamma_correctors[i].get_value(n[i], gammas[color][i]) * colors[color][i]; } if(std::isnormal(ret)) return ret; else return 0.0; } std::vector gamma_correctors; std::array, 3> gammas; std::array, 3> colors; }; } #endif