diff options
-rw-r--r-- | README.md | 15 | ||||
-rw-r--r-- | docs/p4.pdf | bin | 5197562 -> 5197678 bytes | |||
-rw-r--r-- | main.cpp | 89 |
3 files changed, 59 insertions, 45 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..f654e3f --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# Building +Just run make. Depends on libpng. + +# Info +This project was my final for CS200 at JCCC. It uses multiple threads to draw the mandelbrot. When one thread is finished, it will communicate with other threads to split the load; work delegation is the main showcase of this project. + +# Writeup +For the writeup portion of this project I did last year, please visit [here](https://git.bpcspace.com/brett/Mandelbrot-CS200/src/branch/master/docs/p4.pdf). +Here you will be able to see demos, as well as flowcharts and pseudo code for some of the functionallity. + +# Problems +Due to the fact I had to complete this project in just a few days, there are a few problems I'd fix if I were to do it again. + +The largest issue is that the thread worker class is not extensible. I have rendering in the same function as thread communication; you should not need to reimpliment the syncronization aspects of the thread just to change how it renders. +Additionally, I'm not sure if there was a simpler way to prevent race conditions then to manually create a mutex when modifying multiple variables. diff --git a/docs/p4.pdf b/docs/p4.pdf Binary files differindex 858774b..86c225c 100644 --- a/docs/p4.pdf +++ b/docs/p4.pdf @@ -12,22 +12,15 @@ using namespace std; -//defaults - -//TODO remove temp_settings +//Argument defaults. Really not used to using constants over preprocessor defines; this feels cursed const uint32_t DEFAULT_WIDTH = 1920; const uint32_t DEFAULT_HEIGHT = 1080; const int DEFAULT_JOBS = 1; const string DEFAULT_IMG_PATH = "out.png"; -//CONTENDOR_HI REPLACEMENT - 50000 iterations const complex<double> DEFAULT_MIN_CORD (-0.74364386269 - 0.00000003000, 0.13182590271 - 0.00000003000); const complex<double> DEFAULT_MAX_CORD (-0.74364386269 + 0.00000003000, 0.13182590271 + 0.00000003000); -//CONTENDOR_ZOOM- 50000 iterations -//const complex<double> DEFAULT_MIN_CORD (-0.74364386269 - 0.00000001000, 0.13182590271 - 0.00000001000); -//const complex<double> DEFAULT_MAX_CORD (-0.74364386269 + 0.00000001000, 0.13182590271 + 0.00000001000); - const unsigned int DEFAULT_ITERS = 50000; const unsigned int DEFAULT_BAILOUT = 256; @@ -66,10 +59,45 @@ bool getopt_int(t& number, char *optarg, char opt, char *arg) { return false; } +/** colors using linear histrogram method with generic hue shift **/ +//TODO figure out how to pass constant arrays without allowing pointed material to be modified +void calc_colors(const double *value_map, unsigned int *histogram, png &image, unsigned int max_iters) { + double below, above, hue; + int c; + uint32_t x, y; + int rgb[3]; + unsigned int histogram_sum = 0; + double current_hue = 0; + double *freq_hue = new double[max_iters](); + + //find the sum of all histogram values, we could ajust this to increase or decrease contrast + for(unsigned int p = 0; p < max_iters; p++) histogram_sum += histogram[p]; + + for(unsigned int i = 0; i < max_iters; i++) { + current_hue += histogram[i] / (double)histogram_sum; + freq_hue[i] = current_hue; + } + + for(y = 0; y < image.height(); y++) { + for(x = 0; x < image.width(); x++) { + below = freq_hue[(int)value_map[(y * image.width()) + x]]; + above = freq_hue[(int)ceil(value_map[((y * image.width()) + x) + 1])]; + hue = (((above - below) * fmod(value_map[(y * image.width()) + x], 1.0)) + below); + rgb[0] = 255 * cos((M_PI * hue) - M_PI); + rgb[1] = 255 * cos((M_PI * hue) - ((M_PI) / 2.0)); + rgb[2] = 255 * cos(M_PI * hue); + for(c = 0; c < 3; c++) if(rgb[c] < 0) rgb[c] = 0; + image.set_pixel(x, y, (png_byte)rgb[0], (png_byte)rgb[1], (png_byte)rgb[2]); + } + } +} + int main(int argc, char **argv) { + + //argument options uint32_t width = DEFAULT_WIDTH; uint32_t height = DEFAULT_HEIGHT; @@ -80,10 +108,9 @@ int main(int argc, char **argv) { unsigned int m_iters = DEFAULT_ITERS; unsigned int bailout = DEFAULT_BAILOUT; bool jobs_set = false; + int arg; //for getopt - //I could not find a better way to turn a string into a complex variable stringstream complex_str_buffer; - int arg; while((arg = getopt(argc, argv, "hw:H:o:j:c:C:i:I:")) != -1) { switch(arg) { case 'h': @@ -129,15 +156,11 @@ int main(int argc, char **argv) { "See " << argv[0] << " -h for help.\n" << endl; } - double *vmap = new double[width * height]; + //dependent on getopt settings + double *bail_map = new double[width * height]; unsigned int *histogram = new unsigned int[m_iters](); - unsigned int histogram_sum = 0; - double *freq_hue = new double[m_iters](); - double current_hue = 0; - unsigned int width_per_job = width / jobs; atomic<uint32_t> progress(0); - png image(img_path, width, height); thread threads[jobs]; @@ -149,14 +172,14 @@ int main(int argc, char **argv) { for(unsigned int j = 0; j < jobs - 1; j++) { worker_objects[j] = new mthread(j * width_per_job, (j + 1) * width_per_job, min_cord, max_cord, bailout, m_iters, - image, vmap, histogram, worker_objects, j, jobs, progress); + image, bail_map, histogram, worker_objects, j, jobs, progress); } //last worker thread needs the width to go all the way to the edge of the screen, //regardless of rounding issues worker_objects[jobs - 1] = new mthread((jobs - 1) * width_per_job, width - 1, min_cord, max_cord, bailout, m_iters, - image, vmap, histogram, worker_objects, jobs - 1, jobs, progress); + image, bail_map, histogram, worker_objects, jobs - 1, jobs, progress); for(unsigned int j = 0; j < jobs; j++) worker_objects[j]->dispatch(); @@ -173,36 +196,12 @@ int main(int argc, char **argv) { //now to color the image cout << "Coloring image... (this shouldn't take more then a few seconds)" << endl; - //find the sum of all histogram values, we could ajust this to increase or decrease contrast - for(unsigned int p = 0; p < m_iters; p++) histogram_sum += histogram[p]; - - for(unsigned int i = 0; i < m_iters; i++) { - current_hue += histogram[i] / (double)histogram_sum; - freq_hue[i] = current_hue; - } - - //now to calculate the colors - { - double below, above, hue; - int c; - uint32_t x, y; - int rgb[3]; - for(y = 0; y < height; y++) { - for(x = 0; x < width; x++) { - below = freq_hue[(int)vmap[(y * width) + x]]; - above = freq_hue[(int)ceil(vmap[((y * width) + x) + 1])]; - hue = (((above - below) * fmod(vmap[(y * width) + x], 1.0)) + below); - rgb[0] = 255 * cos((M_PI * hue) - M_PI); - rgb[1] = 255 * cos((M_PI * hue) - ((M_PI) / 2.0)); - rgb[2] = 255 * cos(M_PI * hue); - for(c = 0; c < 3; c++) if(rgb[c] < 0) rgb[c] = 0; - image.set_pixel(x, y, (png_byte)rgb[0], (png_byte)rgb[1], (png_byte)rgb[2]); - } - } - } + //actually writes image as well + calc_colors(bail_map, histogram, image, m_iters); for(unsigned int j = 0; j < jobs; j++) delete worker_objects[j]; + //image will be deleted (and written) upon funciton exit cout << "Image exported to " << img_path << "." << endl; } |