/*  gpr2ps.c - converts a GPR bitmap file to a postscript file
 *
 *  This file contains system-specific graphics routines.
 *  These routines use Apollo Graphics Primitive Resource (GPR) calls.
 *
 *
 *  Bugs/Fixes : If you make any improvements/bug fixes to this program,
 *               please send them to the authors.
 *
 *
 *  Authors and History :
 *
 *  05/13/91    oliveria@caen.engin.umich.edu
 *              Added rotate (-r) option. Support for color postscript
 *              and pixel oriented bitmaps. Added box (-b) option.
 *  02/07/91    ccsmm@uk.ac.bath (Martin Maclaren)
 *              Overhaul.
 *  02/15/90    oliveria@caen.engin.umich.edu
 *              Cleaned it up and converted to sr10.
 *  11/15/88    amadi@caen.engin.umich.edu
 *              Added the -s,-x,-y,-N,-L,bw,-gr,-o,-help options.
 *   ?/ ?/ ?    pha@caen.engin.umich.edu
 *              Original program creation
 */

/*
 * Copyright (C) 1991 by the author(s).
 * All rights reserved.
 *
 * Permission is granted to copy, modify and distribute this program for any
 * purpose and without charge, provided this copyright notice is included in
 * the copy.
 *
 * This program is distributed on an as-is basis.  There will be  ABSOLUTELY
 * NO WARRANTY  for any part of this software to work correctly.  In no case
 * will the author(s)  be liable to you for any lost revenue  or  profits or
 * other special,  indirect and consequential damages caused by the usage of
 * this program.
 */

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>

#ifdef SYSV
#include <unistd.h>      /* for getuid() & access() */
#include <malloc.h>
#else

uid_t getuid(void);
long time(long *tloc);
char *malloc(unsigned size);
int access(char *path, int mode);

#endif
#include <pwd.h>         /* for passwd struct, and getpwuid() */
#include <math.h>        /* for atof() */

int getopt(int argc, char **argv, char *optstring);
void exit(int stauts);
void gethostname(char *h, int s);

#include <apollo/base.h>
#include <apollo/gpr.h>
#include <apollo/pgm.h>
#include <apollo/error.h>

/* User definable values */

#define MAX_XRES    1280        /* Possibly  8192                  */
#define MAX_YRES    1024        /*    "      8192                  */
#define MAX_PLANES     8        /*    "      32                    */

#define PAPER_X     8.27        /* A4  8.27 inches, 210 mm         */
#define PAPER_Y    11.69        /* A4 11.69 inches, 297 mm         */
#define MARGIN      0.30        /* Size of non-printable margin    */

/* End of user definable values */

char  *progname;                /* The basename of this program    */

status_$t           status;
gpr_$color_vector_t color_vect;
short               num_colors;

double  aspect     = 1.0;   /* -a aspect ratio factor          */
int		bflg	   = 0;		/* -b box flag                     */
int		cflg	   = 0;		/* -c color postscript flag        */
int		dflg	   = 0;		/* -d debug flag, default off      */
int		epsf       = 0;		/* -e EPS file (no showpage)       */
int		gflg	   = 0;		/* -g grayscale flag, default off  */
int		iflg	   = 0;		/* -i invert flag, default off     */
int		jflg	   = 0;		/* -j just print postscript header */
int     oflg	   = 0;		/* -o output flag, default off     */
int     pflg	   = 0;		/* -p patchlevel flag, default off */
int     degrees	   = 0;		/* -r degrees_to_rotate, default 0 */
double	scalefact  = 1.0;	/* -s scale factor                 */
int     Sflg	   = 0;		/* -S display info about bitmap    */
int     vflg	   = 0;		/* -v verbose flag, default off    */
int		xflg, yflg = 0;		/* -x,-y flags                     */
double	xoffset    = 0.0;	/* -x xoffset                      */
double	yoffset    = 0.0;	/* -y yoffset                      */

FILE   *outfile    = NULL;
#define VERSION    "1"
#define PATCHLEVEL "05"

/*****************************************************************************/

void check(char *message)
{
 if (status.all != status_$ok) {
    error_$print (status);
    (void) fprintf(stderr,"%s: Error occurred in %s.\n", progname, message);
    pgm_$set_severity(pgm_$internal_fatal);
    pgm_$exit();
 }
 return;
}

/*****************************************************************************/

