Layers, colors, ugly blur (as test)
This commit is contained in:
parent
620b4c331c
commit
7d46a96a05
3 changed files with 127 additions and 13 deletions
49
Canvas.hpp
49
Canvas.hpp
|
@ -20,14 +20,17 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include "array.hpp"
|
#include <array>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
class Canvas2D {
|
class Canvas2D {
|
||||||
typedef unsigned int value_type;
|
typedef T value_type;
|
||||||
typedef std::vector<value_type> Row;
|
typedef std::vector<value_type> Row;
|
||||||
typedef std::vector<Row> Storage;
|
typedef std::vector<Row> Storage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static constexpr size_t dimension = 2;
|
||||||
|
|
||||||
Canvas2D(size_t width, size_t height)
|
Canvas2D(size_t width, size_t height)
|
||||||
: storage(height, Row(width, 0))
|
: storage(height, Row(width, 0))
|
||||||
{}
|
{}
|
||||||
|
@ -122,10 +125,18 @@ public:
|
||||||
return (*canvas)[r][c];
|
return (*canvas)[r][c];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value_type const & operator*() const {
|
||||||
|
return (*canvas)[r][c];
|
||||||
|
}
|
||||||
|
|
||||||
value_type & operator->(){
|
value_type & operator->(){
|
||||||
return (*canvas)[r][c];
|
return (*canvas)[r][c];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value_type const & operator->() const {
|
||||||
|
return (*canvas)[r][c];
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Canvas2D;
|
friend class Canvas2D;
|
||||||
iterator(Canvas2D * canvas, size_t c = 0, size_t r = 0)
|
iterator(Canvas2D * canvas, size_t c = 0, size_t r = 0)
|
||||||
|
@ -198,4 +209,38 @@ private:
|
||||||
Storage storage;
|
Storage storage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Canvas>
|
||||||
|
class LayeredCanvas {
|
||||||
|
public:
|
||||||
|
static constexpr size_t dimension = Canvas::dimension;
|
||||||
|
|
||||||
|
LayeredCanvas(size_t width, size_t height, size_t layers)
|
||||||
|
: canvae(layers, Canvas(width, height))
|
||||||
|
{}
|
||||||
|
|
||||||
|
Canvas & operator[](size_t layer){
|
||||||
|
return canvae[layer];
|
||||||
|
}
|
||||||
|
|
||||||
|
Canvas const & operator[](size_t layer) const {
|
||||||
|
return canvae[layer];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t layers() const {
|
||||||
|
return canvae.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
size_t size() const {
|
||||||
|
return canvae.front().size<N>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void plot(double const * position, size_t layer){
|
||||||
|
canvae[layer].plot(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Canvas> canvae;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace Tonemappers {
|
namespace Tonemappers {
|
||||||
|
|
||||||
|
@ -26,21 +27,27 @@ namespace Tonemappers {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename C, typename I>
|
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) {
|
for (typename C::const_iterator it = canvas.begin(); it != canvas.end(); ++it) {
|
||||||
const double grayscale = get_value(*it);
|
const double grayscale = get_value(*it);
|
||||||
image << typename I::pixel(grayscale, grayscale, grayscale);
|
image << typename I::pixel(grayscale, grayscale, grayscale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
template <typename T>
|
||||||
double get_value(unsigned int n){
|
double get_value(T const & n) const {
|
||||||
return (double) n / (double) max;
|
return (double) n / (double) max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
unsigned int max;
|
unsigned int max;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GammaCorrector : public Normalizer {
|
struct GammaCorrector : public Normalizer {
|
||||||
|
GammaCorrector(double gamma = 1.0)
|
||||||
|
: gamma(gamma)
|
||||||
|
{}
|
||||||
|
|
||||||
template <typename C>
|
template <typename C>
|
||||||
void analyse(C const & canvas){
|
void analyse(C const & canvas){
|
||||||
Normalizer::analyse(canvas);
|
Normalizer::analyse(canvas);
|
||||||
|
@ -50,18 +57,76 @@ namespace Tonemappers {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename C, typename I>
|
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) {
|
for (typename C::const_iterator it = canvas.begin(); it != canvas.end(); ++it) {
|
||||||
const double grayscale = get_value(*it);
|
const double grayscale = get_value(*it);
|
||||||
image << typename I::pixel(grayscale, grayscale, grayscale);
|
image << typename I::pixel(grayscale, grayscale, grayscale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
template <typename T>
|
||||||
double get_value(unsigned int n){
|
double get_value(T const & n, double factor = 1.0) const {
|
||||||
return std::pow(Normalizer::get_value(n), power);
|
return std::pow(Normalizer::get_value(n), factor * power / gamma);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
double power;
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
10
main.cpp
10
main.cpp
|
@ -35,7 +35,11 @@ void render(Attractor & myAttractor, C & canvas, unsigned int iterations){
|
||||||
for(unsigned int i = 0; i < 1000000; ++i) {
|
for(unsigned int i = 0; i < 1000000; ++i) {
|
||||||
myAttractor.iterate();
|
myAttractor.iterate();
|
||||||
myAttractor.project();
|
myAttractor.project();
|
||||||
canvas.plot(myAttractor.projector->projectedPoint);
|
canvas.plot(myAttractor.projector->projectedPoint, 0);
|
||||||
|
double x = rand() / (double) RAND_MAX - 0.5;
|
||||||
|
double y = rand() / (double) RAND_MAX - 0.5;
|
||||||
|
double blur[2] = {myAttractor.projector->projectedPoint[0] + x*0.02, myAttractor.projector->projectedPoint[1] + y*0.02};
|
||||||
|
canvas.plot(blur, 1);
|
||||||
}
|
}
|
||||||
progress.show(j, iterations);
|
progress.show(j, iterations);
|
||||||
}
|
}
|
||||||
|
@ -67,8 +71,8 @@ int main(int argc, char* argv[]) try {
|
||||||
|
|
||||||
std::string filename = output_path + generate_filename();
|
std::string filename = output_path + generate_filename();
|
||||||
|
|
||||||
Canvas2D canvas(width, height);
|
|
||||||
Logger logger(std::cout, LOG_VERBOSE);
|
Logger logger(std::cout, LOG_VERBOSE);
|
||||||
|
LayeredCanvas<Canvas2D<unsigned int> > canvas(width, height, 2);
|
||||||
{
|
{
|
||||||
Attractor my_attractor(attractorFile);
|
Attractor my_attractor(attractorFile);
|
||||||
|
|
||||||
|
@ -84,7 +88,7 @@ int main(int argc, char* argv[]) try {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Tonemappers::GammaCorrector tonemapper;
|
Tonemappers::Colorizer tonemapper(canvas.layers());
|
||||||
tonemapper.analyse(canvas);
|
tonemapper.analyse(canvas);
|
||||||
|
|
||||||
logger.start("saving image");
|
logger.start("saving image");
|
||||||
|
|
Reference in a new issue