home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / LASER / PRTPCX.ZIP / PRTPCX.C < prev   
Encoding:
C/C++ Source or Header  |  1991-01-01  |  17.0 KB  |  614 lines

  1. /*--------------------------------------------------------*/
  2. /* FILE:       PRTPCX.C                                   */
  3. /* DESC:       Prints PCX files on an HP LaserJet.        */
  4. /* AUTHOR:     Marv Luse, Ithaca Street Software          */
  5. /* COMPILERS:  Any (Tested with Zortech and Borland)      */
  6. /* COPYRIGHT:  Use freely, but acknowledge source.        */
  7. /*--------------------------------------------------------*/
  8.  
  9. #include "stdlib.h"
  10. #include "stdio.h"
  11. #include "string.h"
  12. #include "ctype.h"
  13. #include "dos.h"
  14. #include "io.h"
  15.  
  16. #include "pcx.h"
  17.  
  18. typedef struct _rgb_triple
  19. {
  20.      unsigned char r;                              /* red */
  21.      unsigned char g;                            /* green */
  22.      unsigned char b;                             /* blue */
  23. }
  24. rgb_triple;
  25.  
  26. #define TYP_MASK 0xC0        /* mask top 2 bits of a byte */
  27. #define CNT_MASK 0x3F        /* mask bot 6 bits of a byte */
  28.  
  29. char pcx_file[80] = "\0",                /* file to print */
  30.      prt_port[80] = "LPT1";        /* printer destination */
  31.  
  32. int   res  = 100,                           /* resolution */
  33.       inv  = 0,                            /* invert flag */
  34.       xorg = 0,                           /* xorg in dots */
  35.       yorg = 0;                           /* yorg in dots */
  36.  
  37. char  pat[16][8] =                 /* shading pattern set */
  38. {
  39.    { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
  40.    { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA },
  41.    { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 },
  42.    { 0xAA, 0x41, 0xAA, 0x14, 0xAA, 0x41, 0xAA, 0x14 },
  43.    { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 },
  44.    { 0x80, 0x08, 0x80, 0x08, 0x80, 0x08, 0x80, 0x08 },
  45.    { 0x80, 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00 },
  46.    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  47.    { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
  48.    { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA },
  49.    { 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA },
  50.    { 0x14, 0xAA, 0x41, 0xAA, 0x14, 0xAA, 0x41, 0xAA },
  51.    { 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88 },
  52.    { 0x80, 0x08, 0x80, 0x08, 0x80, 0x08, 0x80, 0x08 },
  53.    { 0x08, 0x00, 0x80, 0x00, 0x08, 0x00, 0x80, 0x00 },
  54.    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  55. };
  56.  
  57. /*--------------------------------------------------------*/
  58. /* explain program usage...                               */
  59. /*--------------------------------------------------------*/
  60.  
  61. void explain_pgm( void )
  62. {
  63.    printf( "\n" );
  64.    printf( "usage:     PRTPCX  pcx_file  [prt_port] [sw...]\n" );
  65.    printf( "\n" );
  66.    printf( "pcx_file : file to print\n" );
  67.    printf( "\n" );
  68.    printf( "prt_port : printer port (def = LPT1)\n" );
  69.    printf( "\n" );
  70.    printf( "switches : -i    : invert image\n" );
  71.    printf( "           -rnnn : resolution nnn dpi (def=100)\n" );
  72.    printf( "           -xd.d : x origin d.d inches (def=0.0)\n" );
  73.    printf( "           -yd.d : y origin d.d inches (def=0.0)\n" );
  74.    printf( "\n" );
  75. }
  76.  
  77. /*--------------------------------------------------------*/
  78. /* write a message and quit...                            */
  79. /*--------------------------------------------------------*/
  80.  
  81. void exit_pgm( char *msg )
  82. {
  83.    printf( "%s\n", msg );
  84.    exit( 0 );
  85. }
  86.  
  87. /*--------------------------------------------------------*/
  88. /* process command line args...                           */
  89. /*--------------------------------------------------------*/
  90.  
  91. void process_args( int argc, char *argv[] )
  92. {
  93.    double v;
  94.    int    i;
  95.    char   c;
  96.  
  97.    /* look at command line args */
  98.    for( i=1; i<argc; i++ )
  99.    {
  100.       if( (*argv[i] == '/') || (*argv[i] == '-') )
  101.       {
  102.          c = *(argv[i] + 1);
  103.          switch( tolower(c) )
  104.          {
  105.             case 'i' : /* resolution */
  106.                        inv = 1;
  107.                        break;
  108.  
  109.             case 'r' : /* resolution */
  110.                        sscanf( argv[i], "%d", &res );
  111.                        if( (res != 75)  && (res != 100) &&
  112.                            (res != 150) && (res != 300) )
  113.                           exit_pgm( "Invalid resolution" );
  114.                        break;
  115.  
  116.             case 'x' : /* x org */
  117.                        sscanf( argv[i], "%lf", &v );
  118.                        v *= 300.0;  v += 0.5;
  119.                        xorg = (int) v;
  120.                        break;
  121.  
  122.             case 'y' : /* y org */
  123.                        sscanf( argv[i], "%lf", &v );
  124.                        v *= 300.0;  v += 0.5;
  125.                        yorg = (int) v;
  126.                        break;
  127.  
  128.             default :  /* error */
  129.                        exit_pgm( "Invalid switch" );
  130.                        break;
  131.          }
  132.       }
  133.       else if( pcx_file[0] == 0 )
  134.       {
  135.          strcpy( pcx_file, argv[i] );
  136.          /* add .PCX extension if none provided */
  137.          if( strchr( pcx_file, '.' ) == NULL )
  138.             strcat( pcx_file, ".pcx" );
  139.       }
  140.       else
  141.       {
  142.          strcpy( prt_port, argv[i] );
  143.       }
  144.    }
  145.  
  146.    /* do we have a file name? */
  147.    if( pcx_file[0] == 0 )
  148.       exit_pgm( "No PCX file name given." );
  149. }
  150.  
  151. /*--------------------------------------------------------*/
  152. /* Use DOS func 44h to set raw mode if a char device...   */
  153. /*--------------------------------------------------------*/
  154.  
  155. void set_binary_mode ( FILE *fptr )
  156. {
  157.      int         hand;
  158.      union REGS  r;
  159.  
  160.      /* get file handle */
  161.      hand = fileno(fptr);
  162.  
  163.      /* get device info */
  164.      r.h.ah = 0x44;
  165.      r.h.al = 0x00;
  166.      r.x.bx = hand;
  167.      r.x.dx = 0;
  168.      int86(0x21, &r, &r);
  169.  
  170.      /* check the device... */
  171.      if( (r.h.dl & 0x80) )          /* char device ? */
  172.      {
  173.         if( ! (r.h.dl & 0x20) )     /* cooked mode ? */
  174.         {
  175.            r.h.ah  = 0x44;
  176.            r.h.al  = 0x01;
  177.            r.x.bx  = hand;
  178.            r.h.dh  = 0x00;
  179.            r.h.dl |= 0x20;          /* set raw mode */
  180.            int86(0x21, &r, &r);
  181.         }
  182.      }
  183. }
  184.  
  185. /*--------------------------------------------------------*/
  186. /* Initialize the LaserJet...                             */
  187. /*--------------------------------------------------------*/
  188.  
  189. void init_prt( FILE *fptr, int xo, int yo, int res )
  190. {
  191.    char cmd[24];
  192.  
  193.    /* set cursor position */
  194.    sprintf( cmd, "\033*p%dx%dY", xo, yo );
  195.    fwrite( cmd, strlen(cmd), 1, fptr );
  196.  
  197.    /* set resolution */
  198.    sprintf( cmd, "\033*t%dR", res );
  199.    fwrite( cmd, strlen(cmd), 1, fptr );
  200.  
  201.    /* enter raster graphics mode */
  202.    fwrite( "\033*r1A", 5, 1, fptr );
  203.  
  204.    /* check that it all happened */
  205.    if( ferror(fptr) )
  206.       exit_pgm( "Error in init_prt" );
  207. }
  208.  
  209. /*--------------------------------------------------------*/
  210. /* Terminate on the LaserJet...                           */
  211. /*--------------------------------------------------------*/
  212.  
  213. void term_prt( FILE *fptr )
  214. {
  215.    /* end raster graphics mode */
  216.    fwrite( "\033*rB", 4, 1, fptr );
  217.  
  218.    /* eject a page */
  219.    fwrite( "\014", 1, 1, fptr );
  220. }
  221.  
  222. /*--------------------------------------------------------*/
  223. /* Print a monochrome image...                            */
  224. /*--------------------------------------------------------*/
  225.  
  226. void print_mono( FILE *f_in, FILE *f_out, pcx_header *pH )
  227. {
  228.    int            bytecnt, rowcnt, done;
  229.    int            nrows, ncols, endmask;
  230.    unsigned char  hdr, cnt, dat;
  231.    char           cmd[24];
  232.  
  233.    bytecnt = rowcnt = done = 0;
  234.    nrows = pH->y2 - pH->y1 + 1;
  235.    ncols = pH->x2 - pH->x1 + 1;
  236.    endmask = ( ~(255 >> (ncols & 7)) ) & 255;
  237.    sprintf( cmd, "\033*b%dW", pH->bplin );
  238.  
  239.    while( ! done )
  240.    {
  241.       /* get a byte */
  242.       hdr = fgetc( f_in );
  243.  
  244.       /* decode it */
  245.       if ( (hdr & TYP_MASK) == TYP_MASK )
  246.       {
  247.          cnt = hdr & CNT_MASK;
  248.          dat = fgetc( f_in );
  249.       }
  250.       else
  251.       {
  252.          cnt = 1;
  253.          dat = hdr;
  254.       }
  255.  
  256.       /* if invert selected, bitwise invert */
  257.       if( inv )
  258.          dat = ~dat;
  259.  
  260.       /* send the byte(s) */
  261.       while( cnt-- )
  262.       {
  263.          /* if bytecnt is zero, start a row */
  264.          if( bytecnt == 0 )
  265.             fwrite( cmd, strlen(cmd), 1, f_out );
  266.  
  267.          /* update counter, send byte */
  268.          bytecnt++;
  269.          if( bytecnt == pH->bplin )
  270.          {
  271.             fputc( dat&endmask, f_out );
  272.             bytecnt = 0;
  273.             rowcnt++;
  274.             if( rowcnt == nrows )
  275.                 done = 1;
  276.          }
  277.          else
  278.             fputc( dat, f_out );
  279.       }
  280.    }
  281. }
  282.  
  283. /*--------------------------------------------------------*/
  284. /* Output 16-color scanline...                            */
  285. /*--------------------------------------------------------*/
  286.  
  287. void lineout_16( FILE *f_out, int *scanline, int npix, int rm8 )
  288. {
  289.    int  i, mask, curb, nbytes;
  290.    char cmd[24];
  291.  
  292.    nbytes = (npix + 7) / 8;
  293.    sprintf( cmd, "\033*b%dW", nbytes );
  294.    fwrite( cmd, strlen(cmd), 1, f_out );
  295.  
  296.    curb = 0;
  297.    mask = 0x80;
  298.  
  299.    for( i=0; i<npix; i++ )
  300.    {
  301.       curb |= pat[scanline[i]][rm8] & mask;
  302.       mask >>= 1;
  303.       if( mask == 0 )
  304.       {
  305.          mask = 0x80;
  306.          fputc( curb, f_out );
  307.          curb = 0;
  308.       }
  309.    }
  310.    if( npix & 7 )
  311.       fputc( curb, f_out );
  312. }
  313.  
  314. /*--------------------------------------------------------*/
  315. /* Print a 16-color image...                              */
  316. /*--------------------------------------------------------*/
  317.  
  318. void print_color_16( FILE *f_in, FILE *f_out, pcx_header *pH )
  319. {
  320.    int  bytecnt, rowcnt, planecnt, done, hdr, cnt, dat;
  321.    int  i, nrows, ncols, *scanline, sclen, curpx, plmask;
  322.  
  323.    bytecnt = rowcnt = planecnt = done = 0;
  324.    curpx  = 0;
  325.    plmask = 0x08;
  326.    nrows = pH->y2 - pH->y1 + 1;
  327.    ncols = pH->x2 - pH->x1 + 1;
  328.  
  329.    /* scanline will hold a full row of pixels, including */
  330.    /* unused padding pixels.  padding will be ignored.   */
  331.    sclen = pH->bplin * 8 * sizeof(int);
  332.    scanline = (int *) malloc( sclen );
  333.    if( scanline == NULL )
  334.       exit_pgm( "Out of memory in print_color_16" );
  335.    memset( scanline, 0, sclen );
  336.  
  337.    while( ! done )
  338.    {
  339.       /* get a byte */
  340.       hdr = fgetc( f_in );
  341.  
  342.       /* decode it */
  343.       if ( (hdr & TYP_MASK) == TYP_MASK )
  344.       {
  345.          cnt = hdr & CNT_MASK;
  346.          dat = fgetc( f_in );
  347.       }
  348.       else
  349.       {
  350.          cnt = 1;
  351.          dat = hdr;
  352.       }
  353.  
  354.       /* if invert selected, bitwise invert */
  355.       if( inv )
  356.          dat = ~dat;
  357.  
  358.       /* accumulate pixels in scanline buffer */
  359.       while( cnt-- )
  360.       {
  361.          /* isolate 8 pixels in current byte */
  362.          for( i=128; i>0; i>>=1 )
  363.          {
  364.             if( dat & i )
  365.                scanline[curpx] |= plmask;
  366.             curpx++;
  367.          }
  368.  
  369.          /* update counters */
  370.          bytecnt++;
  371.          if( bytecnt == pH->bplin )
  372.          {
  373.             bytecnt = 0;
  374.             curpx = 0;
  375.             planecnt++;
  376.             plmask >>= 1;
  377.             if( planecnt == pH->nplanes )
  378.             {
  379.                lineout_16( f_out, scanline, ncols, rowcnt & 7 );
  380.                memset( scanline, 0, sclen );
  381.                planecnt = 0;
  382.                plmask = 0x08;
  383.                rowcnt++;
  384.                if ( rowcnt == nrows )
  385.                    done = 1;
  386.             }
  387.          }
  388.       }
  389.    }
  390. }
  391.  
  392. /*--------------------------------------------------------*/
  393. /* Fill in pixel lookup table for 256-clr images          */
  394. /*--------------------------------------------------------*/
  395.  
  396. void init_lu_256( rgb_triple *rgb, int *lutbl )
  397. {
  398.      int           i, j, ic;
  399.      unsigned int  ri, gi, bi;
  400.      long          d, dc;
  401.  
  402.      /* set base palette */
  403.      for( i=0; i<16; i++ )
  404.      {
  405.         lutbl[i] = i;
  406.      }
  407.  
  408.      /* compute indexes above 15 */
  409.      for( i=16; i<256; i++ )
  410.      {
  411.         ri = rgb[i].r;
  412.         gi = rgb[i].g;
  413.         bi = rgb[i].b;
  414.         ic = 0;
  415.  
  416.         /* dc is "distance" from rgb[i] to rgb[0] */
  417.         dc  = (rgb[0].r - ri) * (rgb[0].r - ri);
  418.         dc += (rgb[0].g - gi) * (rgb[0].g - gi);
  419.         dc += (rgb[0].b - bi) * (rgb[0].b - bi);
  420.  
  421.         for( j=1; j<16; j++ )
  422.         {
  423.            /* d is "distance" from rgb[i] to rgb[j] */
  424.            d  = (rgb[j].r - ri) * (rgb[j].r - ri);
  425.            d += (rgb[j].g - gi) * (rgb[j].g - gi);
  426.            d += (rgb[j].b - bi) * (rgb[j].b - bi);
  427.  
  428.            if( d < dc )
  429.            {
  430.              dc = d;
  431.              ic = j;
  432.            }
  433.         }
  434.  
  435.         lutbl[i] = ic;
  436.      }
  437. }
  438.  
  439. /*--------------------------------------------------------*/
  440. /* Print a 256-color image...                             */
  441. /*--------------------------------------------------------*/
  442.  
  443. void print_color_256( FILE *f_in, FILE *f_out, pcx_header *pH )
  444. {
  445.    rgb_triple *rgb;
  446.    int        *lutbl, *scanline;
  447.    int         bytecnt, rowcnt, done, hdr, cnt, dat;
  448.    int         nrows, ncols, sclen;
  449.  
  450.    /* allocate palette variables */
  451.    rgb = (rgb_triple *) malloc( sizeof(rgb_triple) * 256 );
  452.    if( rgb == NULL )
  453.       exit_pgm( "Out of memory in print_color_256" );
  454.    lutbl = (int *) malloc( sizeof(int) * 256 );
  455.    if( lutbl == NULL )
  456.       exit_pgm( "Out of memory in print_color_256" );
  457.  
  458.    /* read palette info from end of file */
  459.    if( fseek( f_in, -768L, SEEK_END ) )
  460.       exit_pgm( "Error seeking to palette" );
  461.    if( fread( rgb, sizeof(rgb_triple), 256, f_in ) != 256 )
  462.       exit_pgm( "Error reading palette" );
  463.  
  464.    /* construct lookup table */
  465.    init_lu_256( rgb, lutbl );
  466.  
  467.    /* reposition file ptr to start of image */
  468.    if( fseek( f_in, 128, SEEK_SET ) )
  469.       exit_pgm( "Error seeking to image" );
  470.  
  471.    /* allocate scanline buffer */
  472.    sclen = pH->bplin * sizeof(int);
  473.    scanline = (int *) malloc( sclen );
  474.    if( scanline == NULL )
  475.       exit_pgm( "Out of memory in print_color_16" );
  476.  
  477.    bytecnt = rowcnt = done = 0;
  478.    nrows = pH->y2 - pH->y1 + 1;
  479.    ncols = pH->x2 - pH->x1 + 1;
  480.  
  481.    while( ! done )
  482.    {
  483.       /* get a byte */
  484.       hdr = fgetc( f_in );
  485.  
  486.       /* decode it */
  487.       if ( (hdr & TYP_MASK) == TYP_MASK )
  488.       {
  489.          cnt = hdr & CNT_MASK;
  490.          dat = fgetc( f_in );
  491.       }
  492.       else
  493.       {
  494.          cnt = 1;
  495.          dat = hdr;
  496.       }
  497.  
  498.       /* if invert selected, bitwise invert */
  499.       if( inv )
  500.          dat = ~dat;
  501.  
  502.       /* accumulate pixels in scanline buffer */
  503.       while( cnt-- )
  504.       {
  505.          /* put pixel into scanline buffer */
  506.          scanline[bytecnt] = lutbl[dat];
  507.  
  508.          /* update counter */
  509.          bytecnt++;
  510.          if( bytecnt == pH->bplin )
  511.          {
  512.             lineout_16( f_out, scanline, ncols, rowcnt & 7 );
  513.             bytecnt = 0;
  514.             rowcnt++;
  515.             if( rowcnt == nrows )
  516.                 done = 1;
  517.          }
  518.       }
  519.    }
  520. }
  521.  
  522. /*--------------------------------------------------------*/
  523. /* Print the specified PCX file...                        */
  524. /*--------------------------------------------------------*/
  525.  
  526. void print_pcx( char *pcxf, char *prtf, int xo, int yo, int r )
  527. {
  528.    FILE        *f_in, *f_out;
  529.    pcx_header   pcxH;
  530.  
  531.    /* set up */
  532.    if( (f_in = fopen( pcxf, "rb" )) == NULL )
  533.       exit_pgm( "Error opening PCX file" );
  534.    if( (f_out = fopen( prtf, "wb" )) == NULL )
  535.       exit_pgm( "Error opening printer" );
  536.    set_binary_mode( f_out );
  537.  
  538.    /* read the pcx header */
  539.    if( fread(&pcxH, sizeof(pcx_header), 1, f_in) != 1 )
  540.       exit_pgm( "Error reading PCX header" );
  541.  
  542.    /* initialize the printer */
  543.    printf( "\nPrinting '%s'...", pcxf );
  544.    init_prt( f_out, xo, yo, r );
  545.  
  546.    /* indicate image dimensions */
  547.    printf( "%d W x %d H, %d bytes/line, ",
  548.            pcxH.x2-pcxH.x1+1, pcxH.y2-pcxH.y1+1, pcxH.bplin );
  549.  
  550.    /* determine the image type, call the appropriate */
  551.    /* image processing function...                   */
  552.  
  553.    /* monochrome bitmap */
  554.    if( (pcxH.nplanes == 1) && (pcxH.bitpx == 1) )
  555.    {
  556.       printf( "monochrome..." );
  557.       print_mono( f_in, f_out, &pcxH );
  558.    }
  559.  
  560.    /* 16-color bitmap */
  561.    else if( pcxH.nplanes == 4 )
  562.    {
  563.       printf( "16 color..." );
  564.       print_color_16( f_in, f_out, &pcxH );
  565.    }
  566.  
  567.    /* 256-color bitmap */
  568.    else if( pcxH.bitpx == 8 )
  569.    {
  570.       printf( "256 color..." );
  571.       print_color_256( f_in, f_out, &pcxH );
  572.    }
  573.  
  574.    /* unsupported image type */
  575.    else
  576.       printf( "Unsupported image type, skipping print!" );
  577.  
  578.    /* finish up on the printer */
  579.    term_prt( f_out );
  580.    printf( "done" );
  581.  
  582.    /* clean up */
  583.    fclose( f_in );
  584.    fclose( f_out );
  585. }
  586.  
  587. /*--------------------------------------------------------*/
  588. /*                        M A I N                         */
  589. /*--------------------------------------------------------*/
  590.  
  591. void main( int argc, char *argv[] )
  592. {
  593.    /* sign-on */
  594.    printf( "\nPrint PCX File on LaserJet\n" );
  595.  
  596.    /* help indicated? */
  597.    if( (argc < 2) || (*argv[1] == '?') )
  598.    {
  599.         explain_pgm();
  600.         exit( 0 );
  601.    }
  602.  
  603.    /* process command line... */
  604.    process_args( argc, argv );
  605.  
  606.    /* print the file */
  607.    print_pcx( pcx_file, prt_port, xorg, yorg, res );
  608.  
  609.    /* sign-off */
  610.    printf( "\nend-of-pgm" );
  611. }
  612.  
  613. /*---------------- End of File PRTPCX.C ------------------*/
  614.