HylaFAX The world's most advanced open source fax server

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: multi-image tiff -> PDF?



On Sat, 26 Dec 1998, Darrell Berry wrote:

> i've found a package called tifflib, which generates higher quality, and
> much faster-rendering (tho larger) PostScript from TIFFs...its located
> at
> 
> http://kubax9.kub.nl:2080/Decomate-1.0/tiff-v3.4-tar.gz
> 
> and its rather cool (worth a look!)
> 
> and GhostView 5.50 has a nice ps2pdf filter...chaining the two together
> generates very high quality PDF fax images...
> 
> --
> 
> the only problem (and one shared with fax2ps), is that partial pages are
> 'bottom-justified' on the page, which will no doubt look a little odd to
> our users, who are used to fax machines 'top-justifying' partiial pages
> (ie cover pages etc which take up less than a full A4 image appear at
> the top of the page, not the bottom, as they do with both fax2ps and
> tiff2ps)...
> 
> do you have any clue as to hacking the image or ps output to change
> this?

I posted a patch for tiff2ps (also part of the tiff package) which fixes
this some time ago.  I've attached it again to this message.
It requires you to specify the page size with -h and -w, and also
compresses long faxes vertically rather than cutting them off as it did
previously.
Let me know if it helps.

~ John Williams
--- tiff2ps.c	1998/09/29 15:42:13	1.1
+++ tiff2ps.c	1998/10/08 16:56:50
@@ -56,9 +56,9 @@
 int	ascii85breaklen;
 
 int	TIFF2PS(FILE*, TIFF*, float, float);
-void	PSpage(FILE*, TIFF*, uint32, uint32);
-void	PSColorContigPreamble(FILE*, uint32, uint32, int);
-void	PSColorSeparatePreamble(FILE*, uint32, uint32, int);
+void	PSpage(FILE*, TIFF*, uint32, uint32, uint32);
+void	PSColorContigPreamble(FILE*, uint32, uint32, uint32, int);
+void	PSColorSeparatePreamble(FILE*, uint32, uint32, uint32, int);
 void	PSDataColorContig(FILE*, TIFF*, uint32, uint32, int);
 void	PSDataColorSeparate(FILE*, TIFF*, uint32, uint32, int);
 void	PSDataPalette(FILE*, TIFF*, uint32, uint32);
@@ -71,6 +71,8 @@
 void 	PSTail(FILE*, int);
 
 static	void usage(int);
+#define MIN(a,b)	((a)<(b)?(a):(b))
+#define MAX(a,b)	((a)>(b)?(a):(b))
 
 int
 main(int argc, char* argv[])
@@ -263,10 +265,10 @@
 }
 
 static void
-setupPageState(TIFF* tif, uint32* pw, uint32* ph, float* pprw, float* pprh)
+setupPageState(TIFF* tif, uint32* pw, uint32* ph, float* pprw, float* pprh, float *xres, float *yres)
 {
 	uint16 res_unit;
-	float xres, yres;
+	/*float xres, yres;*/
 
 	TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, pw);
 	TIFFGetField(tif, TIFFTAG_IMAGELENGTH, ph);
@@ -274,20 +276,20 @@
 	/*
 	 * Calculate printable area.
 	 */
-	if (!TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres))
-		xres = PS_UNIT_SIZE;
-	if (!TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres))
-		yres = PS_UNIT_SIZE;
+	if (!TIFFGetField(tif, TIFFTAG_XRESOLUTION, xres))
+		*xres = PS_UNIT_SIZE;
+	if (!TIFFGetField(tif, TIFFTAG_YRESOLUTION, yres))
+		*yres = PS_UNIT_SIZE;
 	switch (res_unit) {
 	case RESUNIT_CENTIMETER:
-		xres /= 2.54, yres /= 2.54;
+		*xres /= 2.54, *yres /= 2.54;
 		break;
 	case RESUNIT_NONE:
-		xres *= PS_UNIT_SIZE, yres *= PS_UNIT_SIZE;
+		*xres *= PS_UNIT_SIZE, *yres *= PS_UNIT_SIZE;
 		break;
 	}
-	*pprh = PSUNITS(*ph, yres);
-	*pprw = PSUNITS(*pw, xres);
+	*pprh = PSUNITS(*ph, *yres);
+	*pprw = PSUNITS(*pw, *xres);
 }
 
 static int
