home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / libtiff / lbtif3_3.tar / tools / fax2tiff.c next >
C/C++ Source or Header  |  1993-08-26  |  9KB  |  294 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/tiff/tools/RCS/fax2tiff.c,v 1.23 93/08/26 15:07:08 sam Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1990, 1991, 1992 Sam Leffler
  7.  * Copyright (c) 1991, 1992 Silicon Graphics, Inc.
  8.  *
  9.  * Permission to use, copy, modify, distribute, and sell this software and 
  10.  * its documentation for any purpose is hereby granted without fee, provided
  11.  * that (i) the above copyright notices and this permission notice appear in
  12.  * all copies of the software and related documentation, and (ii) the names of
  13.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  14.  * publicity relating to the software without the specific, prior written
  15.  * permission of Sam Leffler and Silicon Graphics.
  16.  * 
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  18.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  19.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  20.  * 
  21.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  22.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  23.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  24.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  25.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  26.  * OF THIS SOFTWARE.
  27.  */
  28.  
  29. /* 
  30.  * Convert a CCITT Group 3 FAX file to TIFF Group 3 format.
  31.  */
  32. #include <stdio.h>
  33. #include <stdlib.h>        /* should have atof & getopt */
  34. #include "tiffiop.h"
  35.  
  36. TIFF    faxTIFF;
  37. #define XSIZE        1728
  38. u_char    rowbuf[howmany(XSIZE,8)];
  39. u_char    refbuf[howmany(XSIZE,8)];
  40.  
  41. int    verbose;
  42. int    stretch;
  43. uint16    badfaxrun;
  44. uint32    badfaxlines;
  45.  
  46. int    copyFaxFile(TIFF* tifin, TIFF* tifout);
  47.  
  48. void
  49. usage(void)
  50. {
  51.     fprintf(stderr, "usage: fax2tiff [-2BLMW] [-R inres] [-14cfmpsv] [-o out.tif] faxfile ...\n");
  52.     exit(-1);
  53. }
  54.  
  55. void
  56. main(int argc, char* argv[])
  57. {
  58.     FILE *in;
  59.     TIFF *out = NULL;
  60.     int compression = COMPRESSION_CCITTFAX3;
  61.     int fillorder = FILLORDER_LSB2MSB;
  62.     long group3options = GROUP3OPT_FILLBITS|GROUP3OPT_2DENCODING;
  63.     int photometric = PHOTOMETRIC_MINISWHITE;
  64.     int isClassF = 1;
  65.     int rows;
  66.     int c;
  67.     int pn, npages;
  68.     extern int optind;
  69.     extern char* optarg;
  70.  
  71.     memset(&faxTIFF, 0, sizeof (faxTIFF));
  72.     TIFFSetField(&faxTIFF, TIFFTAG_IMAGEWIDTH,    XSIZE);
  73.     TIFFSetField(&faxTIFF, TIFFTAG_SAMPLESPERPIXEL,    1);
  74.     TIFFSetField(&faxTIFF, TIFFTAG_BITSPERSAMPLE,    1);
  75.     TIFFSetField(&faxTIFF, TIFFTAG_FILLORDER,    FILLORDER_LSB2MSB);
  76.     TIFFSetField(&faxTIFF, TIFFTAG_PLANARCONFIG,    PLANARCONFIG_CONTIG);
  77.     TIFFSetField(&faxTIFF, TIFFTAG_PHOTOMETRIC,    PHOTOMETRIC_MINISWHITE);
  78.     TIFFSetField(&faxTIFF, TIFFTAG_YRESOLUTION,    196.);
  79.     TIFFSetField(&faxTIFF, TIFFTAG_RESOLUTIONUNIT,    RESUNIT_INCH);
  80.     /* NB: this is normally setup when a directory is read */
  81.     faxTIFF.tif_scanlinesize = TIFFScanlineSize(&faxTIFF);
  82.  
  83.     while ((c = getopt(argc, argv, "R:o:2BLMW14cflmpsvwz")) != -1)
  84.         switch (c) {
  85.             /* input-related options */
  86.         case '2':        /* input is 2d-encoded */
  87.             TIFFSetField(&faxTIFF,
  88.                 TIFFTAG_GROUP3OPTIONS, GROUP3OPT_2DENCODING);
  89.             break;
  90.         case 'B':        /* input has 0 mean black */
  91.             TIFFSetField(&faxTIFF,
  92.                 TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
  93.             break;
  94.         case 'L':        /* input has lsb-to-msb fillorder */
  95.             TIFFSetField(&faxTIFF,
  96.                 TIFFTAG_FILLORDER, FILLORDER_LSB2MSB);
  97.             break;
  98.         case 'M':        /* input has msb-to-lsb fillorder */
  99.             TIFFSetField(&faxTIFF,
  100.                 TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
  101.             break;
  102.         case 'R':        /* input resolution */
  103.             TIFFSetField(&faxTIFF,
  104.                 TIFFTAG_YRESOLUTION, atof(optarg));
  105.             break;
  106.         case 'W':        /* input has 0 mean white */
  107.             TIFFSetField(&faxTIFF,
  108.                 TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
  109.             break;
  110.  
  111.             /* output-related options */
  112.         case '1':        /* generate 1d-encoded output */
  113.             group3options &= ~GROUP3OPT_2DENCODING;
  114.             break;
  115.         case '4':        /* generate g4-encoded output */
  116.             compression = COMPRESSION_CCITTFAX4;
  117.             break;
  118.         case 'c':        /* generate "classic" g3 format */
  119.             isClassF = 0;
  120.             break;
  121.         case 'f':        /* generate Class F format */
  122.             isClassF = 1;
  123.             break;
  124.         case 'm':        /* output's fillorder is msb-to-lsb */
  125.             fillorder = FILLORDER_MSB2LSB;
  126.             break;
  127.         case 'o':
  128.             out = TIFFOpen(optarg, "w");
  129.             if (out == NULL)
  130.                 exit(-2);
  131.             break;
  132.         case 'p':        /* zero pad output scanline EOLs */
  133.             group3options &= ~GROUP3OPT_FILLBITS;
  134.             break;
  135.         case 's':        /* stretch image by dup'ng scanlines */
  136.             stretch = 1;
  137.             break;
  138.         case 'w':        /* undocumented -- for testing */
  139.             photometric = PHOTOMETRIC_MINISBLACK;
  140.             break;
  141.  
  142.         case 'z':        /* undocumented -- for testing */
  143.             compression = COMPRESSION_LZW;
  144.             break;
  145.  
  146.         case 'v':        /* -v for info */
  147.             verbose++;
  148.             break;
  149.         case '?':
  150.             usage();
  151.             /*NOTREACHED*/
  152.         }
  153.     if (out == NULL) {
  154.         out = TIFFOpen("fax.tif", "w");
  155.         if (out == NULL)
  156.             exit(-2);
  157.     }
  158.     faxTIFF.tif_fillorder = out->tif_fillorder;    /* XXX */
  159.     faxTIFF.tif_readproc = out->tif_readproc;    /* XXX */
  160.     faxTIFF.tif_writeproc = out->tif_writeproc;    /* XXX */
  161.     faxTIFF.tif_seekproc = out->tif_seekproc;    /* XXX */
  162.     faxTIFF.tif_closeproc = out->tif_closeproc;    /* XXX */
  163.     faxTIFF.tif_sizeproc = out->tif_sizeproc;    /* XXX */
  164.     faxTIFF.tif_mapproc = out->tif_mapproc;        /* XXX */
  165.     faxTIFF.tif_unmapproc = out->tif_unmapproc;    /* XXX */
  166.  
  167.     npages = argc - optind;
  168.     if (npages < 1)
  169.         usage();
  170.  
  171.     /* NB: this must be done after directory info is setup */
  172.     TIFFSetField(&faxTIFF, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX3);
  173.     for (pn = 0; optind < argc; pn++, optind++) {
  174.         in = fopen(argv[optind], "r");
  175.         if (in == NULL) {
  176.             fprintf(stderr,
  177.                 "%s: %s: Can not open\n", argv[0], argv[optind]);
  178.             continue;
  179.         }
  180.         faxTIFF.tif_fd = fileno(in);
  181.         faxTIFF.tif_clientdata = (thandle_t) faxTIFF.tif_fd;
  182.         faxTIFF.tif_name = argv[optind];
  183.         TIFFSetField(out, TIFFTAG_IMAGEWIDTH, XSIZE);
  184.         TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 1);
  185.         TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
  186.         TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
  187.         TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
  188.         TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1);
  189.         if (compression == COMPRESSION_CCITTFAX3) {
  190.             TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, group3options);
  191.             TIFFModeCCITTFax3(out, isClassF);
  192.         }
  193.         if (compression == COMPRESSION_CCITTFAX3 ||
  194.             compression == COMPRESSION_CCITTFAX4)
  195.             TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, -1L);
  196.         else
  197.             TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
  198.                 (uint32) (8*1024)/TIFFScanlineSize(out));
  199.         TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  200.         TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
  201.         TIFFSetField(out, TIFFTAG_SOFTWARE, "fax2tiff");
  202.         TIFFSetField(out, TIFFTAG_XRESOLUTION, 204.0);
  203.         if (!stretch) {
  204.             float yres;
  205.             TIFFGetField(&faxTIFF, TIFFTAG_YRESOLUTION, &yres);
  206.             TIFFSetField(out, TIFFTAG_YRESOLUTION, yres);
  207.         } else
  208.             TIFFSetField(out, TIFFTAG_YRESOLUTION, 196.);
  209.         TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
  210.         TIFFSetField(out, TIFFTAG_PAGENUMBER, pn+1, npages);
  211.  
  212.         rows = copyFaxFile(&faxTIFF, out);
  213.         fclose(in);
  214.  
  215.         TIFFSetField(out, TIFFTAG_IMAGELENGTH, rows);
  216.  
  217.         if (verbose) {
  218.             fprintf(stderr, "%s:\n", argv[optind]);
  219.             fprintf(stderr, "%d rows in input\n", rows);
  220.             fprintf(stderr, "%d total bad rows\n", badfaxlines);
  221.             fprintf(stderr, "%d max consecutive bad rows\n", badfaxrun);
  222.         }
  223.         if (compression == COMPRESSION_CCITTFAX3 && isClassF) {
  224.             TIFFSetField(out, TIFFTAG_BADFAXLINES, badfaxlines);
  225.             TIFFSetField(out, TIFFTAG_CLEANFAXDATA, badfaxlines ?
  226.                 CLEANFAXDATA_REGENERATED : CLEANFAXDATA_CLEAN);
  227.             TIFFSetField(out, TIFFTAG_CONSECUTIVEBADFAXLINES, badfaxrun);
  228.         }
  229.         TIFFWriteDirectory(out);
  230.     }
  231.     TIFFClose(out);
  232.     exit(0);
  233. }
  234.  
  235. int
  236. copyFaxFile(TIFF* tifin, TIFF* tifout)
  237. {
  238.     long row;
  239.     uint16 badrun;
  240.     int ok;
  241.  
  242.     tifin->tif_rawdatasize = TIFFGetFileSize(tifin);
  243.     tifin->tif_rawdata = _TIFFmalloc(tifin->tif_rawdatasize);
  244.     if (!ReadOK(tifin, tifin->tif_rawdata, tifin->tif_rawdatasize)) {
  245.         TIFFError(tifin->tif_name, "%s: Read error at scanline 0");
  246.         return (0);
  247.     }
  248.     tifin->tif_rawcp = tifin->tif_rawdata;
  249.     tifin->tif_rawcc = tifin->tif_rawdatasize;
  250.  
  251.     (*tifin->tif_predecode)(tifin);
  252.     tifin->tif_row = 0;
  253.     badfaxlines = 0;
  254.     badfaxrun = 0;
  255.  
  256.     memset(refbuf, 0, sizeof (refbuf));
  257.     row = 0;
  258.     badrun = 0;        /* current run of bad lines */
  259.     while (tifin->tif_rawcc > 0) {
  260.         ok = (*tifin->tif_decoderow)(tifin, rowbuf, sizeof (rowbuf), 0);
  261.         if (!ok) {
  262.             badfaxlines++;
  263.             badrun++;
  264.             /* regenerate line from previous good line */
  265.             memcpy(rowbuf, refbuf, sizeof (rowbuf));
  266.         } else {
  267.             if (badrun > badfaxrun)
  268.                 badfaxrun = badrun;
  269.             badrun = 0;
  270.             memcpy(refbuf, rowbuf, sizeof (rowbuf));
  271.         }
  272.         tifin->tif_row++;
  273.  
  274.         if (TIFFWriteScanline(tifout, rowbuf, row, 0) < 0) {
  275.             fprintf(stderr, "%s: Write error at row %ld.\n",
  276.                 tifout->tif_name, row);
  277.             break;
  278.         }
  279.         row++;
  280.         if (stretch) {
  281.             if (TIFFWriteScanline(tifout, rowbuf, row, 0) < 0) {
  282.                 fprintf(stderr, "%s: Write error at row %ld.\n",
  283.                     tifout->tif_name, row);
  284.                 break;
  285.             }
  286.             row++;
  287.         }
  288.     }
  289.     if (badrun > badfaxrun)
  290.         badfaxrun = badrun;
  291.     free(tifin->tif_rawdata);
  292.     return (row);
  293. }
  294.