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.
137 lines
3.0 KiB
137 lines
3.0 KiB
#include "../Logger.hpp"
|
|
#include <fstream>
|
|
#include <cmath>
|
|
#include <cstdlib>
|
|
#include <cassert>
|
|
|
|
#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");
|
|
|
|
}
|
|
|