home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / PRINTER / PCL_PACK.ZIP / PCL_PACK.C next >
Encoding:
C/C++ Source or Header  |  1990-11-08  |  5.1 KB  |  237 lines

  1. /*
  2.  * compress HP PCL-format bit image data
  3.  * usage: pcl_pack input output
  4.  * copyright 1990 Digital Insight
  5.  */
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include <string.h>
  9. #include <stdlib.h>
  10.  
  11. #define MAX_RUN 128        /* max compressed run length */
  12.  
  13. char inbuf[4096];        /* image input buffer */
  14. char pbuf[4096];        /* packed output buffer */
  15. char esbuf[100];        /* escape sequence buffer */
  16.  
  17. char rawbuf[8192];        /* raw input buffer */
  18. char *rawptr = rawbuf;        /* current position in buffer */
  19. int rawbytes;            /* bytes left in buffer */
  20.  
  21. FILE *in_fp;
  22. FILE *out_fp;
  23.  
  24. /*
  25.  * Abort program with error message
  26.  */
  27. void fail(char *msg)
  28. {
  29.     puts(msg);
  30.     exit(1);
  31. }
  32.  
  33. /*
  34.  * Buffered input from in_fp. Used in place of fread() to speed things up
  35.  * (depending on the stream I/O library's own buffer size)
  36.  */
  37. int bfread(char *buf, int nbytes)
  38. {
  39.     int bytes_read = 0;        /* bytes read so far */
  40.     register int partial;        /* partial transfer count */
  41.  
  42.     while (nbytes > 0) {
  43.         if (rawbytes == 0) {    /* buffer empty, get some more */
  44.             rawbytes = fread(rawptr=rawbuf, 1, sizeof(rawbuf), 
  45.                      in_fp);
  46.             if (rawbytes == 0)
  47.                 break;
  48.         }
  49.  
  50.         partial = nbytes;    /* transfer data from buffer */
  51.         if (partial > rawbytes)
  52.             partial = rawbytes;
  53.         memcpy(buf, rawptr, partial);
  54.         bytes_read += partial;
  55.         rawptr     += partial;
  56.         buf        += partial;
  57.         nbytes     -= partial;
  58.         rawbytes   -= partial;
  59.     }
  60.  
  61.     return bytes_read;
  62. }
  63.  
  64. /*
  65.  * Buffered input from in_fp. Used in place of fgetc() to speed things up
  66.  * (depending on the stream I/O library's own buffer size)
  67.  */
  68. int bfgetc(void)
  69. {
  70.     if (rawbytes == 0) {    /* buffer empty, get some more */
  71.         rawbytes = fread(rawptr=rawbuf, 1, sizeof(rawbuf), in_fp);
  72.         if (rawbytes == 0)
  73.             return EOF;
  74.     }
  75.  
  76.     rawbytes--;
  77.     return *rawptr++;
  78. }
  79.  
  80. /*
  81.  * Copy input to output up to next escape sequence;
  82.  * save sequence in esbuf[]. Return sequence length.
  83.  */
  84. int read_seq(void)
  85. {
  86.     int c;
  87.     char *seq = esbuf;
  88.  
  89.     do {                /* read up to escape char */
  90.         if ((c = bfgetc()) == EOF)
  91.             exit(0);    /* done! */
  92.         fputc(c, out_fp);
  93.     } while (c != 0x1B);
  94.  
  95.     do {                /* read seq thru uppercase char */
  96.         *seq++ = c = bfgetc();
  97.         if (c == EOF)
  98.             fail("unexpected end of input");
  99.     } while (!isupper(c));
  100.  
  101.     *seq = 0;            /* terminate sequence */
  102.     return seq-esbuf;
  103. }
  104.  
  105. /*
  106.  * Read line of image data into inbuf; return length.
  107.  * Any other data (text, escape sequences) are sent directly to output.
  108.  */
  109. int read_line(void)
  110. {
  111.     register int n;
  112.     char *pos;
  113.  
  114.     for (;;) {            /* look for [esc]*b...W/M */
  115.         n = read_seq();
  116.         
  117.         if (n < 3 || esbuf[0] != '*' || esbuf[1] != 'b') {
  118.             /* some other seq, send out */
  119.             fwrite(esbuf, 1, n, out_fp);    
  120.             continue;
  121.         }
  122.  
  123.         for (pos=esbuf+2; *pos; pos++) {    
  124.             /* get #<func> */
  125.             n = (int)strtol(pos, &pos, 10);
  126.             switch (*pos) {
  127.             case 'W':    /* found image data */
  128.                 goto got_image;
  129.             case 'm':    /* compression mode */
  130.             case 'M':
  131.                 if (n != 0) 
  132.                     fail("Input is already compressed");
  133.                 break;
  134.             default:    /* some other sequence */
  135.                 /* split off and output */
  136.                 if (islower(*pos))
  137.                     *pos = toupper(*pos);
  138.                 fprintf(out_fp, "*b%d%c\1xB", n, *pos++);
  139.             }
  140.         }
  141.     }
  142.  
  143.   got_image:
  144.     if (bfread(inbuf, n) != n) 
  145.         fail("Unexpected end of input");
  146.  
  147.     while (n>1 && inbuf[n-1] == 0)    /* remove trailing zero bytes */
  148.         n--;
  149.  
  150.       return n;
  151. }
  152.  
  153. /*
  154.  * Pack image data lines
  155.  */
  156. void pack(void)
  157. {
  158.     static int first=1;        /* first time? */
  159.     register char *rptr;        /* repeat pointer */
  160.     register char *bptr;        /* input buffer position */
  161.     char *bend;            /* end of input */
  162.     char *pptr;            /* pack buffer position */
  163.     int  n, cnt;
  164.  
  165.     for (;;) {
  166.         n = read_line();    /* (last output was [esc]) */
  167.         bend = inbuf+n;
  168.  
  169.         for (bptr=inbuf, pptr=pbuf; bptr<bend;) {
  170.  
  171.             /* find number of repeated bytes */
  172.             for (rptr=bptr+1; rptr<bend && *rptr==*bptr; rptr++)
  173.                 ;
  174.             cnt = rptr - bptr;
  175.             while (cnt > 1) {
  176.                 n = (cnt < MAX_RUN) ? cnt : MAX_RUN;
  177.                 *pptr++ = 1 - n;
  178.                 *pptr++ = *bptr;
  179.                 cnt     -= n;
  180.                 bptr    += n;
  181.             }
  182.  
  183.             /* finished with repeat run? */
  184.             if (rptr >= bend)
  185.                 break;
  186.  
  187.             /* find number of non-repeated bytes */
  188.             for (rptr=bptr+1; rptr<bend && *rptr != *(rptr-1); rptr++)
  189.                 ;
  190.             cnt = rptr - bptr - 1;
  191.             if (rptr >= bend)
  192.                 cnt++;
  193.             while (cnt > 0) {
  194.                 n = (cnt < MAX_RUN) ? cnt : MAX_RUN;
  195.                 *pptr++ = n - 1;
  196.                 memcpy(pptr, bptr, n);
  197.                 cnt -= n;
  198.                 bptr += n;
  199.                 pptr += n;
  200.             }
  201.         }
  202.  
  203.         n = pptr - pbuf;
  204.         if (first) {        /* set compaction mode */
  205.             first = 0;    /* (note: ESC already output) */
  206.             fwrite("*b2M\x1B", 5, 1, out_fp);
  207.         }
  208.  
  209.         /* output compressed image data */
  210.         fprintf(out_fp, "*b%dW", n);
  211.         if (fwrite(pbuf, 1, n, out_fp) != n)
  212.             fail("can't write output");
  213.     }
  214. }
  215.  
  216. main(int argc, char **argv)
  217. {
  218.     if (argc != 3) {
  219.         puts("Compress HP PCL-format graphics file");
  220.         puts("(c) Copyright 1990 Digital Insight");
  221.         puts("Usage: pcl_pack <infile> <outfile>");
  222.         exit(1);
  223.     }
  224.  
  225.     if ((in_fp = fopen(argv[1], "rb")) == NULL) {
  226.         perror(argv[1]);
  227.         exit(1);
  228.     }
  229.  
  230.     if ((out_fp = fopen(argv[2], "wb")) == NULL) {
  231.         perror(argv[2]);
  232.         exit(1);
  233.     }
  234.  
  235.     pack();
  236. }
  237.