/* 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 #include #include #include #ifdef SYSV #include /* for getuid() & access() */ #include #else uid_t getuid(void); long time(long *tloc); char *malloc(unsigned size); int access(char *path, int mode); #endif #include /* for passwd struct, and getpwuid() */ #include /* for atof() */ int getopt(int argc, char **argv, char *optstring); void exit(int stauts); void gethostname(char *h, int s); #include #include #include #include /* 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< (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 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 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 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 */