diff --git a/AttractorKernel.hpp b/AttractorKernel.hpp index c661c8d..fe48bef 100644 --- a/AttractorKernel.hpp +++ b/AttractorKernel.hpp @@ -22,7 +22,6 @@ protected: // stuff used by subclasses AttractorKernel(const unsigned int dimension, const unsigned int numberOfParameters); - void reallocParameters(const unsigned int numberOfParameters); public: diff --git a/Canvas.cpp b/Canvas.cpp index 4d1ab75..ed60db7 100644 --- a/Canvas.cpp +++ b/Canvas.cpp @@ -1,241 +1,3 @@ -#include "Logger.hpp" -#include -#include -#include -#include - -#include "pngwriter/pngwriter.h" - #include "Canvas.hpp" - -Canvas::Canvas(unsigned int width, unsigned int height, unsigned int num_colors): - dim(2), width(width), height(height), num_colors(num_colors), v(0) { - - int_array = new unsigned int[width*height*num_colors]; - size = new unsigned int[2]; - size[0] = width; - size[1] = height; - - assert(int_array != NULL); - - clear(); - - LogDebug("New Canvas\n"); -} - -void Canvas::clear() { - for ( unsigned int i = 0; i < width*height*num_colors; i++ ) { - int_array[i] = 0; - } -} - - - -//void Canvas::update_viewwindow() { -// -// //width and height of attractor -// const double dx = xmax - xmin; -// const double dy = ymax - ymin; -// -// //fix aspect ratio -// if ( dx > dy * ((float)width / height) ) { -// const double height2 = dx * ((float)height / width); -// const double middle = 0.5 * (ymax + ymin); -// ymax = middle + 0.5 * height2; -// ymin = middle - 0.5 * height2; -// -// } else { -// const double width2 = dy * ((float)width / height); -// const double middle = 0.5 * (xmax + xmin); -// xmax = middle + 0.5 * width2; -// xmin = middle - 0.5 * width2; -// } -// -// //add a 4% marge -// xmin -= 0.02 * dx; -// xmax += 0.02 * dx; -// ymin -= 0.02 * dy; -// ymax += 0.02 * dy; -// -// //constants for speed -// constant1 = width / (xmax - xmin); -// constant2 = height / (ymax - ymin); -//} - -void Canvas::plot(double x, double y) { - // gets x and y coordinate - // ranges [-1, 1] and [-1, 1] - // so how to do the aspect shiz, i don't know - const unsigned int x_int = x*width + width*.5; - const unsigned int y_int = y*width + height*.5; - const unsigned int index = x_int + width * y_int; - - if(x_int < width && y_int < height) { - int_array[index]++; - } -} - -void Canvas::plot(double x, double y, unsigned int c) { - // same as plot(double x, double y) - // now with color control - const unsigned int x_int = x*width + width*.5; - const unsigned int y_int = y*width + height*.5; - const unsigned int index = x_int + width * y_int + width*height*c; - - if(x_int < width && y_int < height) { - int_array[index]++; - } -} - -void Canvas::plot(double x, double y, unsigned int c, double intensity) { - // same as plot(double x, double y, unsigned int c) - // but now uses the float array (not yet implemented -} - -/* - I/O functions -*/ -void Canvas::output() { - LogMoreInfo("Canvas: \n Dimensions: %d x %d x %d\n", width, height, num_colors); -} - -void Canvas::output_file(const char * filename){ - unsigned int * max_int = new unsigned int[num_colors]; - double * power = new double[num_colors]; - - for ( unsigned int i = 0; i < num_colors; i++ ) { - max_int[i] = 0; - double cumulative = 0; - unsigned int n = 0; - - for ( unsigned int j = 0; j < width*height; j++) { - if ( max_int[i] < int_array[j+i*width*height] ) { - max_int[i] = int_array[j+i*width*height]; - } - if ( int_array[j+i*width*height] ) { - cumulative += int_array[j+i*width*height]; - n++; - } - } - - if ( n > 100 ) { - const double average = cumulative / (double)n; - power[i] = -2.5/log(average/(double)max_int[i]); - if ( power[i] < 0 ) - power[i] = 1; - } else { - power[i] = 1; - } - - if ( n <= 10 ) { - LogInfo("not enough data\n"); - } - } - - const double vibrancy = 2.0; - double averagePower = 0; - for ( unsigned int i = 0; i < num_colors; i++ ) { - averagePower += power[i]; - } - averagePower /= (double)num_colors; - for ( unsigned int i = 0; i < num_colors; i++ ) { - power[i] = vibrancy*power[i] + (1.0 - vibrancy)*averagePower; - } - - pngwriter * pngFile = new pngwriter(width, height, 0.0, filename); - pngFile->setcompressionlevel(9); - pngFile->settext("Attractor", "Joshua Moerman", "A awesome attractor", "AwesomeAttractor"); - - for ( unsigned int x = 0; x < width; x++ ) { - for ( unsigned int y = 0; y < height; y++ ) { - double r = 0.0; - double g = 0.0; - double b = 0.0; - for ( unsigned int c = 0; c < num_colors; c++ ) { - const double norm_value = (double)int_array[x + y*width + c*width*height]/max_int[c]; - switch(c){ - case 0: { - r = (pow(norm_value, power[c]))*3.5; - break; - } - case 1: { - g = (pow(norm_value, power[c]))*3.0; - break; - } - case 2: { - b = (pow(norm_value, power[c]))*3.0; - break; - } - default: - break; - } - } - //pngwriter clips values for me - pngFile->plot(x, y, r, g, b); - } - } - - - delete[] max_int; - delete[] power; - - LogInfo("Writing %s\n", filename); - - std::ofstream file(filename); - if ( !file ) { - LogError("Couldn't write to file"); - } - pngFile->close(); - - LogMoreInfo("File written"); - -} - -void Canvas::output_file(){ - char filename[50]; - time_t t = time(0); - struct tm* lt = localtime(&t); - int r = rand() % 10; - - sprintf(filename, "render/attractor_%04d-%02d-%02d_%02d-%02d-%02d-%01d.png", lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec, r); - - output_file(filename); -} - - -void Canvas::output_raw(const char * filename){ - - std::ofstream outfile (filename, std::ofstream::binary); - - outfile.write(reinterpret_cast(int_array), sizeof(unsigned int)*width*height*num_colors); - -} - -void Canvas::output_raw(){ - char filename[52]; - time_t t = time(0); - struct tm* lt = localtime(&t); - int r = rand() % 10; - - sprintf(filename, "render/canv%dx%d_%04d-%02d-%02d_%02d-%02d-%02d-%01d.canv", width, height, lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec, r); - - output_raw(filename); -} - -void Canvas::input_raw(const char * filename){ - std::ifstream infile(filename, std::ifstream::binary); - - if ( ! infile ) { - LogError("Could not read file %s", filename); - return; - } - - infile.seekg (0, std::ios::end); - int length = infile.tellg(); - infile.seekg (0, std::ios::beg); - - LogDebug("Length: %d =? %d\n", length, static_cast(width*height*num_colors*sizeof(unsigned int))); - - infile.read (reinterpret_cast(int_array), sizeof (unsigned int)*width*height*num_colors); -} +// lol diff --git a/Canvas.hpp b/Canvas.hpp index e54a6d0..1b2c659 100644 --- a/Canvas.hpp +++ b/Canvas.hpp @@ -2,49 +2,21 @@ #define CANVAS_HPP -//#include "Vector.hpp" -#include "Attractor.hpp" -#include "Projector.hpp" +class Canvas { +protected: -// TODO : Canvas class abstraheren (zodat er makkelijk verschillende soorten canvae gemaakt kunnen worden) + unsigned int dimension; + Canvas (const unsigned int dimension) : dimension (dimension) {}; -class Canvas{ - friend class Projector; +public: - unsigned int dim; - unsigned int width; - unsigned int height; - unsigned int num_colors; + unsigned int getDimension() const { return dimension; }; - unsigned int * size; + virtual ~Canvas() {}; - unsigned int * int_array; - - public: - - double v; - - Canvas(unsigned int width, unsigned int height, unsigned int num_colors = 1); - - void clear(); - - void plot(double x, double y); - void plot(double x, double y, unsigned int c); - // TODO : make double array in canvas (ander soort canvas) - // TODO : subpixel sampling (anders soort canvas) - void plot(double x, double y, unsigned int c, double intensity); - - void output(); - //void output(Vector& point); - - void output_file(const char * filename); - void output_file(); - void output_raw(const char * filename); - void output_raw(); - void input_raw(const char * filename); + virtual void clear() = 0; + virtual void plot (const double * normalizedPosition) = 0; + virtual void output_file (const char * filename) const = 0; }; - - #endif // CANVAS_HPP - diff --git a/canvae/PNG.cpp b/canvae/PNG.cpp new file mode 100644 index 0000000..7788fd5 --- /dev/null +++ b/canvae/PNG.cpp @@ -0,0 +1,137 @@ +#include "../Logger.hpp" +#include +#include +#include +#include + +#include "../pngwriter/pngwriter.h" + +#include "PNG.hpp" + + +PNG::PNG(unsigned int width, unsigned int height, unsigned int num_colors): + Canvas(2), width(width), height(height), num_colors(num_colors), v(0) { + + int_array = new unsigned int[width*height*num_colors]; + + assert(int_array != NULL); + + clear(); + + LogDebug("New Canvas\n"); +} + +void PNG::clear() { + for ( unsigned int i = 0; i < width*height*num_colors; i++ ) { + int_array[i] = 0; + } +} + +void PNG::plot(double * position) { + const double& x = position[0]; + const double& y = position[1]; + + const unsigned int x_int = x*width + width*.5; + const unsigned int y_int = y*width + height*.5; + const unsigned int index = x_int + width * y_int; + + if(x_int < width && y_int < height) { + int_array[index]++; + } +} + +/* + I/O functions +*/ + +void PNG::output_file(const char * filename){ + unsigned int * max_int = new unsigned int[num_colors]; + double * power = new double[num_colors]; + + for ( unsigned int i = 0; i < num_colors; i++ ) { + max_int[i] = 0; + double cumulative = 0; + unsigned int n = 0; + + for ( unsigned int j = 0; j < width*height; j++) { + if ( max_int[i] < int_array[j+i*width*height] ) { + max_int[i] = int_array[j+i*width*height]; + } + if ( int_array[j+i*width*height] ) { + cumulative += int_array[j+i*width*height]; + n++; + } + } + + if ( n > 100 ) { + const double average = cumulative / (double)n; + power[i] = -2.5/log(average/(double)max_int[i]); + if ( power[i] < 0 ) + power[i] = 1; + } else { + power[i] = 1; + } + + if ( n <= 10 ) { + LogInfo("not enough data\n"); + } + } + + const double vibrancy = 2.0; + double averagePower = 0; + for ( unsigned int i = 0; i < num_colors; i++ ) { + averagePower += power[i]; + } + averagePower /= (double)num_colors; + for ( unsigned int i = 0; i < num_colors; i++ ) { + power[i] = vibrancy*power[i] + (1.0 - vibrancy)*averagePower; + } + + pngwriter * pngFile = new pngwriter(width, height, 0.0, filename); + pngFile->setcompressionlevel(9); + pngFile->settext("Attractor", "Joshua Moerman", "A awesome attractor", "AwesomeAttractor"); + + for ( unsigned int x = 0; x < width; x++ ) { + for ( unsigned int y = 0; y < height; y++ ) { + double r = 0.0; + double g = 0.0; + double b = 0.0; + for ( unsigned int c = 0; c < num_colors; c++ ) { + const double norm_value = (double)int_array[x + y*width + c*width*height]/max_int[c]; + switch(c){ + case 0: { + r = (pow(norm_value, power[c]))*3.5; + break; + } + case 1: { + g = (pow(norm_value, power[c]))*3.0; + break; + } + case 2: { + b = (pow(norm_value, power[c]))*3.0; + break; + } + default: + break; + } + } + //pngwriter clips values for me + pngFile->plot(x, y, r, g, b); + } + } + + + delete[] max_int; + delete[] power; + + LogInfo("Writing %s\n", filename); + + std::ofstream file(filename); + if ( !file ) { + LogError("Couldn't write to file"); + } + pngFile->close(); + + LogMoreInfo("File written"); + +} diff --git a/canvae/PNG.hpp b/canvae/PNG.hpp new file mode 100644 index 0000000..ae2d6c4 --- /dev/null +++ b/canvae/PNG.hpp @@ -0,0 +1,27 @@ +#ifndef PNG_HPP +#define PNG_HPP + +#include "../Canvas.hpp" + +class PNG : public Canvas { + unsigned int width; + unsigned int height; + unsigned int num_colors; + + unsigned int * int_array; + +public: + + double v; + + PNG (unsigned int width, unsigned int height, unsigned int num_colors = 1); + + virtual void clear(); + virtual void plot (const double * normalizedPosition); + virtual void output_file (const char * filename) const; +}; + + + +#endif // PNG_HPP + diff --git a/canvae/Raw.cpp b/canvae/Raw.cpp new file mode 100644 index 0000000..c0c8e32 --- /dev/null +++ b/canvae/Raw.cpp @@ -0,0 +1,58 @@ +#include "../Logger.hpp" +#include +#include +#include +#include +#include +#include +#include + +#include "Raw.hpp" + + +Raw::Raw (const unsigned int dimension, const unsigned int* sizes_): + Canvas(dimension) { + + sizes = new unsigned int[dimension]; + assert(sizes != NULL); + std::copy(sizes_, sizes_ + dimension, sizes); + + sizesMultiplied = new unsigned int[dimension]; + assert(sizesMultiplied != NULL); + sizesMultiplied[0] = 1; + for ( unsigned int i = 1; i < dimension; ++i ) { + sizesMultiplied[i] = sizesMultiplied[i-1]*sizes[i-1]; + } + + arraySize = std::accumulate(sizes, sizes + dimension, multiplies); + pixelArray = new unsigned int[arraySize]; + assert(pixelArray != NULL); + + clear(); + + LogDebug("New RawCanvas of dimension %d\n", dimension); +} + +void Raw::clear() { + std::fill_n(pixelArray, arraySize, 0); +} + +void Raw::plot(double * position) { + unsigned int index = 0; + for ( unsigned int i = 0; i < dimension; ++i ) { + index += (position[i]*sizes[i] + 0.5*sizes[i])*sizesMultiplied[i]; + } + + if(index < arraySize) { + int_array[index]++; + } +} + +/* + I/O functions +*/ + +void Raw::output_file(const char * filename){ + std::ofstream outfile (filename, std::ofstream::binary); + outfile.write(reinterpret_cast(int_array), sizeof(unsigned int)*width*height*num_colors); +} diff --git a/canvae/Raw.hpp b/canvae/Raw.hpp new file mode 100644 index 0000000..a6b5032 --- /dev/null +++ b/canvae/Raw.hpp @@ -0,0 +1,24 @@ +#ifndef RAW_HPP +#define RAW_HPP + +#include "../Canvas.hpp" + +class Raw : public Canvas { + unsigned int * sizes; + unsigned int sizesMultiplied; + unsigned int * pixelArray; + unsigned int arraySize; + +public: + + Raw (const unsigned int dimension, const unsigned int* sizes); + + virtual void clear(); + virtual void plot (const double * normalizedPosition); + virtual void output_file (const char * filename) const; +}; + + + +#endif // RAW_HPP + diff --git a/main.cpp b/main.cpp index 47e5ca4..eb029a8 100644 --- a/main.cpp +++ b/main.cpp @@ -13,6 +13,16 @@ int verbose; +/* + char filename[50]; + time_t t = time(0); + struct tm* lt = localtime(&t); + int r = rand() % 10; + + sprintf(filename, "render/attractor_%04d-%02d-%02d_%02d-%02d-%02d-%01d.png", lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec, r); + +*/ + void showHelpText(){ std::cout << "Awesome Attractor, version " << __DATE__ << std::endl; std::cout << "Usage: AwesomeAttractor [OPTION]... FILE" << std::endl << std::endl; @@ -64,7 +74,8 @@ int main(int argc, char *argv[]) { Attractor myAttractor(attractorFile); Projector projection; - Canvas canvas(width, height, 3); + unsigned int sizes[] = {128, 128, 128}; + Canvas* canvas = new Raw(3, sizes); projection.canvas = &canvas; myAttractor.projectors.push_back(&projection);