/////////////////////////////////////////////////////////////////////////
// This program is copyright 2000 (c) 2000.                            //
// by Carnegie Mellon University Multirobot Lab                        //
// All rights reserved.                                                //
/////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define I_WIDTH  176
#define I_HEIGHT 144

#define O_COLS  4
#define O_WIDTH (I_WIDTH*O_COLS)

// #define RED(y,u,v)   (int)(1.000*y - 0.000*u + 1.140*v)
// #define GREEN(y,u,v) (int)(1.010*y - 0.374*u - 0.580*v)
// #define BLUE(y,u,v)  (int)(0.948*y + 1.926*u - 0.000*v)

typedef unsigned char uchar;

struct rgb{
  uchar red,green,blue;
};

struct yuv{
  uchar y,u,v;
};


const rgb black = {0,0,0};
const yuv yuv_black = {0,0,0};

#define MAX 255


int bound(int low,int high,int n)
{
  if(n < low ) n = low;
  if(n > high) n = high;
  return(n);
}

rgb yuv2rgb(yuv c)
{
  rgb r;
  int y,u,v;

  y = c.y;
  u = c.u*2 - MAX;
  v = c.v*2 - MAX;

  r.red   = bound(0,MAX,y + u);
  r.green = bound(0,MAX,(int)(y - 0.51*u - 0.19*v));
  r.blue  = bound(0,MAX,y + v);

  return(r);
}

uchar *readppm(char *file,int &width,int &height)
{
  char str[256];
  int w,h;
  uchar *img;
  FILE *in;

  img = NULL;
  in = fopen(file,"rb");
  if(!in) return(NULL);

  fgets(str,256,in);  // header name
  if(strcmp(str,"P6\n")) goto end;

  do{
    fgets(str,256,in); // ignore comments
  }while(str[0] == '#');

  // image dimensions
  w = h = 0;
  sscanf(str,"%d %d",&w,&h);
  if(!w || !h) goto end;

  do{
    fgets(str,256,in); // ignore comments
  }while(str[0] == '#');

  // ignore max value

  img = new uchar[w*h*3];
  if(!img) goto end;

  fread(img,sizeof(uchar),w*h*3,in);
  width = w;
  height = h;
  // printf("Read %s.\n",file);

end:
  fclose(in);
  return(img);
}

void convert(rgb *img,yuv *trn,int ox,int oy,uchar *in)
{
  int x,y,i;
  yuv c;

  for(y=0; y<I_HEIGHT; y++){
    for(x=0; x<I_WIDTH; x++){
      i = (y*I_WIDTH + x)*3;
      c.y = in[i  ];
      c.u = in[i+1];
      c.v = in[i+2];

      trn[(y + oy)*O_WIDTH + x + ox] = c;
      img[(y + oy)*O_WIDTH + x + ox] = yuv2rgb(c);
    }
  }
}

int consolidate(int low,int high,char *imgfile,char *trnfile)
{
  char fname[32];
  uchar *in;
  int iw,ih;

  FILE *out;
  rgb *img;
  yuv *trn;
  int w,h,i;

  if(high < low) return(2);

  w = O_WIDTH;
  h = (((high - low + 1) + O_COLS-1) / O_COLS) * I_HEIGHT;
  img = new rgb[w*h];
  trn = new yuv[w*h];
  if(!img || !trn) return(3);

  for(i=0; i<w*h; i++) img[i] = black;
  for(i=0; i<w*h; i++) trn[i] = yuv_black;

  for(i=low; i<=high; i++){
    sprintf(fname,"%03d.ppm",i);
    in = readppm(fname,iw,ih);

    if(in &&
       iw==I_WIDTH && ih==I_HEIGHT){
      printf("Converting %d...",i);
      convert(img,trn,
          (i%O_COLS)*I_WIDTH,(i/O_COLS)*I_HEIGHT,
          in);
      printf("done.\n");
    }

    if(in) delete(in);
  }

  // Save label file
  out = fopen(imgfile,"wb");
  if(!out) return(4);

  fprintf(out,"P6\n# Created by CM-Trio image converter\n%d %d\n255\n",w,h);
  fwrite(img,sizeof(rgb),w*h,out);
  delete(img);
  fclose(out);

  // Save yuv training example file
  out = fopen(trnfile,"wb");
  if(!out) return(5);

  fprintf(out,"P6\n# Created by CM-Trio image converter\n%d %d\n255\n",w,h);
  fwrite(trn,sizeof(yuv),w*h,out);
  delete(trn);
  fclose(out);

  return(0);
}

int main(int argc,char **argv)
{
  int l,r;

  if(argc != 5){
    printf("Usage: convert <low index> <high index> <image> <examples>\n");
    return(1);
  }

  l = atoi(argv[1]);
  r = atoi(argv[2]);

  return(consolidate(l,r,argv[3],argv[4]));
}
