Beispiel #1
0
/*
 * Return the number of bytes required to store a complete
 * decoded and packed raster scanline (as opposed to the
 * I/O size returned by TIFFScanlineSize which may be less
 * if data is store as separate planes).
 */
tsize_t
TIFFRasterScanlineSize(TIFF* tif)
{
	TIFFDirectory *td = &tif->tif_dir;
	tsize_t scanline;
	
	scanline = multiply (tif, td->td_bitspersample, td->td_imagewidth,
			     "TIFFRasterScanlineSize");
	if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
		scanline = multiply (tif, scanline, td->td_samplesperpixel,
				     "TIFFRasterScanlineSize");
		return ((tsize_t) TIFFhowmany8(scanline));
	} else
		return ((tsize_t) multiply (tif, TIFFhowmany8(scanline),
					    td->td_samplesperpixel,
					    "TIFFRasterScanlineSize"));
}
Beispiel #2
0
/*
 * Return the number of bytes to read/write in a call to
 * one of the scanline-oriented i/o routines.  Note that
 * this number may be 1/samples-per-pixel if data is
 * stored as separate planes.
 */
tsize_t
TIFFScanlineSize(TIFF* tif)
{
	TIFFDirectory *td = &tif->tif_dir;
	tsize_t scanline;

	if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
		if (td->td_photometric == PHOTOMETRIC_YCBCR
		    && !isUpSampled(tif)) {
			uint16 ycbcrsubsampling[2];

			TIFFGetField(tif, TIFFTAG_YCBCRSUBSAMPLING,
				     ycbcrsubsampling + 0,
				     ycbcrsubsampling + 1);

			if (ycbcrsubsampling[0] == 0) {
				TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
					     "Invalid YCbCr subsampling");
				return 0;
			}

			scanline = TIFFroundup(td->td_imagewidth,
					       ycbcrsubsampling[0]);
			scanline = TIFFhowmany8(multiply(tif, scanline,
							 td->td_bitspersample,
							 "TIFFScanlineSize"));
			return ((tsize_t)
				summarize(tif, scanline,
					  multiply(tif, 2,
						scanline / ycbcrsubsampling[0],
						"TIFFVStripSize"),
					  "TIFFVStripSize"));
		} else {
			scanline = multiply(tif, td->td_imagewidth,
					    td->td_samplesperpixel,
					    "TIFFScanlineSize");
		}
	} else
		scanline = td->td_imagewidth;
	return ((tsize_t) TIFFhowmany8(multiply(tif, scanline,
						td->td_bitspersample,
						"TIFFScanlineSize")));
}
Beispiel #3
0
/*
 * Compute the # bytes in a variable height, row-aligned strip.
 */
tsize_t
TIFFVStripSize(TIFF* tif, uint32 nrows)
{
	TIFFDirectory *td = &tif->tif_dir;

	if (nrows == (uint32) -1)
		nrows = td->td_imagelength;
	if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
	    td->td_photometric == PHOTOMETRIC_YCBCR &&
	    !isUpSampled(tif)) {
		/*
		 * Packed YCbCr data contain one Cb+Cr for every
		 * HorizontalSampling*VerticalSampling Y values.
		 * Must also roundup width and height when calculating
		 * since images that are not a multiple of the
		 * horizontal/vertical subsampling area include
		 * YCbCr data for the extended image.
		 */
                uint16 ycbcrsubsampling[2];
                tsize_t w, scanline, samplingarea;
		ycbcrsubsampling[0] = 0;
		ycbcrsubsampling[1] = 0;

                TIFFGetField( tif, TIFFTAG_YCBCRSUBSAMPLING, 
                              ycbcrsubsampling + 0, 
                              ycbcrsubsampling + 1 );
		/* make sure we dont get division by 0 due to bad tiffs */
		if (!ycbcrsubsampling[0]) ycbcrsubsampling[0] = 1;
		if (!ycbcrsubsampling[1]) ycbcrsubsampling[1] = 1;

		samplingarea = ycbcrsubsampling[0]*ycbcrsubsampling[1];
		if (samplingarea == 0) {
			_TIFFError(tif, tif->tif_name,
				"Invalid YCbCr subsampling");
			return 0;
		}

		w = TIFFroundup(td->td_imagewidth, ycbcrsubsampling[0]);
		scanline = TIFFhowmany8(multiply(tif, w, td->td_bitspersample,
						 "TIFFVStripSize"));
		nrows = TIFFroundup(nrows, ycbcrsubsampling[1]);
		/* NB: don't need TIFFhowmany here 'cuz everything is rounded */
		scanline = multiply(tif, nrows, scanline, "TIFFVStripSize");
		return ((tsize_t)
		    summarize(tif, scanline,
			      multiply(tif, 2, scanline / samplingarea,
				       "TIFFVStripSize"), "TIFFVStripSize"));
	} else
		return ((tsize_t) multiply(tif, nrows, TIFFScanlineSize(tif),
					   "TIFFVStripSize"));
}
Beispiel #4
0
/*
 * Compute the # bytes in each row of a tile.
 */