static void usage(char *message)
{
  char
    **p;

  static char
    *options[]=
    {
      "-a aspect_ratio_fact  Scale the original image aspect ratio by aspect_ratio_fact",
      "-b                    Place a box around the image",
      "-c                    Create a color postscript file",
      "-e                    Create an Encapsulated Postscript file (no showpage in postscript file)",
      "-g                    Create a 4-bit grayscale postscript file (ignored for monochrome bitmaps)",
      "-h                    Display program options",
      "-i                    Invert black and white",
      "-j                    Output postscript header and footer only",
      "-l                    Landscape orientation (default is Portrait). Corresponds to -r 90",
      "-o outfile.ps         Output postscript file name is outfile.ps",
      "-p                    Display version and patchlevel",
      "-r degrees            Rotate image by 'degrees' degrees",
      "-s scalefact          Scale factor (default is scalefact = 1)",
      "                      scalefact < 0 maximizes the image, scalefact = 0 converts bitmap to 300 dpi",
      "-S                    Display statistics about bitmap file",
      "-v                    Verbose",
      "-x offset             X offset in inches from lower left corner of page (after rotation, if any)",
      "-y offset             Y offset in inches from lower left corner of page (after rotation, if any)",
      (char *) NULL
    };

  if (message != (char *) NULL) (void) fprintf(stderr,"Can't continue, %s.\n\n",message);

  (void) fprintf(stderr,"Usage: %s [options ...] bitmap_file_name\n",progname); 
  (void) fprintf(stderr,"\nwhere options include: \n");
  for (p=options; *p != (char *) NULL; p++) (void) fprintf(stderr,"  %s\n",*p);
  (void) fprintf(stderr,"\nIf the  '-o outfile.ps' option is not used, output is to standard output. \n");
  exit(1);
}

/*****************************************************************************
 *                                                                           *
 * Initialize display                                                        *
 *                                                                           *
/*****************************************************************************/

void init_display(void)
{
 gpr_$display_mode_t disp_mode = gpr_$no_display;
 gpr_$offset_t       size;
 gpr_$plane_t        hi_plane;
 gpr_$bitmap_desc_t  bitmap_desc;

 hi_plane    = (short) (MAX_PLANES - 1);
 size.x_size = (short) (MAX_XRES);
 size.y_size = (short) (MAX_YRES);

 gpr_$init(disp_mode, (short)0, size, hi_plane, &bitmap_desc, &status);
 check("init_display: gpr_$init");
 return;
}

/*****************************************************************************
 *                                                                           *
 * Open bitmap file                                                          *
 *                                                                           *
/*****************************************************************************/

