1994.11.03 14:35 "Fix of tiff2ps", by Alberto Accomazzi

A while ago I reported a problem with the way tiff2ps generated PostScript level2 files from multi-strip tiff files. The problem was that the strip data was just concatenated, strip after strip, breaking the encoding. I think I fixed the problem but am not too proud of the solution, which is to create different image strips in the postscript file by replicating the data structure and encoding in the original TIFF file.

The advantage of this approach is that you don't have to decompress the TIFF data and then recompress it as a single stream when writing out the PS file, so the conversion is very fast; the disadvantage is that the PS file is larger than it could be (the lower rowsperstrip the bigger the file) and that the postscript code looks, well, kind of ugly. With this fix tiff2ps should produce correct level 2 postscript on any tiff file.

Anyway, here's the diff. I won't be offended if somebody who knows more than I do about TIFF and PostScript rewrites it, but at least this seems to solve my problem.

- Alberto

*** tiff2ps.c   Wed Nov  2 15:32:07 1994
--- ../tools/tiff2ps.c  Wed Nov  2 09:55:30 1994
***************
*** 301,329 ****
        fprintf(fd, "%%%%EOF\n");
  }

- /* returns TRUE iff raw TIFF data to PS can be generated */
- static int PSLevel2Raw(TIFF* tif)
- {
-       uint16 compression;
-         
-       TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression);
- #define       P(a,b)  (((a)<<4)|((b)&0xf))
-       switch (P(compression, photometric)) {
-       case P(COMPRESSION_CCITTRLE, PHOTOMETRIC_MINISBLACK):
-       case P(COMPRESSION_CCITTRLE, PHOTOMETRIC_MINISWHITE):
-       case P(COMPRESSION_CCITTFAX3, PHOTOMETRIC_MINISBLACK):
-       case P(COMPRESSION_CCITTFAX3, PHOTOMETRIC_MINISWHITE):
-       case P(COMPRESSION_CCITTFAX4, PHOTOMETRIC_MINISBLACK):
-       case P(COMPRESSION_CCITTFAX4, PHOTOMETRIC_MINISWHITE):
-       case P(COMPRESSION_LZW, PHOTOMETRIC_MINISBLACK):
-               return (TRUE);
-       default:
-               return (FALSE);
-       }
- #undef P
- }


  static int
  emitPSLevel2FilterFunction(FILE* fd, TIFF* tif, uint32 w, uint32 h)
  {
--- 301,306 ----
***************
*** 403,427 ****
        case PHOTOMETRIC_MINISWHITE:
                PhotoshopBanner(fd, w, h, 1, 1, "image");
                if (level2) {
!                       if (PSLevel2Raw(tif)) {
!                               PSRawDataBW(fd, tif, w, h);
                        } else {
!                               fprintf(fd, "%lu %lu %d\n", w, h, 
!                                       bitspersample);
!                               fprintf(fd, "[%lu 0 0 -%lu 0 %lu]\n", w, h, h);
!                               fprintf(fd, 
!                                       "currentfile /ASCII%sDecode filter\n",
!                                       ascii85 ? "85" : "Hex");
!                               fprintf(fd, "dup 6 1 roll\n");
!                               fprintf(fd, 
!                                       "{image flushfile flushfile} cvx exec\n");
!                               if (ascii85) 
!                                       Ascii85Init();
!                               PSDataBW(fd, tif, w, h);
!                               if (ascii85)
!                                       Ascii85Flush(fd);
!                               putc('>', fd);
                        }
                } else {
                        fprintf(fd, "/scanLine %d string def\n",ps_bytesperrow);
                        fprintf(fd, "%lu %lu %d\n", w, h, bitspersample);
--- 380,407 ----
        case PHOTOMETRIC_MINISWHITE:
                PhotoshopBanner(fd, w, h, 1, 1, "image");
                if (level2) {
!                       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 /ASCII%sDecode filter\n",
!                           ascii85 ? "85" : "Hex");
!                       fprintf(fd, "dup 6 1 roll\n");
!                       rawdata = emitPSLevel2FilterFunction(fd, tif, w, h);
!                       fprintf(fd, "{image flushfile flushfile} cvx exec\n");
!                       if (ascii85) {
!                               Ascii85Init();
!                               if (rawdata)
!                                       PSRawDataBW(fd, tif, w, h);
!                               else
!                                       PSDataBW(fd, tif, w, h);
!                               Ascii85Flush(fd);
                        } else {
!                               if (rawdata)
!                                       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);
***************
*** 670,676 ****
  void
  PSRawDataBW(FILE* fd, TIFF* tif, uint32 w, uint32 h)
  {
!       uint32 *bc, rs, rows = 0, rowc = h;
        uint32 bufsize;
        int breaklen = MAXLINE, cc;
        uint16 fillorder;
--- 650,656 ----
  void
  PSRawDataBW(FILE* fd, TIFF* tif, uint32 w, uint32 h)
  {
!       uint32 *bc;
        uint32 bufsize;
        int breaklen = MAXLINE, cc;
        uint16 fillorder;
***************
*** 678,688 ****
        unsigned char *cp, c;
        tstrip_t s;

- #define MIN(a,b) (((a)>(b))?(b):(a))

        TIFFGetField(tif, TIFFTAG_FILLORDER, &fillorder);
        TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &bc);
-       TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rs);
        bufsize = bc[0];
        tf_buf = (unsigned char*) malloc(bufsize);
        if (tf_buf == NULL) {
--- 658,665 ----
***************
*** 707,725 ****
                }
                if (fillorder == FILLORDER_LSB2MSB)
                        TIFFReverseBits(tf_buf, cc);

-               /* create PS image header for this strip */
-               rows = MIN(rowc,rs);
-               fprintf(fd, "gsave\n");
-               fprintf(fd, "1.000000 %f scale\n", (float) rows / (float) h);
-               fprintf(fd, "%lu %lu %d\n", w, rows, bitspersample);
-               fprintf(fd, "[%lu 0 0 -%lu 0 %lu]\n", w, rows, rowc);
-               fprintf(fd, "currentfile /ASCII%sDecode filter\n",
-                   ascii85 ? "85" : "Hex");
-               fprintf(fd, "dup 6 1 roll\n");
-               emitPSLevel2FilterFunction(fd, tif, w, rows);
-               fprintf(fd, "{image flushfile flushfile} cvx exec\n");

                if (!ascii85) {
                        for (cp = tf_buf; cc > 0; cc--) {
                                DOBREAK(breaklen, 1, fd);
--- 684,689 ----
***************
*** 727,743 ****
                                PUTHEX(c, fd);
                        }
                } else {
-                       Ascii85Init();
                        for (cp = tf_buf; cc > 0; cc--)
                                Ascii85Put(*cp++, fd);
-                       Ascii85Flush(fd);
                }
-               fprintf(fd, ">\ngrestore\n");
-               /* update row offset */
-               rowc -= rs;
        }
        free((char *) tf_buf);
- #undef MIN
  }

  /*
--- 691,701 ----

==========
Alberto Accomazzi              Harvard-Smithsonian Center for Astrophysics
alberto@cfa.harvard.edu        60 Garden Street, MS 70
(617) 495-7076                 Cambridge, MA  02138  USA
http://cfa-www.harvard.edu/~alberto/