#include #include #include #include using namespace std; const int MAXITERATIONS = 2048; int inSet1(double, double, int); int inSet2(double, double, int); int inSet3(double, double, int); int inSet4(double, double, int, double); void initArray(char [][3], int, ifstream &); void bmpHeaders(int, int, int, ofstream &); void writeValue(int, int, ofstream &); int main() { srand(time(NULL)); ofstream fout; ifstream fin; int padding, iterations, fractal, xsize, ysize, numIterations; string input, parFile, imgName, colorFile; double xmin, xmax, ymin, ymax, step, i, r, ff; char colors[MAXITERATIONS+1][3]; bool invalid=true; cout << "Parameters: [D]efault, [F]ile, [C]ustom, [Q]uit: "; cin >> input; if(tolower(input[0]) == 'd') { xmin = -2; ymin = -2; step = 0.004; xsize = 1000; ysize = 1000; numIterations = 255; imgName = "temp.bmp"; colorFile = "colors-default.bmp"; } else if (tolower(input[0]) == 'f') { cout << "Specify a Parameter File: "; cin >> parFile; 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); } } fin >> fractal >> xmin >> xmax >> ymin >> ymax >> xsize >> numIterations >> imgName >> colorFile; if(fractal == 4) { fin >> ff; } fin.close(); step = (xmax-xmin) / xsize; ysize = (ymax - ymin) / step; } else if (tolower(input[0]) == 'c') { cout << "Fractal to Generate:" << endl; cout << " [1] z_(n+1) = (z_n)^2 + C" << endl; cout << " [2] z_(n+1) = (z_n)^3 + C" << endl; cout << " [3] z_(n+1) = (z_n)^4 + C" << endl; cout << " [4] z_(n+1) = (z_n)^4 + C + R" << endl; cout << "Select an Option: "; cin >> fractal; cout << "Minimum x: "; cin >> xmin; cout << "Maximum x: "; cin >> xmax; cout << "Minimum y: "; cin >> ymin; cout << "Maximum y: "; cin >> ymax; cout << "Horizontal Size: "; cin >> xsize; cout << "Maximum Iterations: "; cin >> numIterations; cout << "Output File: "; cin >> imgName; cout << "Color File: "; cin >> colorFile; step = (xmax-xmin) / xsize; ysize = (ymax - ymin) / step; if(fractal == 4) { cout << "Fudge Factor: "; cin >> ff; } } else { exit(0); } fout.open(("output/"+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); } } fin.open(("color_files/"+colorFile).c_str()); if(fin.fail()) { cerr << "ERROR: The color file 'color_files/" << colorFile << "' could not be opened.\nAttempting to use 'colors-default.bmp'.\n"; fin.open("color_files/colors-default.bmp"); if(fin.fail()) { cerr << "ERROR: 'colors-default.bmp' could not be opened.\nAborting.\n"; exit(1); } } initArray(colors, numIterations, fin); fin.close(); writeValue(54,0,fout); padding = (4-((xsize*3)%4))%4; for(int y = 0; y < ysize; ++y) { for(int x = 0; x < xsize; ++x) { r = xmin + (x * step); i = ymin + (y * step); switch(fractal) { case 1: iterations = inSet1(r, i, numIterations); break; case 2: iterations = inSet2(r, i, numIterations); break; case 3: iterations = inSet3(r, i, numIterations); break; case 4: iterations = inSet4(r, i, numIterations, ff); break; default: iterations = inSet1(r, i, numIterations); break; } if(iterations == numIterations) { iterations = 0; } fout << colors[iterations][0] << colors[iterations][1] << colors[iterations][2]; writeValue(padding,0,fout); } } fout.seekp(ios::beg); bmpHeaders(xsize, ysize, padding, fout); fout.close(); return 0; } int inSet1(double cReal, double cImg, int numIterations) { int iteration = 0; bool inSet = true; double r = cReal, i = cImg, tmp; while(inSet && iteration < numIterations) { tmp = r; r = (r*r)-(i*i)+cReal; i = 2*tmp*i+cImg; ++iteration; if((r*r)+(i*i) > 4) { inSet = false; } } return iteration; } int inSet2(double cReal, double cImg, int numIterations) { int iteration = 0; bool inSet = true; long double r = cReal, i = cImg, tmp; while(inSet && iteration < numIterations) { tmp = r; r = (r*r*r)-(3*r*i*i)+cReal; i = (3*tmp*tmp*i)-(i*i*i)+cImg; ++iteration; if((r*r)+(i*i) > 4) { inSet = false; } } return iteration; } int inSet3(double cReal, double cImg, int numIterations) { int iteration = 0; bool inSet = true; long double r = cReal, i = cImg, tmp; while(inSet && iteration <= numIterations) { tmp = r; r = (r*r*r*r)-(6*r*r*i*i)+(i*i*i*i)+cReal; i = (4*tmp*tmp*tmp*i)-(4*tmp*i*i*i)+cImg; ++iteration; if((r*r)+(i*i) > 4) { inSet = false; } } return iteration; } int inSet4(double cReal, double cImg, int numIterations, double ff) { int iteration = 0; bool inSet = true; double r = cReal, i = cImg, tmp, randReal, randImg; while(inSet && iteration < numIterations) { randReal = (((float) rand() / (float) RAND_MAX) - 0.5) * ff; randImg = (((float) rand() / (float) RAND_MAX) - 0.5) * ff; tmp = r; r = (r*r)-(i*i)+cReal+randReal; i = 2*tmp*i+cImg + randImg; ++iteration; if((r*r)+(i*i) > 4) { inSet = false; } } return iteration; } void initArray(char colors[][3], int numIterations, ifstream &fin) { fin.seekg(54); for(int i=0; i<=numIterations; ++i) { for(int j=0; j<=2; ++j) { fin.get(colors[i][j]); } } return; } void bmpHeaders(int xsize, int ysize, int padding, ofstream &fout) { int bmpSize, numPixels; numPixels = (xsize+padding)*ysize; bmpSize = numPixels*3+54; // Magic Number fout << "BM"; // Size of BMP File writeValue(4,bmpSize,fout); // Unused writeValue(4,0,fout); // Offset writeValue(4,54,fout); // Header Size writeValue(4,40,fout); // Height and Width writeValue(4,xsize,fout); writeValue(4,ysize,fout); // Color Planes writeValue(2,1,fout); // Bits per Pixel writeValue(2,24,fout); // Compression writeValue(4,0,fout); // Raw BMP Size writeValue(4,bmpSize-54,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; } 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; }