🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.lang.postscript
2 messages
2 total messages Started by Boyd Blackwell Fri, 14 Aug 1992 03:04
Level II compression questions
#1768
Author: Boyd Blackwell
Date: Fri, 14 Aug 1992 03:04
70 lines
3081 bytes
I have just attempted to convert gnu-compress4.01 to produce compressed 
output suitable for feeding into LZWDecode filter in Level II postscript.  It
works up to the first token length change.  Before beating my haed against the 
wall, I would like to know if anyone already has c code for LZWEncode.

It is like unix compress, BUT

a/ does not start with the magic number and the bit length
b/ DOES start with an explicit table clear  256(10)
c/ appears to change bit length smoothly without a buffer flush
d/ ends with an EOD token (what a good idea!) 257(10)
e/ pushes bits the other way - i.e. the MSBit 
     first (CLEAR is 0x80 0x0.. not 0x00 0x8..)

This is based on the Postscript Language Reference Manual *SECOND* edition 
pp.130 132 - (yes it is worth buying!)

If anyone can correct my interpretation or provide more info, I will post a
corrected article.

Hint:  If you want to test any of these filters, you can let your Laserwriter
IIf or IIg or your Tek Phaser II PXe/i do it for you - they can encode and
decode.  
Here is some smaple  code


%!
%designed as a quick test bdb 6/92
(filter test: ) print
/=print where not {/=print {(               ) cvs print} def 1} if pop % 1 or dict
statusdict begin revision (                           ) 
	printername product
  	print ([) print print (] rev. ) print =print (  ) print
	pagecount =print ( pages ) print
end

(\nLZWEncode ASCII info following this file:\n) print
realtime
(%stdout) (w) file
  /ASCIIHexEncode filter dup
    /LZWEncode filter dup /FILTER exch def
     { FILTER (%stdin) (r) file 256 string readstring 
	{writestring} {writestring closefile closefile 
	 (\nEND: ) print
	 realtime exch sub 1000 div =print ( sec ) print exit} ifelse} loop
-----A---B

% replace the above line (-----A)with your test data line(s) - up to about 20k chars
% the example -----A---B comes from the  Ps Lang. Ref Man (45 45 45 45 45 65...)

Sample run:
===========
% setenv PRINTER scu_colour
% /usr/local/cap/lwpr ~/ps/foo.ps
abInit: [ddp:   4.23, 51], [GW:   4.23, 33] starting
Status: status: idle
status: idle
Sending /users/prl1/bdb112/ps/foo.ps
filter test: Phaser II PXe[Phaser II PXe] rev. 2  103 pages
LZWEncode ASCII info following this file:
800B6050220C0C840A8080>
END: 0.0 sec bdb112@rsphy1>

Note the line 800B.... is the same as p 132. Ps Lang. Ref Man

--
	-Boyd Blackwell
Plasma Research Lab, RSPhysSE, ANU/ GPO Box 4 /Canberra ACT 2601/AUSTRALIA
internet: bdb112@prl1.anu.edu.au
PHONE: +61 62 49 2482 +61 62 51 2605(h) FAX: Boyd Blackwell, PRL +61 62 49 1884
Re: Level II compression questions
#1797
Author: David Haight
Date: Mon, 17 Aug 1992 18:52
200 lines
4603 bytes
In article <1992Aug14.030418.1512@newshost.anu.edu.au> bdb112@rsphy3.anu.edu.au (Boyd Blackwell) writes:
>I have just attempted to convert gnu-compress4.01 to produce compressed 
>output suitable for feeding into LZWDecode filter in Level II postscript.  It
>works up to the first token length change.  Before beating my haed against the 
>wall, I would like to know if anyone already has c code for LZWEncode.
>

.............Code and such deleted

Here's a PS LZW filter we've been using here, PS in LZW compressed out.

#include <stdio.h>

/* Various constants
 */
	 
#define EOD			  257			  /* End of Data marker */
#define CLR			  256			  /* Clear Table Marker */
#define MAXSTRINGS  4096		  /* using 12 bit max codes */
#define TRUE		  (1==1)
#define FALSE		  !TRUE
	 