void open_bitmap(
char                *file_name,
gpr_$bitmap_desc_t  *disk_bitmap_desc,
short               *num_planes,
short               *xres,
short               *yres)
{
 gpr_$attribute_desc_t         attribs;
 gpr_$offset_t                 disk_bm_size;
 gpr_$version_t                version;
 gpr_$bmf_group_header_array_t header;
 short                         groups;
 boolean                       created;

 gpr_$allocate_attribute_block(&attribs, &status);
 check("open_bitmap: gpr_$allocate_attribute_block");

 gpr_$open_bitmap_file(gpr_$readonly, file_name, (short)strlen(file_name), &version,
     &disk_bm_size, &groups, header, attribs, disk_bitmap_desc, &created, &status);
 check("open_bitmap: gpr_$open_bitmap_file");

 *num_planes = header[0].n_sects;

 if (*num_planes > (MAX_PLANES)) 
  {
   fprintf(stderr,"%s: Error: Can only handle (%d) planes, found (%d)\n", progname, (int) (MAX_PLANES), *num_planes);
   fprintf(stderr,"%s: Recompile with larger value for MAX_PLANES.\n", progname);
   pgm_$exit();
  }              

 if (header[0].n_sects == 1 && header[0].pixel_size == 1 ) 
  {  
    color_vect[0] =  gpr_$black ;
    color_vect[1] =  gpr_$white ;   
    num_colors = 2;
    if (dflg) (void) fprintf(stderr,"in open_bitmap: (b/w) num_colors=%d \n",num_colors);
  }
 else
  {
    gpr_$inq_bitmap_file_color_map(*disk_bitmap_desc, (short) 0,(short) 256, color_vect, &status);   
    if ((status.all == gpr_$no_color_map_in_file) || (status.all == gpr_$invalid_color_map) )
     {                    
      if (dflg) (void) fprintf(stderr,"in open_bitmap: no color map in bitmap file, using display colormap. \n");
      gpr_$inq_color_map((gpr_$pixel_value_t) 0, (short) 256, color_vect, &status);    
      check("in main, after calling gpr_$inq_color_map");
      num_colors = 256;
      if (dflg) (void) fprintf(stderr,"in open_bitmap: (bad colormap) num_colors=%d \n",num_colors);
     } 
    else 
     {
      if (header[0].n_sects == 1 )
        {
         num_colors = 1<<header[0].pixel_size;
         if (dflg) (void) fprintf(stderr,"in open_bitmap: (pixel oriented bitmap) num_colors=%d, pixel_size=%d \n",num_colors,header[0].pixel_size);
        }
      else
        {
         num_colors = 1<<header[0].n_sects;
         if (dflg) (void) fprintf(stderr,"in open_bitmap: (plane oriented bitmap) num_colors=%d, n_planes=%d \n",num_colors,header[0].n_sects);
        }
     }
  }

 *xres = disk_bm_size.x_size;
 *yres = disk_bm_size.y_size;

 if ((*xres > (MAX_XRES)) || (*yres > (MAX_YRES))) 
  {
   fprintf(stderr,"%s: Error: Can only handle (%d,%d) bitmap, found (%d,%d)\n", progname, (int) (MAX_XRES), (int) (MAX_YRES), *xres, *yres);
   fprintf(stderr,"%s: Recompile with larger value for MAX_XRES and/or MAX_YRES.\n", progname);
   pgm_$exit();
  }

 if (Sflg)
   {
     (void) fprintf(stderr,"\nBitmap file name    : %s \n",file_name);
     (void) fprintf(stderr,"Image Characteristics \n");
     (void) fprintf(stderr,"  Image Size        : %d  %d \n",disk_bm_size.x_size,disk_bm_size.y_size);
     (void) fprintf(stderr,"  Number of groups  : %d \n",groups);
     (void) fprintf(stderr,"  Number of planes  : %d \n",header[0].n_sects);
     (void) fprintf(stderr,"  Pixel size        : %d \n",header[0].pixel_size);
     (void) fprintf(stderr,"  Allocated Size    : %d \n",header[0].allocated_size);
     (void) fprintf(stderr,"  Bytes per line    : %d \n",header[0].bytes_per_line);
     (void) fprintf(stderr,"  Bytes per section : %d \n\n",header[0].bytes_per_sect);
   }

 return;
}

/*****************************************************************************
 *                                                                           *
 * Set up the postscript header of the output file                           *
 *                                                                           *
/*****************************************************************************/

