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.
 
 
 

161 lines
4.5 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>
#include "stf_ext.hpp"
#include "Random.hpp"
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)
: power(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({{std::vector<double>(n_planes, 2.0), std::vector<double>(n_planes, 2.0), std::vector<double>(n_planes, 2.0)}})
, colors({{std::vector<double>(n_planes, 2.0), std::vector<double>(n_planes, 2.0), std::vector<double>(n_planes, 2.0)}})
{}
Colorizer(size_t n_planes, Random::parameters)
: gamma_correctors(n_planes)
, gammas({{Random::make_vector(1.0, 3.0, n_planes), Random::make_vector(1.0, 3.0, n_planes), Random::make_vector(1.0, 3.0, n_planes)}})
, colors({{Random::make_vector(-2.0, 4.0, n_planes), Random::make_vector(-2.0, 4.0, n_planes), Random::make_vector(-2.0, 4.0, n_planes)}})
{}
Colorizer(size_t n_planes, stfu::node const & n)
: gamma_correctors(n_planes)
, gammas(stfu::from_stf<Matrix>(n.getChild("gamma_matrix")))
, colors(stfu::from_stf<Matrix>(n.getChild("color_matrix")))
{}
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));
}
}
}
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;
}
stfu::node to_stf() const {
stfu::node node;
node.addValue("class") = "colorizer";
node.addChild("gamma_matrix") = stfu::to_stf(gammas);
node.addChild("color_matrix") = stfu::to_stf(colors);
return node;
}
static Colorizer from_stf(stfu::node const & n) {
if (n.getValue("class") != "colorizer") std::cerr << "trying to read an stf as colorizer whil class != \"colorizer\"";
auto g = stfu::from_stf<Matrix>(n.getChild("gamma_matrix"));
auto c = stfu::from_stf<Matrix>(n.getChild("color_matrix"));
Colorizer tonemapper(g[0].size());
tonemapper.gammas = g;
tonemapper.colors = c;
return tonemapper;
}
protected:
std::vector<GammaCorrector> gamma_correctors;
typedef std::array<std::vector<double>, 3> Matrix;
Matrix gammas;
Matrix colors;
};
}
#endif