My old project for strange attractors
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 

137 lines
3.3 KiB

//
// 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 <algorithm>
#include <numeric>
#include <cmath>
#include <array>
namespace Tonemappers {
struct Normalizer {
Normalizer()
: max(0)
{}
template <typename C>
void analyse(C const & canvas){
max = *std::max_element(canvas.begin(), canvas.end());
}
template <typename C, typename I>
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 <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);
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 <typename C, typename I>
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 <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.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 <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[i].get_value(n[i], gammas[color][i]) * colors[color][i];
}
if(std::isnormal(ret))
return ret;
else
return 0.0;
}
std::vector<GammaCorrector> gamma_correctors;
std::array<std::vector<double>, 3> gammas;
std::array<std::vector<double>, 3> colors;
};
}
#endif