void ps_init(
char         *infn,
short        yres,
short        xres,
int          nr,
int          nc,
unsigned int np,
unsigned int nc1)
{
 double         asp, height_inch, width_inch;
 double         height_pt, width_pt;
 double         PAPER_X_PT, PAPER_Y_PT;
 double         maxx = (PAPER_X - (MARGIN * 2));
 double         maxy = (PAPER_Y - (MARGIN * 2));
 char           hostname[256];
 struct passwd  *pswd;
 long           clock;
 double         llx,lly,urx,ury;
 double         bbllx,bblly,bburx,bbury,costheta,sintheta;
 double         tx,ty,sx,sy;
 float          pi  = 3.1415926;
 float          pt_per_inch  = 72;    /* in Postscript 1 inch = 72 pt */

 if (dflg) (void) fprintf(stderr,"     in ps_init, xres=%d, yres=%d, nr=%d, nc=%d, np=%u, nc1=%d\n",xres,yres,nr,nc,np,nc1);

 asp = (double)yres / (double)xres;   /* true aspect ratio */

 if (scalefact > 0) {                 /* use given scale factor, -s (or default) */
  if (asp > 0.6666) {
     height_inch = 5.0 * scalefact;
     width_inch = height_inch / (asp * aspect);
  }
  else {
     width_inch = 7.5 * scalefact;
     height_inch = width_inch * asp * aspect;
  }
 }
 else {                               /* Maximize image size, preserving original aspect ratio */
	width_inch = maxx;
	height_inch = asp * width_inch;
	if (height_inch > maxy) {
		height_inch = maxy;
		width_inch = height_inch / asp;
       }
 } /* end if (scalefact > 0) */

 if (vflg) {
  (void) fprintf(stderr,"Scale factor (-s)       = %f\n",scalefact);
  (void) fprintf(stderr,"Original aspect ratio   = %f\n",asp);
  if (fabs(scalefact) > 0.00001) 
   {
    (void) fprintf(stderr,"Aspect ratio scale (-a) = %f\n",aspect);
    (void) fprintf(stderr,"New aspect ratio        = %f\n",height_inch/width_inch);
   }
  (void) fprintf(stderr,"Rotation                = %d degrees \n",degrees);
  (void) fprintf(stderr,"(X,Y) Offset in inches  = (%f,%f)\n",xoffset,yoffset);
  (void) fprintf(stderr,"Output colour           = ");
  switch (np) 
   {
	case 1:
          (void) fprintf(stderr,"BLACK-WHITE POSTSCRIPT");
          break;
	case 4:
          (void) fprintf(stderr,"GRAYSCALE POSTSCRIPT");
          break;
	case 8:
          (void) fprintf(stderr,"COLOR POSTSCRIPT");
          break;
	default:
          (void) fprintf(stderr,"I do not know how to handle this.");
          break;
   }

  (void) fprintf(stderr," %s\n",(iflg) ? "(inverted)" : "");
 }

 if (dflg) (void) fprintf(stderr,"xflg=%d , yflg=%d , xoffset=%f , yoffset=%f \n",xflg,yflg,xoffset,yoffset);
 if (dflg) (void) fprintf(stderr,"degrees=%d \n",degrees);

 costheta = cos(degrees*pi/180.);
 sintheta = sin(degrees*pi/180.);

 if (fabs(scalefact) < 0.00001)    /* if scalefact=0 postscript file will have same dimensions as bitmap */
  { 
   PAPER_X_PT = PAPER_X *  pt_per_inch;
   PAPER_Y_PT = PAPER_Y *  pt_per_inch;
   width_pt  = (nc *  pt_per_inch)/300.;
   height_pt = (nr *  pt_per_inch)/300.;
   llx = (PAPER_X_PT - width_pt*costheta + height_pt*sintheta)/2.0 + (xflg*xoffset*costheta - yflg*yoffset*sintheta)*pt_per_inch;
   lly = (PAPER_Y_PT - width_pt*sintheta - height_pt*costheta)/2.0 + (xflg*xoffset*sintheta + yflg*yoffset*costheta)*pt_per_inch;
   urx = (PAPER_X_PT + width_pt*costheta - height_pt*sintheta)/2.0 + (xflg*xoffset*costheta - yflg*yoffset*sintheta)*pt_per_inch;
   ury = (PAPER_Y_PT + width_pt*sintheta + height_pt*costheta)/2.0 + (xflg*xoffset*sintheta + yflg*yoffset*costheta)*pt_per_inch;

   bbllx = llx - height_pt*sintheta;
   bblly = lly;
   bburx = urx + height_pt*sintheta;
   bbury = ury;

   tx = llx; 
   ty = lly; 
   sx = width_pt;
   sy = height_pt;
  }
 else
  {
   llx = (PAPER_X - width_inch*costheta + height_inch*sintheta)/2.0 + (xflg*xoffset*costheta - yflg*yoffset*sintheta);
   lly = (PAPER_Y - width_inch*sintheta - height_inch*costheta)/2.0 + (xflg*xoffset*sintheta + yflg*yoffset*costheta);
   urx = (PAPER_X + width_inch*costheta - height_inch*sintheta)/2.0 + (xflg*xoffset*costheta - yflg*yoffset*sintheta);
   ury = (PAPER_Y + width_inch*sintheta + height_inch*costheta)/2.0 + (xflg*xoffset*sintheta + yflg*yoffset*costheta);

   bbllx = llx - height_inch*sintheta;
   bblly = lly;
   bburx = urx + height_inch*sintheta;
   bbury = ury;

   llx   *= pt_per_inch;   lly *= pt_per_inch;   urx *= pt_per_inch;   ury *= pt_per_inch;
   bbllx *= pt_per_inch; bblly *= pt_per_inch; bburx *= pt_per_inch; bbury *= pt_per_inch;

   tx = llx; 
   ty = lly; 
   sx = width_inch *pt_per_inch; 
   sy = height_inch*pt_per_inch; 
 } 

 if (epsf)
   {
     (void) fprintf(outfile,"%%!PS-Adobe-2.0 EPSF-2.0\n");
    }
  else
    {
     (void) fprintf(outfile,"%%!!PS-Adobe-2.0\n");
    }
 (void) fprintf(outfile,"%%%%Title: %s\n", infn);
 pswd = getpwuid (getuid ());
 (void) gethostname (hostname, sizeof (hostname));
 (void) fprintf(outfile,"%%%%Creator: %s \n",progname);
 (void) fprintf(outfile,"%%%%CreationDate: %s",(time (&clock), ctime (&clock)));
 (void) fprintf(outfile,"%%%%For: %s@%s (%s)\n",pswd->pw_name,hostname,pswd->pw_gecos);
 (void) fprintf(outfile,"%%%%Pages: 1\n");
 (void) fprintf(outfile,"%%%%BoundingBox:  %f %f %f %f\n",bbllx,bblly,bburx,bbury);
 (void) fprintf(outfile,"%%%%EndComments\n");
 (void) fprintf(outfile,"%%%%EndProlog\n");
 (void) fprintf(outfile,"%%%%Page 1 1\n\n");

 if (bflg)
   {
      (void) fprintf(outfile,"gsave\n");
      (void) fprintf(outfile,"/w %f def \n",sx); 
      (void) fprintf(outfile,"/h %f def \n",sy); 
      (void) fprintf(outfile,"/theta %d def \n",degrees); 
      (void) fprintf(outfile,"/llx %f def \n",llx); 
      (void) fprintf(outfile,"/lly %f def \n",lly); 
      (void) fprintf(outfile,"/urx %f def \n",urx); 
      (void) fprintf(outfile,"/ury %f def \n",ury); 
      (void) fprintf(outfile,"llx lly moveto \n");
      (void) fprintf(outfile,"urx theta sin h mul add ury theta cos h mul sub lineto \n");
      (void) fprintf(outfile,"urx ury lineto \n");
      (void) fprintf(outfile,"llx theta sin h mul sub lly theta cos h mul add lineto \n");
      (void) fprintf(outfile,"closepath stroke \n");
      (void) fprintf(outfile,"grestore \n\n");
   }

 (void) fprintf(outfile,"gsave\n");
 (void) fprintf(outfile,"%f %f translate\n",tx,ty);
 (void) fprintf(outfile,"%d rotate\n",degrees);
 (void) fprintf(outfile,"%f %f scale\n",sx,sy);
 if (iflg) (void) fprintf(outfile,"{1 exch sub} settransfer\n");
 (void) fprintf(outfile,"/picstr %u string def\n",nc1);
 (void) fprintf(outfile,"/width  %d def\n",nc); 
 (void) fprintf(outfile,"/height %d def\n",nr); 
 (void) fprintf(outfile,"/depth  %u def\n",np); 
 (void) fprintf(outfile,"width height depth\n"); 
 (void) fprintf(outfile,"[width 0 0 height neg 0 height] %% scan image from top to bottom \n");
 if(np == 8)
 (void) fprintf(outfile,"{ currentfile picstr readhexstring pop } false 3 colorimage\n");
 else
 (void) fprintf(outfile,"{ currentfile picstr readhexstring pop } image\n");

 return;
}

