#include #include #include #include #include #include using namespace std; #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(); #ifdef HARDDEBUG cout << "New canvas" << endl; #endif } 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() { cout << "Canvas: " << endl; cout << "Dimensions: " << width << " x " << height << " x " << num_colors << endl; } 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 ) { cout << "not enough data" << endl; } } const double vibrancy = v; double averagePower = 0; for ( unsigned int i = 0; i < num_colors; i++ ) { averagePower += power[i]; } averagePower /= 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.0; 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; pngFile->close(); } 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){ ofstream outfile (filename, 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){ ifstream infile(filename, ifstream::binary); if ( ! infile ) { cout << "poep" << endl; return; } infile.seekg (0, ios::end); int length = infile.tellg(); infile.seekg (0, ios::beg); cout << "length: " << length << " =? " << static_cast(width*height*num_colors*sizeof(unsigned int)) << endl; infile.read (reinterpret_cast(int_array), sizeof (unsigned int)*width*height*num_colors); }