tsize_t
TIFFTileRowSize(TIFF* tif)
{
	TIFFDirectory *td = &tif->tif_dir;
	tsize_t rowsize;
	
	if (td->td_tilelength == 0 || td->td_tilewidth == 0)
		return ((tsize_t) 0);
	rowsize = multiply(tif, td->td_bitspersample, td->td_tilewidth,
			   "TIFFTileRowSize");
	if (td->td_planarconfig == PLANARCONFIG_CONTIG)
		rowsize = multiply(tif, rowsize, td->td_samplesperpixel,
				   "TIFFTileRowSize");
	return ((tsize_t) TIFFhowmany8(rowsize));
}
Beispiel #5
0
/*
 * Compute the # bytes in a variable length, row-aligned tile.
 */
tsize_t
TIFFVTileSize(TIFF* tif, uint32 nrows)
{
	TIFFDirectory *td = &tif->tif_dir;
	tsize_t tilesize;

	if (td->td_tilelength == 0 || td->td_tilewidth == 0 ||
	    td->td_tiledepth == 0)
		return ((tsize_t) 0);
	if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
	    td->td_photometric == PHOTOMETRIC_YCBCR &&
	    !isUpSampled(tif)) {
		/*
		 * Packed YCbCr data contain one Cb+Cr for every
		 * HorizontalSampling*VerticalSampling Y values.
		 * Must also roundup width and height when calculating
		 * since images that are not a multiple of the
		 * horizontal/vertical subsampling area include
		 * YCbCr data for the extended image.
		 */
		tsize_t w =
		    TIFFroundup(td->td_tilewidth, td->td_ycbcrsubsampling[0]);
		tsize_t rowsize =
		    TIFFhowmany8(multiply(tif, w, td->td_bitspersample,
					  "TIFFVTileSize"));
		tsize_t samplingarea =
		    td->td_ycbcrsubsampling[0]*td->td_ycbcrsubsampling[1];
		if (samplingarea == 0) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Invalid YCbCr subsampling");
			return 0;
		}
		nrows = TIFFroundup(nrows, td->td_ycbcrsubsampling[1]);
		/* NB: don't need TIFFhowmany here 'cuz everything is rounded */
		tilesize = multiply(tif, nrows, rowsize, "TIFFVTileSize");
		tilesize = summarize(tif, tilesize,
				     multiply(tif, 2, tilesize / samplingarea,
					      "TIFFVTileSize"),
				     "TIFFVTileSize");
	} else
		tilesize = multiply(tif, nrows, TIFFTileRowSize(tif),
				    "TIFFVTileSize");
	return ((tsize_t)
	    multiply(tif, tilesize, td->td_tiledepth, "TIFFVTileSize"));
}
Beispiel #6
0
/*
 * Return nearest TIFFDataType to the sample type of an image.
 */
