home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************
- * *
- * University of Utah - APOLLO Graphics Helper Routine *
- * Copyright 1985 University of Utah *
- * *
- * SCRIBEPIC *
- * *
- * Module: Main module (scribepic.c) *
- * *
- * Version Date Person Description *
- *----------------------------------------------------------------------*
- * 0.1 2-Jun-85 J. Schimpf Make a MACPAINT style file *
- * from a screen *
- * 0.2 5-Jun-85 J. Schimpf Use level 2 I/O for speed *
- * 0.3 5-Jun-85 J. Schimpf Added read GMF format stuff *
- * 0.4 14-Jun-85 J. Schimpf Don't invert windows only *
- * screens *
- * 0.5 26-Jun-85 J. Schimpf Added margin,height & POSTSCRIPT*
- * info so SCRIBE picture file *
- * can be built *
- * *
- * Description of code: *
- * Copy Apollo Window or Screen to a file suitable for use in a *
- * SCRIBE @picture command. (See Below) *
- * File produced is a POSTSCRIPT program with the run length *
- * encoded version of the bit map following it *
- * *
- * SCRIBE Picture Command is of the form: *
- * *
- * @picture(size=2inch, ScalableLaser=[mypic.ps]) *
- * *
- * And the command used to make the mypic.ps file (assuming you *
- * have a window or screen bit map in the file screen) is *
- * *
- * scribepic -f screen -h 2 -m 6 -o mypic.ps *
- * *
- * This sets the height at 2 inches, the distance between *
- * margins as 6 inches and the output file as mypic.ps *
- * the other values are defaulted (see below) *
- * *
- * SYNTAX: scribepic -f (filename) [-i] [-b] *
- * [-o <output file>] *
- * [-m <page margin (in)>] *
- * [-h <Picture height(in)>] *
- * [-P <POSTSCRIPT CODE FILE>] *
- * [-u <Translate picture UP (in)>] *
- * *
- * Parameter Use Default *
- *----------------------------------------------------------------------*
- * ****** FILE CONTROL ***** *
- * *
- * -f <filename> Input Screen file NONE - ERROR if missing *
- * -b Input is APOLLO BM file GMF file assumed *
- * (All STD screens & *
- * Apollo windows are GMF)*
- * -i Invert Input file NOT Inverted *
- * -o <filename> Output Picture file STDOUT *
- * *
- * ***** SCRIBE FORMAT CONTROL ***** *
- * *
- * -m <Margin> Page margin (inches) 6 inches *
- * -h <Height> Picture heigh (inches) 2 inches *
- * -u <Move up> Move picture up page 0 inches *
- * *
- * ***** POSTSCRIPT CONTROL **** *
- * *
- * -P <CODE FILE> Postscript code ~/bin/scribepic.ps *
- * *
- *----------------------------------------------------------------------*
- * *
- * Output File is of the form: *
- * <POSTSCRIPT CODE> *
- * <Invert> <X size> <Y size> <Margin> <Height> <Move UP> *
- * <Run length encoded bitmap (see cmprs_line) *
- * *
- * Procedures: *
- * *
- * Written+ Name Description *
- *----------------------------------------------------------------------*
- * y main() Bring in bit map to memory bm *
- * y get_bitmap() Read bitmap file *
- * y get_line() Get one scan line *
- * y cmprs_line() Compress 1 scan line *
- * y out_buf() Output one scan line as hex *
- * y write_buf() Output one character to output *
- * y hex_con() Convert nibble to ASCII hex *
- * *
- * EXTERNAL *
- * gmf_inq() Get info on GMF file *
- * *
- * + (N - no; Y - yes (y - untested); P - partially written) *
- * *
- ***********************************************************************/
-
- /* Include files ***********/
-
- #include <stdio.h>
- #include "/sys/ins/base.ins.c"
- #include "/sys/ins/gpr.ins.c"
- #include "/sys/ins/gmf.ins.c"
-
- /* Global Constants *******/
-
- #define GPR_MODE gpr_$borrow /* Display MODE */
- #define TRUE 1
- #define FALSE 0
-
- #define SCREEN_X 1024 /* DN 300 Screen constants */
- #define SCREEN_Y 800
- #define SCREEN_WD 64
-
- #define MAX_SCAN_LINE 256
- #define BUF_SZ 50000
-
- #define LF 0x0a
-
- #define SAME 1
- #define NOTSAME 0
-
- /* Flags & defaults for user */
-
- #define INVFLAG 'i'
- #define FFLAG 'f'
- #define BITFLAG 'b'
- #define OUTFLAG 'o'
- #define MARGFLAG 'm'
- #define HEIGHTFLAG 'h'
- #define UPFLAG 'u'
- #define POSTFLAG 'P'
-
- #define OUTDEF stdout
- #define POSTDEF "//a/utah/printers/scribe/scribepic.ps"
-
- #define MARGINDEF 6 /* Assume 6" margins */
- #define HEIGHTDEF 2 /* Assume 2" height */
- #define UPDEF 0 /* Assume 0" move UP */
-
- /* Globals used by all routines */
-
- int line_sz; /* # Bytes/scan line */
- int separation; /* Bytes between scan lines */
- int x_size,y_size; /* Raster size */
- char *bitp; /* Pointer to bitmap */
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
-
- name_$pname_t filename;
- gpr_$bitmap_desc_t bitmap,get_bitmap(),get_gmf();
- status_$t status;
- int psn = 0;
- int outnum;
- int n,i,j,size;
- int invert,bitfile;
- unsigned char scanline[MAX_SCAN_LINE];
- float height,margin,up,atof();
- FILE *fopen(),*fout,*fpost;
- char postfile[30],outfile[30];
-
- /* Scan command line for input file & other stuff, set other stuff
- for defaults
- */
-
- /* Set default file control stuff */
-
- invert = TRUE;
- bitfile = FALSE;
- filename[0] = '\0';
-
- fout = OUTDEF;
- strcpy(postfile,POSTDEF);
-
- /* Set default SCRIBE stuff */
-
- height = HEIGHTDEF;
- margin = MARGINDEF;
- up = UPDEF;
-
- /* Now scan command line and set all the stuff */
-
- for( i=1; i<argc; i++ )
- {
- if( argv[i][0] == '-' )
- {
- switch( argv[i][1] ) {
-
- case INVFLAG: invert = FALSE;
- break;
-
- case FFLAG: strcpy(filename,argv[i+1]);
- break;
-
- case BITFLAG: bitfile = TRUE;
- break;
-
- case OUTFLAG: strcpy(outfile,argv[i+1]);
- break;
-
- case POSTFLAG: strcpy(postfile,argv[i+1]);
- break;
-
- case MARGFLAG: margin = atof( argv[i+1] );
- break;
-
- case HEIGHTFLAG: height = atof( argv[i+1] );
- break;
-
- case UPFLAG: up = atof( argv[i+1] );
- break;
-
- }
- }
- }
-
- if( strlen(filename) == 0 )
- {
- fprintf(stderr,"*** scribepic: Syntax No filename input\n");
- exit(-1);
- }
-
- /* Open Output & postscript files - use defaults if failure */
-
- if( (fout = fopen(outfile,"w")) == NULL )
- {
- printf("*** scribepic: Bad output file %s\n",outfile);
- printf("**** Stdout used\n");
- fout = OUTDEF;
- }
-
- if( (fpost = fopen(postfile,"r")) == NULL )
- {
- printf("*** scribepic:Cannot find POSTSCRIPT file %s\n",postfile);
- printf("**** %s used\n",POSTDEF);
- strcpy(postfile,POSTDEF);
- if( ( fpost = fopen(postfile,"r")) == NULL )
- {
- fprintf(stderr,"scribepic:Cannot find DEFAULT POSTSCRIPT file %s\n",postfile);
- exit(-1);
- }
- }
-
- /* Get fileid associated with output */
-
- outnum = fileno( fout );
-
- /* Get the bit map on the screen where we can fiddle with it */
-
- if( bitfile )
- bitmap = get_bitmap(filename);
- else
- bitmap = get_gmf(filename);
-
- if( bitmap == NULL )
- {
- fprintf(stderr,"makemap: Bad bit map file - %s\n",filename);
- exit(-1);
- }
-
- /* Initialize the buffer */
-
- out_buf(scanline,-1,outnum);
-
- /* Put out the POSTSCRIPT file first to output */
-
- while( 1 )
- {
- fgets(scanline,MAX_SCAN_LINE,fpost);
- if( feof( fpost ) )
- break;
- fputs(scanline,fout);
- }
- fflush(fout);
-
- /* Put out the x & y size of the file first in the file
- NOTE: X size is # bytes/line
- */
-
- sprintf(scanline,"%d %d %d %f %f %f\n",
- invert,line_sz,y_size,margin,height,up);
- for( i=0; i< strlen(scanline); i++ )
- write_buf(scanline[i],0,outnum);
-
- /* Loop through scan lines reading data and compressing it for output */
-
- for( i=0; i<y_size; i++ )
- {
- size = get_line(bitp,i,line_sz,separation,scanline);
- size = comprs_line(scanline,size);
- out_buf(scanline,size,outnum);
- }
-
- /* Flush the buffer */
-
- out_buf(scanline,-1,outnum);
-
- gpr_$terminate(0,status);
- }
-
- /***************************************************************************
- *
- * GET_BITMAP(filename)
- *
- * INPUT: filename - Bitmap file name
- *
- * OUTPUT: Bitmap discriptor NULL if not found
- * line_sz - # Bytes/scan line set
- * separation - Bytes between scan lines
- * x_size,y_size - Size of map in raster units
- *
- * SIDE EFFECTS: Bit map moved into virtual memory
- * Graphics inited for BORROW mode
- *
- ****************************************************************************/
-
- gpr_$bitmap_desc_t get_bitmap(filename)
- char filename[];
- {
- gpr_$window_t window;
- gpr_$bmf_group_header_array_t header;
- short length,sep;
- gpr_$plane_t hi_plane = 7;
- short groups;
- gpr_$bitmap_desc_t bitmap,filebm;
- status_$t status;
- gpr_$version_t version;
- gpr_$attribute_desc_t attribs;
- boolean created;
-
- length = strlen(filename);
-
- /* Init the bit map dimensions */
-
- window.window_base.x_coord = (short) 0;
- window.window_base.y_coord = (short) 0;
- window.window_size.x_size = (short) SCREEN_X;
- window.window_size.y_size = (short) SCREEN_Y;
-
- /* Initialize by borrowing the display */
-
- gpr_$init(GPR_MODE,1,window.window_size,hi_plane,bitmap,status);
-
- /* Set up an attribute block for the Xfer */
-
- gpr_$allocate_attribute_block(attribs,status);
-
- /* Open the bit map file */
-
- gpr_$open_bitmap_file(gpr_$readonly,filename,length,
- version,window.window_size,groups,header,
- attribs,filebm,created,status);
-
- /* If it didn't open tell user and quit */
-
- if( status.fail )
- {
- bitmap = NULL;
- gpr_$terminate(0,status);
- return( bitmap );
- }
-
- /* Move Bit map to internal bit map */
-
- gpr_$pixel_blt(filebm,window,window.window_base,status);
-
- /* Get the information on this bitmap
- Scan line separation
- X_size in bytes
- Y_size in scan lines
- Scan line separation
- */
-
- gpr_$inq_bitmap_pointer(bitmap,bitp,sep,status);
- line_sz = header[0].bytes_per_line;
- separation = 2*sep;
- x_size = window.window_size.x_size;
- y_size = window.window_size.y_size;
-
- return( bitmap );
- }
-
- /***************************************************************************
- *
- * GET_GMF(filename)
- *
- * INPUT: filename - GMF file name
- *
- * OUTPUT: Bitmap discriptor NULL if not found
- * line_sz - # Bytes/scan line set
- * separation - Bytes between scan lines
- * x_size,y_size - Size of map in raster units
- *
- * SIDE EFFECTS: Bit map moved into virtual memory
- * Graphics inited for BORROW mode
- * If this is a full window then DON'T invert it before
- * use
- *
- ****************************************************************************/
-
- gpr_$bitmap_desc_t get_gmf(filename)
- char filename[];
- {
- gpr_$window_t window;
- gpr_$bmf_group_header_array_t header;
- short length,sep;
- gpr_$plane_t hi_plane = 7;
- short groups,words,bpi,x_dim,y_dim;
- gpr_$bitmap_desc_t bitmap,filebm;
- status_$t status;
- gpr_$version_t version;
- gpr_$attribute_desc_t attribs;
- stream_$id_t stream;
- length = strlen(filename);
-
- /* Init the bit map dimensions */
-
- window.window_base.x_coord = (short) 0;
- window.window_base.y_coord = (short) 0;
- window.window_size.x_size = (short) SCREEN_X;
- window.window_size.y_size = (short) SCREEN_Y;
-
- /* Initialize by borrowing the display */
-
- gpr_$init(GPR_MODE,1,window.window_size,hi_plane,bitmap,status);
-
- /* Set up an attribute block for the Xfer */
-
- gpr_$allocate_attribute_block(attribs,status);
-
- /* Open the GMF file and read it in */
-
- gmf_$open(filename,length,gmf_$read,stream,status);
-
- /* If it didn't open tell user and quit */
-
- if( status.fail )
- {
- bitmap = NULL;
- gpr_$terminate(0,status);
- return( bitmap );
- }
-
- /* Get access and display information, bitmap & GMF stuff */
-
- gpr_$enable_direct_access(status);
-
- gpr_$inq_bitmap_pointer(bitmap,bitp,sep,status);
- separation = 2*sep;
-
- /* Get information on GMF file, use JW's function */
-
- gmf_$inquire(&stream,&x_dim,&y_dim,&words,&status);
-
- /* ***** words is really # 16 bits words/line - just divide
- x_dim by 16 to get what we want We used it to hold bits/inch
- which we will throw away
- */
-
- words = x_dim/(short)16;
- line_sz = 2 * (int) words;
- x_size = (int) x_dim;
- y_size = (int) y_dim;
-
- /* Set window for blt */
-
- window.window_size.x_size = x_dim;
- window.window_size.y_size = y_dim;
-
- /* Move the plane onto the bit map */
-
- gmf_$restore_plane(stream,(short)SCREEN_X,(short)SCREEN_Y,
- (short)SCREEN_WD,bitp,bpi,status);
-
- /* Since this is a GMF we have to invert it (GMF stuff comes out
- inverted) but only if it is a WINDOW if screen leave it alone
- */
-
- if( x_size == SCREEN_X && y_size == SCREEN_Y )
- {
- gpr_$set_raster_op((short)0,(short)10,status); /* Compliment */
- gpr_$pixel_blt(bitmap,window,window.window_base,status);
- }
-
- /* Close GMF & return bit map to user */
-
- gmf_$close(stream,status);
- return( bitmap );
- }
-
- /****************************************************************************
- *
- * GET_LINE(ptr,line,size,sep,out)
- *
- * INPUT: ptr - Pointer to UL corner of BM
- * line - Scan line # to read out
- * size - # bytes/scan line
- * sep - Gaps between scan lines
- *
- * OUTPUT: scanline - Scan line data
- * # Bytes in scan line
- *
- *****************************************************************************/
-
- get_line(ptr,line,size,sep,out)
- unsigned char *ptr,out[];
- int line,size,sep;
- {
- int i,j;
- unsigned char *locptr;
-
- /*---------------------------------------------------------------------------
-
- OPERATION:
-
- 1) Set bit pointer to point to this scan line
- 2) Move scan line data to scanline
- 3) Return count
-
- ----------------------------------------------------------------------------*/
-
- locptr = ptr + sep*line;
-
- for( i=0; i<size; i++ )
- {
- out[i] = *(locptr);
- *(locptr++) = ~out[i];
- }
-
- return( size );
- }
-
- /*****************************************************************************
- *
- * COMPRS_LINE(line,size)
- *
- * INPUT: line - Scan line to be compressed
- * size - # bytes in scan line
- *
- * OUTPUT: size of new scan line
- * line compressed as shown below
- *
- * Compression is as follows:
- *
- * <CNT><Byte><Byte>... If <CNT> < 0x80 i.e. <CNT> different bytes
- * <CNT><Byte> If <CNT> > 0x80 i.e. <CNT> repeated bytes
- *
- *****************************************************************************/
-
- comprs_line(line,size)
- unsigned char line[];
- int size;
- {
- int i,j,k,cntpsn,count;
- int flag;
- unsigned char pixel;
- unsigned char out[MAX_SCAN_LINE];
-
- /*-----------------------------------------------------------------------------
-
- OPERATION:
-
- 1) Init counters, Check line - if first two byte == set flag
- flag for same else, set for NOTSAME
- 2) Reserve a slot in the output list for the count
- 3)
-
- ------------------------------------------------------------------------------*/
-
-
-
- i = 0;
- j = 2;
- if( line[0] == line[1] )
- {
- flag = SAME;
- cntpsn = 0;
- out[1] = line[0];
- }
- else
- {
- flag = NOTSAME;
- cntpsn = 0;
- out[1] = line[0];
- }
-
- while( i < size )
- {
- switch( flag ) {
-
- /* Same case see how far the run goes then update stuff */
-
- case SAME: count = 0;
- for( k=i; k<size; k++ )
- {
- if( out[j-1] != line[k] )
- break;
- else
- count++;
- }
-
- /* If count is zero then just skip all this stuff and try again
- with the flag the other way
- */
- if( count != 0 )
- {
-
- /* Ok update the count and save the byte in the output line
- NOTE: Count is just 2's compliment of the value
- */
- pixel = -1 * (count-1);
- out[cntpsn] = 0xff & pixel;
-
- /* Set the flag for the other & go to advance j to next frame */
-
- flag = NOTSAME;
- }
- else
- flag = NOTSAME;
- break;
-
- /* Not the same, look for a run of something if found quit */
-
- case NOTSAME: count = 0;
- for( k=i+1; k<size; k++ )
- {
- if( out[j-1] == line[k] )
- break;
- else
- {
- count++;
- out[j++] = line[k];
- }
- }
- /* If count is zero then skip all the updating stuff and just try the
- other method
- */
- if( count != 0 )
- {
-
- out[cntpsn] = count - 1;
-
- /* Set the flag for the other and back up the psn to get the
- start of the run
- */
-
- k = k - 1;
- j--;
- flag = SAME;
- }
- else
- flag = SAME;
- break;
- }
-
-
- /* End of loop update the positions of the count save lcn and
- next character to look at
-
- Only do update on non zero counts
- */
-
- if( count != 0 )
- {
- cntpsn = j;
- out[++j] = line[k];
- j++;
- i = k;
- }
- }
-
- /* All done now j is the size of the output array, so move it
- back to the orignal array and return the size
- */
-
- size = j - 2;
-
- for( i=0; i<size; i++ )
- line[i] = out[i];
-
- return( size );
- }
-
- /********************************************************************************
- *
- * OUT_BUF(data,size,channel)
- *
- * INPUT: data - Output data in bytes to be transmitted
- * as hex followed by a newline
- * size - # Bytes of data
- * -1 => Initialize buffer for run flush channel
- *
- * channel - fileid to use for output
- *
- * OUTPUT: If size = -1 Reset buffer pointers for output
- * flush channel data ignored
- *
- * <>-1 Output data to buffer and write each time full
- *
- *********************************************************************************/
-
- out_buf(data,size,channel)
- char data[];
- int size,channel;
- {
- int i;
- char hexh,hexl,hex_con();
-
- /* Ok look for the flush command */
-
- if( size == -1 )
- {
- write_buf(hexl,1,channel);
- return;
- }
-
- /* No flush - output the data as hex bytes to the buffer
- if full write
- */
-
- for( i=0; i<size; i++ )
- {
-
- /* Convert the data to hex - two bytes */
-
- hexh = hex_con(data[i],1);
- hexl = hex_con(data[i],0);
-
- /* Output the bytes to the buffer */
-
- write_buf(hexh,0,channel);
- write_buf(hexl,0,channel);
- }
-
- /* Put a LF on the end of the line */
-
- write_buf(LF,0,channel);
- }
-
- /******************************************************************************
- *
- * WRITE_BUF(ch,flush,channel)
- *
- * INPUT: ch - Character to be written to buffer
- * flush - 0 Write character to buffer
- * 1 Flush channel and reset
- * channel - Channel to write to
- *
- * OUTPUT: Data written to channel and buffer written if necessary
- *
- ******************************************************************************/
-
- write_buf(ch,flush,channel)
- char ch;
- int flush,channel;
- {
- static int bufpsn = 0;
- static char buffer[BUF_SZ];
-
- /* Initialize and flush channel, if there is data flush it */
-
- if( flush == 1 )
- {
- if( bufpsn != 0 )
- write(channel,buffer,bufpsn);
-
- fsync(channel);
- bufpsn = 0;
- return;
- }
- else
- {
-
- /* Write the stuff out to the channel */
-
- buffer[bufpsn++] = ch;
- if( bufpsn == BUF_SZ )
- {
- write(channel,buffer,BUF_SZ);
- bufpsn = 0;
- }
- }
- }
-
- /*******************************************************************************
- *
- * HEX_CON(ch,nibble)
- *
- * INPUT: ch - Character to convert to hex
- * nibble - 0 Top nibble
- * 1 Bottom nibble
- *
- * OUTPUT: Hex character representation of the nibble
- *
- ********************************************************************************/
-
- char hex_con(ch,nibble)
- char ch;
- int nibble;
- {
- char nib;
-
- /* Select the nibble from the character */
-
- if( nibble == 1 )
- nib = ( 0xf0 & ch ) >> 4;
- else
- nib = 0x0f & ch;
-
- /* Convert to hex */
-
- if( nib > 9 )
- nib = nib + 'a' - 10;
- else
- nib = nib + '0';
-
- return( nib );
- }
-