/****************************************************************************/

void write_pix(int ascbyte, unsigned int np)
{
 static short int   lasercol = 0;
 static short int   bitcnt   = 0;
 static short int   bits     = 0;
 static char        hex[17]  = "0123456789ABCDEF";
 char               lo[6];
 int                li;

 switch (np) 
  {
	case 1:
		bits |= (ascbyte == 0);
		if (++bitcnt>3) 
         {
		  bitcnt = 0;
		  if ((++lasercol) > 78)
           {
		    fputc('\n',outfile);
		    lasercol=1;
           }
		  fputc(hex[bits],outfile);
		  bits = 0;
         }
		else
		  bits <<= 1;
          break;
	case 4:
		if ((++lasercol) > 72) 
         {
          fputc('\n',outfile);
          lasercol=1;
         }
		fputc(hex[ascbyte],outfile);
		break;
	case 8:
		if ((++lasercol) > 11) 
         {
          fputc('\n',outfile);
          lasercol=1;
         }                 

            lo[0] = ascbyte & 15;   
            lo[5] = ascbyte>>20 & 15;
            lo[4] = ascbyte>>16 & 15;
            lo[3] = ascbyte>>12 & 15;
            lo[2] = ascbyte>>8 & 15;
            lo[1] = ascbyte>>4 & 15;
                for(li=5;li>-1;li--)
		fputc(hex[lo[li]],outfile);
		break;
  }
 return;
}

