home *** CD-ROM | disk | FTP | other *** search
- /*
- * compress HP PCL-format bit image data
- * usage: pcl_pack input output
- * copyright 1990 Digital Insight
- */
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- #include <stdlib.h>
-
- #define MAX_RUN 128 /* max compressed run length */
-
- char inbuf[4096]; /* image input buffer */
- char pbuf[4096]; /* packed output buffer */
- char esbuf[100]; /* escape sequence buffer */
-
- char rawbuf[8192]; /* raw input buffer */
- char *rawptr = rawbuf; /* current position in buffer */
- int rawbytes; /* bytes left in buffer */
-
- FILE *in_fp;
- FILE *out_fp;
-
- /*
- * Abort program with error message
- */
- void fail(char *msg)
- {
- puts(msg);
- exit(1);
- }
-
- /*
- * Buffered input from in_fp. Used in place of fread() to speed things up
- * (depending on the stream I/O library's own buffer size)
- */
- int bfread(char *buf, int nbytes)
- {
- int bytes_read = 0; /* bytes read so far */
- register int partial; /* partial transfer count */
-
- while (nbytes > 0) {
- if (rawbytes == 0) { /* buffer empty, get some more */
- rawbytes = fread(rawptr=rawbuf, 1, sizeof(rawbuf),
- in_fp);
- if (rawbytes == 0)
- break;
- }
-
- partial = nbytes; /* transfer data from buffer */
- if (partial > rawbytes)
- partial = rawbytes;
- memcpy(buf, rawptr, partial);
- bytes_read += partial;
- rawptr += partial;
- buf += partial;
- nbytes -= partial;
- rawbytes -= partial;
- }
-
- return bytes_read;
- }
-
- /*
- * Buffered input from in_fp. Used in place of fgetc() to speed things up
- * (depending on the stream I/O library's own buffer size)
- */
- int bfgetc(void)
- {
- if (rawbytes == 0) { /* buffer empty, get some more */
- rawbytes = fread(rawptr=rawbuf, 1, sizeof(rawbuf), in_fp);
- if (rawbytes == 0)
- return EOF;
- }
-
- rawbytes--;
- return *rawptr++;
- }
-
- /*
- * Copy input to output up to next escape sequence;
- * save sequence in esbuf[]. Return sequence length.
- */
- int read_seq(void)
- {
- int c;
- char *seq = esbuf;
-
- do { /* read up to escape char */
- if ((c = bfgetc()) == EOF)
- exit(0); /* done! */
- fputc(c, out_fp);
- } while (c != 0x1B);
-
- do { /* read seq thru uppercase char */
- *seq++ = c = bfgetc();
- if (c == EOF)
- fail("unexpected end of input");
- } while (!isupper(c));
-
- *seq = 0; /* terminate sequence */
- return seq-esbuf;
- }
-
- /*
- * Read line of image data into inbuf; return length.
- * Any other data (text, escape sequences) are sent directly to output.
- */
- int read_line(void)
- {
- register int n;
- char *pos;
-
- for (;;) { /* look for [esc]*b...W/M */
- n = read_seq();
-
- if (n < 3 || esbuf[0] != '*' || esbuf[1] != 'b') {
- /* some other seq, send out */
- fwrite(esbuf, 1, n, out_fp);
- continue;
- }
-
- for (pos=esbuf+2; *pos; pos++) {
- /* get #<func> */
- n = (int)strtol(pos, &pos, 10);
- switch (*pos) {
- case 'W': /* found image data */
- goto got_image;
- case 'm': /* compression mode */
- case 'M':
- if (n != 0)
- fail("Input is already compressed");
- break;
- default: /* some other sequence */
- /* split off and output */
- if (islower(*pos))
- *pos = toupper(*pos);
- fprintf(out_fp, "*b%d%c\1xB", n, *pos++);
- }
- }
- }
-
- got_image:
- if (bfread(inbuf, n) != n)
- fail("Unexpected end of input");
-
- while (n>1 && inbuf[n-1] == 0) /* remove trailing zero bytes */
- n--;
-
- return n;
- }
-
- /*
- * Pack image data lines
- */
- void pack(void)
- {
- static int first=1; /* first time? */
- register char *rptr; /* repeat pointer */
- register char *bptr; /* input buffer position */
- char *bend; /* end of input */
- char *pptr; /* pack buffer position */
- int n, cnt;
-
- for (;;) {
- n = read_line(); /* (last output was [esc]) */
- bend = inbuf+n;
-
- for (bptr=inbuf, pptr=pbuf; bptr<bend;) {
-
- /* find number of repeated bytes */
- for (rptr=bptr+1; rptr<bend && *rptr==*bptr; rptr++)
- ;
- cnt = rptr - bptr;
- while (cnt > 1) {
- n = (cnt < MAX_RUN) ? cnt : MAX_RUN;
- *pptr++ = 1 - n;
- *pptr++ = *bptr;
- cnt -= n;
- bptr += n;
- }
-
- /* finished with repeat run? */
- if (rptr >= bend)
- break;
-
- /* find number of non-repeated bytes */
- for (rptr=bptr+1; rptr<bend && *rptr != *(rptr-1); rptr++)
- ;
- cnt = rptr - bptr - 1;
- if (rptr >= bend)
- cnt++;
- while (cnt > 0) {
- n = (cnt < MAX_RUN) ? cnt : MAX_RUN;
- *pptr++ = n - 1;
- memcpy(pptr, bptr, n);
- cnt -= n;
- bptr += n;
- pptr += n;
- }
- }
-
- n = pptr - pbuf;
- if (first) { /* set compaction mode */
- first = 0; /* (note: ESC already output) */
- fwrite("*b2M\x1B", 5, 1, out_fp);
- }
-
- /* output compressed image data */
- fprintf(out_fp, "*b%dW", n);
- if (fwrite(pbuf, 1, n, out_fp) != n)
- fail("can't write output");
- }
- }
-
- main(int argc, char **argv)
- {
- if (argc != 3) {
- puts("Compress HP PCL-format graphics file");
- puts("(c) Copyright 1990 Digital Insight");
- puts("Usage: pcl_pack <infile> <outfile>");
- exit(1);
- }
-
- if ((in_fp = fopen(argv[1], "rb")) == NULL) {
- perror(argv[1]);
- exit(1);
- }
-
- if ((out_fp = fopen(argv[2], "wb")) == NULL) {
- perror(argv[2]);
- exit(1);
- }
-
- pack();
- }
-