home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-05-23 | 34.6 KB | 1,310 lines |
- Newsgroups: comp.sources.misc
- From: tony@sdd.hp.com (Tony Parkhurst)
- Subject: v30i018: pclcomp - HP-PCL Compression Filter, Part02/02
- Message-ID: <1992May23.181623.19262@sparky.imd.sterling.com>
- X-Md4-Signature: b1595abd728d7f6e5225722881b29620
- Date: Sat, 23 May 1992 18:16:23 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: tony@sdd.hp.com (Tony Parkhurst)
- Posting-number: Volume 30, Issue 18
- Archive-name: pclcomp/part02
- Environment: LaserJet
- Supersedes: pclcomp: Volume 25, Issue 10-11
-
- #!/bin/sh
- # this is PP.02 (part 2 of a multipart archive)
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file pclcomp.c continued
- #
- if test ! -r _shar_seq_.tmp; then
- echo 'Please unpack part 1 first!'
- exit 1
- fi
- (read Scheck
- if test "$Scheck" != 2; then
- echo Please unpack part "$Scheck" next!
- exit 1
- else
- exit 0
- fi
- ) < _shar_seq_.tmp || exit 1
- if test ! -f _shar_wnt_.tmp; then
- echo 'x - still skipping pclcomp.c'
- else
- echo 'x - continuing file pclcomp.c'
- sed 's/^X//' << 'SHAR_EOF' >> 'pclcomp.c' &&
- ** fourth plane as <esc>*b0W to terminate the row, instead of the recommended
- ** 'W' as the 3rd plane. This routine handles the extra without disturbing
- ** the mode 3 seed rows.
- **
- ** In the future, this routine could be used to strip out the 4th plane.
- */
- X
- Process_extra(bytes, terminator)
- int bytes;
- char terminator;
- {
- X int i;
- X
- X /* toss any excess data */
- X
- X for(i = 0; i < bytes; i++)
- X getchar();
- X
- X /* last plane? force move down to next row */
- X
- X if(terminator == 'W')
- X {
- X /* <esc>*b has already been output */
- X printf("0W");
- X
- X firstrow = FALSE; /* not on first row anymore */
- X
- X }
- X
- }
- X
- /*
- ** ChangeMode() simply outputs the sequence to change compression modes.
- */
- X
- ChangeMode(newmode)
- int newmode;
- {
- X /*
- X ** <esc>*b have already been output.
- X ** terminator is 'm' instead of 'M' since will be followed by 'W'
- X */
- X printf("%1dm", newmode);
- X outmode = newmode;
- }
- X
- X
- /*-----------------------------------------------------------------------*\
- X | |
- X | Function Name: Uncompress_0 |
- X | |
- X | Description: |
- X | |
- X | This is the routine that handles a Mode 0 graphics block transfer |
- X | to the Formatter Module. |
- X | |
- \*-----------------------------------------------------------------------*/
- X
- /* FUNCTION */
- X
- Uncompress_0(input_bytes, output_bytes, address)
- X
- unsigned int
- X input_bytes, /* Count of bytes to be read. */
- X output_bytes; /* Count of bytes to be stored. */
- X
- unsigned char
- X *address; /* Pointer to where to store bytes. */
- X
- {
- X /* LOCAL VARIABLES */
- X
- X unsigned char
- X *store_ptr; /* Pointer to where to store the byte. */
- X
- X unsigned int
- X read_bytes, /* Local copy of input_bytes. */
- X write_bytes; /* Local copy of output_bytes. */
- X
- X /* CODE */
- X
- X /* Initialize the local variables. */
- X
- X read_bytes = input_bytes;
- X write_bytes = output_bytes;
- X store_ptr = address;
- X
- X
- X /* transfer the lesser of available bytes or available room */
- X
- X Transfer_Block( MIN(write_bytes,read_bytes), store_ptr);
- X
- X /* now zero fill or throw excess data away */
- X
- X if ( read_bytes > write_bytes )
- X Discard_Block(read_bytes - write_bytes); /* throw excess */
- X else {
- X store_ptr += read_bytes; /* adjust pointer */
- X write_bytes -= read_bytes; /* zero fill count */
- X
- X memset(store_ptr, 0, write_bytes);
- X }
- X
- X return ( input_bytes );
- }
- X
- X
- /*-----------------------------------------------------------------------*\
- X | |
- X | Function Name: Uncompress_1 |
- X | |
- X | Description: |
- X | |
- X | This is the routine that handles a Mode 1 graphics block transfer |
- X | to the Formatter Module. Mode 1 graphics is a compacted mode. |
- X | The data in Mode 1 is in pairs. The first byte is a replicate |
- X | count and the second byte is the data. The data byte is stored |
- X | then replicated the replicate count. Therefore a replicate count |
- X | of 0 means the data byte is stored once. The input byte count |
- X | must be an even amount for the data to be in byte pairs. |
- X | |
- \*-----------------------------------------------------------------------*/
- X
- /* FUNCTION */
- X
- Uncompress_1(input_bytes, output_bytes, address)
- X
- unsigned int
- X input_bytes, /* Count of bytes to be read. */
- X output_bytes; /* Count of bytes to be stored. */
- X
- unsigned char
- X *address; /* Pointer to where to store bytes. */
- X
- {
- X /* LOCAL VARIABLES */
- X
- X unsigned char
- X *store_ptr, /* Pointer to where to store the byte. */
- X input_char; /* Byte to be replicated. */
- X
- X unsigned int
- X read_bytes, /* Local copy of input_bytes. */
- X write_bytes; /* Local copy of output_bytes. */
- X
- X int
- X replicate_count; /* Number of times to replicate data. */
- X
- X /* CODE */
- X
- X /* Initialize the local variables. */
- X
- X read_bytes = input_bytes;
- X write_bytes = output_bytes;
- X store_ptr = address;
- X
- X /* Check for an even input count. */
- X
- X if ((read_bytes % 2) == 0)
- X {
- X /* Even so input data is in pairs as required. So store the data. */
- X
- X while ((read_bytes != 0) && (write_bytes != 0))
- X {
- X /* First get the replicate count and the byte to store. */
- X
- X replicate_count = (unsigned char) Get_Character();
- X input_char = Get_Character();
- X read_bytes -= 2;
- X
- X /* Since write_bytes was 0 there is room to store the byte. */
- X
- X *store_ptr++ = input_char;
- X write_bytes--;
- X
- X /* Now make sure there is room for the replicated data. */
- X
- X if (replicate_count > write_bytes)
- X {
- X /* Too much so limit to the room available. */
- X
- X replicate_count = write_bytes;
- X }
- X
- X /* Update the amount to be written. */
- X
- X write_bytes -= replicate_count;
- X
- X /* Then replicate it. */
- X
- X while (replicate_count != 0)
- X {
- X /* Store the byte the decrement the count. */
- X
- X *store_ptr++ = input_char;
- X
- X replicate_count--;
- X }
- X }
- X
- X }
- X /* Discard any left over input. */
- X /* OR */
- X /* Discard all of the input data as odd byte count. */
- X
- X Discard_Block(read_bytes);
- X
- X read_bytes = store_ptr - address; /* how much was done? */
- X
- X /* zero fill if needed */
- X memset(store_ptr, 0, write_bytes);
- X
- X return(read_bytes);
- }
- X
- X
- /*-----------------------------------------------------------------------*\
- X | |
- X | Function Name: Uncompress_2 |
- X | |
- X | Description: |
- X | |
- X | This is the routine that handles a Mode 2 graphics block transfer |
- X | to the Formatter Module. Mode 2 graphics is a compacted mode. |
- X | The data in Mode 2 is of one of two types. The first type is a |
- X | class type and the second type is a data type. The class type is |
- X | a single byte which is a combination of replicate count and a sub |
- X | mode. There are two sub modes within mode 2, sub mode 0 and sub |
- X | mode 1. These sub modes are flagged by the MSB of the class type |
- X | byte. If the MSB = 0 then the replicate count is the value of the |
- X | class type byte. In sub mode 0 the replicate count ranges from 1 |
- X | to 127. In sub mode 0 the next byte and then the replicate count |
- X | of bytes are of the data type and stored. If the MSB = 1 then the |
- X | sub mode is 1 and the replicate count is the negative value of the |
- X | class type. In sub mode 1 the replicate count is stored in 2s |
- X | compliment form and ranges from -1 to -127. In sub mode 1 the |
- X | next byte is of the data type and is stored. That data byte is |
- X | then replicated and stored the replicate count. If the class type |
- X | byte is 128 then there is no data type byte. |
- X | |
- \*-----------------------------------------------------------------------*/
- X
- /* FUNCTION */
- X
- Uncompress_2(input_bytes, output_bytes, address)
- X
- unsigned int
- X input_bytes, /* Count of bytes to be read. */
- X output_bytes; /* Count of bytes to be stored. */
- X
- unsigned char
- X *address; /* Pointer to where to store bytes. */
- X
- {
- X /* LOCAL VARIABLES */
- X
- X unsigned char
- X *store_ptr, /* Pointer to where to store the byte. */
- X input_char, /* Byte to be replicated. */
- X sub_mode; /* Flag if sub mode is 0 or 1. */
- X
- X unsigned int
- X read_bytes, /* Local copy of input_bytes. */
- X write_bytes; /* Local copy of output_bytes. */
- X
- X int
- X replicate_count; /* Number of times to replicate data. */
- X
- X /* CODE */
- X
- X /* Initialize the local variables. */
- X
- X read_bytes = input_bytes;
- X write_bytes = output_bytes;
- X store_ptr = address;
- X
- X while ((read_bytes > 1) && (write_bytes != 0))
- X {
- X /* First get the class type byte and the first data type byte. */
- X
- X replicate_count = Get_Character();
- X
- X /* First check that this not an ignore class type. */
- X
- X if (replicate_count != 128)
- X {
- X /* Not ignore so get the data class byte. */
- X
- X input_char = Get_Character();
- X read_bytes -= 2;
- X
- X /* Since write_bytes wasn't 0 there is room to store the byte. */
- X
- X *store_ptr++ = input_char;
- X write_bytes--;
- X
- X /* Determine the sub mode. */
- X
- X if (replicate_count > 128)
- X {
- X /* Sub mode 1. */
- X
- X sub_mode = 1;
- X /* replicate count was unsigned char */
- X replicate_count = 256 - replicate_count;
- X }
- X else
- X {
- X /* Sub mode 0. */
- X
- X sub_mode = 0;
- X
- X /* See if there is enoungh input left for the data byte count. */
- X
- X if (replicate_count > read_bytes)
- X {
- X /* Too many data bytes so limit to the input left. */
- X
- X replicate_count = read_bytes;
- X }
- X }
- X
- X /* Now make sure there is room for the replicated data. */
- X
- X if (replicate_count > write_bytes)
- X {
- X /* Too much so limit to the room available. */
- X
- X replicate_count = write_bytes;
- X }
- X
- X /* Update the amount to be written. */
- X
- X write_bytes -= replicate_count;
- X
- X /* Then replicate it. */
- X
- X if (sub_mode == 0)
- X {
- X /* Sub mode 0 so get the replicate count of data bytes. */
- X
- X Transfer_Block(replicate_count, store_ptr);
- X
- X read_bytes -= replicate_count;
- X
- X /* Find the last byte stored. */
- X
- X store_ptr += replicate_count;
- X }
- X else
- X {
- X /* Sub mode 1 so just duplicate the original byte. */
- X
- X while (replicate_count != 0)
- X {
- X /* Store the byte the decrement the count. */
- X
- X *store_ptr++ = input_char;
- X
- X replicate_count--;
- X }
- X }
- X }
- X else
- X {
- X /* Ignore class so don't get the data class byte. */
- X
- X read_bytes--;
- X }
- X }
- X
- X /* Now discard any left over input. */
- X
- X Discard_Block(read_bytes);
- X
- X read_bytes = store_ptr - address;
- X
- X /* zero fill if needed */
- X memset(store_ptr, 0, write_bytes);
- X
- X
- X return(read_bytes);
- }
- X
- X
- /*-----------------------------------------------------------------------*\
- X | |
- X | Function Name: Uncompress_3 |
- X | |
- X | Description: |
- X | |
- X | This is the routine that handles a Mode 3 graphics block transfer |
- X | to the Formatter Module. Mode 3 graphics is a compacted mode. |
- X | Mode 3 data is a difference from one row to the next. In order to |
- X | work, each row must be saved to be a seed for the next. This |
- X | mode is used in conjuction with other compaction modes when the |
- X | data remains fairly constant between pairs of rows. |
- X | The data is in the form: |
- X | <command byte>[<optional offset bytes>]<1 to 8 replacement bytes> |
- X | The command byte is in the form: |
- X | Bits 5-7: Number of bytes to replace (1 - 8) |
- X | Bits 0-4: Relative offset from last byte. |
- X | (If the offset is 31, then add the following bytes for offset |
- X | until an offset byte of less then 255 (but inclusive) |
- X | |
- \*-----------------------------------------------------------------------*/
- X
- /* FUNCTION */
- X
- Uncompress_3(input_bytes, output_bytes, address)
- X
- unsigned int
- X input_bytes, /* Count of bytes to be read. */
- X output_bytes; /* Count of bytes to be stored. */
- X
- unsigned char
- X *address; /* Pointer to where to store bytes. */
- X
- {
- X /* LOCAL VARIABLES */
- X
- X unsigned char
- X *store_ptr; /* Pointer to where to store the byte. */
- X
- X unsigned int
- X read_bytes, /* Local copy of input_bytes. */
- X write_bytes; /* Local copy of output_bytes. */
- X
- X unsigned int
- X replace, /* number of bytes to replace, 1-8 */
- X offset; /* relative offset */
- X
- X unsigned char command;
- X
- X /* CODE */
- X
- X /* Initialize the local variables. */
- X
- X read_bytes = input_bytes;
- X write_bytes = output_bytes;
- X store_ptr = address;
- X
- X /*
- X ** read_bytes has to be at least 2 to be valid
- X */
- X
- X while ( read_bytes > 1 && write_bytes > 0 )
- X {
- X
- X /* start by getting the command byte */
- X
- X command = Get_Character();
- X
- X replace = (command >> 5) + 1;
- X offset = command & 0x1f;
- X
- X read_bytes--;
- X
- X /*
- X ** Sometimes offsets go past the end. If so, bail.
- X */
- X
- X if ( offset >= write_bytes )
- X break;
- X
- X write_bytes -= offset;
- X store_ptr += offset;
- X
- X /*
- X ** If the first offset value is 31, then we must
- X ** get more offsets until we encounter a byte value
- X ** less than 255 (even if it's 0).
- X */
- X
- X if ( offset == 31 ) /* get more offsets */
- X
- X do{
- X offset = Get_Character();
- X
- X read_bytes--;
- X
- X /*
- X ** Check for pre-mature finish
- X */
- X
- X if ( read_bytes == 0 )
- X return;
- X
- X /*
- X ** Check for excessive offset.
- X */
- X
- X if ( offset >= write_bytes )
- X {
- X /*
- X ** Resetting write_bytes is needed
- X ** to get out of outer loop so
- X ** that the call to Discard_Block()
- X ** is made at the end.
- X */
- X
- X write_bytes = 0;
- X break;
- X }
- X
- X write_bytes -= offset;
- X store_ptr += offset;
- X
- X } while (offset == 255); /* 255 = keep going */
- X
- X /* now do the byte replacement */
- X
- X while ( replace-- && write_bytes > 0 && read_bytes > 0 )
- X {
- X *store_ptr++ = Get_Character();
- X read_bytes--;
- X write_bytes--;
- X }
- X }
- X
- X /*
- X ** Don't do any zero fill with mode 3,
- X ** and discard any leftover input.
- X */
- X
- X Discard_Block(read_bytes);
- X
- X return;
- }
- X
- X
- Discard_Block(count)
- unsigned int count;
- {
- X while ( count-- )
- X getchar();
- }
- X
- Transfer_Block( count, dest )
- unsigned int count;
- unsigned char *dest;
- {
- X fread(dest, 1, count, stdin);
- }
- X
- X
- /*
- ** Compress_0() does mode 0 compression (which is a no compression).
- */
- X
- Compress_0(src, dest, count)
- unsigned char *src, *dest;
- int count;
- {
- X memcpy(dest, src, count);
- X
- X if ( zerostrip )
- X while ( count && dest[count-1] == 0 )
- X count--;
- X
- X return(count);
- X
- }
- X
- X
- X
- /*
- ******************************************************************************
- **
- ** Compress_1() does PCL compression mode 1 on the data.
- ** This mode is run length encoding.
- **
- ** Given an input byte count of n, then the worst case output size
- ** would be 2 * n.
- **
- ******************************************************************************
- */
- X
- Compress_1(src, dest, count)
- unsigned char *src, *dest;
- register int count;
- {
- X unsigned char *outptr = dest, *inptr = src;
- X
- X unsigned char data; /* data values to match */
- X
- X unsigned char temp;
- X
- X int repcount; /* repeat count */
- X
- X
- X /*
- X ** "count" is the number of bytes in "src" to compress
- X ** into "dest".
- X */
- X
- X while ( count )
- X {
- X data = *inptr++; /* get value to work with */
- X count--;
- X
- X repcount = 0; /* no repeats yet */
- X
- X /*
- X ** Look for successive bytes that match "data".
- X */
- X
- X while ( count && *inptr == data )
- X {
- X repcount++;
- X inptr++;
- X count--;
- X }
- X
- X /*
- X ** Now if we are out of data (count == 0), then
- X ** if the repeated byte was zero, then we can ignore it
- X ** unless the user disabled zero stripping.
- X */
- X
- X if ( count == 0 && data == 0 && zerostrip )
- X break; /* done */
- X
- X /*
- X ** Now output the repeat count and the value.
- X **
- X ** If the repeat count exceeds 255, then we must send
- X ** more repeat-value pairs.
- X **
- X ** Each time thru the loop, repcount needs to be decremented
- X ** to keep in sync. That is, if repcount == 256, then the
- X ** first time thru the loop, <255> <data> are output, then
- X ** repcount is now 1. So the next time thru the loop,
- X ** repcount needs to be adjusted to 0 so that the next pair
- X ** is <0> <data>. Thus, 1 data plus 255 repeats of data
- X ** plus 1 data + 0 repeats of data ==> 257 total bytes
- X ** of "data", which is what a repcount of 256 means.
- X */
- X
- X do
- X {
- X temp = MIN(repcount, 255);
- X
- X *outptr++ = temp;
- X
- X repcount -= temp;
- X
- X *outptr++ = data;
- X
- X } while ( repcount-- );
- X }
- X
- X return ( outptr - dest ); /* size of compressed data */
- }
- X
- X
- /*
- ******************************************************************************
- **
- ** Compress_2() does PCL compression mode 2 on the data.
- ** This mode is a combination of modes 0 and 1.
- **
- ** Given an input byte count of n, then the worst case output size
- ** would be n + (n + 127)/128.
- **
- ******************************************************************************
- */
- X
- Compress_2(src, dest, count)
- unsigned char *src, *dest;
- register int count;
- {
- X unsigned char *outptr, *inptr;
- X unsigned char *saveptr;
- X
- X unsigned char data; /* data byte */
- X unsigned char lastbyte; /* last byte */
- X int repcount; /* repeat count */
- X int litcount; /* literal count */
- X
- X /*
- X ** src points to the input data.
- X ** dest points to the output buffer.
- X ** count is the number of input bytes.
- X */
- X
- X inptr = src;
- X outptr = dest;
- X
- X /*
- X ** Start loop thru data. Check for possible repeat at beginning.
- X */
- X
- X while ( count )
- X {
- X data = *inptr++; /* get value to work with */
- X count--;
- X
- X repcount = 0; /* no repeat count yet */
- X
- X
- X /*
- X ** Check for repeat, since we are not in the middle
- X ** of a literal run, it does not have to be more than
- X ** two bytes of similar data.
- X */
- X
- X while ( count && *inptr == data )
- X {
- X repcount++;
- X inptr++;
- X count--;
- X }
- X
- X /*
- X ** Now, if we are out of data (count == 0), then
- X ** if the repeated byte was zero, then ignore it
- X ** completely (don't bother outputing the trailing zeros).
- X **
- X ** To always strip zero's, simply remove the "zerostrip"
- X ** from the test.
- X */
- X
- X if ( count == 0 && data == 0 && zerostrip)
- X break; /* done */
- X
- X
- X /*
- X ** If there was a repeat (repcount > 0), then we
- X ** can output the command here, otherwise, we
- X ** need to go into literal run mode.
- X **
- X ** Note: This is a while loop because the repeat count
- X ** may actually be greater than 127.
- X */
- X
- X if ( repcount >= 1 ) /* repeat mode */
- X {
- X while (repcount > 127)
- X {
- X *outptr++ = 129; /* count 127 */
- X *outptr++ = data; /* value */
- X repcount-= 128; /* offset */
- X }
- X
- X if (repcount > 0)
- X {
- X *outptr++ = 256 - repcount; /* count */
- X *outptr++ = data; /* value */
- X
- X /*
- X ** Now pop to the top of the loop
- X ** looking for more repeat counts.
- X */
- X
- X continue; /* top of loop */
- X }
- X
- X /*
- X ** Special case: If we have arrived at this point,
- X ** then repcount is now equal to 0. This means
- X ** that when we entered this section, repcount
- X ** was a multiple of 128 (i.e. 128 :-).
- X **
- X ** This means that there were 129 identical bytes,
- X ** so the output does a replicate of 127 which
- X ** gives 128 bytes, and we now have one byte left
- X ** over which should NOT be output as a repeat
- X ** run, rather it should be merged into the following
- X ** literal run (if it exists).
- X **
- X ** So, we will simply fall thru to the next section
- X ** of code which assumes that we are working on
- X ** a literal run.
- X */
- X
- X }
- X
- X /*
- X ** Literal run: At this point, the current data byte
- X ** does NOT match the following byte. We will transfer
- X ** these non-identical bytes until:
- X **
- X ** 1) we run out of input data (count == 0).
- X ** 2) we run out of room in this output block (128)
- X ** 3) we come across a value which occurs at least
- X ** three times in a row. A value occuring only
- X ** twice in a row does NOT justify dropping
- X ** out of a literal run.
- X **
- X ** Special case: If we run out of room in the output block
- X ** (which is 128 bytes), the last two values are the same,
- X ** AND there is more input, it makes sense to restart
- X ** the repeat detector in case the following bytes are
- X ** repeats of the two. A simple check of the following
- X ** byte will determine this.
- X ** (This case falls out with the test for triples below).
- X **
- X ** Special case: If we run out of room in the output block
- X ** (which is 128 bytes), the last value is the same as
- X ** the next one on the input, then it is better to let
- X ** that byte be used in a possible replicate run following
- X ** the literal run. If the last byte matches ONLY the
- X ** following byte, (and not the one after that,) it is
- X ** a wash, but for best results, we will test the
- X ** following two bytes.
- X **
- X */
- X
- X litcount = 0;
- X saveptr = outptr++; /* save location of the command byte */
- X
- X *outptr++ = data; /* save the first byte. */
- X
- X lastbyte = data; /* remember for testing */
- X
- X while ( count && litcount < 127 )
- X {
- X data = *inptr++;
- X count--;
- X litcount++;
- X *outptr++ = data;
- X
- X /*
- X ** Test to see if this byte matched the last one.
- X ** If so, check the next one for a triple.
- X */
- X
- X if ( lastbyte == data && count && *inptr == data )
- X {
- X /*
- X ** We have a triple, adjust accordingly.
- X **
- X ** Add two bytes back onto the input.
- X */
- X
- X count += 2;
- X inptr -= 2;
- X outptr -= 2;
- X litcount -= 2;
- X
- X break; /* out of loop */
- X }
- X
- X lastbyte = data; /* save data byte */
- X }
- X
- X /*
- X ** Check the special case number 2 above.
- X */
- X
- X if ( litcount == 127 && count > 1 && data == *inptr
- X && data == inptr[1] )
- X {
- X /* Restore the last byte to the input stream */
- X
- X count += 1;
- X inptr -= 1;
- X outptr -= 1;
- X litcount -= 1;
- X }
- X
- X
- X /*
- X ** Save the literal run count.
- X */
- X
- X *saveptr = litcount;
- X
- X /*
- X ** Now go back to the top and look for repeats.
- X */
- X }
- X
- X count = outptr - dest; /* for return value */
- X
- X return ( count );
- }
- X
- X
- X
- /*
- ******************************************************************************
- **
- ** Compress_3() does PCL compression mode 3 on the data.
- ** This mode is delta row encoding.
- **
- ** Given an input byte count of n, then the worst case output size
- ** would be n + (n + 7)/8
- **
- ******************************************************************************
- */
- X
- Compress_3(seed, new, dest, count)
- unsigned char *seed, *new, *dest;
- register int count;
- {
- X unsigned char *sptr=seed, *nptr=new, *dptr=dest;
- X unsigned char *saveptr;
- X
- X int delta, xfer;
- X unsigned char command;
- X
- X
- X /*
- X ** "count" is the number of bytes of data in "new" that need to
- X ** be compressed into "dest" using "seed" as the basis for diffs.
- X */
- X
- X while ( count > 0 )
- X {
- X delta = 0; /* position counter */
- X
- X /*
- X ** Hunt through the data until the new data is different
- X ** from the seed data.
- X */
- X
- X while ( *sptr == *nptr && delta < count )
- X {
- X delta++;
- X sptr++;
- X nptr++;
- X }
- X
- X /*
- X ** Either a difference has been found, or we ran out of data.
- X */
- X
- X if ( delta >= count ) /* too far */
- X break; /* done */
- X
- X count -= delta;
- X
- X /*
- X ** Now set up the output with the command byte[s].
- X ** (leaving the actual byte copy count till last.)
- X */
- X
- X /*
- X ** The first command byte can only hold up to 31.
- X ** If the delta is larger, then following bytes will
- X ** be needed.
- X */
- X
- X saveptr = dptr++; /* save the address for command byte */
- X
- X command = MIN(delta, 31);
- X
- X /*
- X ** Any remaining count follows.
- X **
- X ** If count is 31, then a following byte must be given,
- X ** even if 0. Same holds if 255 is given in succesive bytes.
- X */
- X
- X if ( command == 31 )
- X {
- X delta -= command; /* adjust for first count */
- X
- X do {
- X xfer = MIN(delta,255);
- X
- X delta -= xfer;
- X
- X *dptr++ = xfer;
- X
- X } while ( xfer == 255 );
- X
- X
- X }
- X
- X
- X /*
- X ** Now transfer up to 8 bytes, stopping when the new byte
- X ** matches the seed byte. One could make a case for
- X ** transfering a matching byte too (if stuck in the middle
- X ** of the 8 bytes), but it does not impact the worst case,
- X ** and in the long run, the compression will not be as good.
- X ** Also, we need to make sure that we don't overrun count.
- X ** ("count" is checked first so we don't reference past the
- X ** end of the memory block).
- X */
- X
- X for ( xfer = 0;
- X count && *sptr != *nptr && xfer < 8;
- X xfer++)
- X {
- X *dptr++ = *nptr++; /* transfer byte */
- X sptr++; /* bump seed pointer too */
- X count--;
- X }
- X
- X /*
- X ** Now xfer is the number of bytes transfered, but the
- X ** number range is 3 bits (0-7), so decrement and merge
- X ** it into the command byte and put it in the data.
- X */
- X
- X command += ((xfer - 1) << 5);
- X
- X *saveptr = command;
- X
- X }
- X
- X return ( dptr - dest );
- }
- X
- X
- /*----------------------------------------------------------------------*\
- X * This is here in case <ESC>*rU is sent after <ESC>*r#A, in which case *
- X * we must deallocate the memory to provide for a different amount of *
- X * planes when graphics are sent. *
- \*----------------------------------------------------------------------*/
- X
- free_mem()
- {
- X int r;
- X
- X
- X if ( !memflag )
- X return; /* no memory to free */
- X
- X free(new_row);
- X
- X for(r = MAXMODES -1; r >= 0; r--)
- X free(out_row[r]);
- X
- X for(r = num_planes - 1; r >= 0; r--)
- X free(seed_row[r]);
- X
- X memflag = FALSE;
- }
- X
- /*
- ** Get_Frac() simply gets the fractional part of a value. This is here
- ** because scanf() will consume a trailing 'e' or 'E', which is a problem
- ** in PCL.
- */
- X
- static float Get_Frac()
- {
- X float result = 0.0;
- X int c;
- X float position = 10.0;
- X
- X while ( (c = getchar()) != EOF )
- X {
- X /*
- X ** Do we have a digit?
- X */
- X
- X if ( !isdigit(c) ) /* not a digit */
- X {
- X ungetc( c, stdin ); /* put it back */
- X break; /* quit */
- X }
- X
- X result += ((c - '0') / position);
- X
- X position *= 10.0;
- X }
- X
- X return ( result );
- }
- SHAR_EOF
- echo 'File pclcomp.c is complete' &&
- chmod 0444 pclcomp.c ||
- echo 'restore of pclcomp.c failed'
- Wc_c="`wc -c < 'pclcomp.c'`"
- test 70635 -eq "$Wc_c" ||
- echo 'pclcomp.c: original size 70635, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= pclcomp.man ==============
- if test -f 'pclcomp.man' -a X"$1" != X"-c"; then
- echo 'x - skipping pclcomp.man (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting pclcomp.man (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'pclcomp.man' &&
- X
- X
- X
- X PCLCOMP(1) PCLCOMP(1)
- X
- X
- X
- X NAME
- X pclcomp - Compress PCL graphics files.
- X
- X SYNOPSIS
- X pclcomp [ -0123drsvxz ] [ -n num ] [ infile [ outfile ]]
- X
- X DESCRIPTION
- X Pclcomp compresses (or decompresses) HP-PCL (Printer Control
- X Language) graphics data. The supported compression modes
- X are 0 (uncompressed), 1, 2 and 3. Pclcomp will read files
- X using any of the modes 0 through 3, and will output using
- X the modes which will give the best compression. This
- X compressed version of the file may be sent directly to a PCL
- X compatible printer, thus reducing I/O bandwidth. Pictures
- X may also be saved in compressed form, reducing disk usage.
- X In addition, PCL "imaging" files for the PaintJet XL are
- X also supported.
- X
- X The options to pclcomp control the compression modes. By
- X default, pclcomp will use modes 0, 2 and 3, but the user may
- X restrict which output modes it uses by specifying them on
- X the command line with the -0, -1, -2 and -3 options. To
- X decompress a file, simply specify -0 as the only mode to use
- X for output. Mode 0 ( -0 ) should always be allowed since
- X modes 1, 2 and 3 cannot be guaranteed to be better than mode
- X 0 for all types of pictures.
- X
- X The -z option disables the zero "strip" feature. Since most
- X printers do zero "filling", pclcomp, by default, "strips"
- X the trailing zeros of each row (or plane) of data. Some
- X printers or programs may require that zero "stripping" be
- X disabled.
- X
- X By default, pclcomp expects the input raster width to be
- X 2400 pixels (8" at 300 dpi), and if it is different (e.g.
- X PaintJet), then the raster width should be specified by the
- X Source Raster Width escape sequence (<esc>*r#S). However,
- X many applications do not set the width and assume a default,
- X therefore, the user may use the -n option to pclcomp to
- X specify a new default raster width. For PaintJet (8" at 180
- X dpi), the number should be 1440. If the PCL file contains
- X the Source Raster Width escape sequence, it will override
- X this default. If pclcomp thinks that more data is coming in
- X than the specified width, it will generate a warning, and
- X continue processing (and perhaps truncating) data.
- X
- X The -x option will cause pclcomp to remove any horizontal
- X offset sequences from the data. Only use this option if
- X white is defined to be zero (as with LaserJets). This will
- X shrink the data more if modes 2 or 3 are used.
- X
- X The -r option causes pclcomp to append a reset sequence
- X
- X
- X
- X - 1 - Formatted: April 20, 1992
- X
- X
- X
- X
- X
- X
- X PCLCOMP(1) PCLCOMP(1)
- X
- X
- X
- X (<esc>E) to the end of the job.
- X
- X Use the -d option to pclcomp if the output is to be sent to
- X a DeskJet printer.
- X
- X Some applications erroneously send <esc>*rB and <esc>*rA
- X sequences between every row of graphics data. The -s option
- X to pclcomp will "strip" all <esc>*rB sequences, and all
- X <esc>*rA sequences after the first occurrence of this
- X sequence. In addition, text and control characters residing
- X between <esc>*rA and <esc>*rB sequences will be discarded.
- X While this will work well for many jobs, it may have
- X problems on multi-page or complex jobs.
- X
- X The -v option simply gives statistics to stderr about which
- X compression modes were used.
- X
- X EXAMPLES
- X To compress a PCL file for LaserJet III, use:
- X pclcomp infile outfile
- X
- X To compress a PCL file for the PaintJet (A size page at 180 dpi), use:
- X pclcomp -01 -n 1440 infile outfile
- X
- X To compress a PCL file for DeskJet, use:
- X pclcomp -d012 infile outfile
- X
- X To fully decompress a PCL file, use:
- X pclcomp -0z < infile > outfile
- X
- X WARNINGS
- X The -z option can cause the output to be larger than the
- X input.
- X
- X The -s option is useful, but it can cause erroneous output.
- X
- X The -x option can cause black areas on the left side of the
- X picture on color printers.
- X
- X AUTHOR
- X Tony Parkhurst, Hewlett-Packard, San Diego Division
- X (tony@sdd.hp.com)
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X
- X - 2 - Formatted: April 20, 1992
- X
- X
- X
- SHAR_EOF
- chmod 0664 pclcomp.man ||
- echo 'restore of pclcomp.man failed'
- Wc_c="`wc -c < 'pclcomp.man'`"
- test 4053 -eq "$Wc_c" ||
- echo 'pclcomp.man: original size 4053, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= printer.note ==============
- if test -f 'printer.note' -a X"$1" != X"-c"; then
- echo 'x - skipping printer.note (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting printer.note (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'printer.note' &&
- X
- X
- Here is a list of HP printers and the compression modes they support:
- X
- X
- X
- Printer Modes
- ------- -----
- X
- LaserJet 0
- LaserJet+ 0
- LaserJet 500 0
- LaserJet 2000 0
- LaserJet II 0
- LaserJet IID 0
- LaserJet IIP 0 1 2
- LaserJet III 0 1 2 3
- LaserJet IIID 0 1 2 3
- LaserJet IIISi 0 1 2 3
- LaserJet IIIP 0 1 2 3 5 (Method 5 is not supported by pclcomp)
- X
- DeskJet 0 1 2
- DeskJet+ 0 1 2
- DeskJet 500 0 1 2 3
- DeskJet 500 C 0 1 2 3 9 (Method 9 is not supported by pclcomp)
- X
- PaintJet 0 1
- PaintJet XL 0 1 2 3
- X
- X
- Mode 0 is uncompressed graphics data.
- SHAR_EOF
- chmod 0664 printer.note ||
- echo 'restore of printer.note failed'
- Wc_c="`wc -c < 'printer.note'`"
- test 546 -eq "$Wc_c" ||
- echo 'printer.note: original size 546, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- rm -f _shar_seq_.tmp
- echo You have unpacked the last part
- exit 0
- exit 0 # Just in case...
-