/*****************************************************************************/

void convert(char *infn)
{
 short               xres, yres;            /* x y bitmap size */
 short               num_planes;
 gpr_$bitmap_desc_t  disk_bitmap_desc;

 int                 *gray,i;
 register short      x, y;
 register int        pix;
 gpr_$window_t       src;
 gpr_$pixel_value_t  dest[MAX_XRES];
 unsigned int        np, nc1;
 unsigned int        xrf;
 unsigned long       n_black = 0L;         /* Number of non-zero pixels */

 init_display();
 open_bitmap(infn, &disk_bitmap_desc, &num_planes, &xres, &yres);

 gpr_$set_bitmap(disk_bitmap_desc,&status);
 check("convert: gpr_$set_bitmap");

 if (dflg) (void) fprintf(stderr,"Flags asked: gflg=%d , cflg=%d , iflg=%d\n",gflg,cflg,iflg);
 if (vflg)
  {
   (void) fprintf(stderr,"(%d,%d) bitmap read with %d plane(s), ",xres,yres,num_planes);
   (void) fprintf(stderr,"and a %d-color colormap.\n",num_colors);
  }

 if (dflg) (void) fprintf(stderr,"in convert: num_colors=%d \n",num_colors);

 if ((num_colors == 2) && gflg)
  {
   if (vflg) (void) fprintf(stderr,"Monochrome bitmap, therefore \"-g\" flag ignored.\n");
   gflg = 0;
  }

 if ((num_colors == 2) && cflg)
  {
   if (vflg) (void) fprintf(stderr,"Monochrome bitmap, therefore \"-c\" flag ignored.\n");
   cflg = 0;
  }

 if (dflg) (void) fprintf(stderr,"Flags  used: gflg=%d , cflg=%d , iflg=%d\n",gflg,cflg,iflg);

 if (num_colors > 2)                    /* Build gray table */
   {               
    if (dflg) (void) fprintf(stderr,"Building grayscale values ... \n");
	if (vflg && gflg) (void) fprintf(stderr,"Grayscale values:\n");
	gray = (int *) malloc (num_colors * sizeof (int));
	for (i=0; i<num_colors; i++)
       {
		gray[i] = (int) (0.299 * ((color_vect[i] / 65536) & 0xFF) +
				 0.587 * ((color_vect[i] / 256  ) & 0xFF) +
				 0.114 * ((color_vect[i]        ) & 0xFF));
		gray[i] = (int)(gray[i] / 16.0);
		if (vflg && gflg) (void) fprintf(stderr,"%d%s",gray[i],(i != (num_colors-1)) ? "," : ")\n");
       }
   }

 if (dflg) (void) fprintf(stderr,"xres = %d \n",xres);
 if (xres % 8)
  xrf = xres + (8 - (xres % 8));             /* 8 bit alignment */
 else
  xrf = xres;
 if (dflg) (void) fprintf(stderr,"xrf = %d \n",xrf);

 if (num_colors > 2)
   {
    if (gflg)                                /* gray scale    */
     {
      np = 4;                                /* 4 bits/sample */
      nc1 = xrf/2;
      if (dflg) (void) fprintf(stderr,"gflg = %d , np = %d , nc1 = %d\n",gflg,np,nc1); 
     }
    else if (cflg)                           /* color postscript */
     {
      np = 8;                                /* 8 bits/sample */
      nc1 = xrf;
      if (dflg) (void) fprintf(stderr,"cflg = %d , np = %d , nc1 = %d\n",cflg,np,nc1);
     }
    else
     {
      np = 1;
      nc1 = xrf/8;                           /* string width for readstring */
      if (dflg) (void) fprintf(stderr,"using monochrome , np = %d , nc1 = %d\n",np,nc1); 
     }
   }
 else
   {
    np = 1;
    nc1 = xrf/8;                             /* string width for readstring */
    if (dflg) (void) fprintf(stderr,"monochrome , np = %d , nc1 = %d\n",np,nc1); 
   }

 if (dflg) (void) fprintf(stderr,"calling ps_init, xres=%d, yres=%d, nr=%d, nc=%d, np=%u, nc1=%d\n",xres,yres,yres,xrf,np,nc1);
 ps_init(infn,yres,xres,yres,xrf,np,nc1);

 if (!jflg)                                  /* not just the header */
  {
   src.window_base.x_coord = (short) 0;
   src.window_size.x_size  = xres;
   src.window_size.y_size  = (short) 1;

   for(y=0; y<yres; y++) 
    {
     src.window_base.y_coord = y;
     gpr_$read_pixels(src,dest,&status);              /* read one row */
     /*   check("convert: gpr_$read_pixels");         /* for speed */


     for(x=0; x<xres; x++)
      {
       pix = dest[x];
       if (num_colors > 2)                    /* if colour */
         {                
         if(cflg) pix= color_vect[pix] ;
          else
          pix = gray[pix];
         }
       write_pix(pix,np);
       if (pix) n_black++;                   /* counter of non-zero pixels */
      }


     for(x=xres; x<xrf; x++) { write_pix(0,np); }   /* alignment */
    }

   if (vflg) (void) fprintf(stderr,"%% non-zero pixels       = %f\n", 100.0 * n_black / (xres * yres));
  }

 gpr_$terminate (false, &status);
 check("convert: gpr_$terminate");

 (void) fprintf(outfile,"\n");
 if (!epsf) (void) fprintf(outfile,"showpage\n");
 (void) fprintf(outfile,"grestore\n");
 (void) fprintf(outfile,"%%%%Trailer\n");
 if (vflg) (void) fprintf(stderr,"Done !!!\n");

 return;

} /* end convert */

