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);
  }