/* split a ppm image into separate rgb files */

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

static inline unsigned char clamp(int x)
{
  return x&0xFF;
}

int main(int argc, char *argv[])
{
  int w, h;
  int i, j;
  FILE *in,*out;
  char *name;
  char redname[64];
  char greenname[64];
  char bluename[64];
  char line[256];
  unsigned char *buf = NULL;
  unsigned char *new = NULL;
  unsigned char *a, *b;

  name = argv[1];
  snprintf(redname, 64, "%s-red", name);
  snprintf(greenname, 64, "%s-green", name);
  snprintf(bluename, 64, "%s-blue", name);

  in = fopen(name, "rb");
  fgets(line, 256, in);
  if (memcmp(line, "P6", 2)) {
	fprintf(stderr, "%s is not a ppm file\n", name);
	exit(1);
  }
  fgets(line, 256, in);
  sscanf(line, "%d %d", &w, &h);
  fprintf(stderr, "%s looks like a %dx%d ppm file\n", name, w, h);

  buf = malloc(3*w*h);
  fread(buf, 3, w*h, in);
  fclose(in);

  new = malloc(3*w*h);

  fprintf(stderr, "saving red channel to %s\n", redname);
  a = buf;
  b = new;
  for (j = 0; j < h; j++) {
    for (i = 0; i < w; i++) {
      *b++ = *a; a++;
      *b++ = 0; a++;
      *b++ = 0; a++;
    }
  }
  out = fopen(redname, "wb");
  fprintf(out, "P6\n%d %d\n255\n", w, h);
  fwrite(new, 3, w*h, out);
  fclose(out);

  fprintf(stderr, "saving green channel to %s\n", greenname);
  a = buf;
  b = new;
  for (j = 0; j < h; j++) {
    for (i = 0; i < w; i++) {
      *b++ = 0; a++;
      *b++ = *a; a++;
      *b++ = 0; a++;
    }
  }
  out = fopen(greenname, "wb");
  fprintf(out, "P6\n%d %d\n255\n", w, h);
  fwrite(new, 3, w*h, out);
  fclose(out);

  fprintf(stderr, "saving blue channel to %s\n", bluename);
  a = buf;
  b = new;
  for (j = 0; j < h; j++) {
    for (i = 0; i < w; i++) {
      *b++ = 0; a++;
      *b++ = 0; a++;
      *b++ = *a; a++;
    }
  }
  out = fopen(bluename, "wb");
  fprintf(out, "P6\n%d %d\n255\n", w, h);
  fwrite(new, 3, w*h, out);
  fclose(out);

  fprintf(stderr, "converting image to YCrCb\n");
  a = buf;
  b = new;
  for (j = 0; j < h; j++) {
    for (i = 0; i < w; i++) {
       b[0] = clamp(0.257*a[0] + 0.504*a[1] + 0.098*a[2]);
       b[1] = clamp(0.439*a[0] + 0.368*a[1] - 0.071*a[2]);
       b[2] = clamp(-0.148*a[0] - 0.291*a[1] + 0.439*a[2]);
       a += 3; b += 3;
    }
  }

  snprintf(redname, 32, "%s-Y", name);
  fprintf(stderr, "saving Y channel to %s\n", redname);
  out = fopen(redname, "wb");
  fprintf(out, "P6\n%d %d\n255\n", w, h);
  b = new;
  for (j = 0; j < h; j++) {
    for (i = 0; i < w; i++) {
      fwrite(b, 1, 1, out);
      fwrite(b, 1, 1, out);
      fwrite(b, 1, 1, out);
      b += 3;
    }
  }
  fclose(out);
 
  snprintf(redname, 32, "%s-Cr", name);
  fprintf(stderr, "saving Cr channel to %s\n", redname);
  out = fopen(redname, "wb");
  fprintf(out, "P6\n%d %d\n255\n", w, h);
  b = new;
  for (j = 0; j < h; j++) {
    for (i = 0; i < w; i++) {
      fwrite(b+1, 1, 1, out);
      fwrite("\0", 1, 1, out);
      fwrite("\0", 1, 1, out);
      b += 3;
    }
  }
  fclose(out);
 
  snprintf(redname, 32, "%s-Cb", name);
  fprintf(stderr, "saving Cb channel to %s\n", redname);
  out = fopen(redname, "wb");
  fprintf(out, "P6\n%d %d\n255\n", w, h);
  b = new;
  for (j = 0; j < h; j++) {
    for (i = 0; i < w; i++) {
      fwrite("\0", 1, 1, out);
      fwrite("\0", 1, 1, out);
      fwrite(b+2, 1, 1, out);
      b += 3;
    }
  }
  fclose(out);
 

  free(new);
  free(buf);

  return 0;
}


