//##############################################################################
// Author : Aviral Mittal
// Author's Email : avimit@yahoo.com
// University of Edinburgh
//
//This program extracts frames from a qcif file and stores them in pgm format
//Which can be read using xv tool.
//Usage: unix> qcif_read <in file> <n1-n2>
//Where n1 is the start frame number, n2 is the end frame number desired.
//Example: unix> qcif_read bridge.qcif 45-47
//This command will produce following 3 files
//0000000045.pgm
//0000000046.pgm
//0000000047.pgm
////////////////////////////////////////////////////////////////////////////////
//Version History
//Version 2.1
//date of release 28 May 2006
//Changes w.r.t prev Release:
//1). file generlised with respect to row,col
//2). Successfully passed pointer to pointer in array
////////////////////////////////////////////////////////////////////////////////
//Notes on passing a multidimensional array in a function.
////////////////////////////////////////////////////////////////////////////////
//an array luma[row][col] should be passed in a function as
//myfunc(char luma[][col], int col); function prototype;
//myfunc(luma,col); function call
//This is because if a sinle dimentional array array1[row] exists
//Then it will be passed in a function as
//myfunc(array1[]);
//myfunc(char luma[][col],col) is similar to myfunc(char * luma[col],col)
//col is being sent so that the function knows how many arrays(signgle dim)
//is being passed.
//Similar to when a single dim array is passed in a function, there must be
//a way to let the function know the number of elements in the array.
////////////////////////////////////////////////////////////////////////////////
//Version History
//Version 2.0
//date of release 27 May 2006
//Changes w.r.t prev Release:
//1). Use of Vectors luma,cb,cr to read valued form file
//2). Use of a function print_luma to write image to file
// The net effect of above changes : The output has become very fast.
////////////////////////////////////////////////////////////////////////////////
//Version History
//Version 1.1
//date of release 24 May 2006
//Changes w.r.t prev Release:
//1. Fixed the bug caused by 'fclose' when called on an unopend file
//   The error message was "Segmentation Fault", which only appeared
//   when using a non 0 start frame number.
//   Because it was trying to close a file which never opened.
//2. The extension of the filename corrected to pgm instead of pmg
//3. The fopen is now done using "rb" instead of "r", after windows bullshited.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//Version History
//Version 1.0
//date of release 23 May 2006
////////////////////////////////////////////////////////////////////////////////
//WARNING!: The command line arguments are not checked. Its the 
//responsibility of the user to put correct command line options
//or funny things might happen.
//##############################################################################
#define NULL (0)
#include <stdio.h>
#include <string.h>
#define roww 144
#define coll 176

//Function Prototype Declaration
void print_header(FILE * fout,int row, int col);
void print_luma(FILE * fout,unsigned char luma[][coll],int row, int col);
void int2str(int xx, char * mstr);
//Function Prototype Declaration Ends

int main(int argc, char * argv[])
{
int kk =0;
int row = roww;
int col = coll;
int prn = 1;//change it to 0 to skip printing of informative messages.
FILE *fi;//fi = fopen(argv[1], "r");
FILE *fr;//fo = fopen(argv[2], "w");
unsigned char def_name[] = "default8A.pgm";
char * inpfile = NULL;
int stfr=0;
int finfr=0;

char * mstr = NULL;

unsigned char luma[row][col];
unsigned char cb[88][72];
unsigned char cr[88][72];


inpfile="default.qcif";

switch(argc)
  {
    case 1 :
      { 
        printf("###################################################\n");
        printf("##This Program extracts frames from qcif file and\n");
        printf("##Stores them in pgm format readable by xv\n");
        printf("###################################################\n");
        printf("Usage: unix> qcif_read <in file> <n1-n2>\n"); 
        printf("Where n1 is the start frame, n2 is the last frame desired\n"); 
        printf("Example: unix> qcif_read bridge.qcif 45-47\n"); 
        printf("###################################################\n");
        exit(-1);
      }// case 1 :
    case 2 :
      { 
        inpfile=argv[1];
        if(prn) printf("INFO! Input file is %s\n",inpfile);
        break;
      }// case 2 :
    case 3 :
      { 
        inpfile=argv[1];
        if(prn) printf("INFO! Input file is %s\n",inpfile);
        //grab start frame and end frame numbers in variables.
        //The input argv is a string. so a string of type
        //23-45 which contains the start and end frame to be printed
        //must be processed to get integers stfr, start frame number
        //finfr, finish frame number.
        while(*argv[2] != '-')
        {
          stfr = *argv[2]-48+stfr; //Convert argv[2] to an integer stfr
          argv[2]++;
          stfr=stfr*10;
        }
        stfr=stfr/10; //Re-adjust the result
        argv[2]++;
        while(*argv[2])
        {
          finfr = *argv[2]-48+finfr;
          argv[2]++;
          finfr=finfr*10;
        }
        finfr=finfr/10; //Re-adjust the result
        break;
      }// case 3 :
    default: 
      {
        printf("ERROR! Too many args at command line. Exiting....\n");
        exit(-1);
      }
  }// switch(argc)

//printf("length of string = %d\n",strlen(def_name));

  printf("Start frame=%d,End frame=%d\n",stfr,finfr);
  mstr = def_name;
  //printf("mstr is now pointing %s\n",mstr);
  if(!(fi = fopen(inpfile, "rb")))
  {
    printf("Cannot open file :%s Exiting . . . .\n",inpfile);
    exit(-1);
  }// if(!(fi = fopen(inpfile, "r")))


 // Read the frame 
   for(kk=0;kk<=finfr;kk++)
   {
     fread(&luma,1,row*col,fi); //read whole luma frame
     if(kk>=stfr) //Only print frame in a file if required
     {
       int2str(kk,mstr);
       printf("Output file: %s\n",mstr);
         if(!(fr = fopen(mstr,"w")))
         {
           printf("Cannot open file %s Exiting . . . .\n",mstr);
           exit(-1);
         }
       print_header(fr,row,col);
       print_luma(fr,luma,row,col);
       fclose(fr);
     }// if(kk>=stfr)
     //Now read the Cb Cr values for the same frame
     fread(&cb,1,88*72,fi);
     fread(&cb,1,88*72,fi);
   }// for(kk=0;ii<finfr;kk++)
}// int main(int argc, char * argv[])
void print_header(FILE * fout,int row,int col)
{
  fprintf(fout,"P2\n");
  fprintf(fout,"%d %d\n",col,row);
  fprintf(fout,"255\n");
}// void print_header(char * fname)

void int2str(int xx, char * mstr)
{
  int remainder = 1; 
  int ii =0;
  while(*mstr) mstr++; //point to the end of string;
  mstr=mstr-5; //point to the last character, to overwrite it.
  for(ii=0;ii<9;ii++)
  {
    remainder = xx%10;
    xx = xx/10;
    *mstr = '0'+remainder;//Convert int to char
    mstr--;
  }// for(ii=0;ii<9;ii++)
}// void int2str(int xx, char * mstr)

void print_luma(FILE * fout,unsigned char luma[][coll],int row, int col)
{
  int ii = 0;
  int jj = 0;
  int * temp;
  for(ii=0;ii<row;ii++)
  {
    for(jj=0;jj<col;jj++)
    {
      fprintf(fout,"%d\n",*(*luma+jj));
    }
    luma++;
  }
}// void print_luma(FILE * fout,char luma[][coll],int row, int col);