TIFFDataType
_TIFFSampleToTagType(TIFF* tif)
{
	uint32 bps = TIFFhowmany8(tif->tif_dir.td_bitspersample);

	switch (tif->tif_dir.td_sampleformat) {
	case SAMPLEFORMAT_IEEEFP:
		return (bps == 4 ? TIFF_FLOAT : TIFF_DOUBLE);
	case SAMPLEFORMAT_INT:
		return (bps <= 1 ? TIFF_SBYTE :
		    bps <= 2 ? TIFF_SSHORT : TIFF_SLONG);
	case SAMPLEFORMAT_UINT:
		return (bps <= 1 ? TIFF_BYTE :
		    bps <= 2 ? TIFF_SHORT : TIFF_LONG);
	case SAMPLEFORMAT_VOID:
		return (TIFF_UNDEFINED);
	}
	/*NOTREACHED*/
	return (TIFF_UNDEFINED);
}
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);
}
int
copyFaxFile(TIFF* tifin, TIFF* tifout)
{
    uint32 row;
    uint32 linesize = TIFFhowmany8(xsize);
    uint16 badrun;
    int ok;

    tifin->tif_rawdatasize = TIFFGetFileSize(tifin);
    tifin->tif_rawdata = _TIFFmalloc(tifin->tif_rawdatasize);
    if (tifin->tif_rawdata == NULL) {
        TIFFError(tifin->tif_name, "Not enough memory");
        return (0);
    }
    if (!ReadOK(tifin, tifin->tif_rawdata, tifin->tif_rawdatasize)) {
        TIFFError(tifin->tif_name, "Read error at scanline 0");
        return (0);
    }
    tifin->tif_rawcp = tifin->tif_rawdata;
    tifin->tif_rawcc = tifin->tif_rawdatasize;

    (*tifin->tif_setupdecode)(tifin);
    (*tifin->tif_predecode)(tifin, (tsample_t) 0);
    tifin->tif_row = 0;
    badfaxlines = 0;
    badfaxrun = 0;

    _TIFFmemset(refbuf, 0, linesize);
    row = 0;
    badrun = 0;		/* current run of bad lines */
    while (tifin->tif_rawcc > 0) {
        ok = (*tifin->tif_decoderow)(tifin, (tdata_t) rowbuf,
                                     linesize, 0);
        if (!ok) {
            badfaxlines++;
            badrun++;
            /* regenerate line from previous good line */
            _TIFFmemcpy(rowbuf, refbuf, linesize);
        } else {
            if (badrun > badfaxrun)
                badfaxrun = badrun;
            badrun = 0;
            _TIFFmemcpy(refbuf, rowbuf, linesize);
        }
        tifin->tif_row++;

        if (TIFFWriteScanline(tifout, rowbuf, row, 0) < 0) {
            fprintf(stderr, "%s: Write error at row %ld.\n",
                    tifout->tif_name, (long) row);
            break;
        }
        row++;
        if (stretch) {
            if (TIFFWriteScanline(tifout, rowbuf, row, 0) < 0) {
                fprintf(stderr, "%s: Write error at row %ld.\n",
                        tifout->tif_name, (long) row);
                break;
            }
            row++;
        }
    }
    if (badrun > badfaxrun)
        badfaxrun = badrun;
    _TIFFfree(tifin->tif_rawdata);
    return (row);
}
Beispiel #9
0
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
    TIFF *faxTIFF = NULL;
    FIBITMAP *dib = NULL;
    FIMEMORY *memory = NULL;

    //int verbose = 0;
    int stretch = 0;
    int rows;
    float resX = 204.0;
    float resY = 196.0;

    uint32 xsize = G3_DEFAULT_WIDTH;
    int compression_in = COMPRESSION_CCITTFAX3;
    int fillorder_in = FILLORDER_LSB2MSB;
    uint32 group3options_in = 0;    // 1d-encoded
    uint32 group4options_in = 0;    // compressed
    int photometric_in = PHOTOMETRIC_MINISWHITE;

    if(handle==NULL) return NULL;

    try {
        // set default load options

        compression_in = COMPRESSION_CCITTFAX3;         // input is g3-encoded
        group3options_in &= ~GROUP3OPT_2DENCODING;      // input is 1d-encoded (g3 only)
        fillorder_in = FILLORDER_MSB2LSB;               // input has msb-to-lsb fillorder

        /*
          Original input-related fax2tiff options

          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 's':       // stretch image by dup'ng scanlines
          stretch = 1;
          break;
          case 'v':       // -v for info
          verbose++;
          break;
          }
          }

        */

        // open a temporary memory buffer to save decoded scanlines
        memory = FreeImage_OpenMemory();
        if(!memory) throw FI_MSG_ERROR_MEMORY;

        // wrap the raw fax file
        faxTIFF = TIFFClientOpen("(FakeInput)", "w",
                                 // TIFFClientOpen() fails if we don't set existing value here
                                 NULL,
                                 _g3ReadProc, _g3WriteProc,
                                 _g3SeekProc, _g3CloseProc,
                                 _g3SizeProc, _g3MapProc,
                                 _g3UnmapProc);

        if (faxTIFF == NULL) {
            throw "Can not create fake input file";
        }
        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);

        resX = 204;
        if (!stretch) {
            TIFFGetField(faxTIFF, TIFFTAG_YRESOLUTION, &resY);
        } else {
            resY = 196;
        }

        // decode the raw fax data
        rows = copyFaxFile(io, handle, faxTIFF, xsize, stretch, memory);
        if(rows <= 0) throw "Error when decoding raw fax file : check the decoder options";


        // allocate the output dib
        dib = FreeImage_Allocate(xsize, rows, 1);
        unsigned pitch = FreeImage_GetPitch(dib);
        uint32 linesize = TIFFhowmany8(xsize);

        // fill the bitmap structure ...
        // ... palette
        RGBQUAD *pal = FreeImage_GetPalette(dib);
        if(photometric_in == PHOTOMETRIC_MINISWHITE) {
            pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255;
            pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 0;
        } else {
            pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
            pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
        }
        // ... resolution
        FreeImage_SetDotsPerMeterX(dib, (unsigned)(resX/0.0254000 + 0.5));
        FreeImage_SetDotsPerMeterY(dib, (unsigned)(resY/0.0254000 + 0.5));

        // read the decoded scanline and fill the bitmap data
        FreeImage_SeekMemory(memory, 0, SEEK_SET);
        BYTE *bits = FreeImage_GetScanLine(dib, rows - 1);
        for(int k = 0; k < rows; k++) {
            FreeImage_ReadMemory(bits, linesize, 1, memory);
            bits -= pitch;
        }

        // free the TIFF wrapper
        TIFFClose(faxTIFF);

        // free the memory buffer
        FreeImage_CloseMemory(memory);

    } catch(const char *message) {
        if(memory) FreeImage_CloseMemory(memory);
        if(faxTIFF) TIFFClose(faxTIFF);
        if(dib) FreeImage_Unload(dib);
        FreeImage_OutputMessageProc(s_format_id, message);
        return NULL;
    }

    return dib;

}
Beispiel #10
0
static int
copyFaxFile(FreeImageIO *io, fi_handle handle, TIFF* tifin, uint32 xsize, int stretch, FIMEMORY *memory) {
    BYTE *rowbuf = NULL;
    BYTE *refbuf = NULL;
    uint32 row;
    uint16 badrun;
    uint16  badfaxrun;
    uint32  badfaxlines;
    int ok;

    try {

        uint32 linesize = TIFFhowmany8(xsize);
        rowbuf = (BYTE*) _TIFFmalloc(linesize);
        refbuf = (BYTE*) _TIFFmalloc(linesize);
        if (rowbuf == NULL || refbuf == NULL) {
            throw FI_MSG_ERROR_MEMORY;
        }

        tifin->tif_rawdatasize = G3GetFileSize(io, handle);
        tifin->tif_rawdata = (tidata_t) _TIFFmalloc(tifin->tif_rawdatasize);
        if (tifin->tif_rawdata == NULL) {
            throw FI_MSG_ERROR_MEMORY;
        }

        if(!G3ReadFile(io, handle, tifin->tif_rawdata, tifin->tif_rawdatasize)) {
            throw "Read error at scanline 0";
        }
        tifin->tif_rawcp = tifin->tif_rawdata;
        tifin->tif_rawcc = tifin->tif_rawdatasize;

        (*tifin->tif_setupdecode)(tifin);
        (*tifin->tif_predecode)(tifin, (uint16) 0);
        tifin->tif_row = 0;
        badfaxlines = 0;
        badfaxrun = 0;

        _TIFFmemset(refbuf, 0, linesize);
        row = 0;
        badrun = 0;     // current run of bad lines
        while (tifin->tif_rawcc > 0) {
            ok = (*tifin->tif_decoderow)(tifin, rowbuf, linesize, 0);
            if (!ok) {
                badfaxlines++;
                badrun++;
                // regenerate line from previous good line
                _TIFFmemcpy(rowbuf, refbuf, linesize);
            } else {
                if (badrun > badfaxrun)
                    badfaxrun = badrun;
                badrun = 0;
                _TIFFmemcpy(refbuf, rowbuf, linesize);
            }
            tifin->tif_row++;

            FreeImage_WriteMemory(rowbuf, linesize, 1, memory);
            row++;
            if (stretch) {
                FreeImage_WriteMemory(rowbuf, linesize, 1, memory);
                row++;
            }
        }
        if (badrun > badfaxrun)
            badfaxrun = badrun;

        _TIFFfree(tifin->tif_rawdata);
        tifin->tif_rawdata = NULL;

        _TIFFfree(rowbuf);
        _TIFFfree(refbuf);

        /*
          if (verbose) {
          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);
          }
        */

    } catch(const char *message) {
        if(rowbuf) _TIFFfree(rowbuf);
        if(refbuf) _TIFFfree(refbuf);
        if(tifin->tif_rawdata) {
            _TIFFfree(tifin->tif_rawdata);
            tifin->tif_rawdata = NULL;
        }
        FreeImage_OutputMessageProc(s_format_id, message);

        return -1;
    }

    return (row);
}
Beispiel #11
0
/*
 * Compute the # bytes in a variable height, row-aligned strip.
 */
