/* Circular moire pattern generator. ./circular_moire_dither_bayer > output.pgm Forked from circular_moire.c to use ordered dither pattern. https://en.wikipedia.org/wiki/Ordered_dithering */ #include #include #include #include #ifdef _WIN32 #include #include #endif #define CIRCLE_COUNT 3 #if 0 #define PATTERN_SIZE 4 static const int pattern[PATTERN_SIZE][PATTERN_SIZE] = { { 0, 8, 2, 10}, {12, 4, 14, 6}, { 3, 11, 1, 9}, {15, 7, 13, 5} }; #else #define PATTERN_SIZE 8 static const int pattern[PATTERN_SIZE][PATTERN_SIZE] = { { 0, 32, 8, 40, 2, 34, 10, 42}, {48, 16, 56, 24, 50, 18, 58, 26}, {12, 44, 4, 36, 14, 46, 6, 38}, {60, 28, 52, 20, 62, 30, 54, 22}, { 3, 35, 11, 43, 1, 33, 9, 41}, {51, 19, 59, 27, 49, 17, 57, 25}, {15, 47, 7, 39, 13, 45, 5, 37}, {63, 31, 55, 23, 61, 29, 53, 21} }; #endif int main(int argc, char **argv) { int width, height, x, y, i; double cx[CIRCLE_COUNT], cy[CIRCLE_COUNT], scale[CIRCLE_COUNT], a; if( argc != 3 || (width = atoi(argv[1])) <= 0 || (height = atoi(argv[2])) <= 0 ) { return printf("%s \n", *argv); } if( width >= 0x8000 || height >= 0x8000 ) return !puts("Output size too large."); #ifdef _WIN32 setmode(STDOUT_FILENO, O_BINARY); #endif srand(time(NULL)); for(i = 0; i < CIRCLE_COUNT; i++) { cx[i] = (double)rand() / RAND_MAX * width; cy[i] = (double)rand() / RAND_MAX * height; scale[i] = ((double)rand() / RAND_MAX * 30.0 + 6.0) / (width < height ? width : height); } printf("P5\n%d %d\n255\n", width, height); for(y = 0; y < height; y++) { for(x = 0; x < width; x++) { a = 0; for(i = 0; i < CIRCLE_COUNT; i++) a += sin(hypot(x - cx[i], y - cy[i]) * scale[i]) + 1.0; a /= 2.0 * CIRCLE_COUNT; a = a + (pattern[y % PATTERN_SIZE][x % PATTERN_SIZE] / (double)(PATTERN_SIZE * PATTERN_SIZE) - 0.5); fputc(a > 0.5 ? 255 : 0, stdout); } } return 0; }