/* write a color bar with (roughly) logarithmic scale as BMP image to FILE. */ static void write_scale(apr_file_t *file) { int x; word value = 0, inc = 1; /* write header to file */ write_bitmap_header(file, 64, 1); for (x = 0; x < 64; ++x) { apr_size_t written; byte color[3] = { 128, 128, 128 }; select_color(color, value); if (value + (int)inc < 0x10000) { value += inc; if (value >= 8 * inc) inc *= 2; } written = sizeof(color); apr_file_write(file, color, &written); } }
/* Write the cluster read map for all files in INFO as BMP image to FILE. * If MAX_X is not 0, scale all lines to MAX_X pixels. Use POOL for * allocations. */ static void write_bitmap(apr_array_header_t *info, int max_x, apr_file_t *file, apr_pool_t *pool) { int ysize = info->nelts; int xsize = 0; int x, y; apr_size_t row_size; apr_size_t written; color_t *line, *scaled_line; svn_boolean_t do_scale = max_x > 0; /* xsize = max cluster number */ for (y = 0; y < ysize; ++y) if (xsize < APR_ARRAY_IDX(info, y, file_stats_t *)->read_map->nelts) xsize = APR_ARRAY_IDX(info, y, file_stats_t *)->read_map->nelts; /* limit picture dimensions (16k pixels in each direction) */ if (xsize >= 0x4000) xsize = 0x3fff; if (ysize >= 0x4000) ysize = 0x3fff; if (max_x == 0) max_x = xsize; /* rows in BMP files must be aligned to 4 bytes */ row_size = APR_ALIGN(max_x * sizeof(color_t), 4); /**/ line = apr_pcalloc(pool, xsize * sizeof(color_t)); scaled_line = apr_pcalloc(pool, row_size); /* write header to file */ write_bitmap_header(file, max_x, ysize); /* write all rows */ for (y = 0; y < ysize; ++y) { file_stats_t *file_info = APR_ARRAY_IDX(info, y, file_stats_t *); int block_count = file_info->read_map->nelts; for (x = 0; x < xsize; ++x) { color_t color = { 128, 128, 128 }; if (x < block_count) { word count = APR_ARRAY_IDX(file_info->read_map, x, word); select_color(color, count); } memcpy(line[x], color, sizeof(color)); } scale_line(scaled_line, max_x, line, block_count ? block_count : 1); written = row_size; apr_file_write(file, do_scale ? scaled_line : line, &written); } }
int generate_mandelbrot_simple(const char* filename) { int return_code = EXIT_FAILURE; unsigned long start, end; // Allocate buffer for picture data pixel_data_t *data = calloc(WIDTH * HEIGHT, sizeof(pixel_data_t)); if (data) { // Create and open the output file FILE *file = fopen(filename, "wb"); if (file) { // write the header write_bitmap_header(file, WIDTH, HEIGHT); // init time measurement start = current_time_millis(); // calculate the data for the picture calc_mandelbrot(data, WIDTH, HEIGHT, 0, 0, WIDTH, HEIGHT); // write the data to the file fwrite(data, sizeof(pixel_data_t), WIDTH * HEIGHT, file); // close the file fclose(file); // print the measured time end = current_time_millis(); printf("%.2f seconds\n", (double) (end - start) / 1000); // success return_code = EXIT_SUCCESS; } else { printf("Could not create the output file: %s\n", strerror(errno)); } // free buffer free(data); } else { printf("Could not allocate memory for buffer.\n"); } return return_code; }
int generate_mandelbrot_loop(const char* filename) { int return_code = EXIT_FAILURE; unsigned long start, end; // Create and open the output file, write header FILE *file = fopen(filename, "wb"); if (!file) { printf("Could not create the output file: %s\n", strerror(errno)); return return_code; } // write header write_bitmap_header(file, WIDTH, HEIGHT); // close file handler fclose(file); // init time measurement start = current_time_millis(); //return -1; // Loop int i; for (i=1; i<=MAX_PROCESSES; i++) { // Slicing: Slice width, height and offsets int sliceWidth = WIDTH; int sliceHeight = HEIGHT/MAX_PROCESSES; int widthOffset = 0; int heightOffset = (i-1) * sliceHeight; // Allocate buffers for picture data pixel_data_t *data = calloc(sliceWidth * sliceHeight, sizeof(pixel_data_t)); if (data) { // Open the output file FILE *file = fopen(filename, "a+"); if (file) { // calculate the data for the picture calc_mandelbrot(data, WIDTH, HEIGHT, widthOffset, heightOffset, sliceWidth, sliceHeight); // write the data to the file fwrite(data, sizeof(pixel_data_t), sliceWidth * sliceHeight, file); // close the file fclose(file); } else { printf("Could not open the output file: %s\n", strerror(errno)); return return_code; } // free buffer free(data); } else { printf("Could not allocate memory for buffer.\n"); return return_code; } } // print the measured time end = current_time_millis(); printf("\n%.2f seconds\n", (double) (end - start) / 1000); // success return_code = EXIT_SUCCESS; return return_code; }
int generate_mandelbrot_parallel(const char* filename) { int return_code = EXIT_FAILURE; unsigned long start, end; // Create and open the output file, write header FILE *file = fopen(filename, "wb+"); if (!file) { printf("Could not create the output file: %s\n", strerror(errno)); return return_code; } // write header write_bitmap_header(file, WIDTH, HEIGHT); // store header size for later offset long headerOffset = ftell(file); // close file handler fclose(file); // init time measurement start = current_time_millis(); // set up loop and forking variables int i, status; pid_t pid = 1, wpid; for (i=0; i<=MAX_PROCESSES; i++) { if (pid>0) { // in parent process -> fork pid = fork(); } if (pid<0) { // error while forking -> exit program printf("Error while forking: %s\n", strerror(errno)); return return_code; } else if (pid==0) { // in child process -> do image generation work // Slicing: Slice the dimensions of the image into equally sized, horizontal stripes int sliceWidth = WIDTH; int sliceHeight = HEIGHT/MAX_PROCESSES; int widthOffset = 0; int heightOffset = (i-1) * sliceHeight; // Allocate buffers for picture data pixel_data_t *data = calloc(sliceWidth * sliceHeight, sizeof(pixel_data_t)); if (data) { // Open the output file FILE *file = fopen(filename, "rb+"); if (file) { // calculate the data for the picture calc_mandelbrot(data, WIDTH, HEIGHT, widthOffset, heightOffset, sliceWidth, sliceHeight); // seek right position // SizeOfPixel * NumberOfPixels * PositionOfTheCurrentSlice + HeaderSize long byteoffset = sizeof(pixel_data_t)*sliceWidth*sliceHeight*(i-1) + headerOffset; fseek(file, byteoffset, SEEK_SET); // write the data to the file fwrite(data, sizeof(pixel_data_t), sliceWidth * sliceHeight, file); // close the file fclose(file); // exit the process, return to main exit(1); } else { printf("Could not open the output file: %s\n", strerror(errno)); return return_code; } // free buffer free(data); } else { printf("Could not allocate memory for buffer.\n"); return return_code; } } } // wait for children to finish for (i=0; i<MAX_PROCESSES; i++) { wait(&status); } //re-write header in case it got overwritten - yes we know this is a bug. we don't know how to solve it. this gets around the symptoms, it's as good as we got it file = fopen(filename, "rb+"); if (!file) { printf("Could not create the output file: %s\n", strerror(errno)); return return_code; } fseek(file, 0, SEEK_SET); // write header write_bitmap_header(file, WIDTH, HEIGHT); // close file handler fclose(file); // print the measured time end = current_time_millis(); printf("\n%.2f seconds\n", (double) (end - start) / 1000); // success return_code = EXIT_SUCCESS; return return_code; }