tsize_t
TIFFVStripSize(TIFF* tif, uint32 nrows)
{
	TIFFDirectory *td = &tif->tif_dir;
	uint32 stripsize;

	if (nrows == (uint32) -1)
		nrows = td->td_imagelength;
	if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
	    td->td_photometric == PHOTOMETRIC_YCBCR &&
	    !isUpSampled(tif)) {
		/*
		 * Packed YCbCr data contain one Cb+Cr for every
		 * HorizontalSampling*VerticalSampling Y values.
		 * Must also roundup width and height when calculating
		 * since images that are not a multiple of the
		 * horizontal/vertical subsampling area include
		 * YCbCr data for the extended image.
		 */
		uint16 ycbcrsubsampling[2];
		uint32 w, scanline, samplingarea;

		TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING,
				      ycbcrsubsampling + 0,
				      ycbcrsubsampling + 1);

		samplingarea = ycbcrsubsampling[0]*ycbcrsubsampling[1];
		if (samplingarea == 0) {
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
				     "Invalid YCbCr subsampling");
			return 0;
		}

		w = TIFFroundup(td->td_imagewidth, ycbcrsubsampling[0]);
		scanline = TIFFhowmany8(multiply(tif, w, td->td_bitspersample,
						 "TIFFVStripSize"));
		nrows = TIFFroundup(nrows, ycbcrsubsampling[1]);
		/* NB: don't need TIFFhowmany here 'cuz everything is rounded */
		scanline = multiply(tif, nrows, scanline, "TIFFVStripSize");
		/* a zero anywhere in here means overflow, must return zero */
		if (scanline > 0) {
			uint32 extra =
			    multiply(tif, 2, scanline / samplingarea,
				     "TIFFVStripSize");
			if (extra > 0)
				stripsize = summarize(tif, scanline, extra,
						      "TIFFVStripSize");
			else
				stripsize = 0;
		} else
			stripsize = 0;
	} else
		stripsize = multiply(tif, nrows, TIFFScanlineSize(tif),
				     "TIFFVStripSize");
	/* Because tsize_t is signed, we might have conversion overflow */
	if (((tsize_t) stripsize) < 0) {
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", "TIFFVStripSize");
		stripsize = 0;
	}
	return (tsize_t) stripsize;
}