/* This is the structure for a single entry into the string table
 */
	 
typedef struct
{
	 short prefix;
	 short suffix;
	 short next;
} stringrec;

/* Global data
 */

int codeWidth = 9, bitsInAcc = 0;	/* Used by code send function */
unsigned long acc;						/* =bits left over from a sendcode */
int nextIndex;								/* Used by newentry function */
stringrec stringarray[4096];			/* This is the string table */
long incount = 0, outcount = 0;		/* Input/output tally */


void Initialize(void);
void SendCode(short theCode);
int FindString(short *prefix, short suffix);
int main(int argc, char *argv[]);
void AddString(short prefix, short suffix);
void ShowStats(void);
	 
void Initialize()
{
	 int index;

	 for(index = 0; index < 256; index++)
	 {
		  stringarray[index].prefix = -1;
		  stringarray[index].suffix = (char) index;
		  stringarray[index].next = -1;
	 }
	 nextIndex = EOD + 1;
	 codeWidth = 9;
}
	 
void SendCode(short theCode)
{
	 acc += (long) theCode << (32 - codeWidth - bitsInAcc);
	 bitsInAcc += codeWidth;
	 while(bitsInAcc >= 8)
	 {
		  fputc(acc >> 24, stdout);
		  acc = acc << 8;
		  bitsInAcc -= 8;
		  outcount++;
	 }

	 if(theCode == CLR)
	 {
		  Initialize();
	 }

	 if(theCode == EOD && bitsInAcc != 0)
	 {
		  fputc(acc >> 24, stdout);
		  outcount++;
	 }

	 return;
}

int main(int argc, char *argv[])
{
	 short lastCode;
	 short thisCode;
	 double comppct;

	 if(argc != 1)
	 {
		  if(argc != 2)
		  {
				fprintf(stderr, "\nToo many arguments.\n");
				fflush(stderr);
				return(1);
		  }
		  if(*argv[1] == 'h')
		  {
				fprintf(stdout, "\ncurrentfile /LZWDecode filter cvx exec\n");
				incount += 41;
				fflush(stdout);
		  }
	 }
	 
	 fprintf(stderr, "\nCompressing...");
	 fflush(stderr);
	 
	 SendCode(CLR);
	 
	 if((lastCode = fgetc(stdin)) == EOF)
	 {
		  ++incount;
		  SendCode(EOD);
  		  return;
	 }
	 
	 while((thisCode = fgetc(stdin)) != EOF)
	 {
		  if(!(++incount & 0x00004FFF))
		  {
				ShowStats();
		  }

		  if(FindString(&lastCode, thisCode))
		  {
				continue;
		  } else
		  {
				SendCode(lastCode);
				AddString(lastCode, thisCode);
				lastCode = thisCode;
		  }

	 }

	 SendCode(lastCode);
	 SendCode(EOD);

	 ShowStats();
	 fprintf(stderr, "\nDone.\n");
	 fflush(stderr);
	 
	 return;
}

int FindString(short *prefix, short suffix)
{
	 short index = *prefix;

	 while(index != -1)
	 {
		  if(stringarray[index].prefix == *prefix &&
			  stringarray[index].suffix == suffix)
		  {
				*prefix = index;
				return(TRUE);
		  } else
		  {
				index = stringarray[index].next;
		  }
	 }

	 return(FALSE);
}

void AddString(short prefix, short suffix)
{
	 
	 stringarray[nextIndex].prefix = prefix;
	 stringarray[nextIndex].suffix = suffix;
	 stringarray[nextIndex].next = stringarray[prefix].next;
	 stringarray[prefix].next = nextIndex;

	 if(++nextIndex >> codeWidth)
	 {
		  if(++codeWidth > 12)
		  {
				--codeWidth;
				SendCode(CLR);
		  }
	 }
	 return;
}

void ShowStats()
{
	 double comppct;
	 
	 comppct = 100.0 * (1.0 - (double) outcount / (double) incount);
	 fprintf(stderr, "\rCompressing: %d bytes input, %d bytes output, %3.2f%% saved.",
				incount, outcount, comppct);
	 fflush(stderr);
}
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads