Decoupling rendering and colouring.
[maximus:book.git] / colour.c
1 #include <math.h>
2 #include <stdio.h>
3
4 int channel(float c) {
5   return fminf(fmaxf(roundf(255 * c), 0), 255);
6 }
7
8 void hsv2rgb(float h, float s, float v, float *red, float *grn, float *blu) {
9   float i, f, p, q, t, r, g, b;
10   if (s == 0) { r = g = b = v; } else {
11     h = 6 * (h - floorf(h));
12     int ii = i = floorf(h);
13     f = h - i;
14     p = v * (1 - s);
15     q = v * (1 - (s * f));
16     t = v * (1 - (s * (1 - f)));
17     switch(ii) {
18       case 0: r = v; g = t; b = p; break;
19       case 1: r = q; g = v; b = p; break;
20       case 2: r = p; g = v; b = t; break;
21       case 3: r = p; g = q; b = v; break;
22       case 4: r = t; g = p; b = v; break;
23       default:r = v; g = p; b = q; break;
24     }
25   }
26   *red = r;
27   *grn = g;
28   *blu = b;
29 }
30
31 void colour(int *r, int *g, int *b, int final_n) {
32   float hue = final_n / 64.0f;
33   float sat = (final_n & 1) ? 0.75f : 0.25f;
34   float val = (final_n == 0) ? 0.0f :
35               (final_n & 2) ? 0.75f : 0.25f;
36   float red, grn, blu;
37   hsv2rgb(hue, sat, val, &red, &grn, &blu);
38   *r = channel(red);
39   *g = channel(grn);
40   *b = channel(blu);
41 }
42
43 int main() {
44   int width = 0;
45   int height = 0;
46   if (2 == scanf("P6 %d %d 255", &width, &height)) {
47     if (getchar() == '\n') {
48       printf("P6\n%d %d\n255\n", width, height);
49       for (int j = 0; j < height; ++j) {
50         for (int i = 0; i < width; ++i) {
51           int r = getchar();
52           int g = getchar();
53           int b = getchar();
54           int final_n = (r << 16) | (g << 8) | b;
55           colour(&r, &g, &b, final_n);
56           putchar(r);
57           putchar(g);
58           putchar(b);
59         }
60       }
61     }
62   }
63   return 0;
64 }