/*--------------------------------------------------------------------------*/
/*                                                                          */
/*                      matrix2eps, version 0.2, Aug 2001                   */ 
/*                 by Ben Vollmayr-Lee (bvollmay@bucknell.edu)              */
/*                 free for use, modification, or distribution              */
/*                                                                          */
/*--------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#define MAXLINE 100

main(int argc, char *argv[])
{
  int i,j,nrow,ncol, textcol, outflag, **m, **imatrix(int,int,int,int);
  int color(char *, char *);
  void help(), error(char *);
  void free_imatrix(int **,int, int, int, int);
  char infile[MAXLINE],date[MAXLINE],outfile[MAXLINE], wc[MAXLINE],
    rgb1[MAXLINE], rgb2[MAXLINE];
  FILE *fin, *fout;
  double temp, threshold;

  /*---defaults---*/
  threshold = 0.0;
  strcpy(rgb1,"1 1 1"); 
  strcpy(rgb2,"0 0 0");
  outflag=0;

  /*--- deal with command line options ----*/
  i = 1;
  while( i < argc){
    if( argv[i][0] != '-' ){                               /* input file */
      strcpy(infile,argv[i]);
      i++;
    }
    else if( !strcmp("-h",argv[i]) || !strcmp("--h",argv[i]) ){  /* help */
      help();                                                
    }
    else if( !strcmp("-t",argv[i]) ){                      /* threshold */
      threshold = atof(argv[i+1]);
      i += 2;
    }
    else if( !strcmp("-c",argv[i]) ){                      /* color by name */
      if( color(argv[i+1],rgb1) ) 
	error("matrix2eps: unrecognized first color name\n");
      if( color(argv[i+2],rgb2) ) 
	error("matrix2eps: unrecognized second color name\n");
      i += 3;
    }
    else if( !strcmp("-crgb", argv[i]) ){                   /* color by rgb */
      for(j=1; j<=6; j++) 
	if( argv[i+j][0] == '-' ) 
	  error("matrix2eps: insufficient number of rgb arguments\n");
      sprintf(rgb1,"%s %s %s",argv[i+1],argv[i+2],argv[i+3]);
      sprintf(rgb2,"%s %s %s",argv[i+4],argv[i+5],argv[i+6]);
      i += 7;
    }
    else if( !strcmp("-o",argv[i]) ){                       /* outfile name */
      if( argv[i+1][0] == '-' ) 
	error("matrix2eps: couldn't resolve output file name\n");
      strcpy(outfile,argv[i+1]);
      outflag++;
      i += 2;
    }
    else {                                          /* if nothing else... */
      error("matrix2eps: unresolved command line arguments\n");
    }
  }

  if( !outflag ){
    j=0;
    while( infile[j] != '.' && infile[j] != '\0'){
      outfile[j] = infile[j]; 
      j++;
    }  
    outfile[j] = '\0';
    strcat(outfile,".eps");
  }

  if( (i = open(infile, O_RDONLY, 0)) == -1 )
    error("matrix2eps: unable to open matrix file\n");
  close(i);

  /*--- figure out nrow & ncol using Unix wc ---*/
  sprintf(wc,"wc %s > .matrix2eps_wc",infile);  system(wc);
  fin = fopen(".matrix2eps_wc","r");
  fscanf(fin,"%d%d",&nrow,&j);
  fclose(fin);
  if( j % nrow ) fprintf(stderr,"matrix is not properly formatted!\n");
  ncol = j/nrow;
  if( nrow % 2 ) fprintf(stderr,"matrix has an odd number of rows\n");
  if( ncol % 2 ) fprintf(stderr,"matrix has an odd number of columns\n");
  system("\\rm .matrix2eps_wc");

  m = imatrix(1,ncol,1,nrow);
  fin = fopen(infile,"r");
  for(j=1; j<=nrow; j++)
    for(i=1; i<=ncol; i++){
      fscanf(fin,"%lf",&temp);
      if(temp < threshold) m[i][j] = 0; 
      else m[i][j] = 1; 
    }  
  fclose(fin);
 
  /*---output----*/
  fout = fopen(outfile,"w");
  fprintf(fout,"%%!PS-Adobe-2.0\n");
  fprintf(fout,"%%%%Title: %s\n",outfile);
  fprintf(fout,"%%%%Creator: matrix2eps version 0.1.1\n");
  fprintf(fout,"%%%%CreationDate: ");
  fclose(fout);
  sprintf(date,"date >> %s",outfile);
  system(date);
  fout = fopen(outfile,"a");
  fprintf(fout,"%%%%BoundingBox: 0 0 %d %d\n",ncol+1,nrow+1);
  fprintf(fout,"%%%%Orientation: none of your business!\n");
  fprintf(fout,"%%%%Pages: 1\n");
  fprintf(fout,"%%%%EndComments\n");
  fprintf(fout,"/V {newpath moveto %s setrgbcolor\n",rgb1);
  fprintf(fout,"0 1 rlineto 1 0 rlineto 0 -1 rlineto closepath\n");
  fprintf(fout,"fill } def\n");
  fprintf(fout,"/W {newpath moveto %s setrgbcolor\n",rgb2);
  fprintf(fout,"0 1 rlineto 1 0 rlineto 0 -1 rlineto closepath\n");
  fprintf(fout,"fill } def\n");
  fprintf(fout,"/A {2 0 translate 0 0 V 0 1 V 1 0 V 1 1 V} def\n");
  fprintf(fout,"/B {2 0 translate 0 0 V 0 1 V 1 0 V 1 1 W} def\n");
  fprintf(fout,"/C {2 0 translate 0 0 V 0 1 V 1 0 W 1 1 V} def\n");
  fprintf(fout,"/D {2 0 translate 0 0 V 0 1 V 1 0 W 1 1 W} def\n");
  fprintf(fout,"/E {2 0 translate 0 0 V 0 1 W 1 0 V 1 1 V} def\n");
  fprintf(fout,"/F {2 0 translate 0 0 V 0 1 W 1 0 V 1 1 W} def\n");
  fprintf(fout,"/G {2 0 translate 0 0 V 0 1 W 1 0 W 1 1 V} def\n");
  fprintf(fout,"/H {2 0 translate 0 0 V 0 1 W 1 0 W 1 1 W} def\n");
  fprintf(fout,"/I {2 0 translate 0 0 W 0 1 V 1 0 V 1 1 V} def\n");
  fprintf(fout,"/J {2 0 translate 0 0 W 0 1 V 1 0 V 1 1 W} def\n");
  fprintf(fout,"/K {2 0 translate 0 0 W 0 1 V 1 0 W 1 1 V} def\n");
  fprintf(fout,"/L {2 0 translate 0 0 W 0 1 V 1 0 W 1 1 W} def\n");
  fprintf(fout,"/M {2 0 translate 0 0 W 0 1 W 1 0 V 1 1 V} def\n");
  fprintf(fout,"/N {2 0 translate 0 0 W 0 1 W 1 0 V 1 1 W} def\n");
  fprintf(fout,"/O {2 0 translate 0 0 W 0 1 W 1 0 W 1 1 V} def\n");
  fprintf(fout,"/P {2 0 translate 0 0 W 0 1 W 1 0 W 1 1 W} def\n");
  fprintf(fout,"/T {-%d 2 translate} def\n",ncol);
  fprintf(fout,"-1 1 translate\n");
  textcol=0;
  for(j=1; j<nrow; j += 2){
    for(i=1; i<ncol; i += 2){
      fputc(8*m[i][j] + 4*m[i][j+1] + 2*m[i+1][j] + m[i+1][j+1] + 'A',fout);
      textcol += 2;
      if( textcol < 77)  fputc(' ',fout);
      else{              fputc('\n',fout); textcol = 0; }
    }
    fputc('T',fout);
    textcol += 2;
    if( textcol < 77)  fputc(' ',fout);
    else{              fputc('\n',fout); textcol = 0; }
  }
  fclose(fout);
  return;
}

