|
|
@ -12,6 +12,7 @@ |
|
|
|
#include <algorithm> |
|
|
|
#include <numeric> |
|
|
|
#include <cmath> |
|
|
|
#include <array> |
|
|
|
|
|
|
|
namespace Tonemappers { |
|
|
|
|
|
|
@ -26,21 +27,27 @@ namespace Tonemappers { |
|
|
|
} |
|
|
|
|
|
|
|
template <typename C, typename I> |
|
|
|
void process(C const & canvas, I & image){ |
|
|
|
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); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected: |
|
|
|
double get_value(unsigned int n){ |
|
|
|
template <typename T> |
|
|
|
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 <typename C> |
|
|
|
void analyse(C const & canvas){ |
|
|
|
Normalizer::analyse(canvas); |
|
|
@ -50,18 +57,76 @@ namespace Tonemappers { |
|
|
|
} |
|
|
|
|
|
|
|
template <typename C, typename I> |
|
|
|
void process(C const & canvas, I & image){ |
|
|
|
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); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected: |
|
|
|
double get_value(unsigned int n){ |
|
|
|
return std::pow(Normalizer::get_value(n), power); |
|
|
|
template <typename T> |
|
|
|
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.0); |
|
|
|
gammas[1].push_back(3.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(3.0); |
|
|
|
colors[1].push_back(0.0); |
|
|
|
colors[2].push_back(0.0); |
|
|
|
|
|
|
|
colors[0].push_back(0.0); |
|
|
|
colors[1].push_back(2.0); |
|
|
|
colors[2].push_back(3.0); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename C> |
|
|
|
void analyse(C const & canvas){ |
|
|
|
for (size_t i = 0; i < gamma_correctors.size(); ++i) { |
|
|
|
gamma_correctors[i].analyse(canvas[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
template <typename C, typename I> |
|
|
|
typename std::enable_if<C::dimension == 2, void>::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<decltype(c1), 2> const a = {{c1, c2}}; |
|
|
|
image << typename I::pixel(get_value(a, 0), get_value(a, 1), get_value(a, 2)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected: |
|
|
|
template <typename T> |
|
|
|
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[color].get_value(n[i], gammas[color][i]) * colors[color][i]; |
|
|
|
} |
|
|
|
return ret; |
|
|
|
} |
|
|
|
std::vector<GammaCorrector> gamma_correctors; |
|
|
|
std::array<std::vector<double>, 3> gammas; |
|
|
|
std::array<std::vector<double>, 3> colors; |
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|