@@ -317,18 +319,19 @@
 	uint32 subfiletype;
 	uint16* sampleinfo;
 	static int npages = 0;
+	float xres,yres;
 
 	if (!TIFFGetField(tif, TIFFTAG_XPOSITION, &ox))
 		ox = 0;
 	if (!TIFFGetField(tif, TIFFTAG_YPOSITION, &oy))
 		oy = 0;
-	setupPageState(tif, &w, &h, &prw, &prh);
+	setupPageState(tif, &w, &h, &prw, &prh, &xres, &yres);
 
 	do {
 	        tf_numberstrips = TIFFNumberOfStrips(tif);
 		TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP,
 		    &tf_rowsperstrip);
-		setupPageState(tif, &w, &h, &prw, &prh);
+		setupPageState(tif, &w, &h, &prw, &prh, &xres, &yres);
 		if (!npages)
 		        PSHead(fd, tif, w, h, prw, prh, ox, oy);
 		tf_bytesperrow = TIFFScanlineSize(tif);
@@ -361,12 +364,22 @@
 			fprintf(fd, "%%%%Page: %d %d\n", npages, npages);
 			fprintf(fd, "gsave\n");
 			fprintf(fd, "100 dict begin\n");
-			if (pw != 0 && ph != 0)
-				fprintf(fd, "%f %f scale\n",
-				    pw*PS_UNIT_SIZE, ph*PS_UNIT_SIZE);
-			else
+			if (pw != 0 && ph != 0) {
+				if (ph*PS_UNIT_SIZE < prh) {
+					fprintf(fd, "%f %f scale\n",
+					    MIN(pw*PS_UNIT_SIZE,prw), 
+					    ph*PS_UNIT_SIZE );
+					PSpage(fd, tif, w, h, h);
+				} else {
+					fprintf(fd, "%f %f scale\n",
+					    MIN(pw*PS_UNIT_SIZE,prw),
+					    prh );
+					PSpage(fd, tif, w, h, (unsigned long)(ph*yres));
+				}
+			} else {
 				fprintf(fd, "%f %f scale\n", prw, prh);
-			PSpage(fd, tif, w, h);
+				PSpage(fd, tif, w, h, h);
+			}
 			fprintf(fd, "end\n");
 			fprintf(fd, "grestore\n");
 			fprintf(fd, "showpage\n");
@@ -901,7 +914,7 @@
 }
 
 void
-PSpage(FILE* fd, TIFF* tif, uint32 w, uint32 h)
+PSpage(FILE* fd, TIFF* tif, uint32 w, uint32 h, uint32 ph)
 {
 	if (level2 && PS_Lvl2page(fd, tif, w, h))
 		return;
@@ -910,20 +923,20 @@
 	case PHOTOMETRIC_RGB:
 		if (planarconfiguration == PLANARCONFIG_CONTIG) {
 			fprintf(fd, "%s", RGBcolorimage);
-			PSColorContigPreamble(fd, w, h, 3);
+			PSColorContigPreamble(fd, w, h, ph, 3);
 			PSDataColorContig(fd, tif, w, h, 3);
 		} else {
-			PSColorSeparatePreamble(fd, w, h, 3);
+			PSColorSeparatePreamble(fd, w, h, ph, 3);
 			PSDataColorSeparate(fd, tif, w, h, 3);
 		}
 		break;
 	case PHOTOMETRIC_SEPARATED:
 		/* XXX should emit CMYKcolorimage */
 		if (planarconfiguration == PLANARCONFIG_CONTIG) {
-			PSColorContigPreamble(fd, w, h, 4);
+			PSColorContigPreamble(fd, w, h, ph, 4);
 			PSDataColorContig(fd, tif, w, h, 4);
 		} else {
-			PSColorSeparatePreamble(fd, w, h, 4);
+			PSColorSeparatePreamble(fd, w, h, ph, 4);
 			PSDataColorSeparate(fd, tif, w, h, 4);
 		}
 		break;
@@ -935,7 +948,7 @@
 		fprintf(fd, "%lu %lu 8\n",
 		    (unsigned long) w, (unsigned long) h);
 		fprintf(fd, "[%lu 0 0 -%lu 0 %lu]\n",
-		    (unsigned long) w, (unsigned long) h, (unsigned long) h);
+		    (unsigned long) w, (unsigned long) h, (unsigned long) ph);
 		fprintf(fd, "{currentfile scanLine readhexstring pop} bind\n");
 		fprintf(fd, "false 3 colorimage\n");
 		PSDataPalette(fd, tif, w, h);
