Пример #1
0
int
main(int argc, char* argv[])
{
    FILE *in;
    TIFF *out = NULL;
    TIFFErrorHandler whandler = NULL;
    int compression_in = COMPRESSION_CCITTFAX3;
    int compression_out = COMPRESSION_CCITTFAX3;
    int fillorder_in = FILLORDER_LSB2MSB;
    int fillorder_out = FILLORDER_LSB2MSB;
    uint32 group3options_in = 0;	/* 1d-encoded */
    uint32 group3options_out = 0;	/* 1d-encoded */
    uint32 group4options_in = 0;	/* compressed */
    uint32 group4options_out = 0;	/* compressed */
    uint32 defrowsperstrip = (uint32) 0;
    uint32 rowsperstrip;
    int photometric_in = PHOTOMETRIC_MINISWHITE;
    int photometric_out = PHOTOMETRIC_MINISWHITE;
    int mode = FAXMODE_CLASSF;
    int rows;
    int c;
    int pn, npages;
    float resY = 196.0;
    extern int optind;
    extern char* optarg;


    while ((c = getopt(argc, argv, "R:X:o:1234ABLMPUW5678abcflmprsuvwz?")) != -1)
        switch (c) {
        /* input-related options */
        case '3':		/* input is g3-encoded */
            compression_in = COMPRESSION_CCITTFAX3;
            break;
        case '4':		/* input is g4-encoded */
            compression_in = COMPRESSION_CCITTFAX4;
            break;
        case 'U':		/* input is uncompressed (g3 and g4) */
            group3options_in |= GROUP3OPT_UNCOMPRESSED;
            group4options_in |= GROUP4OPT_UNCOMPRESSED;
            break;
        case '1':		/* input is 1d-encoded (g3 only) */
            group3options_in &= ~GROUP3OPT_2DENCODING;
            break;
        case '2':		/* input is 2d-encoded (g3 only) */
            group3options_in |= GROUP3OPT_2DENCODING;
            break;
        case 'P':	/* input has not-aligned EOL (g3 only) */
            group3options_in &= ~GROUP3OPT_FILLBITS;
            break;
        case 'A':		/* input has aligned EOL (g3 only) */
            group3options_in |= GROUP3OPT_FILLBITS;
            break;
        case 'W':		/* input has 0 mean white */
            photometric_in = PHOTOMETRIC_MINISWHITE;
            break;
        case 'B':		/* input has 0 mean black */
            photometric_in = PHOTOMETRIC_MINISBLACK;
            break;
        case 'L':		/* input has lsb-to-msb fillorder */
            fillorder_in = FILLORDER_LSB2MSB;
            break;
        case 'M':		/* input has msb-to-lsb fillorder */
            fillorder_in = FILLORDER_MSB2LSB;
            break;
        case 'R':		/* input resolution */
            resY = (float) atof(optarg);
            break;
        case 'X':		/* input width */
            xsize = (uint32) atoi(optarg);
            break;

        /* output-related options */
        case '7':		/* generate g3-encoded output */
            compression_out = COMPRESSION_CCITTFAX3;
            break;
        case '8':		/* generate g4-encoded output */
            compression_out = COMPRESSION_CCITTFAX4;
            break;
        case 'u':	/* generate uncompressed output (g3 and g4) */
            group3options_out |= GROUP3OPT_UNCOMPRESSED;
            group4options_out |= GROUP4OPT_UNCOMPRESSED;
            break;
        case '5':	/* generate 1d-encoded output (g3 only) */
            group3options_out &= ~GROUP3OPT_2DENCODING;
            break;
        case '6':	/* generate 2d-encoded output (g3 only) */
            group3options_out |= GROUP3OPT_2DENCODING;
            break;
        case 'c':		/* generate "classic" g3 format */
            mode = FAXMODE_CLASSIC;
            break;
        case 'f':		/* generate Class F format */
            mode = FAXMODE_CLASSF;
            break;
        case 'm':		/* output's fillorder is msb-to-lsb */
            fillorder_out = FILLORDER_MSB2LSB;
            break;
        case 'l':		/* output's fillorder is lsb-to-msb */
            fillorder_out = FILLORDER_LSB2MSB;
            break;
        case 'o':
            out = TIFFOpen(optarg, "w");
            if (out == NULL) {
                fprintf(stderr,
                        "%s: Can not create or open %s\n",
                        argv[0], optarg);
                return EXIT_FAILURE;
            }
            break;
        case 'a':	/* generate EOL-aligned output (g3 only) */
            group3options_out |= GROUP3OPT_FILLBITS;
            break;
        case 'p':	/* generate not EOL-aligned output (g3 only) */
            group3options_out &= ~GROUP3OPT_FILLBITS;
            break;
        case 'r':		/* rows/strip */
            defrowsperstrip = atol(optarg);
            break;
        case 's':		/* stretch image by dup'ng scanlines */
            stretch = 1;
            break;
        case 'w':		/* undocumented -- for testing */
            photometric_out = PHOTOMETRIC_MINISWHITE;
            break;
        case 'b':		/* undocumented -- for testing */
            photometric_out = PHOTOMETRIC_MINISBLACK;
            break;
        case 'z':		/* undocumented -- for testing */
            compression_out = COMPRESSION_LZW;
            break;
        case 'v':		/* -v for info */
            verbose++;
            break;
        case '?':
            usage();
            /*NOTREACHED*/
        }
    npages = argc - optind;
    if (npages < 1)
        usage();

    rowbuf = _TIFFmalloc(TIFFhowmany8(xsize));
    refbuf = _TIFFmalloc(TIFFhowmany8(xsize));
    if (rowbuf == NULL || refbuf == NULL) {
        fprintf(stderr, "%s: Not enough memory\n", argv[0]);
        return (EXIT_FAILURE);
    }

    if (out == NULL) {
        out = TIFFOpen("fax.tif", "w");
        if (out == NULL) {
            fprintf(stderr, "%s: Can not create fax.tif\n",
                    argv[0]);
            return (EXIT_FAILURE);
        }
    }

    faxTIFF = TIFFClientOpen("(FakeInput)", "w",
                             /* TIFFClientOpen() fails if we don't set existing value here */
                             TIFFClientdata(out),
                             TIFFGetReadProc(out), TIFFGetWriteProc(out),
                             TIFFGetSeekProc(out), TIFFGetCloseProc(out),
                             TIFFGetSizeProc(out), TIFFGetMapFileProc(out),
                             TIFFGetUnmapFileProc(out));
    if (faxTIFF == NULL) {
        fprintf(stderr, "%s: Can not create fake input file\n",
                argv[0]);
        return (EXIT_FAILURE);
    }
    TIFFSetMode(faxTIFF, O_RDONLY);
    TIFFSetField(faxTIFF, TIFFTAG_IMAGEWIDTH,	xsize);
    TIFFSetField(faxTIFF, TIFFTAG_SAMPLESPERPIXEL,	1);
    TIFFSetField(faxTIFF, TIFFTAG_BITSPERSAMPLE,	1);
    TIFFSetField(faxTIFF, TIFFTAG_FILLORDER,	fillorder_in);
    TIFFSetField(faxTIFF, TIFFTAG_PLANARCONFIG,	PLANARCONFIG_CONTIG);
    TIFFSetField(faxTIFF, TIFFTAG_PHOTOMETRIC,	photometric_in);
    TIFFSetField(faxTIFF, TIFFTAG_YRESOLUTION,	resY);
    TIFFSetField(faxTIFF, TIFFTAG_RESOLUTIONUNIT,	RESUNIT_INCH);

    /* NB: this must be done after directory info is setup */
    TIFFSetField(faxTIFF, TIFFTAG_COMPRESSION, compression_in);
    if (compression_in == COMPRESSION_CCITTFAX3)
        TIFFSetField(faxTIFF, TIFFTAG_GROUP3OPTIONS, group3options_in);
    else if (compression_in == COMPRESSION_CCITTFAX4)
        TIFFSetField(faxTIFF, TIFFTAG_GROUP4OPTIONS, group4options_in);
    for (pn = 0; optind < argc; pn++, optind++) {
        in = fopen(argv[optind], "r" BINMODE);
        if (in == NULL) {
            fprintf(stderr,
                    "%s: %s: Can not open\n", argv[0], argv[optind]);
            continue;
        }
#if defined(_WIN32) && defined(USE_WIN32_FILEIO)
        TIFFSetClientdata(faxTIFF, (thandle_t)_get_osfhandle(fileno(in)));
#else
        TIFFSetClientdata(faxTIFF, (thandle_t)fileno(in));
#endif
        TIFFSetFileName(faxTIFF, (const char*)argv[optind]);
        TIFFSetField(out, TIFFTAG_IMAGEWIDTH, xsize);
        TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 1);
        TIFFSetField(out, TIFFTAG_COMPRESSION, compression_out);
        TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric_out);
        TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
        TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1);
        switch (compression_out) {
        /* g3 */
        case COMPRESSION_CCITTFAX3:
            TIFFSetField(out, TIFFTAG_GROUP3OPTIONS,
                         group3options_out);
            TIFFSetField(out, TIFFTAG_FAXMODE, mode);
            rowsperstrip =
                (defrowsperstrip)?defrowsperstrip:(uint32)-1L;
            break;

        /* g4 */
        case COMPRESSION_CCITTFAX4:
            TIFFSetField(out, TIFFTAG_GROUP4OPTIONS,
                         group4options_out);
            TIFFSetField(out, TIFFTAG_FAXMODE, mode);
            rowsperstrip =
                (defrowsperstrip)?defrowsperstrip:(uint32)-1L;
            break;

        default:
            rowsperstrip = (defrowsperstrip) ?
                           defrowsperstrip : TIFFDefaultStripSize(out, 0);
        }
        TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
        TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
        TIFFSetField(out, TIFFTAG_FILLORDER, fillorder_out);
        TIFFSetField(out, TIFFTAG_SOFTWARE, "fax2tiff");
        TIFFSetField(out, TIFFTAG_XRESOLUTION, 204.0);
        if (!stretch) {
            TIFFGetField(faxTIFF, TIFFTAG_YRESOLUTION, &resY);
            TIFFSetField(out, TIFFTAG_YRESOLUTION, resY);
        } else
            TIFFSetField(out, TIFFTAG_YRESOLUTION, 196.);
        TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
        TIFFSetField(out, TIFFTAG_PAGENUMBER, pn, npages);

        if (!verbose)
            whandler = TIFFSetWarningHandler(NULL);
        rows = copyFaxFile(faxTIFF, out);
        fclose(in);
        if (!verbose)
            (void) TIFFSetWarningHandler(whandler);

        TIFFSetField(out, TIFFTAG_IMAGELENGTH, rows);

        if (verbose) {
            fprintf(stderr, "%s:\n", argv[optind]);
            fprintf(stderr, "%d rows in input\n", rows);
            fprintf(stderr, "%ld total bad rows\n",
                    (long) badfaxlines);
            fprintf(stderr, "%d max consecutive bad rows\n", badfaxrun);
        }
        if (compression_out == COMPRESSION_CCITTFAX3 &&
                mode == FAXMODE_CLASSF) {
            TIFFSetField(out, TIFFTAG_BADFAXLINES, badfaxlines);
            TIFFSetField(out, TIFFTAG_CLEANFAXDATA, badfaxlines ?
                         CLEANFAXDATA_REGENERATED : CLEANFAXDATA_CLEAN);
            TIFFSetField(out, TIFFTAG_CONSECUTIVEBADFAXLINES, badfaxrun);
        }
        TIFFWriteDirectory(out);
    }
    TIFFClose(out);
    _TIFFfree(rowbuf);
    _TIFFfree(refbuf);
    return (EXIT_SUCCESS);
}
ret_t check_tagorder(ctiff_t * ctif) {
  tif_rules("tags are in ascending order");
  thandle_t client = TIFFClientdata(ctif->tif);
  TIFFReadWriteProc readproc = TIFFGetReadProc(ctif->tif);
  TIFFSeekProc seekproc = TIFFGetSeekProc(ctif->tif);
  if (! seekproc) {
    perror ("could not get TIFFGetSeekProc");
  }
  if (! readproc) {
    perror ("could not get TIFFGetReadProc");
  }

  uint32 offset = get_ifd0_pos(ctif);
  int count = get_ifd0_count(ctif);

  /* read count of tags (2 Bytes) */
  int i;
  /* replace i/o operatrions with in-memory-operations */
  uint8 * ifdentries = NULL;
  ifdentries = malloc ( sizeof(uint8) * 12 * count);
  /*
     if (read(fd, ifdentries, 12 * count) != 12*count) {
     perror ("TIFF Header read error5");
     exit(EXIT_FAILURE);
     }
     */
  seekproc(client, offset+2, SEEK_SET);

  if ( readproc( client, ifdentries, 12 * count) != 12*count ) {
    perror ("TIFF Header read error5");
    exit( EXIT_FAILURE );
  }

  uint8 * e = ifdentries;
  uint16 lasttag = 0;
  for (i = 0; i<count; i++) {
    uint8 lo = *e;
    e++;
    uint8 hi = *e;
    uint16 tag = (hi << 8) + lo;
    e++;
    if (is_byteswapped(ctif))
      TIFFSwabShort(&tag);
    if (i>0 && lasttag >= tag) {
      // printf("tag idx=%i, tag=%u (0x%04x) (0x%02x) (0x%02x)\n", i, tag, tag, hi, lo);
      free( ifdentries );
      // FIXME: tif_fails?
      char array[TIFFAILSTRLEN];
      snprintf(array, sizeof(array), "Invalid TIFF directory; tags are not sorted in ascending order, previous tag:%u (%s) , actual tag:%u (%s) at pos %i of %i\n", lasttag,  TIFFTagName(lasttag),  tag,  TIFFTagName(tag), i, count);
      return tif_fails(array);
    }
    lasttag = tag;
    e+=10;
  }
  /* loop each tag until end or given tag found */
  free( ifdentries );
  ret_t res;
  res.returnmsg=NULL;
  res.returncode=0;
  return res;
}