#include #include #include /* write_bmp_header(): * * In: * f: A file open for writing ('w') * (width, height): image dimensions * * Return: * 0 on success, -1 on failure * */ int write_bmp_header(FILE *f, int width, int height) { unsigned int row_size_in_bytes = width * 3 + ((width * 3) % 4 == 0 ? 0 : (4 - (width * 3) % 4)); // Define all fields in the bmp header char id[2] = "BM"; unsigned int filesize = 54 + (int)(row_size_in_bytes * height * sizeof(char)); short reserved[2] = {0,0}; unsigned int offset = 54; unsigned int size = 40; unsigned short planes = 1; unsigned short bits = 24; unsigned int compression = 0; unsigned int image_size = width * height * 3 * sizeof(char); int x_res = 0; int y_res = 0; unsigned int ncolors = 0; unsigned int importantcolors = 0; // Write the bytes to the file, keeping track of the // number of written "objects" size_t ret = 0; ret += fwrite(id, sizeof(char), 2, f); ret += fwrite(&filesize, sizeof(int), 1, f); ret += fwrite(reserved, sizeof(short), 2, f); ret += fwrite(&offset, sizeof(int), 1, f); ret += fwrite(&size, sizeof(int), 1, f); ret += fwrite(&width, sizeof(int), 1, f); ret += fwrite(&height, sizeof(int), 1, f); ret += fwrite(&planes, sizeof(short), 1, f); ret += fwrite(&bits, sizeof(short), 1, f); ret += fwrite(&compression, sizeof(int), 1, f); ret += fwrite(&image_size, sizeof(int), 1, f); ret += fwrite(&x_res, sizeof(int), 1, f); ret += fwrite(&y_res, sizeof(int), 1, f); ret += fwrite(&ncolors, sizeof(int), 1, f); ret += fwrite(&importantcolors, sizeof(int), 1, f); // Success means that we wrote 17 "objects" successfully return (ret != 17); } /* * compute_julia_pixel(): compute RBG values of a pixel in a * particular Julia set image. * * In: * (x,y): pixel coordinates * (width, height): image dimensions * tint_bias: a float to "tweak" the tint (1.0 is "no tint") * Out: * rgb: an already-allocated 3-byte array into which R, G, and B * values are written. * * Return: * 0 in success, -1 on failure * */ int compute_julia_pixel(int x, int y, int width, int height, float tint_bias, unsigned char *rgb) { // Check coordinates if ((x < 0) || (x >= width) || (y < 0) || (y >= height)) { fprintf(stderr,"Invalid (%d,%d) pixel coordinates in a %d x %d image\n", x, y, width, height); return -1; } // "Zoom in" to a pleasing view of the Julia set float X_MIN = -1.6, X_MAX = 1.6, Y_MIN = -0.9, Y_MAX = +0.9; float float_y = (Y_MAX - Y_MIN) * (float)y / height + Y_MIN ; float float_x = (X_MAX - X_MIN) * (float)x / width + X_MIN ; // Point that defines the Julia set float julia_real = -.79; float julia_img = .15; // Maximum number of iteration int max_iter = 300; // Compute the complex series convergence float real=float_y, img=float_x; int num_iter = max_iter; while (( img * img + real * real < 2 * 2 ) && ( num_iter > 0 )) { float xtemp = img * img - real * real + julia_real; real = 2 * img * real + julia_img; img = xtemp; num_iter--; } // Paint pixel based on how many iterations were used, using some funky colors float color_bias = (float) num_iter / max_iter; rgb[0] = (num_iter == 0 ? 200 : - 500.0 * pow(tint_bias, 1.2) * pow(color_bias, 1.6)); rgb[1] = (num_iter == 0 ? 100 : -255.0 * pow(color_bias, 0.3)); rgb[2] = (num_iter == 0 ? 100 : 255 - 255.0 * pow(tint_bias, 1.2) * pow(color_bias, 3.0)); return 0; } int main(int argc, char **argv){ if(argc != 2){ fprintf(stderr, "Usage: %s \n", argv[0]); exit(EXIT_FAILURE); } int n = atoi(argv[1]); if(n % 2 == 1){ fprintf(stderr, "n (%d) should be even!\n", n); exit(EXIT_FAILURE); } unsigned char *v = (unsigned char *) malloc(n * 2 * n * 3 * sizeof(unsigned char)); int x,y ; for(x = 0; x < 2 * n; x++) for(y = 0; y < n; y++) if(compute_julia_pixel(x, y, 2 * n, n, 1.0, &v[x * n + y]) == -1) printf("error computing pixel (%d %d)\n", x, y); FILE *f = fopen("julia.bmp", "w"); if(write_bmp_header(f, 2 * n, n) == -1) printf("error writing the header \n"); for(x = 0; x < 2 * n; x++) for(y = 0; y < n; y++) fwrite(&v[x * n + y], sizeof(char), 3, f); fclose(f); free(v); return 0; }