/* cloud1.c - Don Yang (uguu.org) 09/26/09 */ #include #include #include #define DIVISION_COUNT 10 #define IMAGE_SIZE (1 << DIVISION_COUNT) #define INIT_RANGE 0.3 #define INIT_OFFSET 0.0 #define ROUGHNESS 0.9 #define RandomNumber() (((double)rand()) / (double)RAND_MAX) static double Image[IMAGE_SIZE + 1][IMAGE_SIZE + 1]; static void GenerateImage(void) { int x, y, cx, cy, nx, ny, step; double displace_scale; /* Generate corners */ Image[0][0] = INIT_OFFSET + INIT_RANGE * RandomNumber(); Image[IMAGE_SIZE][0] = INIT_OFFSET + INIT_RANGE * RandomNumber(); Image[0][IMAGE_SIZE] = INIT_OFFSET + INIT_RANGE * RandomNumber(); Image[IMAGE_SIZE][IMAGE_SIZE] = INIT_OFFSET + INIT_RANGE * RandomNumber(); /* Divide recursively */ displace_scale = ROUGHNESS; for(step = IMAGE_SIZE; step > 1; step /= 2) { for(y = 0; y < IMAGE_SIZE; y = ny) { cy = y + step / 2; ny = y + step; for(x = 0; x < IMAGE_SIZE; x = nx) { cx = x + step / 2; nx = x + step; /* Add center point */ Image[cy][cx] = (Image[y][x] + Image[y][nx] + Image[ny][x] + Image[ny][nx]) / 4.0; /* Add edge points */ Image[y][cx] = (Image[y][x] + Image[y][nx] + Image[cy][cx]) / 3.0; Image[cy][x] = (Image[y][x] + Image[cy][cx] + Image[ny][x]) / 3.0; Image[cy][nx] = (Image[y][nx] + Image[cy][cx] + Image[ny][nx]) / 3.0; Image[ny][cx] = (Image[cy][cx] + Image[ny][x] + Image[ny][nx]) / 3.0; /* Display newly added points */ Image[y][cx] += (RandomNumber() - 0.5) * displace_scale; Image[cy][x] += (RandomNumber() - 0.5) * displace_scale; Image[cy][cx] += (RandomNumber() - 0.5) * displace_scale; Image[cy][nx] += (RandomNumber() - 0.5) * displace_scale; Image[ny][cx] += (RandomNumber() - 0.5) * displace_scale; } } displace_scale *= 0.5; } } /* Write image to stdout */ static void WriteImage() { int x, y, c; printf("P2\n%d %d\n255\n", IMAGE_SIZE, IMAGE_SIZE); for(y = 0; y < IMAGE_SIZE; y++) { for(x = 0; x < IMAGE_SIZE; x++) { c = (int)(Image[y][x] * 255); if( c < 0 ) { (void)puts("0"); } else if( c > 255 ) { (void)puts("255"); } else { printf("%d\n", c); } } } } int main(void) { srand((unsigned)time(NULL)); GenerateImage(); WriteImage(); return 0; }