@@ -948,7 +961,7 @@
 		fprintf(fd, "%lu %lu %d\n",
 		    (unsigned long) w, (unsigned long) h, bitspersample);
 		fprintf(fd, "[%lu 0 0 -%lu 0 %lu]\n",
-		    (unsigned long) w, (unsigned long) h, (unsigned long) h);
+		    (unsigned long) w, (unsigned long) h, (unsigned long) ph);
 		fprintf(fd,
 		    "{currentfile scanLine readhexstring pop} bind\n");
 		fprintf(fd, "image\n");
@@ -959,7 +972,7 @@
 }
 
 void
-PSColorContigPreamble(FILE* fd, uint32 w, uint32 h, int nc)
+PSColorContigPreamble(FILE* fd, uint32 w, uint32 h, uint32 ph, int nc)
 {
 	ps_bytesperrow = nc * (tf_bytesperrow / samplesperpixel);
 	PhotoshopBanner(fd, w, h, 1, nc, "false %d colorimage");
@@ -967,13 +980,13 @@
 	fprintf(fd, "%lu %lu %d\n",
 	    (unsigned long) w, (unsigned long) h, bitspersample);
 	fprintf(fd, "[%lu 0 0 -%lu 0 %lu]\n",
-	    (unsigned long) w, (unsigned long) h, (unsigned long) h);
+	    (unsigned long) w, (unsigned long) h, (unsigned long) ph);
 	fprintf(fd, "{currentfile line readhexstring pop} bind\n");
 	fprintf(fd, "false %d colorimage\n", nc);
 }
 
 void
-PSColorSeparatePreamble(FILE* fd, uint32 w, uint32 h, int nc)
+PSColorSeparatePreamble(FILE* fd, uint32 w, uint32 h, uint32 ph, int nc)
 {
 	int i;
 
@@ -984,7 +997,7 @@
 	fprintf(fd, "%lu %lu %d\n",
 	    (unsigned long) w, (unsigned long) h, bitspersample);
 	fprintf(fd, "[%lu 0 0 -%lu 0 %lu] \n",
-	    (unsigned long) w, (unsigned long) h, (unsigned long) h);
+	    (unsigned long) w, (unsigned long) h, (unsigned long) ph);
 	for (i = 0; i < nc; i++)
 		fprintf(fd, "{currentfile line%d readhexstring pop}bind\n", i);
 	fprintf(fd, "true %d colorimage\n", nc);
From: David Woolley <david@djwhome.demon.co.uk>
Subject: Re: flexfax: multi-image TIFF -> PDF?
To: darrellb@hhcl.com (Darrell Berry)
Date: Mon, 28 Dec 1998 19:14:02 +0000 (GMT)
Cc: flexfax@sgi.com
Reply-To: flexfax@sgi.com
X-Mailer: ELM [version 2.4 PL25]
Sender: owner-flexfax@celestial.com

> does anyone know if a linux-friendly command line tiff2pdf convertor,
> which will sensibly make each image in a multi-image TIFF into a
> separate page in the PDF file?

A general TIFF to PDF convertor would be easy if you didn't mind about
compression, but might be a lot of work if you did want appropriate
compression.  However, you don't actually want a TIFF to PDF convertor;
you want a G3 FAX (wrapped in TIFF) to PDF convertor.  As PDF supports
G3 FAX as a native format, this should almost amount to an exercise in
wrapping the image of each page in an appropriate dictionary.

Things that make it not that simple are that it is possible that the
G3 options in the received file may not be amongst those supported by
Postscript/PDF, so you may have to run a G3 to G3 conversion (tiffcp
might do this) and that you need to construct a page tree.  None of
these should take you more than a few man days, given a copy of the PDF
specification from the Adobe web site.  There is, however, slightly more
work than I'm prepared to do without a real, personal/business, need.

(As far as I can tell, some versions of fax2ps use a roundabout method
of creating a bit map font, rather than directly storing the image.
My guess is that this is done because it renders faster on some printers,
but might also have been done for compatibility with very old versions
of Postscript.  However, it does mean that any route through ps2pdf is
likely to produce excessively large PDF files.




Project hosted by iFAX Solutions