home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------*/
- /* FILE: PRTPCX.C */
- /* DESC: Prints PCX files on an HP LaserJet. */
- /* AUTHOR: Marv Luse, Ithaca Street Software */
- /* COMPILERS: Any (Tested with Zortech and Borland) */
- /* COPYRIGHT: Use freely, but acknowledge source. */
- /*--------------------------------------------------------*/
-
- #include "stdlib.h"
- #include "stdio.h"
- #include "string.h"
- #include "ctype.h"
- #include "dos.h"
- #include "io.h"
-
- #include "pcx.h"
-
- typedef struct _rgb_triple
- {
- unsigned char r; /* red */
- unsigned char g; /* green */
- unsigned char b; /* blue */
- }
- rgb_triple;
-
- #define TYP_MASK 0xC0 /* mask top 2 bits of a byte */
- #define CNT_MASK 0x3F /* mask bot 6 bits of a byte */
-
- char pcx_file[80] = "\0", /* file to print */
- prt_port[80] = "LPT1"; /* printer destination */
-
- int res = 100, /* resolution */
- inv = 0, /* invert flag */
- xorg = 0, /* xorg in dots */
- yorg = 0; /* yorg in dots */
-
- char pat[16][8] = /* shading pattern set */
- {
- { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
- { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA },
- { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 },
- { 0xAA, 0x41, 0xAA, 0x14, 0xAA, 0x41, 0xAA, 0x14 },
- { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 },
- { 0x80, 0x08, 0x80, 0x08, 0x80, 0x08, 0x80, 0x08 },
- { 0x80, 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00 },
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
- { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
- { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA },
- { 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA },
- { 0x14, 0xAA, 0x41, 0xAA, 0x14, 0xAA, 0x41, 0xAA },
- { 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88 },
- { 0x80, 0x08, 0x80, 0x08, 0x80, 0x08, 0x80, 0x08 },
- { 0x08, 0x00, 0x80, 0x00, 0x08, 0x00, 0x80, 0x00 },
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
- };
-
- /*--------------------------------------------------------*/
- /* explain program usage... */
- /*--------------------------------------------------------*/
-
- void explain_pgm( void )
- {
- printf( "\n" );
- printf( "usage: PRTPCX pcx_file [prt_port] [sw...]\n" );
- printf( "\n" );
- printf( "pcx_file : file to print\n" );
- printf( "\n" );
- printf( "prt_port : printer port (def = LPT1)\n" );
- printf( "\n" );
- printf( "switches : -i : invert image\n" );
- printf( " -rnnn : resolution nnn dpi (def=100)\n" );
- printf( " -xd.d : x origin d.d inches (def=0.0)\n" );
- printf( " -yd.d : y origin d.d inches (def=0.0)\n" );
- printf( "\n" );
- }
-
- /*--------------------------------------------------------*/
- /* write a message and quit... */
- /*--------------------------------------------------------*/
-
- void exit_pgm( char *msg )
- {
- printf( "%s\n", msg );
- exit( 0 );
- }
-
- /*--------------------------------------------------------*/
- /* process command line args... */
- /*--------------------------------------------------------*/
-
- void process_args( int argc, char *argv[] )
- {
- double v;
- int i;
- char c;
-
- /* look at command line args */
- for( i=1; i<argc; i++ )
- {
- if( (*argv[i] == '/') || (*argv[i] == '-') )
- {
- c = *(argv[i] + 1);
- switch( tolower(c) )
- {
- case 'i' : /* resolution */
- inv = 1;
- break;
-
- case 'r' : /* resolution */
- sscanf( argv[i], "%d", &res );
- if( (res != 75) && (res != 100) &&
- (res != 150) && (res != 300) )
- exit_pgm( "Invalid resolution" );
- break;
-
- case 'x' : /* x org */
- sscanf( argv[i], "%lf", &v );
- v *= 300.0; v += 0.5;
- xorg = (int) v;
- break;
-
- case 'y' : /* y org */
- sscanf( argv[i], "%lf", &v );
- v *= 300.0; v += 0.5;
- yorg = (int) v;
- break;
-
- default : /* error */
- exit_pgm( "Invalid switch" );
- break;
- }
- }
- else if( pcx_file[0] == 0 )
- {
- strcpy( pcx_file, argv[i] );
- /* add .PCX extension if none provided */
- if( strchr( pcx_file, '.' ) == NULL )
- strcat( pcx_file, ".pcx" );
- }
- else
- {
- strcpy( prt_port, argv[i] );
- }
- }
-
- /* do we have a file name? */
- if( pcx_file[0] == 0 )
- exit_pgm( "No PCX file name given." );
- }
-
- /*--------------------------------------------------------*/
- /* Use DOS func 44h to set raw mode if a char device... */
- /*--------------------------------------------------------*/
-
- void set_binary_mode ( FILE *fptr )
- {
- int hand;
- union REGS r;
-
- /* get file handle */
- hand = fileno(fptr);
-
- /* get device info */
- r.h.ah = 0x44;
- r.h.al = 0x00;
- r.x.bx = hand;
- r.x.dx = 0;
- int86(0x21, &r, &r);
-
- /* check the device... */
- if( (r.h.dl & 0x80) ) /* char device ? */
- {
- if( ! (r.h.dl & 0x20) ) /* cooked mode ? */
- {
- r.h.ah = 0x44;
- r.h.al = 0x01;
- r.x.bx = hand;
- r.h.dh = 0x00;
- r.h.dl |= 0x20; /* set raw mode */
- int86(0x21, &r, &r);
- }
- }
- }
-
- /*--------------------------------------------------------*/
- /* Initialize the LaserJet... */
- /*--------------------------------------------------------*/
-
- void init_prt( FILE *fptr, int xo, int yo, int res )
- {
- char cmd[24];
-
- /* set cursor position */
- sprintf( cmd, "\033*p%dx%dY", xo, yo );
- fwrite( cmd, strlen(cmd), 1, fptr );
-
- /* set resolution */
- sprintf( cmd, "\033*t%dR", res );
- fwrite( cmd, strlen(cmd), 1, fptr );
-
- /* enter raster graphics mode */
- fwrite( "\033*r1A", 5, 1, fptr );
-
- /* check that it all happened */
- if( ferror(fptr) )
- exit_pgm( "Error in init_prt" );
- }
-
- /*--------------------------------------------------------*/
- /* Terminate on the LaserJet... */
- /*--------------------------------------------------------*/
-
- void term_prt( FILE *fptr )
- {
- /* end raster graphics mode */
- fwrite( "\033*rB", 4, 1, fptr );
-
- /* eject a page */
- fwrite( "\014", 1, 1, fptr );
- }
-
- /*--------------------------------------------------------*/
- /* Print a monochrome image... */
- /*--------------------------------------------------------*/
-
- void print_mono( FILE *f_in, FILE *f_out, pcx_header *pH )
- {
- int bytecnt, rowcnt, done;
- int nrows, ncols, endmask;
- unsigned char hdr, cnt, dat;
- char cmd[24];
-
- bytecnt = rowcnt = done = 0;
- nrows = pH->y2 - pH->y1 + 1;
- ncols = pH->x2 - pH->x1 + 1;
- endmask = ( ~(255 >> (ncols & 7)) ) & 255;
- sprintf( cmd, "\033*b%dW", pH->bplin );
-
- while( ! done )
- {
- /* get a byte */
- hdr = fgetc( f_in );
-
- /* decode it */
- if ( (hdr & TYP_MASK) == TYP_MASK )
- {
- cnt = hdr & CNT_MASK;
- dat = fgetc( f_in );
- }
- else
- {
- cnt = 1;
- dat = hdr;
- }
-
- /* if invert selected, bitwise invert */
- if( inv )
- dat = ~dat;
-
- /* send the byte(s) */
- while( cnt-- )
- {
- /* if bytecnt is zero, start a row */
- if( bytecnt == 0 )
- fwrite( cmd, strlen(cmd), 1, f_out );
-
- /* update counter, send byte */
- bytecnt++;
- if( bytecnt == pH->bplin )
- {
- fputc( dat&endmask, f_out );
- bytecnt = 0;
- rowcnt++;
- if( rowcnt == nrows )
- done = 1;
- }
- else
- fputc( dat, f_out );
- }
- }
- }
-
- /*--------------------------------------------------------*/
- /* Output 16-color scanline... */
- /*--------------------------------------------------------*/
-
- void lineout_16( FILE *f_out, int *scanline, int npix, int rm8 )
- {
- int i, mask, curb, nbytes;
- char cmd[24];
-
- nbytes = (npix + 7) / 8;
- sprintf( cmd, "\033*b%dW", nbytes );
- fwrite( cmd, strlen(cmd), 1, f_out );
-
- curb = 0;
- mask = 0x80;
-
- for( i=0; i<npix; i++ )
- {
- curb |= pat[scanline[i]][rm8] & mask;
- mask >>= 1;
- if( mask == 0 )
- {
- mask = 0x80;
- fputc( curb, f_out );
- curb = 0;
- }
- }
- if( npix & 7 )
- fputc( curb, f_out );
- }
-
- /*--------------------------------------------------------*/
- /* Print a 16-color image... */
- /*--------------------------------------------------------*/
-
- void print_color_16( FILE *f_in, FILE *f_out, pcx_header *pH )
- {
- int bytecnt, rowcnt, planecnt, done, hdr, cnt, dat;
- int i, nrows, ncols, *scanline, sclen, curpx, plmask;
-
- bytecnt = rowcnt = planecnt = done = 0;
- curpx = 0;
- plmask = 0x08;
- nrows = pH->y2 - pH->y1 + 1;
- ncols = pH->x2 - pH->x1 + 1;
-
- /* scanline will hold a full row of pixels, including */
- /* unused padding pixels. padding will be ignored. */
- sclen = pH->bplin * 8 * sizeof(int);
- scanline = (int *) malloc( sclen );
- if( scanline == NULL )
- exit_pgm( "Out of memory in print_color_16" );
- memset( scanline, 0, sclen );
-
- while( ! done )
- {
- /* get a byte */
- hdr = fgetc( f_in );
-
- /* decode it */
- if ( (hdr & TYP_MASK) == TYP_MASK )
- {
- cnt = hdr & CNT_MASK;
- dat = fgetc( f_in );
- }
- else
- {
- cnt = 1;
- dat = hdr;
- }
-
- /* if invert selected, bitwise invert */
- if( inv )
- dat = ~dat;
-
- /* accumulate pixels in scanline buffer */
- while( cnt-- )
- {
- /* isolate 8 pixels in current byte */
- for( i=128; i>0; i>>=1 )
- {
- if( dat & i )
- scanline[curpx] |= plmask;
- curpx++;
- }
-
- /* update counters */
- bytecnt++;
- if( bytecnt == pH->bplin )
- {
- bytecnt = 0;
- curpx = 0;
- planecnt++;
- plmask >>= 1;
- if( planecnt == pH->nplanes )
- {
- lineout_16( f_out, scanline, ncols, rowcnt & 7 );
- memset( scanline, 0, sclen );
- planecnt = 0;
- plmask = 0x08;
- rowcnt++;
- if ( rowcnt == nrows )
- done = 1;
- }
- }
- }
- }
- }
-
- /*--------------------------------------------------------*/
- /* Fill in pixel lookup table for 256-clr images */
- /*--------------------------------------------------------*/
-
- void init_lu_256( rgb_triple *rgb, int *lutbl )
- {
- int i, j, ic;
- unsigned int ri, gi, bi;
- long d, dc;
-
- /* set base palette */
- for( i=0; i<16; i++ )
- {
- lutbl[i] = i;
- }
-
- /* compute indexes above 15 */
- for( i=16; i<256; i++ )
- {
- ri = rgb[i].r;
- gi = rgb[i].g;
- bi = rgb[i].b;
- ic = 0;
-
- /* dc is "distance" from rgb[i] to rgb[0] */
- dc = (rgb[0].r - ri) * (rgb[0].r - ri);
- dc += (rgb[0].g - gi) * (rgb[0].g - gi);
- dc += (rgb[0].b - bi) * (rgb[0].b - bi);
-
- for( j=1; j<16; j++ )
- {
- /* d is "distance" from rgb[i] to rgb[j] */
- d = (rgb[j].r - ri) * (rgb[j].r - ri);
- d += (rgb[j].g - gi) * (rgb[j].g - gi);
- d += (rgb[j].b - bi) * (rgb[j].b - bi);
-
- if( d < dc )
- {
- dc = d;
- ic = j;
- }
- }
-
- lutbl[i] = ic;
- }
- }
-
- /*--------------------------------------------------------*/
- /* Print a 256-color image... */
- /*--------------------------------------------------------*/
-
- void print_color_256( FILE *f_in, FILE *f_out, pcx_header *pH )
- {
- rgb_triple *rgb;
- int *lutbl, *scanline;
- int bytecnt, rowcnt, done, hdr, cnt, dat;
- int nrows, ncols, sclen;
-
- /* allocate palette variables */
- rgb = (rgb_triple *) malloc( sizeof(rgb_triple) * 256 );
- if( rgb == NULL )
- exit_pgm( "Out of memory in print_color_256" );
- lutbl = (int *) malloc( sizeof(int) * 256 );
- if( lutbl == NULL )
- exit_pgm( "Out of memory in print_color_256" );
-
- /* read palette info from end of file */
- if( fseek( f_in, -768L, SEEK_END ) )
- exit_pgm( "Error seeking to palette" );
- if( fread( rgb, sizeof(rgb_triple), 256, f_in ) != 256 )
- exit_pgm( "Error reading palette" );
-
- /* construct lookup table */
- init_lu_256( rgb, lutbl );
-
- /* reposition file ptr to start of image */
- if( fseek( f_in, 128, SEEK_SET ) )
- exit_pgm( "Error seeking to image" );
-
- /* allocate scanline buffer */
- sclen = pH->bplin * sizeof(int);
- scanline = (int *) malloc( sclen );
- if( scanline == NULL )
- exit_pgm( "Out of memory in print_color_16" );
-
- bytecnt = rowcnt = done = 0;
- nrows = pH->y2 - pH->y1 + 1;
- ncols = pH->x2 - pH->x1 + 1;
-
- while( ! done )
- {
- /* get a byte */
- hdr = fgetc( f_in );
-
- /* decode it */
- if ( (hdr & TYP_MASK) == TYP_MASK )
- {
- cnt = hdr & CNT_MASK;
- dat = fgetc( f_in );
- }
- else
- {
- cnt = 1;
- dat = hdr;
- }
-
- /* if invert selected, bitwise invert */
- if( inv )
- dat = ~dat;
-
- /* accumulate pixels in scanline buffer */
- while( cnt-- )
- {
- /* put pixel into scanline buffer */
- scanline[bytecnt] = lutbl[dat];
-
- /* update counter */
- bytecnt++;
- if( bytecnt == pH->bplin )
- {
- lineout_16( f_out, scanline, ncols, rowcnt & 7 );
- bytecnt = 0;
- rowcnt++;
- if( rowcnt == nrows )
- done = 1;
- }
- }
- }
- }
-
- /*--------------------------------------------------------*/
- /* Print the specified PCX file... */
- /*--------------------------------------------------------*/
-
- void print_pcx( char *pcxf, char *prtf, int xo, int yo, int r )
- {
- FILE *f_in, *f_out;
- pcx_header pcxH;
-
- /* set up */
- if( (f_in = fopen( pcxf, "rb" )) == NULL )
- exit_pgm( "Error opening PCX file" );
- if( (f_out = fopen( prtf, "wb" )) == NULL )
- exit_pgm( "Error opening printer" );
- set_binary_mode( f_out );
-
- /* read the pcx header */
- if( fread(&pcxH, sizeof(pcx_header), 1, f_in) != 1 )
- exit_pgm( "Error reading PCX header" );
-
- /* initialize the printer */
- printf( "\nPrinting '%s'...", pcxf );
- init_prt( f_out, xo, yo, r );
-
- /* indicate image dimensions */
- printf( "%d W x %d H, %d bytes/line, ",
- pcxH.x2-pcxH.x1+1, pcxH.y2-pcxH.y1+1, pcxH.bplin );
-
- /* determine the image type, call the appropriate */
- /* image processing function... */
-
- /* monochrome bitmap */
- if( (pcxH.nplanes == 1) && (pcxH.bitpx == 1) )
- {
- printf( "monochrome..." );
- print_mono( f_in, f_out, &pcxH );
- }
-
- /* 16-color bitmap */
- else if( pcxH.nplanes == 4 )
- {
- printf( "16 color..." );
- print_color_16( f_in, f_out, &pcxH );
- }
-
- /* 256-color bitmap */
- else if( pcxH.bitpx == 8 )
- {
- printf( "256 color..." );
- print_color_256( f_in, f_out, &pcxH );
- }
-
- /* unsupported image type */
- else
- printf( "Unsupported image type, skipping print!" );
-
- /* finish up on the printer */
- term_prt( f_out );
- printf( "done" );
-
- /* clean up */
- fclose( f_in );
- fclose( f_out );
- }
-
- /*--------------------------------------------------------*/
- /* M A I N */
- /*--------------------------------------------------------*/
-
- void main( int argc, char *argv[] )
- {
- /* sign-on */
- printf( "\nPrint PCX File on LaserJet\n" );
-
- /* help indicated? */
- if( (argc < 2) || (*argv[1] == '?') )
- {
- explain_pgm();
- exit( 0 );
- }
-
- /* process command line... */
- process_args( argc, argv );
-
- /* print the file */
- print_pcx( pcx_file, prt_port, xorg, yorg, res );
-
- /* sign-off */
- printf( "\nend-of-pgm" );
- }
-
- /*---------------- End of File PRTPCX.C ------------------*/
-