1
/* $Id: fax2ps.c,v 1.22 2006/04/20 12:36:23 dron Exp $" */
4
* Copyright (c) 1991-1997 Sam Leffler
5
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
7
* Permission to use, copy, modify, distribute, and sell this software and
8
* its documentation for any purpose is hereby granted without fee, provided
9
* that (i) the above copyright notices and this permission notice appear in
10
* all copies of the software and related documentation, and (ii) the names of
11
* Sam Leffler and Silicon Graphics may not be used in any advertising or
12
* publicity relating to the software without the specific, prior written
13
* permission of Sam Leffler and Silicon Graphics.
15
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
19
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
26
#include "tif_config.h"
48
float defxres = 204.; /* default x resolution (pixels/inch) */
49
float defyres = 98.; /* default y resolution (lines/inch) */
50
const float half = 0.5;
51
const float points = 72.0;
52
float pageWidth = 0; /* image page width (inches) */
53
float pageHeight = 0; /* image page length (inches) */
54
int scaleToPage = 0; /* if true, scale raster to page dimensions */
55
int totalPages = 0; /* total # pages printed */
56
int row; /* current output row */
57
int maxline = 512; /* max output line of PostScript */
60
* Turn a bit-mapped scanline into the appropriate sequence
61
* of PostScript characters to be rendered.
63
* Original version written by Bret D. Whissel,
64
* Florida State University Meteorology Department
68
printruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx)
74
{ 'd', 'n', 512 }, { 'e', 'o', 256 }, { 'f', 'p', 128 },
75
{ 'g', 'q', 64 }, { 'h', 'r', 32 }, { 'i', 's', 16 },
76
{ 'j', 't', 8 }, { 'k', 'u', 4 }, { 'l', 'v', 2 },
80
" !\"#$&'*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abc";
81
int colormode = 1; /* 0 for white, 1 for black */
88
printf("%d m(", row++);
93
if (x+runlength > lastx)
94
runlength = runs[-1] = lastx-x;
96
if (!colormode && runs == erun)
97
break; /* don't bother printing the final white run */
100
* If a runlength is greater than 6 pixels, then spit out
101
* black or white characters until the runlength drops to
102
* 6 or less. Once a runlength is <= 6, then combine black
103
* and white runlengths until a 6-pixel pattern is obtained.
104
* Then write out the special character. Six-pixel patterns
105
* were selected since 64 patterns is the largest power of
106
* two less than the 92 "easily printable" PostScript
107
* characters (i.e., no escape codes or octal chars).
110
while (runlength > 6) { /* Run is greater than six... */
111
if (runlength >= WBarr[l].width) {
116
putchar(colormode ? WBarr[l].black : WBarr[l].white), n--;
117
runlength -= WBarr[l].width;
121
while (runlength > 0 && runlength <= 6) {
125
if (runlength <= bitsleft) {
127
t |= ((1 << runlength)-1) << (bitsleft-runlength);
128
bitsleft -= runlength;
135
if (x+runlength > lastx)
136
runlength = runs[-1] = lastx-x;
139
} else { /* runlength exceeds bits left */
141
t |= ((1 << bitsleft)-1);
142
runlength -= bitsleft;
150
putchar(svalue[t]), n--;
157
* Create a special PostScript font for printing FAX documents. By taking
158
* advantage of the font-cacheing mechanism, a substantial speed-up in
159
* rendering time is realized.
164
static const char* fontPrologue[] = {
165
"/newfont 10 dict def newfont begin /FontType 3 def /FontMatrix [1",
166
"0 0 1 0 0] def /FontBBox [0 0 512 1] def /Encoding 256 array def",
167
"0 1 31{Encoding exch /255 put}for 120 1 255{Encoding exch /255",
168
"put}for Encoding 37 /255 put Encoding 40 /255 put Encoding 41 /255",
169
"put Encoding 92 /255 put /count 0 def /ls{Encoding exch count 3",
170
"string cvs cvn put /count count 1 add def}def 32 1 36{ls}for",
171
"38 1 39{ls}for 42 1 91{ls}for 93 1 99{ls}for /count 100",
172
"def 100 1 119{ls}for /CharDict 5 dict def CharDict begin /white",
173
"{dup 255 eq{pop}{1 dict begin 100 sub neg 512 exch bitshift",
174
"/cw exch def cw 0 0 0 cw 1 setcachedevice end}ifelse}def /black",
175
"{dup 255 eq{pop}{1 dict begin 110 sub neg 512 exch bitshift",
176
"/cw exch def cw 0 0 0 cw 1 setcachedevice 0 0 moveto cw 0 rlineto",
177
"0 1 rlineto cw neg 0 rlineto closepath fill end}ifelse}def /numbuild",
178
"{dup 255 eq{pop}{6 0 0 0 6 1 setcachedevice 0 1 5{0 moveto",
179
"dup 32 and 32 eq{1 0 rlineto 0 1 rlineto -1 0 rlineto closepath",
180
"fill newpath}if 1 bitshift}for pop}ifelse}def /.notdef {}",
181
"def /255 {}def end /BuildChar{exch begin dup 110 ge{Encoding",
182
"exch get 3 string cvs cvi CharDict /black get}{dup 100 ge {Encoding",
183
"exch get 3 string cvs cvi CharDict /white get}{Encoding exch get",
184
"3 string cvs cvi CharDict /numbuild get}ifelse}ifelse exec end",
185
"}def end /Bitfont newfont definefont 1 scalefont setfont",
189
for (i = 0; fontPrologue[i] != NULL; i++)
190
fprintf(fd, "%s\n", fontPrologue[i]);
194
printTIF(TIFF* tif, uint16 pageNumber)
197
uint16 unit, compression;
198
float xres, yres, scale = 1.0;
200
time_t creation_time;
202
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
203
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
204
if (!TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression)
205
|| compression < COMPRESSION_CCITTRLE
206
|| compression > COMPRESSION_CCITT_T6)
208
if (!TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres) || !xres) {
209
TIFFWarning(TIFFFileName(tif),
210
"No x-resolution, assuming %g dpi", defxres);
213
if (!TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres) || !yres) {
214
TIFFWarning(TIFFFileName(tif),
215
"No y-resolution, assuming %g lpi", defyres);
216
yres = defyres; /* XXX */
218
if (TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &unit) &&
219
unit == RESUNIT_CENTIMETER) {
224
pageWidth = w / xres;
226
pageHeight = h / yres;
228
printf("%%!PS-Adobe-3.0\n");
229
printf("%%%%Creator: fax2ps\n");
231
printf("%%%%Title: %s\n", file);
233
creation_time = time(0);
234
printf("%%%%CreationDate: %s", ctime(&creation_time));
235
printf("%%%%Origin: 0 0\n");
236
printf("%%%%BoundingBox: 0 0 %u %u\n",
237
(int)(pageWidth * points), (int)(pageHeight * points)); /* XXX */
238
printf("%%%%Pages: (atend)\n");
239
printf("%%%%EndComments\n");
240
printf("%%%%BeginProlog\n");
242
printf("/d{bind def}def\n"); /* bind and def proc */
243
printf("/m{0 exch moveto}d\n");
244
printf("/s{show}d\n");
245
printf("/p{showpage}d \n"); /* end page */
246
printf("%%%%EndProlog\n");
247
printf("%%%%Page: \"%u\" %u\n", pageNumber, pageNumber);
248
printf("/$pageTop save def gsave\n");
250
scale = pageHeight / (h/yres) < pageWidth / (w/xres) ?
251
pageHeight / (h/yres) : pageWidth / (w/xres);
252
printf("%g %g translate\n",
253
points * (pageWidth - scale*w/xres) * half,
254
points * (scale*h/yres + (pageHeight - scale*h/yres) * half));
255
printf("%g %g scale\n", points/xres*scale, -points/yres*scale);
256
printf("0 setgray\n");
257
TIFFSetField(tif, TIFFTAG_FAXFILLFUNC, printruns);
258
ns = TIFFNumberOfStrips(tif);
260
for (s = 0; s < ns; s++)
261
(void) TIFFReadEncodedStrip(tif, s, (tdata_t) NULL, (tsize_t) -1);
263
printf("grestore $pageTop restore\n");
267
#define GetPageNumber(tif) \
268
TIFFGetField(tif, TIFFTAG_PAGENUMBER, &pn, &ptotal)
271
findPage(TIFF* tif, uint16 pageNumber)
273
uint16 pn = (uint16) -1;
274
uint16 ptotal = (uint16) -1;
275
if (GetPageNumber(tif)) {
276
while (pn != pageNumber && TIFFReadDirectory(tif) && GetPageNumber(tif))
278
return (pn == pageNumber);
280
return (TIFFSetDirectory(tif, (tdir_t)(pageNumber-1)));
284
fax2ps(TIFF* tif, uint16 npages, uint16* pages, char* filename)
290
if (!GetPageNumber(tif))
291
fprintf(stderr, "%s: No page numbers, counting directories.\n",
293
for (i = 0; i < npages; i++) {
294
if (findPage(tif, pages[i]))
295
printTIF(tif, pages[i]);
297
fprintf(stderr, "%s: No page number %d\n", filename, pages[i]);
300
uint16 pageNumber = 0;
302
printTIF(tif, pageNumber++);
303
while (TIFFReadDirectory(tif));
310
pcompar(const void* va, const void* vb)
312
const int* pa = (const int*) va;
313
const int* pb = (const int*) vb;
317
static void usage(int code);
320
main(int argc, char** argv)
324
uint16 *pages = NULL, npages = 0, pageNumber;
325
int c, dowarnings = 0; /* if 1, enable library warnings */
328
while ((c = getopt(argc, argv, "l:p:x:y:W:H:wS")) != -1)
330
case 'H': /* page height */
331
pageHeight = (float)atof(optarg);
333
case 'S': /* scale to page */
336
case 'W': /* page width */
337
pageWidth = (float)atof(optarg);
339
case 'p': /* print specific page */
340
pageNumber = (uint16)atoi(optarg);
342
pages = (uint16*) realloc(pages, (npages+1)*sizeof(uint16));
344
pages = (uint16*) malloc(sizeof(uint16));
345
pages[npages++] = pageNumber;
351
defxres = (float)atof(optarg);
354
defyres = (float)atof(optarg);
357
maxline = atoi(optarg);
363
qsort(pages, npages, sizeof(uint16), pcompar);
365
TIFFSetWarningHandler(0);
368
tif = TIFFOpen(argv[optind], "r");
370
fax2ps(tif, npages, pages, argv[optind]);
373
fprintf(stderr, "%s: Can not open, or not a TIFF file.\n",
375
} while (++optind < argc);
383
fprintf(stderr, "Could not create temporary file, exiting.\n");
387
#if defined(HAVE_SETMODE) && defined(O_BINARY)
388
setmode(fileno(stdin), O_BINARY);
390
while ((n = read(fileno(stdin), buf, sizeof (buf))) > 0)
391
write(fileno(fd), buf, n);
392
lseek(fileno(fd), 0, SEEK_SET);
393
#if defined(_WIN32) && defined(USE_WIN32_FILEIO)
394
tif = TIFFFdOpen(_get_osfhandle(fileno(fd)), "temp", "r");
396
tif = TIFFFdOpen(fileno(fd), "temp", "r");
399
fax2ps(tif, npages, pages, "<stdin>");
402
fprintf(stderr, "Can not open, or not a TIFF file.\n");
405
printf("%%%%Trailer\n");
406
printf("%%%%Pages: %u\n", totalPages);
413
"usage: fax2ps [options] [input.tif ...]",
414
"where options are:",
415
" -w suppress warning messages",
416
" -l chars set maximum output line length for generated PostScript",
417
" -p page# select page to print (can use multiple times)",
418
" -x xres set default horizontal resolution of input data (dpi)",
419
" -y yres set default vertical resolution of input data (lpi)",
420
" -S scale output to page size",
421
" -W width set output page width (inches), default is 8.5",
422
" -H height set output page height (inches), default is 11",
433
fprintf(stderr, "%s\n\n", TIFFGetVersion());
434
for (i = 0; stuff[i] != NULL; i++)
435
fprintf(stderr, "%s\n", stuff[i]);
439
/* vim: set ts=8 sts=8 sw=8 noet: */