/* XANDER'S BUDDHABROT PROGRAM OF DOOM REVISION DATE: 26 March 2012 Expected input file format: line 1: exponent line 2: max iterations line 3: number of random points line 4: output file name (including extension) */ #include #include #include #include #include #include "mtrand.h" using namespace std; int fact(int); int choose(int, int); void z_pow(double [], int); bool in_set(double [], int, int); void bmpHeaders(ofstream &); void writeValue(int, int, ofstream &); int main(int argc, char *argv[]) { MTRand drand; srand(time(NULL)); long int* counters = new long int[40960000]; // 6400x6400 pixels int d, maxIter, pixel, pixelX, pixelY; long int numPoints, maxCount=0; double point[2], tmp[2]; bool inSet; ofstream fout; ifstream fin; string imgName, parFile; time_t start, end; if (argc > 1) { parFile = argv[1]; // READ IN THE PARAMETER FILE cout << "Parameter file is: " << parFile << endl; fin.open(("par_files/"+parFile+".txt").c_str()); if(fin.fail()) { cerr << "ERROR: The parameter file 'par_files/" << parFile << ".txt' could not be opened.\nAttempting to use 'parameters-default.txt'.\n"; fin.open("par_files/parameters-default.txt"); if(fin.fail()) { cerr << "ERROR: 'parameters-default.txt' could not be opened.\nAborting.\n"; exit(1); } } } else { fin.open("par_files/parameters-default.txt"); if(fin.fail()) { cerr << "ERROR: 'parameters-default.txt' could not be opened.\nAborting.\n"; exit(1); } } fin >> d >> maxIter >> numPoints >> imgName; fin.close(); // INITIALIZE THE COUNTERS for(int i=0; i<40960000; ++i) { counters[i] = 0; } start = time(NULL); for(long int i=0; i 0 && pixelX < 6400 && pixelY < 6400 && pixelY > 0) { pixel = 6400*pixelY + pixelX; ++counters[pixel]; if(counters[pixel]>maxCount) { maxCount = counters[pixel]; } z_pow(point,d); point[0] += tmp[0]; point[1] += tmp[1]; } else { j = maxIter + 1; } } ++i; } } // WRITE THE IMAGE FILE fout.open(("output/log-"+imgName).c_str()); if(fout.fail()) { cerr << "ERROR: The output file 'output/" << imgName << "' could not be opened.\nAttempting to use 'temp.bmp'.\n"; fout.open("output/temp.bmp"); if(fout.fail()) { cerr << "ERROR: 'temp.bmp' could not be opened.\nAborting.\n"; exit(1); } } bmpHeaders(fout); for(int i=0; i<40960000; ++i) { if(counters[i]>0){ tmp[1] = (long int) ((log((double) counters[i]) / log((double) maxCount+1)) * 255.0); } writeValue(1,tmp[1],fout); writeValue(1,tmp[1],fout); writeValue(1,tmp[1],fout); } fout.close(); fout.open(("output/linear-"+imgName).c_str()); if(fout.fail()) { cerr << "ERROR: The output file 'output/" << imgName << "' could not be opened.\nAttempting to use 'temp.bmp'.\n"; fout.open("output/temp.bmp"); if(fout.fail()) { cerr << "ERROR: 'temp.bmp' could not be opened.\nAborting.\n"; exit(1); } } bmpHeaders(fout); for(int i=0; i<40960000; ++i) { if(counters[i]>0){ tmp[1] = (long int) ((((double) counters[i]) / ((double) maxCount+1)) * 255.0); } writeValue(1,tmp[1],fout); writeValue(1,tmp[1],fout); writeValue(1,tmp[1],fout); } fout.close(); delete[] counters; end = time(NULL); printf("Render Time: %5d seconds\n", (int) (end-start)); return 0; } /* COMPUTES n! */ int fact(int n) { int res=1; for(int i=2; i<=n; ++i) { res *= i; } return res; } /* COMPUTES C(n,k) */ int choose(int n, int k) { int res = 1; if(k>n/2) { // C(n,k) = C(n,n-k), so work with the smaller of the two k = n-k; } for(int i=n; i>=n-k+1; --i) { res *= i; } return res/fact(k); } /* COMPUTES z^d WHERE z IS COMPLEX AND d IS AN INTEGER */ void z_pow(double z[2], int d) { double res[2], delta; res[0]=0; res[1]=0; // the real and imaginary parts of the result for(int i=0; i<=d; ++i) { delta = choose(d,i)*pow(z[0],d-i)*pow(z[1],i); switch(i%4) { case 0: res[0] += delta; break; case 1: res[1] += delta; break; case 2: res[0] -= delta; break; case 3: res[1] -= delta; break; } } z[0] = res[0]; z[1] = res[1]; return; } /* DETERMINES WHETHER A GIVEN POINT IN THE COMPLEX PLANE IS IN THE dTH DEGREE MULTIBROT SET, AND RETURNS A BOOLEAN. */ bool in_set(double z[2], int d, int numIterations) { int iteration = 1; bool inSet = true; double c[2]; c[0]=z[0]; c[1]=z[1]; if((z[0]*z[0])+(z[1]*z[1]) > 16) { inSet = false; } while(inSet && iteration < numIterations) { z_pow(z,d); z[0] += c[0]; z[1] += c[1]; ++iteration; if((z[0]*z[0])+(z[1]*z[1]) > 16) { inSet = false; } } return inSet; } /* WRITES THE BITMAP HEADERS TO THE OUTPUT FILE */ void bmpHeaders(ofstream &fout) { // Magic Number fout << "BM"; // Size of BMP File writeValue(4,(40960000*3)+54,fout); // Unused writeValue(4,0,fout); // Offset writeValue(4,54,fout); // Header Size writeValue(4,40,fout); // Height and Width writeValue(4,6400,fout); writeValue(4,6400,fout); // Color Planes writeValue(2,1,fout); // Bits per Pixel writeValue(2,24,fout); // Compression writeValue(4,0,fout); // Raw BMP Size writeValue(4,40960000,fout); // Horizontal and Vertical Resolution writeValue(4,2835,fout); writeValue(4,2835,fout); // Colors in Palette writeValue(4,0,fout); // Important Colors writeValue(4,0,fout); return; } /* WRITES A VALUE TO A FILE (I honestly don't remember exactly what this does anymore. :\ ) */ void writeValue(int num, int value, ofstream &fout) { int tmp; for(int i=0; i 255) { tmp = value / 256; tmp = value * 256; fout << (char) (value-tmp); value /= 256; } else if(value >= 0 && value <=255) { fout << (char) value; value = -1; } else { fout << (char) 0; } } return; }