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;
}
}