#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


static int getmagic(FILE *f)
{
   int ic1, ic2;

   if ((ic1 = getc(f)) == EOF) {
       fprintf(stderr, "Premature end of file\n");
       return -1;
   }
   if ((ic2 = getc(f)) == EOF) {
       fprintf(stderr, "Premature end of file\n");
       return -1;
   }
   return ic1 * 256 + ic2;
}

static char pgetc(FILE *f)
{
   register int ic;
   register char c;

   if ((ic = getc(f)) == EOF) {
       fprintf(stderr, "Premature end of file\n");
       return -1;
   }
   c = (char)ic;

   if (c == '#') {
       do {
           if ((ic = getc(f)) == EOF) {
               fprintf(stderr, "Premature end of file\n");
               return -1;
           }
           c = (char)ic;
       } while (c != '\n' && c != '\r');
   }

   return c;
}

static int getint(FILE *f)
{
   register char c;
   register int i;

   do {
       if ((c = pgetc(f)) == -1)
           return -1;
   } while (c == ' ' || c == '\t' || c == '\n' || c == '\r');

   if (c < '0' || c > '9') {
       fprintf(stderr, "Junk in file where an integer should be\n");
       return -1;
   }

   i = 0;
   do {
       i = i * 10 + c - '0';
       if ((c = pgetc(f)) == -1)
           return -1;
   } while (c >= '0' && c <= '9');

   return i;
}

static void readhdr(FILE *f, int *w, int *h)
{
   int magic, maxval;
   static int lastw = -1, lasth = -1;

   if ((magic = getmagic(f)) == -1) exit(1);
   if ((*w = getint(f)) == -1) exit(1);
   if ((*h = getint(f)) == -1) exit(1);
   if ((maxval = getint(f)) == -1) exit(1);

   if (magic != 'P' * 256 + '5') {
       fprintf(stderr, "yuv2rgb: Not a PGM file\n");
       exit(1);
   }
   if (maxval != 255) {
       fprintf(stderr, "yuv2rgb: Maxval != 255\n");
       exit(1);
   }
   if (lastw != -1) {
       if (*w != lastw || *h != lasth) {
           fprintf(stderr, "yuv2rgb: Inconsistent dimensions\n");
           exit(1);
       }
   }
   lastw = *w; lasth = *h;
}

int main(int argc, char **argv)
{
   FILE *fy, *fu, *fv;
   int w, h, x, y;

   if (argc < 4) {
       fprintf(stderr, "usage: yuv2rgb yfile ufile vfile\n");
       exit(1);
   }

   fy = fopen(argv[1], "r");
   fu = fopen(argv[2], "r");
   fv = fopen(argv[3], "r");

   readhdr(fy, &w, &h);
   readhdr(fu, &w, &h);
   readhdr(fv, &w, &h);

   printf("P6\n%d %d\n255\n", w, h);

   for (y = 0; y < h; y++) {
       for (x = 0; x < w; x++) {
           unsigned char y, u, v;
           double c, d, e, rd, gd, bd;
           unsigned char r, g, b;

           fread(&y, 1, 1, fy); fread(&u, 1, 1, fu); fread(&v, 1, 1, fv);

           c = y - 16; d = u - 128; e = v - 128;

           rd = 1.164383 * c + 1.596027 * e + .5;
           gd = 1.164383 * c - 0.391762 * d - 0.812968 * e + .5;
           bd = 1.164383 * c + 2.017232 * d + .5;
           rd = (rd < 0 ? 0 : (rd > 255 ? 255 : rd));
           gd = (gd < 0 ? 0 : (gd > 255 ? 255 : gd));
           bd = (bd < 0 ? 0 : (bd > 255 ? 255 : bd));
           r = rd; g = gd; b = bd;

           fwrite(&r, 1, 1, stdout);
           fwrite(&g, 1, 1, stdout);
           fwrite(&b, 1, 1, stdout);
       }
   }

   return 0;
}