int **imatrix(int nrl, int nrh, int ncl, int nch)
{
   int i,**m;
   
   m=(int **)malloc((unsigned) (nrh-nrl+1)*sizeof(int*));
   m -= nrl;

   for(i=nrl; i<=nrh; i++){
      m[i]=(int *)malloc((unsigned) (nch-ncl+1)*sizeof(int));
      m[i] -= ncl;
    }
   return m;
 }


void free_imatrix(int **m, int nrl, int nrh, int ncl, int nch)
{
   int i;

   for(i=nrh; i>=nrl; i--) free((char*) (m[i]+ncl));
   free((char*) (m+nrl));
 }

int color(char *name, char *rgb)
{
   int error=0;

   if( !strcmp(name,"blue") ) strcpy(rgb,"0 0 1");
   else if( !strcmp(name,"red") ) strcpy(rgb,"1 0 0");
   else if( !strcmp(name,"green") ) strcpy(rgb,"0 1 0");
   else if( !strcmp(name,"black") ) strcpy(rgb,"0 0 0");
   else if( !strcmp(name,"white") ) strcpy(rgb,"1 1 1");
   else if( !strcmp(name,"purple") ) strcpy(rgb,"0.7 0 0.7");
   else if( !strcmp(name,"yellow") ) strcpy(rgb,"0.7 0.7 0");
   else if( !strcmp(name,"aqua") ) strcpy(rgb,"0 0.7 0.7");
   else error=1;
   
   return error;
}

void help()
{
  void usage();
  fprintf(stderr,"matrix2eps (version 0.2)\n\nConverts matrix data (n rows of m cols) to encapsulated postscript\n");
  fprintf(stderr,"(C) Copyright 2001 Benjamin P. Vollmayr-Lee (bvollmay@bucknell.edu)\n");
  fprintf(stderr,"\n");
  usage();
  fprintf(stderr,"\n");
  fprintf(stderr,"Matrix data is converted to one of two colors (default black and white),\n");
  fprintf(stderr,"depending on whether it is above or below a threshold value (default 0).\n");
  fprintf(stderr,"Must have an even number of rows and columns.\n");
  fprintf(stderr,"\n");
  fprintf(stderr,"Available options:\n");
  fprintf(stderr,"   -c color1 color2         Color names: aqua,black,blue,green,purple,red,\n");
  fprintf(stderr,"                            white,yellow (default: black white)\n");
  fprintf(stderr,"   -crgb r1 g1 b1 r2 g2 b2  RGB color values, range 0 to 1 (default 0 0 0 1 1 1)\n");
  fprintf(stderr,"   -h --h                   Help\n");
  fprintf(stderr,"   -o filename              Specify output file (default inputfile.eps)\n");
  fprintf(stderr,"   -t threshold             Set threshold value (default 0)\n");
  exit(0);
}

void error(char *message)
{
  void usage();
  fprintf(stderr,message);
  usage();
  exit(1);
}

void usage()
{
  fprintf(stderr,"usage: matrix2eps filename.mtr [-c color1 color2][-crgb r1 g1 b1 r2 g2 b2]\n");
  fprintf(stderr,"                  [-h --h][-o filename][-t threshold]\n");
  fprintf(stderr,"produces: filename.eps (unless -o is used)\n");
  return;
}