/******************************************************************************/

int main( int argc, char **argv)
{
 extern int     optind;         /* argv index of next argument */
 extern char    *optarg;        /* start of option argument */
 int            arg;            /* option letter match */

 char           *infn  = NULL;   /* input filename */
 char           *outfn = NULL;   /* output filename */

 if ((progname = strrchr(argv[0], '/')) == NULL)
   progname = argv[0];
 else
   progname++;

 if (argc < 2) usage((char *) NULL);       /* Need at least 1 argument */

 while((arg = getopt(argc, argv, "a:bcdeghijlo:pr:s:Svx:y:")) != EOF)
  switch (arg) 
  {
   case 'a': 
            if ((aspect = atof(optarg)) == 0) usage("bad value given for -a");
            if (scalefact < 0) usage("option -a has no meaning with -s (scalefact) < 0");
            break;
   case 'b': bflg++; break;
   case 'c': cflg++; break;
   case 'd': dflg++; break;
   case 'e': epsf++; break;
   case 'g': gflg++; break;
   case 'h': usage((char *)NULL); break;
   case 'i': iflg++; break;
   case 'j': jflg++; break;
   case 'l': 
            degrees = 90; 
            break;
   case 'o':
            oflg++;
            outfn = optarg;
            if (vflg) (void) fprintf(stderr,"Output file : %s \n",outfn);
            break;      
   case 'p': 
            pflg++;
            (void) fprintf(stderr,"%s version %s, patchlevel %s \n",progname,VERSION, PATCHLEVEL);
            break;      
   case 'r': 
            if ((degrees = atoi(optarg)) == 0) usage("bad value given for -r");
            degrees = degrees % 360 ;
            break;
   case 's': 
            scalefact = atof(optarg);
            break;
   case 'S': Sflg++; break;
   case 'v': vflg++; break;
   case 'x': 
            if ((xoffset = atof(optarg)) == 0) usage("bad value given for -x");
            xflg++; break;
   case 'y': 
            if ((yoffset = atof(optarg)) == 0) usage("bad value given for -y");
            yflg++; break;
  }

 if (optind == argc)
	usage("no input bitmap file name found");
 else {
       infn = argv[optind];
       if (access(infn,4) != 0)      /* read permission */
         {
          (void) fprintf(stderr,"%s: Unable to access input file: \"%s\"\n", progname, infn);
          perror("gpr2ps");
          exit(1);
         }
       if (argc - optind > 1)
         {
          (void) fprintf(stderr,"More than one input filename given. Using only \"%s\". \n",infn); 
         }
 }

 if (vflg) (void) fprintf(stderr,"Input file : %s\n", infn);

 if (!oflg)    /* if "-o filename.ps" was not used then write to standard output */
   {
    outfile = stdout;
   }
 else
   {
    outfile = fopen(outfn,"w");
   }

 if (outfile==NULL) 
   {
    (void) fprintf(stderr,"Error opening output file.\n");
    exit(1);
   }

 convert(infn);
 fclose(outfile);
 return(0);

}  /* end of main */

