1994.04.16 23:19 "ASCII85 encoding in tiff2ps (incl. source code)", by Andreas Vogel
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);
}