File fax2pdf.cc of Package fax2pdf

// -*- mode: c++ -*-

//**********************************************************************
//
// Copyright (c) 2000 by Peter Stamfest <peter@stamfest.at>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//**********************************************************************

static char *cvsid = "@(#)$Id: fax2pdf.cc,v 1.3 2002/06/18 04:26:35 stamfest Exp $";
static short int ___n = cvsid - (char*)___n;	// avoid a warning for
						// unused cvsid

#include <iostream>
#include <fstream>
#include <unistd.h>
#include <tiffio.h>
#include "pdf.h"

#define DIRECT

static  void putContig(TIFFRGBAImage*, uint32*,
		       uint32, uint32, uint32, uint32, int32, int32, 
		       unsigned char*);

static unsigned char * storage = 0;
long wbytes;

typedef unsigned long uint32;
typedef long int32;
typedef unsigned char  u_char;

u_char *process(long w, long h, float xr, float yr, uint32 *raster, page *p)
{
 
    //    long wbytes = w / 8 + (((w % 8) > 0) ? 1 : 0);
#ifndef DIRECT   
    int i, j;
    char c;
    int n = 8;
    unsigned char *b;

    for (j = 0 ; j < h ; j++) {
	unsigned char *b = storage + (j * wbytes);
	uint32 *org = raster + (j * w);
	for (i = 0 ; i < w ; i++) {
	    c |= (TIFFGetR(*org++) & 1) << --n;
	    if (n) continue;
	    *b++ = c;
	    n = 8; 
	    c = 0;
	}
    }
    if (n < 8) {
	*b++ = c;
    }
#endif

    // find suitable transformations, in order to show the entire page

    double wanted_w = 72 * w / xr;
    double wanted_h = 72 * h / yr;

    int max_w = p->mediax - 2 * p->cutx;
    int max_h = p->mediay - 2 * p->cuty;

    double fac_w = (double) wanted_w / max_w;
    double fac_h = (double) wanted_h / max_h;

    double factor;
    double actual_w = wanted_w;
    double actual_h = wanted_h;

    if (fac_w > 1.0 || fac_h > 1.0) {
	factor = fac_w > fac_h ? fac_w : fac_h;
	
	actual_w /= factor;
	actual_h /= factor;
    }

    // calculate extra border due to scaling

    int extra_w = (max_w - int(actual_w)) / 2;
    int extra_h = (max_h - int(actual_h)) / 2;

    image *pdfimg = new image(w,h,1,
			      p->cutx + extra_w, 
			      p->mediay - p->cuty - extra_h,
			      actual_w, -actual_h,
			      storage,
			      wbytes * h);
    p->addmark(pdfimg);
    //    cerr << "addmark" << endl;

    if (pdfimg->copied) 
	return storage;
    
    return 0;
}

void usage(char *name, int rc)
{
    cerr << name << ": usage\n"
	 << name << " <input.tif> [<output.pdf>]" << endl;
    exit(rc);
}

main(int argc, char* argv[])
{
    // prepared for commandline options
    ostream *os = 0;
    int c;
    while ((c = getopt(argc, argv, "?")) != -1) {
	switch(c) {
	default: break;
	}
    }    

    if (argc == 1 || argc > 3) usage(argv[0], 1);
    
    if (argc == 3) {
	os = new ofstream(argv[2]);
    } else {
	os = &cout;
    }

    document *d = new document;

    target o(*os);

    d->head(o);

    time_t t;
    time(&t);
    struct tm *tmp = localtime(&t);

    char buf[200];
    strftime(buf, sizeof(buf), "(D:%Y%m%d%H%M%S)", tmp);

    d->theinfo.addinfo("/Producer",
		      "(fax2pdf - (c) 2000 by Peter Stamfest <peter@stamfest.at>)");
    d->theinfo.addinfo("/CreationDate",buf);


    TIFF* tif = TIFFOpen(argv[1], "r");
    if (tif) {
	int dircount = 0;   
	uint32 w, h;
	float xr,yr;
	size_t npixels;
	uint32* raster;

	do {
	    page *p = new page();
	    d->addpage(p);

	    dircount++;
	    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
	    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
	    TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xr);
	    TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yr);

	    npixels = w * h;
	    raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
	    wbytes = w / 8 + (((w % 8) > 0) ? 1 : 0);
	    storage = new unsigned char[wbytes * h];
		
	    // PDF uses byte aligned images
	    
	    TIFFRGBAImage img;
	    char emsg[1024] = "error: processing image";

//  	    cerr << " w=" << w
//  		 << " h=" << h
//  		 << " N=" << npixels 
//  		 << " xr=" << xr 
//  		 << " yr=" << yr 
//  		 << endl;

	    if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
		size_t npixels;

		static  tileContigRoutine   old_putContig;
		//		static  tileSeparateRoutine old_putSeparate;

		/*
		 * Override default ``put routine'' with private
		 * routine that also draws the raster on the display.
		 */
		if (img.put.any == 0) {
		    TIFFError(argv[1],
			      "No \"put\" routine; must not handle"
			      " image format");
		    exit(1);
		}
#ifdef DIRECT   
		if (img.isContig) {
		    old_putContig = img.put.contig;
		    img.put.contig = putContig;
		} else {
		    cerr << "Cannot handle this image format (don't have the put method it needs" << endl;
		}
#endif
		npixels = img.width * img.height;
		wbytes =  img.width / 8 + (((img.width % 8) > 0) ? 1 : 0);
		
		//		unsigned char *bw = storage;
				
		if (raster != NULL) {
		    if (TIFFRGBAImageGet(&img, raster, 
					 img.width, img.height)) {

			unsigned char *c = process(img.width, img.height, 
						   xr, yr, raster, p);
			if (c) delete [] storage;
		    }
		}
		TIFFRGBAImageEnd(&img);
		if (raster) _TIFFfree(raster);
	    } else
		TIFFError(argv[1], emsg);
	    p->done(o, d->thepages);
	    //	    cerr << "objcnt="  << ((obj*)0)->getnrofobj() << endl;
	} 
	while (TIFFReadDirectory(tif));

	TIFFClose(tif);

	d->out(o);
	delete d;
    } else {
	usage(argv[0], 2);
    }
    if (os != &cout) delete os;
    exit(0);
}


static void putContig(TIFFRGBAImage* img, 
		      uint32* cp, 
		      uint32 x, uint32 y, 
		      uint32 w, uint32 h, 
		      int32 fromskew, int32 toskew, 
		      u_char* pp)
{
    uint32 i, j, ww = w / 8; //, wr = w % 8;
    fromskew /= 8;
    u_char *b;

    for (j = 0 ; j < h ; j++) {
	b = storage + (y-j) * wbytes + x / 8;
	for (i = 0 ; i < ww ; i++) {
	    *b++ = ~(*pp++);
	}
	pp += fromskew;
    }
}
openSUSE Build Service is sponsored by