Received: by whizzer.wpd.sgi.com (940413.SGI.8.6.8.1/911001.SGI)
	for tiff-list id MAA07773; Sun, 17 Apr 1994 12:27:56 GMT
Return-Path: <tiff-owner>
Received: from sgi.sgi.com by whizzer.wpd.sgi.com via SMTP (940413.SGI.8.6.8.1/911001.SGI)
	for <tiff-relay@whizzer.wpd.sgi.com> id FAA07766; Sun, 17 Apr 1994 05:27:39 -0700
Received: from iraun1.ira.uka.de by sgi.sgi.com via SMTP (931110.SGI/910110.SGI)
	for tiff-relay@whizzer.wpd.sgi.com id AA21286; Sun, 17 Apr 94 05:27:34 -0700
Received: from boss.pem.com by iraun1.ira.uka.de with SMTP (PP);
          Sun, 17 Apr 1994 14:27:09 +0200
Received: from ssw.de by boss.pem.com id aa21467; 17 Apr 94 7:00 MESZ
Received: from omega.ssw.de by ssw.de with uucp (Smail3.1.28.1 #4) 
          id m0psOpS-0001WlC; Sun, 17 Apr 94 05:51 MET
Received: by omega.ssw.de (Smail3.1.28.1 #2) id m0psJds-000AfqC;
          Sun, 17 Apr 94 01:19 MST
Message-Id: <m0psJds-000AfqC@omega.ssw.de>
From: Andreas Vogel <av@omega.ssw.de>
Subject: ASCII85 encoding in tiff2ps (incl. source code)
To: tiff@sgi.sgi.com
Date: Sun, 17 Apr 1994 01:19:16 +0200 (MST)
Reply-To: av@ssw.de
X-Mailer: ELM [version 2.4 PL23]
Mime-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit
Content-Length: 7180
Sender: tiff-owner@sgi.sgi.com

Hello Sam,

Thank you very much for providing such nice packages like libtiff and
flexfax.

I've worked a lot with tiff2ps and I've found a considerable inprovement.
In all level2 PostScript implementations (including the current version
of ghostscript) there is also a filter named ASCII85. Therefore, instead
of encoding in HEX the ASCII85 encoding saves a huge amount of bytes.

I've implemented the ASCII85 encoding in the program tiff2ps and it works
fine. I've appended a context diff to this mail. You're free to do with
it whatever you want. It's just a donation to your wonderful work.

I'd appreciate if you could send me a short message wether you'll
add my code and/or what do you think of it.

BTW, the diff is against version tiff-3.3b2 and I'm running the whole
stuff on an i486 SVR4.

Thank you very much,

-- 
Andreas Vogel               Bahnhofstr. 13 / 73728 Esslingen / Germany
			    Voice:  +49-711/3967133
			    E-Mail: av@ssw.de


--- CUT HERE --- CUT HERE --- CUT HERE --- CUT HERE --- CUT HERE --- CUT HERE ---

*** tiff2ps.c.ORIG	Wed Mar 16 17:39:23 1994
--- tiff2ps.c	Wed Mar 16 23:22:25 1994
***************
*** 39,44 ****
--- 39,45 ----
  #define	TRUE	1
  #define	FALSE	0
  
+ int     ascii85 = TRUE;                 /* use ASCII85 encoding */
  int	level2 = FALSE;			/* generate PostScript level 2 */
  int	printAll = FALSE;		/* print all images in file */
  int	generateEPSF = TRUE;		/* generate Encapsulated PostScript */
***************
*** 103,113 ****
--- 104,119 ----
  		case '2':
  			level2 = TRUE;
  			break;
+ 		case '8':
+ 			ascii85 = !ascii85;
+ 			break;
  		case '?':
  			usage(-1);
  		}
  	if (argc - optind < 1)
  		usage(-2);
+ 	if (!level2)
+ 	    ascii85 = FALSE;
  	tif = TIFFOpen(filename = argv[optind], "r");
  	if (tif != NULL) {
  		if (dirnum != -1 && !TIFFSetDirectory(tif, dirnum))
***************
*** 383,389 ****
  			int rawdata;
  			fprintf(fd, "%lu %lu %d\n", w, h, bitspersample);
  			fprintf(fd, "[%lu 0 0 -%lu 0 %lu]\n", w, h, h);
! 			fprintf(fd, "currentfile /ASCIIHexDecode filter\n");
  			fprintf(fd, "dup 6 1 roll\n");
  			rawdata = emitPSLevel2FilterFunction(fd, tif, w, h);
  			fprintf(fd, "{image flushfile flushfile} cvx exec\n");
--- 389,398 ----
  			int rawdata;
  			fprintf(fd, "%lu %lu %d\n", w, h, bitspersample);
  			fprintf(fd, "[%lu 0 0 -%lu 0 %lu]\n", w, h, h);
! 			if (ascii85)
! 			    fprintf(fd, "currentfile /ASCII85Decode filter\n");
! 			else
! 			    fprintf(fd, "currentfile /ASCIIHexDecode filter\n");
  			fprintf(fd, "dup 6 1 roll\n");
  			rawdata = emitPSLevel2FilterFunction(fd, tif, w, h);
  			fprintf(fd, "{image flushfile flushfile} cvx exec\n");
***************
*** 391,397 ****
  				PSRawDataBW(fd, tif, w, h);
  			else
  				PSDataBW(fd, tif, w, h);
! 			putc('>', fd);
  		} else {
  			fprintf(fd, "/scanLine %d string def\n",ps_bytesperrow);
  			fprintf(fd, "%lu %lu %d\n", w, h, bitspersample);
--- 400,407 ----
  				PSRawDataBW(fd, tif, w, h);
  			else
  				PSDataBW(fd, tif, w, h);
! 			if (!ascii85)
! 			    putc('>', fd);
  		} else {
  			fprintf(fd, "/scanLine %d string def\n",ps_bytesperrow);
  			fprintf(fd, "%lu %lu %d\n", w, h, bitspersample);
***************
*** 607,612 ****
--- 617,716 ----
  	free((char *) tf_buf);
  }
  
+ 
+ static unsigned char   ascii85buf[10];
+ static int             ascii85count;
+ static int             ascii85breaklen;
+ 
+ static void Ascii85Init ()
+ {
+     ascii85breaklen = 75;
+     ascii85count = 0;
+ }
+ 
+ static char *Ascii85Encode (unsigned char *buf)
+ {
+     static char     retbuf[6];
+     unsigned long   word;
+ 
+     word = ((unsigned long) (((unsigned int) buf[0] << 8) + buf[1]) << 16)
+ 	    + (((unsigned int) buf[2] << 8) + buf[3]);
+ 
+     if (word == 0L)
+ 	retbuf[0] = 'z', retbuf[1] = 0;
+     else
+     {
+ 	unsigned long   q;
+ 	unsigned short  w1;
+ 
+ 	q = word / (85L*85*85*85);  /* actually only a byte */
+ 	retbuf[0] = q + '!';
+ 
+ 	word -= q * (85L*85*85*85); q = word / (85L*85*85);
+ 	retbuf[1] = q + '!';
+ 
+ 	word -= q * (85L*85*85); q = word / (85*85);
+ 	retbuf[2] = q + '!';
+ 
+ 	w1 = (unsigned short) (word - q * (85L*85));
+ 	retbuf[3] = (w1 / 85) + '!';
+ 	retbuf[4] = (w1 % 85) + '!';
+ 	retbuf[5] = 0;
+     }
+ 
+     return (retbuf);
+ }
+ 
+ 
+ static void Ascii85Put (unsigned char code, FILE *fd)
+ {
+     unsigned char       *p;
+     unsigned char       *cp;
+     int                 count;
+ 
+     ascii85buf[ascii85count++] = code;
+     if (ascii85count < 4)
+ 	return;
+ 
+     count = ascii85count;
+     p     = ascii85buf;
+ 
+     while (count >= 4)
+     {
+ 	for (cp = Ascii85Encode (p); *cp; cp++)
+ 	{
+ 	    fputc (*cp, fd);
+ 	    if ((ascii85breaklen -= 1) <= 0)
+ 	    {
+ 		fputc ('\n', fd);
+ 		ascii85breaklen = 75;
+ 	    }
+ 	}
+ 	count -= 4, p += 4;
+     }
+ 
+     memcpy (ascii85buf, p, count);
+     ascii85count = count;
+ }
+ 
+ static void Ascii85Exit (FILE *fd)
+ {
+     /*
+     **  Handle leftover bytes.  1 <= ascii85count <= 3.
+     */
+     if (ascii85count > 0)
+     {
+ 	char    *res;
+ 
+ 	memset (&ascii85buf[ascii85count], 0, 3);
+ 	res = Ascii85Encode (ascii85buf);
+ 	fputs (res[0] == 'z' ? "!!!!" : res, fd);
+     }
+     fputs ("~>\n", fd);
+ }
+ 
+ 
+ 
  void
  PSDataBW(FILE* fd, TIFF* tif, uint32 w, uint32 h)
  {
***************
*** 615,620 ****
--- 719,727 ----
  	unsigned char *tf_buf;
  	unsigned char *cp, c;
  
+ 	if (ascii85)
+ 	    Ascii85Init ();
+ 
  	tf_buf = (unsigned char *) malloc(tf_bytesperrow);
  	if (tf_buf == NULL) {
  		TIFFError(filename, "No space for scanline buffer");
***************
*** 624,639 ****
  		if (TIFFReadScanline(tif, tf_buf, row, 0) < 0)
  			break;
  		for (cp = tf_buf, cc = 0; cc < tf_bytesperrow; cc++) {
- 			DOBREAK(breaklen, 1, fd);
  			c = *cp++;
  			if (photometric == PHOTOMETRIC_MINISWHITE)
  				c = ~c;
! 			PUTHEX(c, fd);
  		}
  	}
  	free((char *) tf_buf);
  }
  
  void
  PSRawDataBW(FILE* fd, TIFF* tif, uint32 w, uint32 h)
  {
--- 731,757 ----
  		if (TIFFReadScanline(tif, tf_buf, row, 0) < 0)
  			break;
  		for (cp = tf_buf, cc = 0; cc < tf_bytesperrow; cc++) {
  			c = *cp++;
  			if (photometric == PHOTOMETRIC_MINISWHITE)
  				c = ~c;
! 			if (ascii85)
! 			{
! 			    Ascii85Put (c, fd);
! 			}
! 			else
! 			{
! 			    DOBREAK(breaklen, 1, fd);
! 			    PUTHEX(c, fd);
! 			}
  		}
  	}
  	free((char *) tf_buf);
+ 
+ 	if (ascii85)
+ 	    Ascii85Exit (fd);
  }
  
+ 
  void
  PSRawDataBW(FILE* fd, TIFF* tif, uint32 w, uint32 h)
  {
***************
*** 645,650 ****
--- 763,771 ----
  	unsigned char *cp, c;
  	tstrip_t s;
  
+ 	if (ascii85)
+ 	    Ascii85Init ();
+ 
  	TIFFGetField(tif, TIFFTAG_FILLORDER, &fillorder);
  	TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &bc);
  	bufsize = bc[0];
***************
*** 672,681 ****
--- 793,812 ----
  		if (fillorder == FILLORDER_LSB2MSB)
  			TIFFReverseBits(tf_buf, cc);
  		for (cp = tf_buf; cc > 0; cc--) {
+ 		    if (ascii85)
+ 		    {
+ 			Ascii85Put (*cp++, fd);
+ 		    }
+ 		    else
+ 		    {
  			DOBREAK(breaklen, 1, fd);
  			c = *cp++;
  			PUTHEX(c, fd);
+ 		    }
  		}
  	}
  	free((char *) tf_buf);
+ 
+ 	if (ascii85)
+ 	    Ascii85Exit (fd);
  }


