home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / libtiff / lbtif3_3.tar / contrib / fax2ps / fax2ps.c < prev    next >
C/C++ Source or Header  |  1993-08-26  |  18KB  |  685 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/tiff/contrib/fax2ps/RCS/fax2ps.c,v 1.30 93/08/26 16:07:35 sam Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1991, 1992, 1993 by Sam Leffler.
  7.  * All rights reserved.
  8.  *
  9.  * This file is provided for unrestricted use provided that this
  10.  * legend is included on all tape media and as a part of the
  11.  * software program in whole or part.  Users may copy, modify or
  12.  * distribute this file at will.
  13.  */
  14. #include <math.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17.  
  18. #include "defs.h"
  19.  
  20. #define    MAXCODEPROBES    5
  21. CodeEntry* codehash[CODEHASH];
  22. CodeEntry* codetable;
  23.  
  24. char**    codeNames;        /* codeNames[code] => ASCII code name */
  25. char*    codeNameSpace;        /* storage space for codeNames and strings */
  26. int    ncodes = 0;        /* number of assigned codes */
  27. int    maxcodes = 0;        /* max # codes that fit in codetable */
  28. int    maxpairs = 0;        /* max # pairs that fit in pairtable */
  29. int    includeStatistics = FALSE;/* if 1, add comments w/ frequency stats */
  30. int    startOfRow;        /* if 1, have yet to emit a code for this row */
  31. int    dopairs = FALSE;    /* if 1, encode pairs of codes */
  32. float    defxres = 204.;        /* default x resolution (pixels/inch) */
  33. float    defyres = 98.;        /* default y resolution (lines/inch) */
  34. float    pageWidth = 8.5;    /* image page width (inches) */
  35. float    pageHeight = 11.0;    /* image page length (inches) */
  36. int    scaleToPage = FALSE;    /* if true, scale raster to page dimensions */
  37.  
  38. CodeEntry*
  39. enterCode(int dx, int len)
  40. {
  41.     int h, c;
  42.     CodeEntry* cp;
  43.  
  44.     cp = codehash[h = HASHCODE(dx,len)];
  45.     if (cp) {
  46.     if (cp->move == dx && cp->runlen == len)
  47.         return (cp);
  48.     c = h ? CODEHASH - h : 1;    /* Knott's rehash algorithm */
  49.     for (;;) {
  50.         if ((h -= c) < 0)
  51.         h += CODEHASH;
  52.         cp = codehash[h];
  53.         if (!cp)
  54.         break;
  55.         if (cp->move == dx && cp->runlen == len)
  56.         return (cp);
  57.     }
  58.     }
  59.     if (ncodes == maxcodes) {
  60.     maxcodes += MAXCODES;
  61.     codetable = (CodeEntry*) (maxcodes == MAXCODES ?
  62.         malloc(maxcodes * sizeof (CodeEntry)) :
  63.         realloc(codetable, maxcodes * sizeof (CodeEntry))
  64.     );
  65.     if (codetable == NULL) {
  66.         fprintf(stderr, "Panic, code table overflow\n");
  67.         exit(-1);
  68.     }
  69.     }
  70.     codehash[h] = cp = &codetable[ncodes++];
  71.     cp->c.count = 0;
  72.     cp->c.code = (u_short) -1;
  73.     cp->c.cost = 0;
  74.     cp->move = dx;
  75.     cp->runlen = len;
  76.     return (cp);
  77. }
  78.  
  79. void
  80. printCode(TIFF* tif, CodeEntry* cp)
  81. {
  82.     if (startOfRow) {
  83.     printf("%d r\n", fax.row);
  84.     startOfRow = FALSE;
  85.     }
  86.     if (cp->c.code == (u_short) -1)
  87.     printf("%d %d f", cp->runlen, cp->move);
  88.     else
  89.     printf("%s", codeNames[cp->c.code]);
  90.     putchar('\n');
  91. }
  92.  
  93. CodePairEntry* pairhash[PAIRHASH];
  94. CodePairEntry* pairtable;
  95. int    npairs = 0;
  96.  
  97. CodePairEntry*
  98. findPair(CodeEntry* a, CodeEntry* b)
  99. {
  100.     int h, c;
  101.     CodePairEntry* pp;
  102.  
  103.     pp = pairhash[h = HASHPAIR(a,b)];
  104.     if (pp->a == a && pp->b == b)
  105.     return (pp);
  106.     c = h ? PAIRHASH - h : 1;        /* Knott's rehash algorithm */
  107.     for (;;) {
  108.     if ((h -= c) < 0)
  109.         h += PAIRHASH;
  110.     pp = pairhash[h];
  111.     if (pp->a == a && pp->b == b)
  112.         return (pp);
  113.     }
  114.     /*NOTREACHED*/
  115. }
  116.  
  117. CodePairEntry*
  118. enterPair(CodeEntry* a, CodeEntry* b)
  119. {
  120.     int h, c;
  121.     CodePairEntry* pp;
  122.  
  123.     pp = pairhash[h = HASHPAIR(a,b)];
  124.     if (pp) {
  125.     if (pp->a == a && pp->b == b)
  126.         return (pp);
  127.     c = h ? PAIRHASH - h : 1;    /* Knott's rehash algorithm */
  128.     for (;;) {
  129.         if ((h -= c) < 0)
  130.         h += PAIRHASH;
  131.         pp = pairhash[h];
  132.         if (!pp)
  133.         break;
  134.         if (pp->a == a && pp->b == b)
  135.         return (pp);
  136.     }
  137.     }
  138.     if (npairs == maxpairs) {
  139.     maxpairs += MAXPAIRS;
  140.     pairtable = (CodePairEntry*) (maxpairs == MAXPAIRS ?
  141.         malloc(maxpairs * sizeof (CodePairEntry)) :
  142.         realloc(pairtable, maxpairs * sizeof (CodePairEntry))
  143.     );
  144.     if (pairtable == NULL) {
  145.         fprintf(stderr, "Panic, pair table overflow\n");
  146.         exit(-1);
  147.     }
  148.     }
  149.     pairhash[h] = pp = &pairtable[npairs++];
  150.     pp->c.count = 0;
  151.     pp->c.code = (u_short) -1;
  152.     pp->c.cost = 0;
  153.     pp->a = a;
  154.     pp->b = b;
  155.     return (pp);
  156. }
  157.  
  158. int
  159. printPair(TIFF* tif, CodeEntry* a, CodeEntry* b)
  160. {
  161.     CodePairEntry* pp = findPair(a,b);
  162.  
  163.     if (pp && pp->c.code != (u_short) -1) {
  164.     if (startOfRow) {
  165.         printf("%d r\n", fax.row);
  166.         startOfRow = FALSE;
  167.     }
  168.     printf("%s\n", codeNames[pp->c.code]);
  169.     return (TRUE);
  170.     } else
  171.     return (FALSE);
  172. }
  173.  
  174. #define    MIN(a,b)    ((a)<(b)?(a):(b))
  175.  
  176. static char alphabet[] = {
  177.     '!', '"', '#', '$', '&', '*', '+', ',', ':', ';', '?', '@',
  178.     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
  179.     'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  180.     '^', '_', '~'
  181. };
  182. static int MaxAlpha = (sizeof (alphabet) / sizeof (alphabet[0]));
  183.  
  184. /*
  185.  * Construct a table of code names from a limited
  186.  * alphabet.  By default, the alphabet is comprised
  187.  * of all the non-special ASCII PostScript characters
  188.  * (except for lower case alphabetics which are avoided
  189.  * to insure we don't construct a PostScript operator
  190.  * name).  The alphabet can be restricted to just the 
  191.  * upper case alphabetics with the -a option.
  192.  */
  193. void
  194. makeCodeNames(int ncodes)
  195. {
  196.     int n, cc, len, nc, digit, code;
  197.     char* cp;
  198.     short key[11];
  199.  
  200.     n = ncodes;
  201.     cc = 0;
  202.     len = 2;        /* minimum length string */
  203.     nc = 1;
  204.     do {
  205.     nc *= MaxAlpha;
  206.     cc += MIN(n, nc) * len++;
  207.     } while ((n -= MIN(n,nc)) > 0);
  208.     codeNameSpace = (char*) malloc(ncodes*sizeof (char*) + cc);
  209.     codeNames = (char**) codeNameSpace;
  210.     cp = (char*) (codeNames + ncodes);
  211.  
  212.     n = ncodes;
  213.     len = 1;
  214.     code = 0;
  215.     nc = 1;
  216.     for (digit = 0; digit < 11; digit++)
  217.     key[digit] = -1;
  218.     do {
  219.     nc *= MaxAlpha;
  220.     cc = MIN(n,nc);
  221.     while (cc-- > 0) {
  222.         for (digit = 0; ++key[digit] == MaxAlpha; key[digit++] = 0)
  223.         ;
  224.         codeNames[code++] = cp;
  225.         switch (len) {
  226.         case 5: *cp++ = alphabet[key[4]];
  227.         case 4: *cp++ = alphabet[key[3]];
  228.         case 3: *cp++ = alphabet[key[2]];
  229.         case 2: *cp++ = alphabet[key[1]];
  230.         case 1: *cp++ = alphabet[key[0]];
  231.         }
  232.         *cp++ = '\0';
  233.     }
  234.     len++;
  235.     } while ((n -= MIN(n,nc)) > 0);
  236. }
  237.  
  238. #define    DIGITS(x)    ((x) < 10 ? 1 : (x) < 100 ? 2 : (x) < 1000 ? 3 : 4)
  239.  
  240. int
  241. codeCost(CodeEntry* cp)
  242. {
  243.     /* 3 is constant overhead for <blank><len><blank><move>f */
  244.     return (3 + DIGITS(cp->move) + DIGITS(cp->runlen));
  245. }
  246.  
  247. /*
  248.  * DEFCOST is the cost to define the specified code for this
  249.  * move-draw operation.  It's calculated according to:
  250.  *    /<code>{<move-draw>}d\n
  251.  * which translates to 5 + cost(code) + cost(move-draw).
  252.  */
  253. #define    DEFCOST(mdc, codelen)    (mdc + codelen + 5)
  254. /*
  255.  * USECOST is the cost to use the code once it's been defined.
  256.  * This is just the number of uses times the length of the code
  257.  * plus one -- the one is for the blank needed by the parser.
  258.  */
  259. #define    USECOST(count, codelen)    (count * (codelen+1))
  260. /*
  261.  * CODEDCOST is the total cost to define and use the defined
  262.  * code (in place of straight move-draw operations).  We assume
  263.  * that the "code" field holds the result of the {pair|code}Cost
  264.  * calculation (see below).
  265.  */
  266. #define    CODEDCOST(c, codelen) \
  267.     (USECOST(c->count, codelen) + DEFCOST(c->code, codelen))
  268.  
  269. int
  270. codeLength(int code)
  271. {
  272.     return (code < MaxAlpha ? 1 : code < MaxAlpha*MaxAlpha ? 2 : 3);
  273. }
  274.  
  275. int
  276. codeCostCompare(Code** c1, Code** c2)
  277. {
  278.     return ((*c2)->cost - (*c1)->cost);
  279. }
  280.  
  281. /*
  282.  * Sort pairs and singletons, assign codes, and 
  283.  * reset counts for the next pass where we test
  284.  * out the encoding.
  285.  */
  286. int
  287. assignCodes(Code** sorted, int clearCounts)
  288. {
  289.     int i, n, code, codelen;
  290.     CodePairEntry* pp;
  291.     CodeEntry* cp;
  292.  
  293.     /*
  294.      * Calculate the cost to use the operation "as is"
  295.      * (i.e. w/o an encoding).  This is simply the number
  296.      * of uses times the cost of the move-draw operation.
  297.      * We save the {pair|code}Cost calculation for reuse
  298.      * below (when making the final decision about which
  299.      * codes are actually worth defining.
  300.      */
  301.     i = 0;
  302.     for (cp = codetable, n = ncodes; n-- > 0; i++, cp++) {
  303.     sorted[i] = &cp->c;
  304.     cp->c.code = codeCost(cp);
  305.     cp->c.cost = cp->c.count * cp->c.code;
  306.     }
  307.     for (pp = pairtable, n = npairs; n-- > 0; i++, pp++) {
  308.     sorted[i] = &pp->c;
  309.     pp->c.code = pp->a->c.code + pp->b->c.code;
  310.     pp->c.cost = pp->c.count * pp->c.code;
  311.     }
  312.     qsort(sorted, ncodes + npairs, sizeof (Code*), codeCostCompare);
  313.     code = 0;
  314.     codelen = codeLength(code);
  315.     for (i = 0, n = npairs + ncodes; n-- > 0; i++) {
  316.     Code* c = sorted[i];
  317.     if (c->cost > CODEDCOST(c, codelen)) {
  318.         c->code = code++;
  319.         codelen = codeLength(code);
  320.     } else
  321.         c->code = (u_short) -1;
  322.     if (clearCounts)
  323.         c->count = 0;
  324.     }
  325.     return (code);
  326. }
  327.  
  328. void
  329. makeCodeTable()
  330. {
  331.     int i, n;
  332.     Code** sorted;
  333.     CodeEntry* cp;
  334.  
  335.     sorted = (Code**) malloc((npairs+ncodes) * sizeof (Code*));
  336.     makeCodeNames(n = assignCodes(sorted, FALSE));
  337.     /*
  338.      * Oversize the dictionary in case the lookup function
  339.      * is optimized for a partially populated data structure.
  340.      * Most any hashing algorithm should do fine with a max
  341.      * 75% population.
  342.      */
  343.     printf("%d dict begin\n", 4*n/3);
  344.     for (i = 0, n = npairs + ncodes; n-- > 0; i++) {
  345.     Code* c = sorted[i];
  346.     if (c->code == (u_short) -1)
  347.         continue;
  348.     if (isPair(c)) {
  349.         CodePairEntry* pp = (CodePairEntry*) c;
  350.         printf("/%s{", codeNames[c->code]);
  351.         cp = pp->a;
  352.         if (cp->c.code < c->code)
  353.         printf("%s", codeNames[cp->c.code]);
  354.         else
  355.         printf("%d %d f", cp->runlen, cp->move);
  356.         putchar(' ');
  357.         cp = pp->b;
  358.         if (cp->c.code < c->code)
  359.         printf("%s", codeNames[cp->c.code]);
  360.         else
  361.         printf("%d %d f", cp->runlen, cp->move);
  362.         printf("}d");
  363.         if (includeStatistics)
  364.         printf("\t%% %d hits", c->count);
  365.         putchar('\n');
  366.     } else {
  367.         cp = (CodeEntry*) c;
  368.         printf("/%s{%d %d f}d", codeNames[c->code], cp->runlen, cp->move);
  369.         if (includeStatistics)
  370.         printf("\t%% %d hits", c->count);
  371.         putchar('\n');
  372.     }
  373.     }
  374.     free((char*) sorted);
  375. }
  376.  
  377. static void
  378. setupPass(TIFF* tif, int pass)
  379. {
  380.     uint32* stripbytecount;
  381.  
  382.     fax.pass = pass;
  383.     fax.row = 0;
  384.     TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &stripbytecount);
  385.     fax.cc = stripbytecount[0];
  386.     fax.bp = fax.buf;
  387.     FaxPreDecode(tif);
  388. }
  389.  
  390. static    int totalPages = 0;
  391.  
  392. void
  393. printTIF(TIFF* tif, int pageNumber)
  394. {
  395.     uint32 w, h;
  396.     uint16 fill, unit, photometric, compression;
  397.     float xres, yres;
  398.     uint32 g3opts;
  399.     uint32* stripbytecount;
  400.  
  401.     TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &stripbytecount);
  402.     fax.cc = stripbytecount[0];
  403.     fax.buf = (u_char*) malloc(fax.cc);
  404.     TIFFReadRawStrip(tif, 0, fax.buf, fax.cc);
  405.     if (TIFFGetField(tif,TIFFTAG_FILLORDER, &fill) && fill != FILLORDER_MSB2LSB)
  406.     TIFFReverseBits(fax.buf, fax.cc);
  407.     TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
  408.     TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
  409.     if (!TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres)) {
  410.     TIFFWarning(TIFFFileName(tif),
  411.         "No x-resolution, assuming %g dpi", defxres);
  412.     xres = defxres;
  413.     }
  414.     if (!TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres)) {
  415.     TIFFWarning(TIFFFileName(tif),
  416.         "No y-resolution, assuming %g lpi", defyres);
  417.     yres = defyres;                    /* XXX */
  418.     }
  419.     if (TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &unit) &&
  420.       unit == RESUNIT_CENTIMETER) {
  421.     xres *= 25.4;
  422.     yres *= 25.4;
  423.     }
  424.     TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric);
  425.     fax.b.white = (photometric == PHOTOMETRIC_MINISBLACK);
  426.     /*
  427.      * Calculate the scanline/tile widths.
  428.      */
  429.     if (isTiled(tif)) {
  430.         fax.b.rowbytes = TIFFTileRowSize(tif);
  431.     TIFFGetField(tif, TIFFTAG_TILEWIDTH, &fax.b.rowpixels);
  432.     } else {
  433.         fax.b.rowbytes = TIFFScanlineSize(tif);
  434.     TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &fax.b.rowpixels);
  435.     }
  436.     if (TIFFGetField(tif, TIFFTAG_GROUP3OPTIONS, &g3opts))
  437.     fax.is2d = (g3opts & GROUP3OPT_2DENCODING) != 0;
  438.     else
  439.     fax.is2d = 0;
  440.     fax.scanline = (u_char*) malloc(2*fax.b.rowbytes);
  441.     fax.b.refline = fax.scanline + fax.b.rowbytes;
  442.     TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression);
  443.     if (compression == COMPRESSION_CCITTFAX4)
  444.     fax.options = FAX3_NOEOL;
  445.     /*
  446.      * First pass: create code and pair frequency tables.
  447.      */
  448.     memset((char*) codehash, 0, sizeof (codehash));
  449.     memset((char*) pairhash, 0, sizeof (pairhash));
  450.     maxcodes = 0;
  451.     maxpairs = 0;
  452.     setupPass(tif, 1);
  453.     ncodes = npairs = 0;
  454.     if (compression == COMPRESSION_CCITTFAX4)
  455.     Fax4DecodeRow(tif, h*w);
  456.     else
  457.     Fax3DecodeRow(tif, h*w);
  458.     if (dopairs) {
  459.     /*
  460.      * Second pass: assign codes according to frequency
  461.      *  thresholds and rescan data to get true usage.
  462.      */
  463.     CodeEntry** sorted = (CodeEntry**)
  464.         malloc((npairs+ncodes) * sizeof (CodeEntry*));
  465.     assignCodes((Code**) sorted, TRUE);
  466.     free((char*) sorted);
  467.     setupPass(tif, 2);
  468.     if (compression == COMPRESSION_CCITTFAX4)
  469.         Fax4DecodeRow(tif, h*w);
  470.     else
  471.         Fax3DecodeRow(tif, h*w);
  472.     }
  473.     /*
  474.      * Third pass: generate code table and encoded data.
  475.      */
  476.     printf("%%%%Page: \"%d\" %d\n", pageNumber, pageNumber);
  477.     printf("gsave\n");
  478.     if (scaleToPage) {
  479.     float yscale = pageHeight / (h/yres);
  480.     float xscale = pageWidth / (w/xres);
  481.     printf("0 %d translate\n", (int)(yscale*(h/yres)*72.));
  482.     printf("%g %g scale\n", (72.*xscale)/xres, -(72.*yscale)/yres);
  483.     } else {
  484.     printf("0 %d translate\n", (int)(72.*h/yres));
  485.     printf("%g %g scale\n", 72./xres, -72./yres);
  486.     }
  487.     printf("0 setgray\n");
  488.     makeCodeTable();
  489.     setupPass(tif, 3);
  490.     while (fax.cc > 0) {
  491.     startOfRow = 1;
  492.     if (compression == COMPRESSION_CCITTFAX4)
  493.         Fax4DecodeRow(tif, w);
  494.     else
  495.         Fax3DecodeRow(tif, w);
  496.     if (!startOfRow)
  497.         printf("s\n");
  498.     }
  499.     printf("p\n");
  500.     printf("grestore\n");
  501.     free((char*) fax.scanline);
  502.     free((char*) fax.buf);
  503.     free(codeNameSpace);
  504.     if (maxcodes > 0) {
  505.     free((char*) codetable);
  506.     codetable = NULL;
  507.     }
  508.     if (maxpairs > 0) {
  509.     free((char*) pairtable);
  510.     pairtable = NULL;
  511.     }
  512.     totalPages++;
  513. }
  514.  
  515. #define    GetPageNumber(tif) \
  516. TIFFGetField(tif, TIFFTAG_PAGENUMBER, &pn, &ptotal)
  517.  
  518. int
  519. findPage(TIFF* tif, int pageNumber)
  520. {
  521.     uint16 pn = -1, ptotal = -1;
  522.     if (GetPageNumber(tif)) {
  523.     while (pn != pageNumber && TIFFReadDirectory(tif) && GetPageNumber(tif))
  524.         ;
  525.     return (pn == pageNumber);
  526.     } else
  527.     return (TIFFSetDirectory(tif, pageNumber-1));
  528. }
  529.  
  530. void
  531. fax2ps(TIFF* tif, int npages, int* pages, char* filename)
  532. {
  533.     if (npages > 0) {
  534.     uint16 pn, ptotal;
  535.     int i;
  536.  
  537.     if (!GetPageNumber(tif))
  538.         fprintf(stderr, "%s: No page numbers, counting directories.\n",
  539.         filename);
  540.     for (i = 0; i < npages; i++) {
  541.         if (findPage(tif, pages[i]))
  542.         printTIF(tif, pages[i]);
  543.         else
  544.         fprintf(stderr, "%s: No page number %d\n", filename, pages[i]);
  545.     }
  546.     } else {
  547.     int pageNumber = 1;
  548.     do
  549.         printTIF(tif, pageNumber++);
  550.     while (TIFFReadDirectory(tif));
  551.     }
  552. }
  553.  
  554. #undef GetPageNumber
  555.  
  556. static int
  557. pcompar(void* va, void* vb)
  558. {
  559.     int* pa = (int*) va;
  560.     int* pb = (int*) vb;
  561.     return (*pa - *pb);
  562. }
  563.  
  564. extern    double atof();
  565.  
  566. main(int argc, char** argv)
  567. {
  568.     extern int optind;
  569.     extern char* optarg;
  570.     int c, pageNumber;
  571.     int* pages = 0, npages = 0;
  572.     int dowarnings = FALSE;    /* if 1, enable library warnings */
  573.     long t;
  574.     TIFF* tif;
  575.  
  576.     while ((c = getopt(argc, argv, "p:x:y:W:H:aswzS")) != -1)
  577.     switch (c) {
  578.     case 'H':        /* page height */
  579.         pageHeight = atof(optarg);
  580.         break;
  581.     case 'S':        /* scale to page */
  582.         scaleToPage = TRUE;
  583.         break;
  584.     case 'W':        /* page width */
  585.         pageWidth = atof(optarg);
  586.         break;
  587.     case 'a':        /* use only upper-case alphabetics */
  588.         MaxAlpha = 26;
  589.         for (t = 0; t < MaxAlpha; t++)
  590.         alphabet[t] = 'A' + t;
  591.         break;
  592.     case 'p':        /* print specific page */
  593.         pageNumber = atoi(optarg);
  594.         if (pageNumber < 1) {
  595.         fprintf(stderr, "%s: Invalid page number (must be > 0).\n",
  596.             optarg);
  597.         exit(-1);
  598.         }
  599.         if (pages)
  600.         pages = (int*) realloc((char*) pages, (npages+1)*sizeof (int));
  601.         else
  602.         pages = (int*) malloc(sizeof (int));
  603.         pages[npages++] = pageNumber;
  604.         break;
  605.     case 's':        /* include frequency statistics as comments */
  606.         includeStatistics = TRUE;
  607.         break;
  608.     case 'w':
  609.         dowarnings = TRUE;
  610.         break;
  611.     case 'x':
  612.         defxres = atof(optarg);
  613.         break;
  614.     case 'y':
  615.         defyres = atof(optarg);
  616.         break;
  617.     case 'z':        /* do pair analysis (not effective) */
  618.         dopairs = TRUE;
  619.         break;
  620.     case '?':
  621.         fprintf(stderr,
  622. "usage: %s [-a] [-w] [-p pagenumber] [-x xres] [-y res] [-s] [-S] [-W pagewidth] [-H pageheight] [files]\n",
  623.         argv[0]);
  624.         exit(-1);
  625.     }
  626.     if (npages > 0)
  627.     qsort(pages, npages, sizeof (int), pcompar);
  628.     if (!dowarnings)
  629.     TIFFSetWarningHandler(0);
  630.     printf("%%!PS-Adobe-3.0\n");
  631.     printf("%%%%Creator: fax2ps\n");
  632. #ifdef notdef
  633.     printf("%%%%Title: %s\n", file);
  634. #endif
  635.     t = time(0);
  636.     printf("%%%%CreationDate: %s", ctime(&t));
  637.     printf("%%%%Origin: 0 0\n");
  638.     printf("%%%%BoundingBox: 0 0 %u %u\n",
  639.     (int)(pageHeight*72), (int)(pageWidth*72));    /* XXX */
  640.     printf("%%%%Pages: (atend)\n");
  641.     printf("%%%%EndComments\n");
  642.     printf("%%%%BeginProlog\n");
  643.     printf("/d{bind def}def\n");            /* bind and def proc */
  644.     printf("/f{0 rmoveto 0 rlineto}d\n");        /* fill span */
  645.     printf("/r{0 exch moveto}d\n");            /* begin row */
  646.     printf("/s{stroke}d\n");                /* stroke row */
  647.     printf("/p{end showpage}d \n");            /* end page */
  648.     printf("%%%%EndProlog\n");
  649.     if (optind < argc) {
  650.     do {
  651.         tif = TIFFOpen(argv[optind], "r");
  652.         if (tif) {
  653.         fax2ps(tif, npages, pages, argv[optind]);
  654.         TIFFClose(tif);
  655.         } else
  656.         fprintf(stderr, "%s: Can not open, or not a TIFF file.\n",
  657.             argv[optind]);
  658.     } while (++optind < argc);
  659.     } else {
  660.     int n, fd;
  661.     char temp[1024], buf[16*1024];
  662.  
  663.     strcpy(temp, "/tmp/fax2psXXXXXX");
  664.     fd = mkstemp(temp);
  665.     if (fd == -1) {
  666.         fprintf(stderr, "Could not create temp file \"%s\"\n", temp);
  667.         exit(-2);
  668.     }
  669.     while ((n = read(fileno(stdin), buf, sizeof (buf))) > 0)
  670.         write(fd, buf, n);
  671.     tif = TIFFOpen(temp, "r");
  672.     unlink(temp);
  673.     if (tif) {
  674.         fax2ps(tif, npages, pages, "<stdin>");
  675.         TIFFClose(tif);
  676.     } else
  677.         fprintf(stderr, "%s: Can not open, or not a TIFF file.\n", temp);
  678.     close(fd);
  679.     }
  680.     printf("%%%%Trailer\n");
  681.     printf("%%%%Pages: %u\n", totalPages);
  682.     printf("%%%%EOF\n");
  683.     exit(0);
  684. }
  685.