]>
Commit | Line | Data |
---|---|---|
1 | /* $Id$ */ | |
2 | ||
3 | /* | |
4 | * Copyright (c) 1988-1997 Sam Leffler | |
5 | * Copyright (c) 1991-1997 Silicon Graphics, Inc. | |
6 | * | |
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. | |
14 | * | |
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. | |
18 | * | |
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 | |
24 | * OF THIS SOFTWARE. | |
25 | */ | |
26 | ||
27 | #include "tif_config.h" | |
28 | ||
29 | #include <stdio.h> | |
30 | #include <stdlib.h> /* for atof */ | |
31 | #include <math.h> | |
32 | #include <time.h> | |
33 | #include <string.h> | |
34 | ||
35 | #ifdef HAVE_UNISTD_H | |
36 | # include <unistd.h> | |
37 | #endif | |
38 | ||
39 | #include "tiffio.h" | |
40 | ||
41 | /* | |
42 | * Revision history | |
43 | * | |
44 | * 2001-Mar-21 | |
45 | * I (Bruce A. Mallett) added this revision history comment ;) | |
46 | * | |
47 | * Fixed PS_Lvl2page() code which outputs non-ASCII85 raw | |
48 | * data. Moved test for when to output a line break to | |
49 | * *after* the output of a character. This just serves | |
50 | * to fix an eye-nuisance where the first line of raw | |
51 | * data was one character shorter than subsequent lines. | |
52 | * | |
53 | * Added an experimental ASCII85 encoder which can be used | |
54 | * only when there is a single buffer of bytes to be encoded. | |
55 | * This version is much faster at encoding a straight-line | |
56 | * buffer of data because it can avoid alot of the loop | |
57 | * overhead of the byte-by-bye version. To use this version | |
58 | * you need to define EXP_ASCII85ENCODER (experimental ...). | |
59 | * | |
60 | * Added bug fix given by Michael Schmidt to PS_Lvl2page() | |
61 | * in which an end-of-data marker ('>') was not being output | |
62 | * when producing non-ASCII85 encoded PostScript Level 2 | |
63 | * data. | |
64 | * | |
65 | * Fixed PS_Lvl2colorspace() so that it no longer assumes that | |
66 | * a TIFF having more than 2 planes is a CMYK. This routine | |
67 | * no longer looks at the samples per pixel but instead looks | |
68 | * at the "photometric" value. This change allows support of | |
69 | * CMYK TIFFs. | |
70 | * | |
71 | * Modified the PostScript L2 imaging loop so as to test if | |
72 | * the input stream is still open before attempting to do a | |
73 | * flushfile on it. This was done because some RIPs close | |
74 | * the stream after doing the image operation. | |
75 | * | |
76 | * Got rid of the realloc() being done inside a loop in the | |
77 | * PSRawDataBW() routine. The code now walks through the | |
78 | * byte-size array outside the loop to determine the largest | |
79 | * size memory block that will be needed. | |
80 | * | |
81 | * Added "-m" switch to ask tiff2ps to, where possible, use the | |
82 | * "imagemask" operator instead of the "image" operator. | |
83 | * | |
84 | * Added the "-i #" switch to allow interpolation to be disabled. | |
85 | * | |
86 | * Unrolled a loop or two to improve performance. | |
87 | */ | |
88 | ||
89 | /* | |
90 | * Define EXP_ASCII85ENCODER if you want to use an experimental | |
91 | * version of the ASCII85 encoding routine. The advantage of | |
92 | * using this routine is that tiff2ps will convert to ASCII85 | |
93 | * encoding at between 3 and 4 times the speed as compared to | |
94 | * using the old (non-experimental) encoder. The disadvantage | |
95 | * is that you will be using a new (and unproven) encoding | |
96 | * routine. So user beware, you have been warned! | |
97 | */ | |
98 | ||
99 | #define EXP_ASCII85ENCODER | |
100 | ||
101 | /* | |
102 | * NB: this code assumes uint32 works with printf's %l[ud]. | |
103 | */ | |
104 | #ifndef TRUE | |
105 | #define TRUE 1 | |
106 | #define FALSE 0 | |
107 | #endif | |
108 | ||
109 | int ascii85 = FALSE; /* use ASCII85 encoding */ | |
110 | int interpolate = TRUE; /* interpolate level2 image */ | |
111 | int level2 = FALSE; /* generate PostScript level 2 */ | |
112 | int level3 = FALSE; /* generate PostScript level 3 */ | |
113 | int printAll = FALSE; /* print all images in file */ | |
114 | int generateEPSF = TRUE; /* generate Encapsulated PostScript */ | |
115 | int PSduplex = FALSE; /* enable duplex printing */ | |
116 | int PStumble = FALSE; /* enable top edge binding */ | |
117 | int PSavoiddeadzone = TRUE; /* enable avoiding printer deadzone */ | |
118 | double maxPageHeight = 0; /* maximum size to fit on page */ | |
119 | double splitOverlap = 0; /* amount for split pages to overlag */ | |
120 | int rotate = FALSE; /* rotate image by 180 degrees */ | |
121 | char *filename; /* input filename */ | |
122 | int useImagemask = FALSE; /* Use imagemask instead of image operator */ | |
123 | uint16 res_unit = 0; /* Resolution units: 2 - inches, 3 - cm */ | |
124 | ||
125 | /* | |
126 | * ASCII85 Encoding Support. | |
127 | */ | |
128 | unsigned char ascii85buf[10]; | |
129 | int ascii85count; | |
130 | int ascii85breaklen; | |
131 | ||
132 | int TIFF2PS(FILE*, TIFF*, double, double, double, double, int); | |
133 | void PSpage(FILE*, TIFF*, uint32, uint32); | |
134 | void PSColorContigPreamble(FILE*, uint32, uint32, int); | |
135 | void PSColorSeparatePreamble(FILE*, uint32, uint32, int); | |
136 | void PSDataColorContig(FILE*, TIFF*, uint32, uint32, int); | |
137 | void PSDataColorSeparate(FILE*, TIFF*, uint32, uint32, int); | |
138 | void PSDataPalette(FILE*, TIFF*, uint32, uint32); | |
139 | void PSDataBW(FILE*, TIFF*, uint32, uint32); | |
140 | void PSRawDataBW(FILE*, TIFF*, uint32, uint32); | |
141 | void Ascii85Init(void); | |
142 | void Ascii85Put(unsigned char code, FILE* fd); | |
143 | void Ascii85Flush(FILE* fd); | |
144 | void PSHead(FILE*, TIFF*, uint32, uint32, double, double, double, double); | |
145 | void PSTail(FILE*, int); | |
146 | ||
147 | #if defined( EXP_ASCII85ENCODER) | |
148 | int Ascii85EncodeBlock( uint8 * ascii85_p, unsigned f_eod, const uint8 * raw_p, int raw_l ); | |
149 | #endif | |
150 | ||
151 | static void usage(int); | |
152 | ||
153 | int | |
154 | main(int argc, char* argv[]) | |
155 | { | |
156 | int dirnum = -1, c, np = 0; | |
157 | int centered = 0; | |
158 | double bottommargin = 0; | |
159 | double leftmargin = 0; | |
160 | double pageWidth = 0; | |
161 | double pageHeight = 0; | |
162 | uint32 diroff = 0; | |
163 | extern char *optarg; | |
164 | extern int optind; | |
165 | FILE* output = stdout; | |
166 | ||
167 | while ((c = getopt(argc, argv, "b:d:h:H:L:i:w:l:o:O:acelmrxyzps1238DT")) != -1) | |
168 | switch (c) { | |
169 | case 'b': | |
170 | bottommargin = atof(optarg); | |
171 | break; | |
172 | case 'c': | |
173 | centered = 1; | |
174 | break; | |
175 | case 'd': | |
176 | dirnum = atoi(optarg); | |
177 | break; | |
178 | case 'D': | |
179 | PSduplex = TRUE; | |
180 | break; | |
181 | case 'i': | |
182 | interpolate = atoi(optarg) ? TRUE:FALSE; | |
183 | break; | |
184 | case 'T': | |
185 | PStumble = TRUE; | |
186 | break; | |
187 | case 'e': | |
188 | PSavoiddeadzone = FALSE; | |
189 | generateEPSF = TRUE; | |
190 | break; | |
191 | case 'h': | |
192 | pageHeight = atof(optarg); | |
193 | break; | |
194 | case 'H': | |
195 | maxPageHeight = atof(optarg); | |
196 | if (pageHeight==0) pageHeight = maxPageHeight; | |
197 | break; | |
198 | case 'L': | |
199 | splitOverlap = atof(optarg); | |
200 | break; | |
201 | case 'm': | |
202 | useImagemask = TRUE; | |
203 | break; | |
204 | case 'o': | |
205 | diroff = (uint32) strtoul(optarg, NULL, 0); | |
206 | break; | |
207 | case 'O': /* XXX too bad -o is already taken */ | |
208 | output = fopen(optarg, "w"); | |
209 | if (output == NULL) { | |
210 | fprintf(stderr, | |
211 | "%s: %s: Cannot open output file.\n", | |
212 | argv[0], optarg); | |
213 | exit(-2); | |
214 | } | |
215 | break; | |
216 | case 'l': | |
217 | leftmargin = atof(optarg); | |
218 | break; | |
219 | case 'a': | |
220 | printAll = TRUE; | |
221 | /* fall thru... */ | |
222 | case 'p': | |
223 | generateEPSF = FALSE; | |
224 | break; | |
225 | case 'r': | |
226 | rotate = TRUE; | |
227 | break; | |
228 | case 's': | |
229 | printAll = FALSE; | |
230 | break; | |
231 | case 'w': | |
232 | pageWidth = atof(optarg); | |
233 | break; | |
234 | case 'z': | |
235 | PSavoiddeadzone = FALSE; | |
236 | break; | |
237 | case '1': | |
238 | level2 = FALSE; | |
239 | level3 = FALSE; | |
240 | ascii85 = FALSE; | |
241 | break; | |
242 | case '2': | |
243 | level2 = TRUE; | |
244 | ascii85 = TRUE; /* default to yes */ | |
245 | break; | |
246 | case '3': | |
247 | level3 = TRUE; | |
248 | ascii85 = TRUE; /* default to yes */ | |
249 | break; | |
250 | case '8': | |
251 | ascii85 = FALSE; | |
252 | break; | |
253 | case 'x': | |
254 | res_unit = RESUNIT_CENTIMETER; | |
255 | break; | |
256 | case 'y': | |
257 | res_unit = RESUNIT_INCH; | |
258 | break; | |
259 | case '?': | |
260 | usage(-1); | |
261 | } | |
262 | for (; argc - optind > 0; optind++) { | |
263 | TIFF* tif = TIFFOpen(filename = argv[optind], "r"); | |
264 | if (tif != NULL) { | |
265 | if (dirnum != -1 | |
266 | && !TIFFSetDirectory(tif, (tdir_t)dirnum)) | |
267 | return (-1); | |
268 | else if (diroff != 0 && | |
269 | !TIFFSetSubDirectory(tif, diroff)) | |
270 | return (-1); | |
271 | np = TIFF2PS(output, tif, pageWidth, pageHeight, | |
272 | leftmargin, bottommargin, centered); | |
273 | TIFFClose(tif); | |
274 | } | |
275 | } | |
276 | if (np) | |
277 | PSTail(output, np); | |
278 | else | |
279 | usage(-1); | |
280 | if (output != stdout) | |
281 | fclose(output); | |
282 | return (0); | |
283 | } | |
284 | ||
285 | static uint16 samplesperpixel; | |
286 | static uint16 bitspersample; | |
287 | static uint16 planarconfiguration; | |
288 | static uint16 photometric; | |
289 | static uint16 compression; | |
290 | static uint16 extrasamples; | |
291 | static int alpha; | |
292 | ||
293 | static int | |
294 | checkImage(TIFF* tif) | |
295 | { | |
296 | switch (photometric) { | |
297 | case PHOTOMETRIC_YCBCR: | |
298 | if ((compression == COMPRESSION_JPEG || compression == COMPRESSION_OJPEG) | |
299 | && planarconfiguration == PLANARCONFIG_CONTIG) { | |
300 | /* can rely on libjpeg to convert to RGB */ | |
301 | TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, | |
302 | JPEGCOLORMODE_RGB); | |
303 | photometric = PHOTOMETRIC_RGB; | |
304 | } else { | |
305 | if (level2 || level3) | |
306 | break; | |
307 | TIFFError(filename, "Can not handle image with %s", | |
308 | "PhotometricInterpretation=YCbCr"); | |
309 | return (0); | |
310 | } | |
311 | /* fall thru... */ | |
312 | case PHOTOMETRIC_RGB: | |
313 | if (alpha && bitspersample != 8) { | |
314 | TIFFError(filename, | |
315 | "Can not handle %d-bit/sample RGB image with alpha", | |
316 | bitspersample); | |
317 | return (0); | |
318 | } | |
319 | /* fall thru... */ | |
320 | case PHOTOMETRIC_SEPARATED: | |
321 | case PHOTOMETRIC_PALETTE: | |
322 | case PHOTOMETRIC_MINISBLACK: | |
323 | case PHOTOMETRIC_MINISWHITE: | |
324 | break; | |
325 | case PHOTOMETRIC_LOGL: | |
326 | case PHOTOMETRIC_LOGLUV: | |
327 | if (compression != COMPRESSION_SGILOG && | |
328 | compression != COMPRESSION_SGILOG24) { | |
329 | TIFFError(filename, | |
330 | "Can not handle %s data with compression other than SGILog", | |
331 | (photometric == PHOTOMETRIC_LOGL) ? | |
332 | "LogL" : "LogLuv" | |
333 | ); | |
334 | return (0); | |
335 | } | |
336 | /* rely on library to convert to RGB/greyscale */ | |
337 | TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT); | |
338 | photometric = (photometric == PHOTOMETRIC_LOGL) ? | |
339 | PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB; | |
340 | bitspersample = 8; | |
341 | break; | |
342 | case PHOTOMETRIC_CIELAB: | |
343 | /* fall thru... */ | |
344 | default: | |
345 | TIFFError(filename, | |
346 | "Can not handle image with PhotometricInterpretation=%d", | |
347 | photometric); | |
348 | return (0); | |
349 | } | |
350 | switch (bitspersample) { | |
351 | case 1: case 2: | |
352 | case 4: case 8: | |
353 | break; | |
354 | default: | |
355 | TIFFError(filename, "Can not handle %d-bit/sample image", | |
356 | bitspersample); | |
357 | return (0); | |
358 | } | |
359 | if (planarconfiguration == PLANARCONFIG_SEPARATE && extrasamples > 0) | |
360 | TIFFWarning(filename, "Ignoring extra samples"); | |
361 | return (1); | |
362 | } | |
363 | ||
364 | #define PS_UNIT_SIZE 72.0F | |
365 | #define PSUNITS(npix,res) ((npix) * (PS_UNIT_SIZE / (res))) | |
366 | ||
367 | static char RGBcolorimage[] = "\ | |
368 | /bwproc {\n\ | |
369 | rgbproc\n\ | |
370 | dup length 3 idiv string 0 3 0\n\ | |
371 | 5 -1 roll {\n\ | |
372 | add 2 1 roll 1 sub dup 0 eq {\n\ | |
373 | pop 3 idiv\n\ | |
374 | 3 -1 roll\n\ | |
375 | dup 4 -1 roll\n\ | |
376 | dup 3 1 roll\n\ | |
377 | 5 -1 roll put\n\ | |
378 | 1 add 3 0\n\ | |
379 | } { 2 1 roll } ifelse\n\ | |
380 | } forall\n\ | |
381 | pop pop pop\n\ | |
382 | } def\n\ | |
383 | /colorimage where {pop} {\n\ | |
384 | /colorimage {pop pop /rgbproc exch def {bwproc} image} bind def\n\ | |
385 | } ifelse\n\ | |
386 | "; | |
387 | ||
388 | /* | |
389 | * Adobe Photoshop requires a comment line of the form: | |
390 | * | |
391 | * %ImageData: <cols> <rows> <depth> <main channels> <pad channels> | |
392 | * <block size> <1 for binary|2 for hex> "data start" | |
393 | * | |
394 | * It is claimed to be part of some future revision of the EPS spec. | |
395 | */ | |
396 | static void | |
397 | PhotoshopBanner(FILE* fd, uint32 w, uint32 h, int bs, int nc, char* startline) | |
398 | { | |
399 | fprintf(fd, "%%ImageData: %ld %ld %d %d 0 %d 2 \"", | |
400 | (long) w, (long) h, bitspersample, nc, bs); | |
401 | fprintf(fd, startline, nc); | |
402 | fprintf(fd, "\"\n"); | |
403 | } | |
404 | ||
405 | /* | |
406 | * pw : image width in pixels | |
407 | * ph : image height in pixels | |
408 | * pprw : image width in PS units (72 dpi) | |
409 | * pprh : image height in PS units (72 dpi) | |
410 | */ | |
411 | static void | |
412 | setupPageState(TIFF* tif, uint32* pw, uint32* ph, double* pprw, double* pprh) | |
413 | { | |
414 | float xres = 0.0F, yres = 0.0F; | |
415 | ||
416 | TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, pw); | |
417 | TIFFGetField(tif, TIFFTAG_IMAGELENGTH, ph); | |
418 | if (res_unit == 0) | |
419 | TIFFGetFieldDefaulted(tif, TIFFTAG_RESOLUTIONUNIT, &res_unit); | |
420 | /* | |
421 | * Calculate printable area. | |
422 | */ | |
423 | if (!TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres) | |
424 | || fabs(xres) < 0.0000001) | |
425 | xres = PS_UNIT_SIZE; | |
426 | if (!TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres) | |
427 | || fabs(yres) < 0.0000001) | |
428 | yres = PS_UNIT_SIZE; | |
429 | switch (res_unit) { | |
430 | case RESUNIT_CENTIMETER: | |
431 | xres *= 2.54F, yres *= 2.54F; | |
432 | break; | |
433 | case RESUNIT_INCH: | |
434 | break; | |
435 | case RESUNIT_NONE: | |
436 | default: | |
437 | xres *= PS_UNIT_SIZE, yres *= PS_UNIT_SIZE; | |
438 | break; | |
439 | } | |
440 | *pprh = PSUNITS(*ph, yres); | |
441 | *pprw = PSUNITS(*pw, xres); | |
442 | } | |
443 | ||
444 | static int | |
445 | isCCITTCompression(TIFF* tif) | |
446 | { | |
447 | uint16 compress; | |
448 | TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress); | |
449 | return (compress == COMPRESSION_CCITTFAX3 || | |
450 | compress == COMPRESSION_CCITTFAX4 || | |
451 | compress == COMPRESSION_CCITTRLE || | |
452 | compress == COMPRESSION_CCITTRLEW); | |
453 | } | |
454 | ||
455 | static tsize_t tf_bytesperrow; | |
456 | static tsize_t ps_bytesperrow; | |
457 | static tsize_t tf_rowsperstrip; | |
458 | static tsize_t tf_numberstrips; | |
459 | static char *hex = "0123456789abcdef"; | |
460 | ||
461 | /* | |
462 | * imagewidth & imageheight are 1/72 inches | |
463 | * pagewidth & pageheight are inches | |
464 | */ | |
465 | int | |
466 | PlaceImage(FILE *fp, double pagewidth, double pageheight, | |
467 | double imagewidth, double imageheight, int splitpage, | |
468 | double lm, double bm, int cnt) | |
469 | { | |
470 | double xtran = 0; | |
471 | double ytran = 0; | |
472 | double xscale = 1; | |
473 | double yscale = 1; | |
474 | double left_offset = lm * PS_UNIT_SIZE; | |
475 | double bottom_offset = bm * PS_UNIT_SIZE; | |
476 | double subimageheight; | |
477 | double splitheight; | |
478 | double overlap; | |
479 | ||
480 | pagewidth *= PS_UNIT_SIZE; | |
481 | pageheight *= PS_UNIT_SIZE; | |
482 | ||
483 | if (maxPageHeight==0) | |
484 | splitheight = 0; | |
485 | else | |
486 | splitheight = maxPageHeight * PS_UNIT_SIZE; | |
487 | overlap = splitOverlap * PS_UNIT_SIZE; | |
488 | ||
489 | /* | |
490 | * WIDTH: | |
491 | * if too wide, scrunch to fit | |
492 | * else leave it alone | |
493 | */ | |
494 | if (imagewidth <= pagewidth) { | |
495 | xscale = imagewidth; | |
496 | } else { | |
497 | xscale = pagewidth; | |
498 | } | |
499 | ||
500 | /* HEIGHT: | |
501 | * if too long, scrunch to fit | |
502 | * if too short, move to top of page | |
503 | */ | |
504 | if (imageheight <= pageheight) { | |
505 | yscale = imageheight; | |
506 | ytran = pageheight - imageheight; | |
507 | } else if (imageheight > pageheight && | |
508 | (splitheight == 0 || imageheight <= splitheight)) { | |
509 | yscale = pageheight; | |
510 | } else /* imageheight > splitheight */ { | |
511 | subimageheight = imageheight - (pageheight-overlap)*splitpage; | |
512 | if (subimageheight <= pageheight) { | |
513 | yscale = imageheight; | |
514 | ytran = pageheight - subimageheight; | |
515 | splitpage = 0; | |
516 | } else if ( subimageheight > pageheight && subimageheight <= splitheight) { | |
517 | yscale = imageheight * pageheight / subimageheight; | |
518 | ytran = 0; | |
519 | splitpage = 0; | |
520 | } else /* sumimageheight > splitheight */ { | |
521 | yscale = imageheight; | |
522 | ytran = pageheight - subimageheight; | |
523 | splitpage++; | |
524 | } | |
525 | } | |
526 | ||
527 | bottom_offset += ytran / (cnt?2:1); | |
528 | if (cnt) | |
529 | left_offset += xtran / 2; | |
530 | fprintf(fp, "%f %f translate\n", left_offset, bottom_offset); | |
531 | fprintf(fp, "%f %f scale\n", xscale, yscale); | |
532 | if (rotate) | |
533 | fputs ("1 1 translate 180 rotate\n", fp); | |
534 | ||
535 | return splitpage; | |
536 | } | |
537 | ||
538 | ||
539 | /* returns the sequence number of the page processed */ | |
540 | int | |
541 | TIFF2PS(FILE* fd, TIFF* tif, | |
542 | double pw, double ph, double lm, double bm, int cnt) | |
543 | { | |
544 | uint32 w, h; | |
545 | float ox, oy; | |
546 | double prw, prh; | |
547 | double scale = 1.0; | |
548 | uint32 subfiletype; | |
549 | uint16* sampleinfo; | |
550 | static int npages = 0; | |
551 | int split; | |
552 | ||
553 | if (!TIFFGetField(tif, TIFFTAG_XPOSITION, &ox)) | |
554 | ox = 0; | |
555 | if (!TIFFGetField(tif, TIFFTAG_YPOSITION, &oy)) | |
556 | oy = 0; | |
557 | setupPageState(tif, &w, &h, &prw, &prh); | |
558 | ||
559 | do { | |
560 | tf_numberstrips = TIFFNumberOfStrips(tif); | |
561 | TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, | |
562 | &tf_rowsperstrip); | |
563 | setupPageState(tif, &w, &h, &prw, &prh); | |
564 | if (!npages) | |
565 | PSHead(fd, tif, w, h, prw, prh, ox, oy); | |
566 | TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, | |
567 | &bitspersample); | |
568 | TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, | |
569 | &samplesperpixel); | |
570 | TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, | |
571 | &planarconfiguration); | |
572 | TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression); | |
573 | TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, | |
574 | &extrasamples, &sampleinfo); | |
575 | alpha = (extrasamples == 1 && | |
576 | sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA); | |
577 | if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) { | |
578 | switch (samplesperpixel - extrasamples) { | |
579 | case 1: | |
580 | if (isCCITTCompression(tif)) | |
581 | photometric = PHOTOMETRIC_MINISWHITE; | |
582 | else | |
583 | photometric = PHOTOMETRIC_MINISBLACK; | |
584 | break; | |
585 | case 3: | |
586 | photometric = PHOTOMETRIC_RGB; | |
587 | break; | |
588 | case 4: | |
589 | photometric = PHOTOMETRIC_SEPARATED; | |
590 | break; | |
591 | } | |
592 | } | |
593 | if (checkImage(tif)) { | |
594 | tf_bytesperrow = TIFFScanlineSize(tif); | |
595 | npages++; | |
596 | fprintf(fd, "%%%%Page: %d %d\n", npages, npages); | |
597 | if (!generateEPSF && ( level2 || level3 )) { | |
598 | double psw, psh; | |
599 | if (pw != 0.0) { | |
600 | psw = pw * PS_UNIT_SIZE; | |
601 | if (res_unit == RESUNIT_CENTIMETER) | |
602 | psw *= 2.54F; | |
603 | } else | |
604 | psw=rotate ? prh:prw; | |
605 | if (ph != 0.0) { | |
606 | psh = ph * PS_UNIT_SIZE; | |
607 | if (res_unit == RESUNIT_CENTIMETER) | |
608 | psh *= 2.54F; | |
609 | } else | |
610 | psh=rotate ? prw:prh; | |
611 | fprintf(fd, | |
612 | "1 dict begin /PageSize [ %f %f ] def currentdict end setpagedevice\n", | |
613 | psw, psh); | |
614 | fputs( | |
615 | "<<\n /Policies <<\n /PageSize 3\n >>\n>> setpagedevice\n", | |
616 | fd); | |
617 | } | |
618 | fprintf(fd, "gsave\n"); | |
619 | fprintf(fd, "100 dict begin\n"); | |
620 | if (pw != 0 || ph != 0) { | |
621 | double psw = pw, psh = ph; | |
622 | if (!psw) | |
623 | psw = prw; | |
624 | if (!psh) | |
625 | psh = prh; | |
626 | if (maxPageHeight) { /* used -H option */ | |
627 | split = PlaceImage(fd,psw,psh,prw,prh, | |
628 | 0,lm,bm,cnt); | |
629 | while( split ) { | |
630 | PSpage(fd, tif, w, h); | |
631 | fprintf(fd, "end\n"); | |
632 | fprintf(fd, "grestore\n"); | |
633 | fprintf(fd, "showpage\n"); | |
634 | npages++; | |
635 | fprintf(fd, "%%%%Page: %d %d\n", | |
636 | npages, npages); | |
637 | fprintf(fd, "gsave\n"); | |
638 | fprintf(fd, "100 dict begin\n"); | |
639 | split = PlaceImage(fd,psw,psh,prw,prh, | |
640 | split,lm,bm,cnt); | |
641 | } | |
642 | } else { | |
643 | double left_offset = lm * PS_UNIT_SIZE; | |
644 | double bottom_offset = bm * PS_UNIT_SIZE; | |
645 | psw *= PS_UNIT_SIZE; | |
646 | psh *= PS_UNIT_SIZE; | |
647 | ||
648 | /* NB: maintain image aspect ratio */ | |
649 | scale = psw/prw < psh/prh ? | |
650 | psw/prw : psh/prh; | |
651 | if (scale > 1.0) | |
652 | scale = 1.0; | |
653 | if (cnt) { | |
654 | bottom_offset += | |
655 | (psh - prh * scale) / 2; | |
656 | left_offset += | |
657 | (psw - prw * scale) / 2; | |
658 | } | |
659 | fprintf(fd, "%f %f translate\n", | |
660 | left_offset, bottom_offset); | |
661 | fprintf(fd, "%f %f scale\n", | |
662 | prw * scale, prh * scale); | |
663 | if (rotate) | |
664 | fputs ("1 1 translate 180 rotate\n", fd); | |
665 | } | |
666 | } else { | |
667 | fprintf(fd, "%f %f scale\n", prw, prh); | |
668 | if (rotate) | |
669 | fputs ("1 1 translate 180 rotate\n", fd); | |
670 | } | |
671 | PSpage(fd, tif, w, h); | |
672 | fprintf(fd, "end\n"); | |
673 | fprintf(fd, "grestore\n"); | |
674 | fprintf(fd, "showpage\n"); | |
675 | } | |
676 | if (generateEPSF) | |
677 | break; | |
678 | TIFFGetFieldDefaulted(tif, TIFFTAG_SUBFILETYPE, &subfiletype); | |
679 | } while (((subfiletype & FILETYPE_PAGE) || printAll) && | |
680 | TIFFReadDirectory(tif)); | |
681 | ||
682 | return(npages); | |
683 | } | |
684 | ||
685 | ||
686 | static char DuplexPreamble[] = "\ | |
687 | %%BeginFeature: *Duplex True\n\ | |
688 | systemdict begin\n\ | |
689 | /languagelevel where { pop languagelevel } { 1 } ifelse\n\ | |
690 | 2 ge { 1 dict dup /Duplex true put setpagedevice }\n\ | |
691 | { statusdict /setduplex known { statusdict begin setduplex true end } if\n\ | |
692 | } ifelse\n\ | |
693 | end\n\ | |
694 | %%EndFeature\n\ | |
695 | "; | |
696 | ||
697 | static char TumblePreamble[] = "\ | |
698 | %%BeginFeature: *Tumble True\n\ | |
699 | systemdict begin\n\ | |
700 | /languagelevel where { pop languagelevel } { 1 } ifelse\n\ | |
701 | 2 ge { 1 dict dup /Tumble true put setpagedevice }\n\ | |
702 | { statusdict /settumble known { statusdict begin true settumble end } if\n\ | |
703 | } ifelse\n\ | |
704 | end\n\ | |
705 | %%EndFeature\n\ | |
706 | "; | |
707 | ||
708 | static char AvoidDeadZonePreamble[] = "\ | |
709 | gsave newpath clippath pathbbox grestore\n\ | |
710 | 4 2 roll 2 copy translate\n\ | |
711 | exch 3 1 roll sub 3 1 roll sub exch\n\ | |
712 | currentpagedevice /PageSize get aload pop\n\ | |
713 | exch 3 1 roll div 3 1 roll div abs exch abs\n\ | |
714 | 2 copy gt { exch } if pop\n\ | |
715 | dup 1 lt { dup scale } { pop } ifelse\n\ | |
716 | "; | |
717 | ||
718 | void | |
719 | PSHead(FILE *fd, TIFF *tif, uint32 w, uint32 h, | |
720 | double pw, double ph, double ox, double oy) | |
721 | { | |
722 | time_t t; | |
723 | ||
724 | (void) tif; (void) w; (void) h; | |
725 | t = time(0); | |
726 | fprintf(fd, "%%!PS-Adobe-3.0%s\n", generateEPSF ? " EPSF-3.0" : ""); | |
727 | fprintf(fd, "%%%%Creator: tiff2ps\n"); | |
728 | fprintf(fd, "%%%%Title: %s\n", filename); | |
729 | fprintf(fd, "%%%%CreationDate: %s", ctime(&t)); | |
730 | fprintf(fd, "%%%%DocumentData: Clean7Bit\n"); | |
731 | fprintf(fd, "%%%%Origin: %ld %ld\n", (long) ox, (long) oy); | |
732 | /* NB: should use PageBoundingBox */ | |
733 | fprintf(fd, "%%%%BoundingBox: 0 0 %ld %ld\n", | |
734 | (long) ceil(pw), (long) ceil(ph)); | |
735 | fprintf(fd, "%%%%LanguageLevel: %d\n", (level3 ? 3 : (level2 ? 2 : 1))); | |
736 | fprintf(fd, "%%%%Pages: (atend)\n"); | |
737 | fprintf(fd, "%%%%EndComments\n"); | |
738 | fprintf(fd, "%%%%BeginSetup\n"); | |
739 | if (PSduplex) | |
740 | fprintf(fd, "%s", DuplexPreamble); | |
741 | if (PStumble) | |
742 | fprintf(fd, "%s", TumblePreamble); | |
743 | if (PSavoiddeadzone && (level2 || level3)) | |
744 | fprintf(fd, "%s", AvoidDeadZonePreamble); | |
745 | fprintf(fd, "%%%%EndSetup\n"); | |
746 | } | |
747 | ||
748 | void | |
749 | PSTail(FILE *fd, int npages) | |
750 | { | |
751 | fprintf(fd, "%%%%Trailer\n"); | |
752 | fprintf(fd, "%%%%Pages: %d\n", npages); | |
753 | fprintf(fd, "%%%%EOF\n"); | |
754 | } | |
755 | ||
756 | static int | |
757 | checkcmap(TIFF* tif, int n, uint16* r, uint16* g, uint16* b) | |
758 | { | |
759 | (void) tif; | |
760 | while (n-- > 0) | |
761 | if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256) | |
762 | return (16); | |
763 | TIFFWarning(filename, "Assuming 8-bit colormap"); | |
764 | return (8); | |
765 | } | |
766 | ||
767 | static void | |
768 | PS_Lvl2colorspace(FILE* fd, TIFF* tif) | |
769 | { | |
770 | uint16 *rmap, *gmap, *bmap; | |
771 | int i, num_colors; | |
772 | const char * colorspace_p; | |
773 | ||
774 | switch ( photometric ) | |
775 | { | |
776 | case PHOTOMETRIC_SEPARATED: | |
777 | colorspace_p = "CMYK"; | |
778 | break; | |
779 | ||
780 | case PHOTOMETRIC_RGB: | |
781 | colorspace_p = "RGB"; | |
782 | break; | |
783 | ||
784 | default: | |
785 | colorspace_p = "Gray"; | |
786 | } | |
787 | ||
788 | /* | |
789 | * Set up PostScript Level 2 colorspace according to | |
790 | * section 4.8 in the PostScript refenence manual. | |
791 | */ | |
792 | fputs("% PostScript Level 2 only.\n", fd); | |
793 | if (photometric != PHOTOMETRIC_PALETTE) { | |
794 | if (photometric == PHOTOMETRIC_YCBCR) { | |
795 | /* MORE CODE HERE */ | |
796 | } | |
797 | fprintf(fd, "/Device%s setcolorspace\n", colorspace_p ); | |
798 | return; | |
799 | } | |
800 | ||
801 | /* | |
802 | * Set up an indexed/palette colorspace | |
803 | */ | |
804 | num_colors = (1 << bitspersample); | |
805 | if (!TIFFGetField(tif, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap)) { | |
806 | TIFFError(filename, | |
807 | "Palette image w/o \"Colormap\" tag"); | |
808 | return; | |
809 | } | |
810 | if (checkcmap(tif, num_colors, rmap, gmap, bmap) == 16) { | |
811 | /* | |
812 | * Convert colormap to 8-bits values. | |
813 | */ | |
814 | #define CVT(x) (((x) * 255) / ((1L<<16)-1)) | |
815 | for (i = 0; i < num_colors; i++) { | |
816 | rmap[i] = CVT(rmap[i]); | |
817 | gmap[i] = CVT(gmap[i]); | |
818 | bmap[i] = CVT(bmap[i]); | |
819 | } | |
820 | #undef CVT | |
821 | } | |
822 | fprintf(fd, "[ /Indexed /DeviceRGB %d", num_colors - 1); | |
823 | if (ascii85) { | |
824 | Ascii85Init(); | |
825 | fputs("\n<~", fd); | |
826 | ascii85breaklen -= 2; | |
827 | } else | |
828 | fputs(" <", fd); | |
829 | for (i = 0; i < num_colors; i++) { | |
830 | if (ascii85) { | |
831 | Ascii85Put((unsigned char)rmap[i], fd); | |
832 | Ascii85Put((unsigned char)gmap[i], fd); | |
833 | Ascii85Put((unsigned char)bmap[i], fd); | |
834 | } else { | |
835 | fputs((i % 8) ? " " : "\n ", fd); | |
836 | fprintf(fd, "%02x%02x%02x", | |
837 | rmap[i], gmap[i], bmap[i]); | |
838 | } | |
839 | } | |
840 | if (ascii85) | |
841 | Ascii85Flush(fd); | |
842 | else | |
843 | fputs(">\n", fd); | |
844 | fputs("] setcolorspace\n", fd); | |
845 | } | |
846 | ||
847 | static int | |
848 | PS_Lvl2ImageDict(FILE* fd, TIFF* tif, uint32 w, uint32 h) | |
849 | { | |
850 | int use_rawdata; | |
851 | uint32 tile_width, tile_height; | |
852 | uint16 predictor, minsamplevalue, maxsamplevalue; | |
853 | int repeat_count; | |
854 | char im_h[64], im_x[64], im_y[64]; | |
855 | char * imageOp = "image"; | |
856 | ||
857 | if ( useImagemask && (bitspersample == 1) ) | |
858 | imageOp = "imagemask"; | |
859 | ||
860 | (void)strcpy(im_x, "0"); | |
861 | (void)sprintf(im_y, "%lu", (long) h); | |
862 | (void)sprintf(im_h, "%lu", (long) h); | |
863 | tile_width = w; | |
864 | tile_height = h; | |
865 | if (TIFFIsTiled(tif)) { | |
866 | repeat_count = TIFFNumberOfTiles(tif); | |
867 | TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width); | |
868 | TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height); | |
869 | if (tile_width > w || tile_height > h || | |
870 | (w % tile_width) != 0 || (h % tile_height != 0)) { | |
871 | /* | |
872 | * The tiles does not fit image width and height. | |
873 | * Set up a clip rectangle for the image unit square. | |
874 | */ | |
875 | fputs("0 0 1 1 rectclip\n", fd); | |
876 | } | |
877 | if (tile_width < w) { | |
878 | fputs("/im_x 0 def\n", fd); | |
879 | (void)strcpy(im_x, "im_x neg"); | |
880 | } | |
881 | if (tile_height < h) { | |
882 | fputs("/im_y 0 def\n", fd); | |
883 | (void)sprintf(im_y, "%lu im_y sub", (unsigned long) h); | |
884 | } | |
885 | } else { | |
886 | repeat_count = tf_numberstrips; | |
887 | tile_height = tf_rowsperstrip; | |
888 | if (tile_height > h) | |
889 | tile_height = h; | |
890 | if (repeat_count > 1) { | |
891 | fputs("/im_y 0 def\n", fd); | |
892 | fprintf(fd, "/im_h %lu def\n", | |
893 | (unsigned long) tile_height); | |
894 | (void)strcpy(im_h, "im_h"); | |
895 | (void)sprintf(im_y, "%lu im_y sub", (unsigned long) h); | |
896 | } | |
897 | } | |
898 | ||
899 | /* | |
900 | * Output start of exec block | |
901 | */ | |
902 | fputs("{ % exec\n", fd); | |
903 | ||
904 | if (repeat_count > 1) | |
905 | fprintf(fd, "%d { %% repeat\n", repeat_count); | |
906 | ||
907 | /* | |
908 | * Output filter options and image dictionary. | |
909 | */ | |
910 | if (ascii85) | |
911 | fputs(" /im_stream currentfile /ASCII85Decode filter def\n", | |
912 | fd); | |
913 | fputs(" <<\n", fd); | |
914 | fputs(" /ImageType 1\n", fd); | |
915 | fprintf(fd, " /Width %lu\n", (unsigned long) tile_width); | |
916 | /* | |
917 | * Workaround for some software that may crash when last strip | |
918 | * of image contains fewer number of scanlines than specified | |
919 | * by the `/Height' variable. So for stripped images with multiple | |
920 | * strips we will set `/Height' as `im_h', because one is | |
921 | * recalculated for each strip - including the (smaller) final strip. | |
922 | * For tiled images and images with only one strip `/Height' will | |
923 | * contain number of scanlines in tile (or image height in case of | |
924 | * one-stripped image). | |
925 | */ | |
926 | if (TIFFIsTiled(tif) || tf_numberstrips == 1) | |
927 | fprintf(fd, " /Height %lu\n", (unsigned long) tile_height); | |
928 | else | |
929 | fprintf(fd, " /Height im_h\n"); | |
930 | ||
931 | if (planarconfiguration == PLANARCONFIG_SEPARATE && samplesperpixel > 1) | |
932 | fputs(" /MultipleDataSources true\n", fd); | |
933 | fprintf(fd, " /ImageMatrix [ %lu 0 0 %ld %s %s ]\n", | |
934 | (unsigned long) w, - (long)h, im_x, im_y); | |
935 | fprintf(fd, " /BitsPerComponent %d\n", bitspersample); | |
936 | fprintf(fd, " /Interpolate %s\n", interpolate ? "true" : "false"); | |
937 | ||
938 | switch (samplesperpixel - extrasamples) { | |
939 | case 1: | |
940 | switch (photometric) { | |
941 | case PHOTOMETRIC_MINISBLACK: | |
942 | fputs(" /Decode [0 1]\n", fd); | |
943 | break; | |
944 | case PHOTOMETRIC_MINISWHITE: | |
945 | switch (compression) { | |
946 | case COMPRESSION_CCITTRLE: | |
947 | case COMPRESSION_CCITTRLEW: | |
948 | case COMPRESSION_CCITTFAX3: | |
949 | case COMPRESSION_CCITTFAX4: | |
950 | /* | |
951 | * Manage inverting with /Blackis1 flag | |
952 | * since there migth be uncompressed parts | |
953 | */ | |
954 | fputs(" /Decode [0 1]\n", fd); | |
955 | break; | |
956 | default: | |
957 | /* | |
958 | * ERROR... | |
959 | */ | |
960 | fputs(" /Decode [1 0]\n", fd); | |
961 | break; | |
962 | } | |
963 | break; | |
964 | case PHOTOMETRIC_PALETTE: | |
965 | TIFFGetFieldDefaulted(tif, TIFFTAG_MINSAMPLEVALUE, | |
966 | &minsamplevalue); | |
967 | TIFFGetFieldDefaulted(tif, TIFFTAG_MAXSAMPLEVALUE, | |
968 | &maxsamplevalue); | |
969 | fprintf(fd, " /Decode [%u %u]\n", | |
970 | minsamplevalue, maxsamplevalue); | |
971 | break; | |
972 | default: | |
973 | /* | |
974 | * ERROR ? | |
975 | */ | |
976 | fputs(" /Decode [0 1]\n", fd); | |
977 | break; | |
978 | } | |
979 | break; | |
980 | case 3: | |
981 | switch (photometric) { | |
982 | case PHOTOMETRIC_RGB: | |
983 | fputs(" /Decode [0 1 0 1 0 1]\n", fd); | |
984 | break; | |
985 | case PHOTOMETRIC_MINISWHITE: | |
986 | case PHOTOMETRIC_MINISBLACK: | |
987 | default: | |
988 | /* | |
989 | * ERROR?? | |
990 | */ | |
991 | fputs(" /Decode [0 1 0 1 0 1]\n", fd); | |
992 | break; | |
993 | } | |
994 | break; | |
995 | case 4: | |
996 | /* | |
997 | * ERROR?? | |
998 | */ | |
999 | fputs(" /Decode [0 1 0 1 0 1 0 1]\n", fd); | |
1000 | break; | |
1001 | } | |
1002 | fputs(" /DataSource", fd); | |
1003 | if (planarconfiguration == PLANARCONFIG_SEPARATE && | |
1004 | samplesperpixel > 1) | |
1005 | fputs(" [", fd); | |
1006 | if (ascii85) | |
1007 | fputs(" im_stream", fd); | |
1008 | else | |
1009 | fputs(" currentfile /ASCIIHexDecode filter", fd); | |
1010 | ||
1011 | use_rawdata = TRUE; | |
1012 | switch (compression) { | |
1013 | case COMPRESSION_NONE: /* 1: uncompressed */ | |
1014 | break; | |
1015 | case COMPRESSION_CCITTRLE: /* 2: CCITT modified Huffman RLE */ | |
1016 | case COMPRESSION_CCITTRLEW: /* 32771: #1 w/ word alignment */ | |
1017 | case COMPRESSION_CCITTFAX3: /* 3: CCITT Group 3 fax encoding */ | |
1018 | case COMPRESSION_CCITTFAX4: /* 4: CCITT Group 4 fax encoding */ | |
1019 | fputs("\n\t<<\n", fd); | |
1020 | if (compression == COMPRESSION_CCITTFAX3) { | |
1021 | uint32 g3_options; | |
1022 | ||
1023 | fputs("\t /EndOfLine true\n", fd); | |
1024 | fputs("\t /EndOfBlock false\n", fd); | |
1025 | if (!TIFFGetField(tif, TIFFTAG_GROUP3OPTIONS, | |
1026 | &g3_options)) | |
1027 | g3_options = 0; | |
1028 | if (g3_options & GROUP3OPT_2DENCODING) | |
1029 | fprintf(fd, "\t /K %s\n", im_h); | |
1030 | if (g3_options & GROUP3OPT_UNCOMPRESSED) | |
1031 | fputs("\t /Uncompressed true\n", fd); | |
1032 | if (g3_options & GROUP3OPT_FILLBITS) | |
1033 | fputs("\t /EncodedByteAlign true\n", fd); | |
1034 | } | |
1035 | if (compression == COMPRESSION_CCITTFAX4) { | |
1036 | uint32 g4_options; | |
1037 | ||
1038 | fputs("\t /K -1\n", fd); | |
1039 | TIFFGetFieldDefaulted(tif, TIFFTAG_GROUP4OPTIONS, | |
1040 | &g4_options); | |
1041 | if (g4_options & GROUP4OPT_UNCOMPRESSED) | |
1042 | fputs("\t /Uncompressed true\n", fd); | |
1043 | } | |
1044 | if (!(tile_width == w && w == 1728U)) | |
1045 | fprintf(fd, "\t /Columns %lu\n", | |
1046 | (unsigned long) tile_width); | |
1047 | fprintf(fd, "\t /Rows %s\n", im_h); | |
1048 | if (compression == COMPRESSION_CCITTRLE || | |
1049 | compression == COMPRESSION_CCITTRLEW) { | |
1050 | fputs("\t /EncodedByteAlign true\n", fd); | |
1051 | fputs("\t /EndOfBlock false\n", fd); | |
1052 | } | |
1053 | if (photometric == PHOTOMETRIC_MINISBLACK) | |
1054 | fputs("\t /BlackIs1 true\n", fd); | |
1055 | fprintf(fd, "\t>> /CCITTFaxDecode filter"); | |
1056 | break; | |
1057 | case COMPRESSION_LZW: /* 5: Lempel-Ziv & Welch */ | |
1058 | TIFFGetFieldDefaulted(tif, TIFFTAG_PREDICTOR, &predictor); | |
1059 | if (predictor == 2) { | |
1060 | fputs("\n\t<<\n", fd); | |
1061 | fprintf(fd, "\t /Predictor %u\n", predictor); | |
1062 | fprintf(fd, "\t /Columns %lu\n", | |
1063 | (unsigned long) tile_width); | |
1064 | fprintf(fd, "\t /Colors %u\n", samplesperpixel); | |
1065 | fprintf(fd, "\t /BitsPerComponent %u\n", | |
1066 | bitspersample); | |
1067 | fputs("\t>>", fd); | |
1068 | } | |
1069 | fputs(" /LZWDecode filter", fd); | |
1070 | break; | |
1071 | case COMPRESSION_DEFLATE: /* 5: ZIP */ | |
1072 | case COMPRESSION_ADOBE_DEFLATE: | |
1073 | if ( level3 ) { | |
1074 | TIFFGetFieldDefaulted(tif, TIFFTAG_PREDICTOR, &predictor); | |
1075 | if (predictor > 1) { | |
1076 | fprintf(fd, "\t %% PostScript Level 3 only."); | |
1077 | fputs("\n\t<<\n", fd); | |
1078 | fprintf(fd, "\t /Predictor %u\n", predictor); | |
1079 | fprintf(fd, "\t /Columns %lu\n", | |
1080 | (unsigned long) tile_width); | |
1081 | fprintf(fd, "\t /Colors %u\n", samplesperpixel); | |
1082 | fprintf(fd, "\t /BitsPerComponent %u\n", | |
1083 | bitspersample); | |
1084 | fputs("\t>>", fd); | |
1085 | } | |
1086 | fputs(" /FlateDecode filter", fd); | |
1087 | } else { | |
1088 | use_rawdata = FALSE ; | |
1089 | } | |
1090 | break; | |
1091 | case COMPRESSION_PACKBITS: /* 32773: Macintosh RLE */ | |
1092 | fputs(" /RunLengthDecode filter", fd); | |
1093 | use_rawdata = TRUE; | |
1094 | break; | |
1095 | case COMPRESSION_OJPEG: /* 6: !6.0 JPEG */ | |
1096 | case COMPRESSION_JPEG: /* 7: %JPEG DCT compression */ | |
1097 | #ifdef notdef | |
1098 | /* | |
1099 | * Code not tested yet | |
1100 | */ | |
1101 | fputs(" /DCTDecode filter", fd); | |
1102 | use_rawdata = TRUE; | |
1103 | #else | |
1104 | use_rawdata = FALSE; | |
1105 | #endif | |
1106 | break; | |
1107 | case COMPRESSION_NEXT: /* 32766: NeXT 2-bit RLE */ | |
1108 | case COMPRESSION_THUNDERSCAN: /* 32809: ThunderScan RLE */ | |
1109 | case COMPRESSION_PIXARFILM: /* 32908: Pixar companded 10bit LZW */ | |
1110 | case COMPRESSION_JBIG: /* 34661: ISO JBIG */ | |
1111 | use_rawdata = FALSE; | |
1112 | break; | |
1113 | case COMPRESSION_SGILOG: /* 34676: SGI LogL or LogLuv */ | |
1114 | case COMPRESSION_SGILOG24: /* 34677: SGI 24-bit LogLuv */ | |
1115 | use_rawdata = FALSE; | |
1116 | break; | |
1117 | default: | |
1118 | /* | |
1119 | * ERROR... | |
1120 | */ | |
1121 | use_rawdata = FALSE; | |
1122 | break; | |
1123 | } | |
1124 | if (planarconfiguration == PLANARCONFIG_SEPARATE && | |
1125 | samplesperpixel > 1) { | |
1126 | uint16 i; | |
1127 | ||
1128 | /* | |
1129 | * NOTE: This code does not work yet... | |
1130 | */ | |
1131 | for (i = 1; i < samplesperpixel; i++) | |
1132 | fputs(" dup", fd); | |
1133 | fputs(" ]", fd); | |
1134 | } | |
1135 | ||
1136 | fprintf( fd, "\n >> %s\n", imageOp ); | |
1137 | if (ascii85) | |
1138 | fputs(" im_stream status { im_stream flushfile } if\n", fd); | |
1139 | if (repeat_count > 1) { | |
1140 | if (tile_width < w) { | |
1141 | fprintf(fd, " /im_x im_x %lu add def\n", | |
1142 | (unsigned long) tile_width); | |
1143 | if (tile_height < h) { | |
1144 | fprintf(fd, " im_x %lu ge {\n", | |
1145 | (unsigned long) w); | |
1146 | fputs(" /im_x 0 def\n", fd); | |
1147 | fprintf(fd, " /im_y im_y %lu add def\n", | |
1148 | (unsigned long) tile_height); | |
1149 | fputs(" } if\n", fd); | |
1150 | } | |
1151 | } | |
1152 | if (tile_height < h) { | |
1153 | if (tile_width >= w) { | |
1154 | fprintf(fd, " /im_y im_y %lu add def\n", | |
1155 | (unsigned long) tile_height); | |
1156 | if (!TIFFIsTiled(tif)) { | |
1157 | fprintf(fd, " /im_h %lu im_y sub", | |
1158 | (unsigned long) h); | |
1159 | fprintf(fd, " dup %lu gt { pop", | |
1160 | (unsigned long) tile_height); | |
1161 | fprintf(fd, " %lu } if def\n", | |
1162 | (unsigned long) tile_height); | |
1163 | } | |
1164 | } | |
1165 | } | |
1166 | fputs("} repeat\n", fd); | |
1167 | } | |
1168 | /* | |
1169 | * End of exec function | |
1170 | */ | |
1171 | fputs("}\n", fd); | |
1172 | ||
1173 | return(use_rawdata); | |
1174 | } | |
1175 | ||
1176 | #define MAXLINE 36 | |
1177 | ||
1178 | int | |
1179 | PS_Lvl2page(FILE* fd, TIFF* tif, uint32 w, uint32 h) | |
1180 | { | |
1181 | uint16 fillorder; | |
1182 | int use_rawdata, tiled_image, breaklen = MAXLINE; | |
1183 | uint32 chunk_no, num_chunks, *bc; | |
1184 | unsigned char *buf_data, *cp; | |
1185 | tsize_t chunk_size, byte_count; | |
1186 | ||
1187 | #if defined( EXP_ASCII85ENCODER ) | |
1188 | int ascii85_l; /* Length, in bytes, of ascii85_p[] data */ | |
1189 | uint8 * ascii85_p = 0; /* Holds ASCII85 encoded data */ | |
1190 | #endif | |
1191 | ||
1192 | PS_Lvl2colorspace(fd, tif); | |
1193 | use_rawdata = PS_Lvl2ImageDict(fd, tif, w, h); | |
1194 | ||
1195 | /* See http://bugzilla.remotesensing.org/show_bug.cgi?id=80 */ | |
1196 | #ifdef ENABLE_BROKEN_BEGINENDDATA | |
1197 | fputs("%%BeginData:\n", fd); | |
1198 | #endif | |
1199 | fputs("exec\n", fd); | |
1200 | ||
1201 | tiled_image = TIFFIsTiled(tif); | |
1202 | if (tiled_image) { | |
1203 | num_chunks = TIFFNumberOfTiles(tif); | |
1204 | TIFFGetField(tif, TIFFTAG_TILEBYTECOUNTS, &bc); | |
1205 | } else { | |
1206 | num_chunks = TIFFNumberOfStrips(tif); | |
1207 | TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &bc); | |
1208 | } | |
1209 | ||
1210 | if (use_rawdata) { | |
1211 | chunk_size = (tsize_t) bc[0]; | |
1212 | for (chunk_no = 1; chunk_no < num_chunks; chunk_no++) | |
1213 | if ((tsize_t) bc[chunk_no] > chunk_size) | |
1214 | chunk_size = (tsize_t) bc[chunk_no]; | |
1215 | } else { | |
1216 | if (tiled_image) | |
1217 | chunk_size = TIFFTileSize(tif); | |
1218 | else | |
1219 | chunk_size = TIFFStripSize(tif); | |
1220 | } | |
1221 | buf_data = (unsigned char *)_TIFFmalloc(chunk_size); | |
1222 | if (!buf_data) { | |
1223 | TIFFError(filename, "Can't alloc %u bytes for %s.", | |
1224 | chunk_size, tiled_image ? "tiles" : "strips"); | |
1225 | return(FALSE); | |
1226 | } | |
1227 | ||
1228 | #if defined( EXP_ASCII85ENCODER ) | |
1229 | if ( ascii85 ) { | |
1230 | /* | |
1231 | * Allocate a buffer to hold the ASCII85 encoded data. Note | |
1232 | * that it is allocated with sufficient room to hold the | |
1233 | * encoded data (5*chunk_size/4) plus the EOD marker (+8) | |
1234 | * and formatting line breaks. The line breaks are more | |
1235 | * than taken care of by using 6*chunk_size/4 rather than | |
1236 | * 5*chunk_size/4. | |
1237 | */ | |
1238 | ||
1239 | ascii85_p = _TIFFmalloc( (chunk_size+(chunk_size/2)) + 8 ); | |
1240 | ||
1241 | if ( !ascii85_p ) { | |
1242 | _TIFFfree( buf_data ); | |
1243 | ||
1244 | TIFFError( filename, "Cannot allocate ASCII85 encoding buffer." ); | |
1245 | return ( FALSE ); | |
1246 | } | |
1247 | } | |
1248 | #endif | |
1249 | ||
1250 | TIFFGetFieldDefaulted(tif, TIFFTAG_FILLORDER, &fillorder); | |
1251 | for (chunk_no = 0; chunk_no < num_chunks; chunk_no++) { | |
1252 | if (ascii85) | |
1253 | Ascii85Init(); | |
1254 | else | |
1255 | breaklen = MAXLINE; | |
1256 | if (use_rawdata) { | |
1257 | if (tiled_image) | |
1258 | byte_count = TIFFReadRawTile(tif, chunk_no, | |
1259 | buf_data, chunk_size); | |
1260 | else | |
1261 | byte_count = TIFFReadRawStrip(tif, chunk_no, | |
1262 | buf_data, chunk_size); | |
1263 | if (fillorder == FILLORDER_LSB2MSB) | |
1264 | TIFFReverseBits(buf_data, byte_count); | |
1265 | } else { | |
1266 | if (tiled_image) | |
1267 | byte_count = TIFFReadEncodedTile(tif, | |
1268 | chunk_no, buf_data, | |
1269 | chunk_size); | |
1270 | else | |
1271 | byte_count = TIFFReadEncodedStrip(tif, | |
1272 | chunk_no, buf_data, | |
1273 | chunk_size); | |
1274 | } | |
1275 | if (byte_count < 0) { | |
1276 | TIFFError(filename, "Can't read %s %d.", | |
1277 | tiled_image ? "tile" : "strip", chunk_no); | |
1278 | if (ascii85) | |
1279 | Ascii85Put('\0', fd); | |
1280 | } | |
1281 | /* | |
1282 | * For images with alpha, matte against a white background; | |
1283 | * i.e. Cback * (1 - Aimage) where Cback = 1. We will fill the | |
1284 | * lower part of the buffer with the modified values. | |
1285 | * | |
1286 | * XXX: needs better solution | |
1287 | */ | |
1288 | if (alpha) { | |
1289 | int adjust, i, j = 0; | |
1290 | int ncomps = samplesperpixel - extrasamples; | |
1291 | for (i = 0; i < byte_count; i+=samplesperpixel) { | |
1292 | adjust = 255 - buf_data[i + ncomps]; | |
1293 | switch (ncomps) { | |
1294 | case 1: | |
1295 | buf_data[j++] = buf_data[i] + adjust; | |
1296 | break; | |
1297 | case 2: | |
1298 | buf_data[j++] = buf_data[i] + adjust; | |
1299 | buf_data[j++] = buf_data[i+1] + adjust; | |
1300 | break; | |
1301 | case 3: | |
1302 | buf_data[j++] = buf_data[i] + adjust; | |
1303 | buf_data[j++] = buf_data[i+1] + adjust; | |
1304 | buf_data[j++] = buf_data[i+2] + adjust; | |
1305 | break; | |
1306 | } | |
1307 | } | |
1308 | byte_count -= j; | |
1309 | } | |
1310 | ||
1311 | if (ascii85) { | |
1312 | #if defined( EXP_ASCII85ENCODER ) | |
1313 | ascii85_l = Ascii85EncodeBlock(ascii85_p, 1, buf_data, byte_count ); | |
1314 | ||
1315 | if ( ascii85_l > 0 ) | |
1316 | fwrite( ascii85_p, ascii85_l, 1, fd ); | |
1317 | #else | |
1318 | for (cp = buf_data; byte_count > 0; byte_count--) | |
1319 | Ascii85Put(*cp++, fd); | |
1320 | #endif | |
1321 | } | |
1322 | else | |
1323 | { | |
1324 | for (cp = buf_data; byte_count > 0; byte_count--) { | |
1325 | putc(hex[((*cp)>>4)&0xf], fd); | |
1326 | putc(hex[(*cp)&0xf], fd); | |
1327 | cp++; | |
1328 | ||
1329 | if (--breaklen <= 0) { | |
1330 | putc('\n', fd); | |
1331 | breaklen = MAXLINE; | |
1332 | } | |
1333 | } | |
1334 | } | |
1335 | ||
1336 | if ( !ascii85 ) { | |
1337 | if ( level2 || level3 ) | |
1338 | putc( '>', fd ); | |
1339 | putc('\n', fd); | |
1340 | } | |
1341 | #if !defined( EXP_ASCII85ENCODER ) | |
1342 | else | |
1343 | Ascii85Flush(fd); | |
1344 | #endif | |
1345 | } | |
1346 | ||
1347 | #if defined( EXP_ASCII85ENCODER ) | |
1348 | if ( ascii85_p ) | |
1349 | _TIFFfree( ascii85_p ); | |
1350 | #endif | |
1351 | ||
1352 | _TIFFfree(buf_data); | |
1353 | #ifdef ENABLE_BROKEN_BEGINENDDATA | |
1354 | fputs("%%EndData\n", fd); | |
1355 | #endif | |
1356 | return(TRUE); | |
1357 | } | |
1358 | ||
1359 | void | |
1360 | PSpage(FILE* fd, TIFF* tif, uint32 w, uint32 h) | |
1361 | { | |
1362 | char * imageOp = "image"; | |
1363 | ||
1364 | if ( useImagemask && (bitspersample == 1) ) | |
1365 | imageOp = "imagemask"; | |
1366 | ||
1367 | if ((level2 || level3) && PS_Lvl2page(fd, tif, w, h)) | |
1368 | return; | |
1369 | ps_bytesperrow = tf_bytesperrow - (extrasamples * bitspersample / 8)*w; | |
1370 | switch (photometric) { | |
1371 | case PHOTOMETRIC_RGB: | |
1372 | if (planarconfiguration == PLANARCONFIG_CONTIG) { | |
1373 | fprintf(fd, "%s", RGBcolorimage); | |
1374 | PSColorContigPreamble(fd, w, h, 3); | |
1375 | PSDataColorContig(fd, tif, w, h, 3); | |
1376 | } else { | |
1377 | PSColorSeparatePreamble(fd, w, h, 3); | |
1378 | PSDataColorSeparate(fd, tif, w, h, 3); | |
1379 | } | |
1380 | break; | |
1381 | case PHOTOMETRIC_SEPARATED: | |
1382 | /* XXX should emit CMYKcolorimage */ | |
1383 | if (planarconfiguration == PLANARCONFIG_CONTIG) { | |
1384 | PSColorContigPreamble(fd, w, h, 4); | |
1385 | PSDataColorContig(fd, tif, w, h, 4); | |
1386 | } else { | |
1387 | PSColorSeparatePreamble(fd, w, h, 4); | |
1388 | PSDataColorSeparate(fd, tif, w, h, 4); | |
1389 | } | |
1390 | break; | |
1391 | case PHOTOMETRIC_PALETTE: | |
1392 | fprintf(fd, "%s", RGBcolorimage); | |
1393 | PhotoshopBanner(fd, w, h, 1, 3, "false 3 colorimage"); | |
1394 | fprintf(fd, "/scanLine %ld string def\n", | |
1395 | (long) ps_bytesperrow * 3L); | |
1396 | fprintf(fd, "%lu %lu 8\n", | |
1397 | (unsigned long) w, (unsigned long) h); | |
1398 | fprintf(fd, "[%lu 0 0 -%lu 0 %lu]\n", | |
1399 | (unsigned long) w, (unsigned long) h, (unsigned long) h); | |
1400 | fprintf(fd, "{currentfile scanLine readhexstring pop} bind\n"); | |
1401 | fprintf(fd, "false 3 colorimage\n"); | |
1402 | PSDataPalette(fd, tif, w, h); | |
1403 | break; | |
1404 | case PHOTOMETRIC_MINISBLACK: | |
1405 | case PHOTOMETRIC_MINISWHITE: | |
1406 | PhotoshopBanner(fd, w, h, 1, 1, imageOp); | |
1407 | fprintf(fd, "/scanLine %ld string def\n", | |
1408 | (long) ps_bytesperrow); | |
1409 | fprintf(fd, "%lu %lu %d\n", | |
1410 | (unsigned long) w, (unsigned long) h, bitspersample); | |
1411 | fprintf(fd, "[%lu 0 0 -%lu 0 %lu]\n", | |
1412 | (unsigned long) w, (unsigned long) h, (unsigned long) h); | |
1413 | fprintf(fd, | |
1414 | "{currentfile scanLine readhexstring pop} bind\n"); | |
1415 | fprintf(fd, "%s\n", imageOp); | |
1416 | PSDataBW(fd, tif, w, h); | |
1417 | break; | |
1418 | } | |
1419 | putc('\n', fd); | |
1420 | } | |
1421 | ||
1422 | void | |
1423 | PSColorContigPreamble(FILE* fd, uint32 w, uint32 h, int nc) | |
1424 | { | |
1425 | ps_bytesperrow = nc * (tf_bytesperrow / samplesperpixel); | |
1426 | PhotoshopBanner(fd, w, h, 1, nc, "false %d colorimage"); | |
1427 | fprintf(fd, "/line %ld string def\n", (long) ps_bytesperrow); | |
1428 | fprintf(fd, "%lu %lu %d\n", | |
1429 | (unsigned long) w, (unsigned long) h, bitspersample); | |
1430 | fprintf(fd, "[%lu 0 0 -%lu 0 %lu]\n", | |
1431 | (unsigned long) w, (unsigned long) h, (unsigned long) h); | |
1432 | fprintf(fd, "{currentfile line readhexstring pop} bind\n"); | |
1433 | fprintf(fd, "false %d colorimage\n", nc); | |
1434 | } | |
1435 | ||
1436 | void | |
1437 | PSColorSeparatePreamble(FILE* fd, uint32 w, uint32 h, int nc) | |
1438 | { | |
1439 | int i; | |
1440 | ||
1441 | PhotoshopBanner(fd, w, h, ps_bytesperrow, nc, "true %d colorimage"); | |
1442 | for (i = 0; i < nc; i++) | |
1443 | fprintf(fd, "/line%d %ld string def\n", | |
1444 | i, (long) ps_bytesperrow); | |
1445 | fprintf(fd, "%lu %lu %d\n", | |
1446 | (unsigned long) w, (unsigned long) h, bitspersample); | |
1447 | fprintf(fd, "[%lu 0 0 -%lu 0 %lu] \n", | |
1448 | (unsigned long) w, (unsigned long) h, (unsigned long) h); | |
1449 | for (i = 0; i < nc; i++) | |
1450 | fprintf(fd, "{currentfile line%d readhexstring pop}bind\n", i); | |
1451 | fprintf(fd, "true %d colorimage\n", nc); | |
1452 | } | |
1453 | ||
1454 | #define DOBREAK(len, howmany, fd) \ | |
1455 | if (((len) -= (howmany)) <= 0) { \ | |
1456 | putc('\n', fd); \ | |
1457 | (len) = MAXLINE-(howmany); \ | |
1458 | } | |
1459 | #define PUTHEX(c,fd) putc(hex[((c)>>4)&0xf],fd); putc(hex[(c)&0xf],fd) | |
1460 | ||
1461 | void | |
1462 | PSDataColorContig(FILE* fd, TIFF* tif, uint32 w, uint32 h, int nc) | |
1463 | { | |
1464 | uint32 row; | |
1465 | int breaklen = MAXLINE, cc, es = samplesperpixel - nc; | |
1466 | unsigned char *tf_buf; | |
1467 | unsigned char *cp, c; | |
1468 | ||
1469 | (void) w; | |
1470 | tf_buf = (unsigned char *) _TIFFmalloc(tf_bytesperrow); | |
1471 | if (tf_buf == NULL) { | |
1472 | TIFFError(filename, "No space for scanline buffer"); | |
1473 | return; | |
1474 | } | |
1475 | for (row = 0; row < h; row++) { | |
1476 | if (TIFFReadScanline(tif, tf_buf, row, 0) < 0) | |
1477 | break; | |
1478 | cp = tf_buf; | |
1479 | if (alpha) { | |
1480 | int adjust; | |
1481 | cc = 0; | |
1482 | for (; cc < tf_bytesperrow; cc += samplesperpixel) { | |
1483 | DOBREAK(breaklen, nc, fd); | |
1484 | /* | |
1485 | * For images with alpha, matte against | |
1486 | * a white background; i.e. | |
1487 | * Cback * (1 - Aimage) | |
1488 | * where Cback = 1. | |
1489 | */ | |
1490 | adjust = 255 - cp[nc]; | |
1491 | switch (nc) { | |
1492 | case 4: c = *cp++ + adjust; PUTHEX(c,fd); | |
1493 | case 3: c = *cp++ + adjust; PUTHEX(c,fd); | |
1494 | case 2: c = *cp++ + adjust; PUTHEX(c,fd); | |
1495 | case 1: c = *cp++ + adjust; PUTHEX(c,fd); | |
1496 | } | |
1497 | cp += es; | |
1498 | } | |
1499 | } else { | |
1500 | cc = 0; | |
1501 | for (; cc < tf_bytesperrow; cc += samplesperpixel) { | |
1502 | DOBREAK(breaklen, nc, fd); | |
1503 | switch (nc) { | |
1504 | case 4: c = *cp++; PUTHEX(c,fd); | |
1505 | case 3: c = *cp++; PUTHEX(c,fd); | |
1506 | case 2: c = *cp++; PUTHEX(c,fd); | |
1507 | case 1: c = *cp++; PUTHEX(c,fd); | |
1508 | } | |
1509 | cp += es; | |
1510 | } | |
1511 | } | |
1512 | } | |
1513 | _TIFFfree((char *) tf_buf); | |
1514 | } | |
1515 | ||
1516 | void | |
1517 | PSDataColorSeparate(FILE* fd, TIFF* tif, uint32 w, uint32 h, int nc) | |
1518 | { | |
1519 | uint32 row; | |
1520 | int breaklen = MAXLINE, cc; | |
1521 | tsample_t s, maxs; | |
1522 | unsigned char *tf_buf; | |
1523 | unsigned char *cp, c; | |
1524 | ||
1525 | (void) w; | |
1526 | tf_buf = (unsigned char *) _TIFFmalloc(tf_bytesperrow); | |
1527 | if (tf_buf == NULL) { | |
1528 | TIFFError(filename, "No space for scanline buffer"); | |
1529 | return; | |
1530 | } | |
1531 | maxs = (samplesperpixel > nc ? nc : samplesperpixel); | |
1532 | for (row = 0; row < h; row++) { | |
1533 | for (s = 0; s < maxs; s++) { | |
1534 | if (TIFFReadScanline(tif, tf_buf, row, s) < 0) | |
1535 | break; | |
1536 | for (cp = tf_buf, cc = 0; cc < tf_bytesperrow; cc++) { | |
1537 | DOBREAK(breaklen, 1, fd); | |
1538 | c = *cp++; | |
1539 | PUTHEX(c,fd); | |
1540 | } | |
1541 | } | |
1542 | } | |
1543 | _TIFFfree((char *) tf_buf); | |
1544 | } | |
1545 | ||
1546 | #define PUTRGBHEX(c,fd) \ | |
1547 | PUTHEX(rmap[c],fd); PUTHEX(gmap[c],fd); PUTHEX(bmap[c],fd) | |
1548 | ||
1549 | void | |
1550 | PSDataPalette(FILE* fd, TIFF* tif, uint32 w, uint32 h) | |
1551 | { | |
1552 | uint16 *rmap, *gmap, *bmap; | |
1553 | uint32 row; | |
1554 | int breaklen = MAXLINE, cc, nc; | |
1555 | unsigned char *tf_buf; | |
1556 | unsigned char *cp, c; | |
1557 | ||
1558 | (void) w; | |
1559 | if (!TIFFGetField(tif, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap)) { | |
1560 | TIFFError(filename, "Palette image w/o \"Colormap\" tag"); | |
1561 | return; | |
1562 | } | |
1563 | switch (bitspersample) { | |
1564 | case 8: case 4: case 2: case 1: | |
1565 | break; | |
1566 | default: | |
1567 | TIFFError(filename, "Depth %d not supported", bitspersample); | |
1568 | return; | |
1569 | } | |
1570 | nc = 3 * (8 / bitspersample); | |
1571 | tf_buf = (unsigned char *) _TIFFmalloc(tf_bytesperrow); | |
1572 | if (tf_buf == NULL) { | |
1573 | TIFFError(filename, "No space for scanline buffer"); | |
1574 | return; | |
1575 | } | |
1576 | if (checkcmap(tif, 1<<bitspersample, rmap, gmap, bmap) == 16) { | |
1577 | int i; | |
1578 | #define CVT(x) ((unsigned short) (((x) * 255) / ((1U<<16)-1))) | |
1579 | for (i = (1<<bitspersample)-1; i >= 0; i--) { | |
1580 | rmap[i] = CVT(rmap[i]); | |
1581 | gmap[i] = CVT(gmap[i]); | |
1582 | bmap[i] = CVT(bmap[i]); | |
1583 | } | |
1584 | #undef CVT | |
1585 | } | |
1586 | for (row = 0; row < h; row++) { | |
1587 | if (TIFFReadScanline(tif, tf_buf, row, 0) < 0) | |
1588 | break; | |
1589 | for (cp = tf_buf, cc = 0; cc < tf_bytesperrow; cc++) { | |
1590 | DOBREAK(breaklen, nc, fd); | |
1591 | switch (bitspersample) { | |
1592 | case 8: | |
1593 | c = *cp++; PUTRGBHEX(c, fd); | |
1594 | break; | |
1595 | case 4: | |
1596 | c = *cp++; PUTRGBHEX(c&0xf, fd); | |
1597 | c >>= 4; PUTRGBHEX(c, fd); | |
1598 | break; | |
1599 | case 2: | |
1600 | c = *cp++; PUTRGBHEX(c&0x3, fd); | |
1601 | c >>= 2; PUTRGBHEX(c&0x3, fd); | |
1602 | c >>= 2; PUTRGBHEX(c&0x3, fd); | |
1603 | c >>= 2; PUTRGBHEX(c, fd); | |
1604 | break; | |
1605 | case 1: | |
1606 | c = *cp++; PUTRGBHEX(c&0x1, fd); | |
1607 | c >>= 1; PUTRGBHEX(c&0x1, fd); | |
1608 | c >>= 1; PUTRGBHEX(c&0x1, fd); | |
1609 | c >>= 1; PUTRGBHEX(c&0x1, fd); | |
1610 | c >>= 1; PUTRGBHEX(c&0x1, fd); | |
1611 | c >>= 1; PUTRGBHEX(c&0x1, fd); | |
1612 | c >>= 1; PUTRGBHEX(c&0x1, fd); | |
1613 | c >>= 1; PUTRGBHEX(c, fd); | |
1614 | break; | |
1615 | } | |
1616 | } | |
1617 | } | |
1618 | _TIFFfree((char *) tf_buf); | |
1619 | } | |
1620 | ||
1621 | void | |
1622 | PSDataBW(FILE* fd, TIFF* tif, uint32 w, uint32 h) | |
1623 | { | |
1624 | int breaklen = MAXLINE; | |
1625 | unsigned char* tf_buf; | |
1626 | unsigned char* cp; | |
1627 | tsize_t stripsize = TIFFStripSize(tif); | |
1628 | tstrip_t s; | |
1629 | ||
1630 | #if defined( EXP_ASCII85ENCODER ) | |
1631 | int ascii85_l; /* Length, in bytes, of ascii85_p[] data */ | |
1632 | uint8 *ascii85_p = 0; /* Holds ASCII85 encoded data */ | |
1633 | #endif | |
1634 | ||
1635 | (void) w; (void) h; | |
1636 | tf_buf = (unsigned char *) _TIFFmalloc(stripsize); | |
1637 | memset(tf_buf, 0, stripsize); | |
1638 | if (tf_buf == NULL) { | |
1639 | TIFFError(filename, "No space for scanline buffer"); | |
1640 | return; | |
1641 | } | |
1642 | ||
1643 | #if defined( EXP_ASCII85ENCODER ) | |
1644 | if ( ascii85 ) { | |
1645 | /* | |
1646 | * Allocate a buffer to hold the ASCII85 encoded data. Note | |
1647 | * that it is allocated with sufficient room to hold the | |
1648 | * encoded data (5*stripsize/4) plus the EOD marker (+8) | |
1649 | * and formatting line breaks. The line breaks are more | |
1650 | * than taken care of by using 6*stripsize/4 rather than | |
1651 | * 5*stripsize/4. | |
1652 | */ | |
1653 | ||
1654 | ascii85_p = _TIFFmalloc( (stripsize+(stripsize/2)) + 8 ); | |
1655 | ||
1656 | if ( !ascii85_p ) { | |
1657 | _TIFFfree( tf_buf ); | |
1658 | ||
1659 | TIFFError( filename, "Cannot allocate ASCII85 encoding buffer." ); | |
1660 | return; | |
1661 | } | |
1662 | } | |
1663 | #endif | |
1664 | ||
1665 | if (ascii85) | |
1666 | Ascii85Init(); | |
1667 | ||
1668 | for (s = 0; s < TIFFNumberOfStrips(tif); s++) { | |
1669 | int cc = TIFFReadEncodedStrip(tif, s, tf_buf, stripsize); | |
1670 | if (cc < 0) { | |
1671 | TIFFError(filename, "Can't read strip"); | |
1672 | break; | |
1673 | } | |
1674 | cp = tf_buf; | |
1675 | if (photometric == PHOTOMETRIC_MINISWHITE) { | |
1676 | for (cp += cc; --cp >= tf_buf;) | |
1677 | *cp = ~*cp; | |
1678 | cp++; | |
1679 | } | |
1680 | if (ascii85) { | |
1681 | #if defined( EXP_ASCII85ENCODER ) | |
1682 | if (alpha) { | |
1683 | int adjust, i; | |
1684 | for (i = 0; i < cc; i+=2) { | |
1685 | adjust = 255 - cp[i + 1]; | |
1686 | cp[i / 2] = cp[i] + adjust; | |
1687 | } | |
1688 | cc /= 2; | |
1689 | } | |
1690 | ||
1691 | ascii85_l = Ascii85EncodeBlock( ascii85_p, 1, cp, cc ); | |
1692 | ||
1693 | if ( ascii85_l > 0 ) | |
1694 | fwrite( ascii85_p, ascii85_l, 1, fd ); | |
1695 | #else | |
1696 | while (cc-- > 0) | |
1697 | Ascii85Put(*cp++, fd); | |
1698 | #endif /* EXP_ASCII85_ENCODER */ | |
1699 | } else { | |
1700 | unsigned char c; | |
1701 | ||
1702 | if (alpha) { | |
1703 | int adjust; | |
1704 | while (cc-- > 0) { | |
1705 | DOBREAK(breaklen, 1, fd); | |
1706 | /* | |
1707 | * For images with alpha, matte against | |
1708 | * a white background; i.e. | |
1709 | * Cback * (1 - Aimage) | |
1710 | * where Cback = 1. | |
1711 | */ | |
1712 | adjust = 255 - cp[1]; | |
1713 | c = *cp++ + adjust; PUTHEX(c,fd); | |
1714 | cp++, cc--; | |
1715 | } | |
1716 | } else { | |
1717 | while (cc-- > 0) { | |
1718 | c = *cp++; | |
1719 | DOBREAK(breaklen, 1, fd); | |
1720 | PUTHEX(c, fd); | |
1721 | } | |
1722 | } | |
1723 | } | |
1724 | } | |
1725 | ||
1726 | if ( !ascii85 ) | |
1727 | { | |
1728 | if ( level2 || level3) | |
1729 | fputs(">\n", fd); | |
1730 | } | |
1731 | #if !defined( EXP_ASCII85ENCODER ) | |
1732 | else | |
1733 | Ascii85Flush(fd); | |
1734 | #else | |
1735 | if ( ascii85_p ) | |
1736 | _TIFFfree( ascii85_p ); | |
1737 | #endif | |
1738 | ||
1739 | _TIFFfree(tf_buf); | |
1740 | } | |
1741 | ||
1742 | void | |
1743 | PSRawDataBW(FILE* fd, TIFF* tif, uint32 w, uint32 h) | |
1744 | { | |
1745 | uint32 *bc; | |
1746 | uint32 bufsize; | |
1747 | int breaklen = MAXLINE, cc; | |
1748 | uint16 fillorder; | |
1749 | unsigned char *tf_buf; | |
1750 | unsigned char *cp, c; | |
1751 | tstrip_t s; | |
1752 | ||
1753 | #if defined( EXP_ASCII85ENCODER ) | |
1754 | int ascii85_l; /* Length, in bytes, of ascii85_p[] data */ | |
1755 | uint8 * ascii85_p = 0; /* Holds ASCII85 encoded data */ | |
1756 | #endif | |
1757 | ||
1758 | (void) w; (void) h; | |
1759 | TIFFGetFieldDefaulted(tif, TIFFTAG_FILLORDER, &fillorder); | |
1760 | TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &bc); | |
1761 | ||
1762 | /* | |
1763 | * Find largest strip: | |
1764 | */ | |
1765 | ||
1766 | bufsize = bc[0]; | |
1767 | ||
1768 | for ( s = 0; ++s < (tstrip_t)tf_numberstrips; ) { | |
1769 | if ( bc[s] > bufsize ) | |
1770 | bufsize = bc[s]; | |
1771 | } | |
1772 | ||
1773 | tf_buf = (unsigned char*) _TIFFmalloc(bufsize); | |
1774 | if (tf_buf == NULL) { | |
1775 | TIFFError(filename, "No space for strip buffer"); | |
1776 | return; | |
1777 | } | |
1778 | ||
1779 | #if defined( EXP_ASCII85ENCODER ) | |
1780 | if ( ascii85 ) { | |
1781 | /* | |
1782 | * Allocate a buffer to hold the ASCII85 encoded data. Note | |
1783 | * that it is allocated with sufficient room to hold the | |
1784 | * encoded data (5*bufsize/4) plus the EOD marker (+8) | |
1785 | * and formatting line breaks. The line breaks are more | |
1786 | * than taken care of by using 6*bufsize/4 rather than | |
1787 | * 5*bufsize/4. | |
1788 | */ | |
1789 | ||
1790 | ascii85_p = _TIFFmalloc( (bufsize+(bufsize/2)) + 8 ); | |
1791 | ||
1792 | if ( !ascii85_p ) { | |
1793 | _TIFFfree( tf_buf ); | |
1794 | ||
1795 | TIFFError( filename, "Cannot allocate ASCII85 encoding buffer." ); | |
1796 | return; | |
1797 | } | |
1798 | } | |
1799 | #endif | |
1800 | ||
1801 | for (s = 0; s < (tstrip_t) tf_numberstrips; s++) { | |
1802 | cc = TIFFReadRawStrip(tif, s, tf_buf, bc[s]); | |
1803 | if (cc < 0) { | |
1804 | TIFFError(filename, "Can't read strip"); | |
1805 | break; | |
1806 | } | |
1807 | if (fillorder == FILLORDER_LSB2MSB) | |
1808 | TIFFReverseBits(tf_buf, cc); | |
1809 | if (!ascii85) { | |
1810 | for (cp = tf_buf; cc > 0; cc--) { | |
1811 | DOBREAK(breaklen, 1, fd); | |
1812 | c = *cp++; | |
1813 | PUTHEX(c, fd); | |
1814 | } | |
1815 | fputs(">\n", fd); | |
1816 | breaklen = MAXLINE; | |
1817 | } else { | |
1818 | Ascii85Init(); | |
1819 | #if defined( EXP_ASCII85ENCODER ) | |
1820 | ascii85_l = Ascii85EncodeBlock( ascii85_p, 1, tf_buf, cc ); | |
1821 | ||
1822 | if ( ascii85_l > 0 ) | |
1823 | fwrite( ascii85_p, ascii85_l, 1, fd ); | |
1824 | #else | |
1825 | for (cp = tf_buf; cc > 0; cc--) | |
1826 | Ascii85Put(*cp++, fd); | |
1827 | Ascii85Flush(fd); | |
1828 | #endif /* EXP_ASCII85ENCODER */ | |
1829 | } | |
1830 | } | |
1831 | _TIFFfree((char *) tf_buf); | |
1832 | ||
1833 | #if defined( EXP_ASCII85ENCODER ) | |
1834 | if ( ascii85_p ) | |
1835 | _TIFFfree( ascii85_p ); | |
1836 | #endif | |
1837 | } | |
1838 | ||
1839 | void | |
1840 | Ascii85Init(void) | |
1841 | { | |
1842 | ascii85breaklen = 2*MAXLINE; | |
1843 | ascii85count = 0; | |
1844 | } | |
1845 | ||
1846 | static char* | |
1847 | Ascii85Encode(unsigned char* raw) | |
1848 | { | |
1849 | static char encoded[6]; | |
1850 | uint32 word; | |
1851 | ||
1852 | word = (((raw[0]<<8)+raw[1])<<16) + (raw[2]<<8) + raw[3]; | |
1853 | if (word != 0L) { | |
1854 | uint32 q; | |
1855 | uint16 w1; | |
1856 | ||
1857 | q = word / (85L*85*85*85); /* actually only a byte */ | |
1858 | encoded[0] = (char) (q + '!'); | |
1859 | ||
1860 | word -= q * (85L*85*85*85); q = word / (85L*85*85); | |
1861 | encoded[1] = (char) (q + '!'); | |
1862 | ||
1863 | word -= q * (85L*85*85); q = word / (85*85); | |
1864 | encoded[2] = (char) (q + '!'); | |
1865 | ||
1866 | w1 = (uint16) (word - q*(85L*85)); | |
1867 | encoded[3] = (char) ((w1 / 85) + '!'); | |
1868 | encoded[4] = (char) ((w1 % 85) + '!'); | |
1869 | encoded[5] = '\0'; | |
1870 | } else | |
1871 | encoded[0] = 'z', encoded[1] = '\0'; | |
1872 | return (encoded); | |
1873 | } | |
1874 | ||
1875 | void | |
1876 | Ascii85Put(unsigned char code, FILE* fd) | |
1877 | { | |
1878 | ascii85buf[ascii85count++] = code; | |
1879 | if (ascii85count >= 4) { | |
1880 | unsigned char* p; | |
1881 | int n; | |
1882 | ||
1883 | for (n = ascii85count, p = ascii85buf; n >= 4; n -= 4, p += 4) { | |
1884 | char* cp; | |
1885 | for (cp = Ascii85Encode(p); *cp; cp++) { | |
1886 | putc(*cp, fd); | |
1887 | if (--ascii85breaklen == 0) { | |
1888 | putc('\n', fd); | |
1889 | ascii85breaklen = 2*MAXLINE; | |
1890 | } | |
1891 | } | |
1892 | } | |
1893 | _TIFFmemcpy(ascii85buf, p, n); | |
1894 | ascii85count = n; | |
1895 | } | |
1896 | } | |
1897 | ||
1898 | void | |
1899 | Ascii85Flush(FILE* fd) | |
1900 | { | |
1901 | if (ascii85count > 0) { | |
1902 | char* res; | |
1903 | _TIFFmemset(&ascii85buf[ascii85count], 0, 3); | |
1904 | res = Ascii85Encode(ascii85buf); | |
1905 | fwrite(res[0] == 'z' ? "!!!!" : res, ascii85count + 1, 1, fd); | |
1906 | } | |
1907 | fputs("~>\n", fd); | |
1908 | } | |
1909 | #if defined( EXP_ASCII85ENCODER) | |
1910 | \f | |
1911 | #define A85BREAKCNTR ascii85breaklen | |
1912 | #define A85BREAKLEN (2*MAXLINE) | |
1913 | ||
1914 | /***************************************************************************** | |
1915 | * | |
1916 | * Name: Ascii85EncodeBlock( ascii85_p, f_eod, raw_p, raw_l ) | |
1917 | * | |
1918 | * Description: This routine will encode the raw data in the buffer described | |
1919 | * by raw_p and raw_l into ASCII85 format and store the encoding | |
1920 | * in the buffer given by ascii85_p. | |
1921 | * | |
1922 | * Parameters: ascii85_p - A buffer supplied by the caller which will | |
1923 | * contain the encoded ASCII85 data. | |
1924 | * f_eod - Flag: Nz means to end the encoded buffer with | |
1925 | * an End-Of-Data marker. | |
1926 | * raw_p - Pointer to the buffer of data to be encoded | |
1927 | * raw_l - Number of bytes in raw_p[] to be encoded | |
1928 | * | |
1929 | * Returns: (int) < 0 Error, see errno | |
1930 | * >= 0 Number of bytes written to ascii85_p[]. | |
1931 | * | |
1932 | * Notes: An external variable given by A85BREAKCNTR is used to | |
1933 | * determine when to insert newline characters into the | |
1934 | * encoded data. As each byte is placed into ascii85_p this | |
1935 | * external is decremented. If the variable is decrement to | |
1936 | * or past zero then a newline is inserted into ascii85_p | |
1937 | * and the A85BREAKCNTR is then reset to A85BREAKLEN. | |
1938 | * Note: for efficiency reasons the A85BREAKCNTR variable | |
1939 | * is not actually checked on *every* character | |
1940 | * placed into ascii85_p but often only for every | |
1941 | * 5 characters. | |
1942 | * | |
1943 | * THE CALLER IS RESPONSIBLE FOR ENSURING THAT ASCII85_P[] IS | |
1944 | * SUFFICIENTLY LARGE TO THE ENCODED DATA! | |
1945 | * You will need at least 5 * (raw_l/4) bytes plus space for | |
1946 | * newline characters and space for an EOD marker (if | |
1947 | * requested). A safe calculation is to use 6*(raw_l/4) + 8 | |
1948 | * to size ascii85_p. | |
1949 | * | |
1950 | *****************************************************************************/ | |
1951 | ||
1952 | int Ascii85EncodeBlock( uint8 * ascii85_p, unsigned f_eod, const uint8 * raw_p, int raw_l ) | |
1953 | ||
1954 | { | |
1955 | char ascii85[5]; /* Encoded 5 tuple */ | |
1956 | int ascii85_l; /* Number of bytes written to ascii85_p[] */ | |
1957 | int rc; /* Return code */ | |
1958 | uint32 val32; /* Unencoded 4 tuple */ | |
1959 | ||
1960 | ascii85_l = 0; /* Nothing written yet */ | |
1961 | ||
1962 | if ( raw_p ) | |
1963 | { | |
1964 | --raw_p; /* Prepare for pre-increment fetches */ | |
1965 | ||
1966 | for ( ; raw_l > 3; raw_l -= 4 ) | |
1967 | { | |
1968 | val32 = *(++raw_p) << 24; | |
1969 | val32 += *(++raw_p) << 16; | |
1970 | val32 += *(++raw_p) << 8; | |
1971 | val32 += *(++raw_p); | |
1972 | ||
1973 | if ( val32 == 0 ) /* Special case */ | |
1974 | { | |
1975 | ascii85_p[ascii85_l] = 'z'; | |
1976 | rc = 1; | |
1977 | } | |
1978 | ||
1979 | else | |
1980 | { | |
1981 | ascii85[4] = (char) ((val32 % 85) + 33); | |
1982 | val32 /= 85; | |
1983 | ||
1984 | ascii85[3] = (char) ((val32 % 85) + 33); | |
1985 | val32 /= 85; | |
1986 | ||
1987 | ascii85[2] = (char) ((val32 % 85) + 33); | |
1988 | val32 /= 85; | |
1989 | ||
1990 | ascii85[1] = (char) ((val32 % 85) + 33); | |
1991 | ascii85[0] = (char) ((val32 / 85) + 33); | |
1992 | ||
1993 | _TIFFmemcpy( &ascii85_p[ascii85_l], ascii85, sizeof(ascii85) ); | |
1994 | rc = sizeof(ascii85); | |
1995 | } | |
1996 | ||
1997 | ascii85_l += rc; | |
1998 | ||
1999 | if ( (A85BREAKCNTR -= rc) <= 0 ) | |
2000 | { | |
2001 | ascii85_p[ascii85_l] = '\n'; | |
2002 | ++ascii85_l; | |
2003 | A85BREAKCNTR = A85BREAKLEN; | |
2004 | } | |
2005 | } | |
2006 | ||
2007 | /* | |
2008 | * Output any straggler bytes: | |
2009 | */ | |
2010 | ||
2011 | if ( raw_l > 0 ) | |
2012 | { | |
2013 | int len; /* Output this many bytes */ | |
2014 | ||
2015 | len = raw_l + 1; | |
2016 | val32 = *++raw_p << 24; /* Prime the pump */ | |
2017 | ||
2018 | if ( --raw_l > 0 ) val32 += *(++raw_p) << 16; | |
2019 | if ( --raw_l > 0 ) val32 += *(++raw_p) << 8; | |
2020 | ||
2021 | val32 /= 85; | |
2022 | ||
2023 | ascii85[3] = (char) ((val32 % 85) + 33); | |
2024 | val32 /= 85; | |
2025 | ||
2026 | ascii85[2] = (char) ((val32 % 85) + 33); | |
2027 | val32 /= 85; | |
2028 | ||
2029 | ascii85[1] = (char) ((val32 % 85) + 33); | |
2030 | ascii85[0] = (char) ((val32 / 85) + 33); | |
2031 | ||
2032 | _TIFFmemcpy( &ascii85_p[ascii85_l], ascii85, len ); | |
2033 | ascii85_l += len; | |
2034 | } | |
2035 | } | |
2036 | ||
2037 | /* | |
2038 | * If requested add an ASCII85 End Of Data marker: | |
2039 | */ | |
2040 | ||
2041 | if ( f_eod ) | |
2042 | { | |
2043 | ascii85_p[ascii85_l++] = '~'; | |
2044 | ascii85_p[ascii85_l++] = '>'; | |
2045 | ascii85_p[ascii85_l++] = '\n'; | |
2046 | } | |
2047 | ||
2048 | return ( ascii85_l ); | |
2049 | ||
2050 | } /* Ascii85EncodeBlock() */ | |
2051 | ||
2052 | #endif /* EXP_ASCII85ENCODER */ | |
2053 | ||
2054 | ||
2055 | char* stuff[] = { | |
2056 | "usage: tiff2ps [options] input.tif ...", | |
2057 | "where options are:", | |
2058 | " -1 generate PostScript Level 1 (default)", | |
2059 | " -2 generate PostScript Level 2", | |
2060 | " -3 generate PostScript Level 3", | |
2061 | " -8 disable use of ASCII85 encoding with PostScript Level 2/3", | |
2062 | " -a convert all directories in file (default is first)", | |
2063 | " -b # set the bottom margin to # inches", | |
2064 | " -c center image (-b and -l still add to this)", | |
2065 | " -d # convert directory number #", | |
2066 | " -D enable duplex printing (two pages per sheet of paper)", | |
2067 | " -e generate Encapsulated PostScript (EPS) (implies -z)", | |
2068 | " -h # assume printed page height is # inches (default 11)", | |
2069 | " -w # assume printed page width is # inches (default 8.5)", | |
2070 | " -H # split image if height is more than # inches", | |
2071 | " -L # overLap split images by # inches", | |
2072 | " -i # enable/disable (Nz/0) pixel interpolation (default: enable)", | |
2073 | " -l # set the left margin to # inches", | |
2074 | " -m use \"imagemask\" operator instead of \"image\"", | |
2075 | " -o # convert directory at file offset #", | |
2076 | " -O file write PostScript to file instead of standard output", | |
2077 | " -p generate regular PostScript", | |
2078 | " -r rotate by 180 degrees", | |
2079 | " -s generate PostScript for a single image", | |
2080 | " -T print pages for top edge binding", | |
2081 | " -x override resolution units as centimeters", | |
2082 | " -y override resolution units as inches", | |
2083 | " -z enable printing in the deadzone (only for PostScript Level 2/3)", | |
2084 | NULL | |
2085 | }; | |
2086 | ||
2087 | static void | |
2088 | usage(int code) | |
2089 | { | |
2090 | char buf[BUFSIZ]; | |
2091 | int i; | |
2092 | ||
2093 | setbuf(stderr, buf); | |
2094 | fprintf(stderr, "%s\n\n", TIFFGetVersion()); | |
2095 | for (i = 0; stuff[i] != NULL; i++) | |
2096 | fprintf(stderr, "%s\n", stuff[i]); | |
2097 | exit(code); | |
2098 | } | |
2099 | ||
2100 | /* vim: set ts=8 sts=8 sw=8 noet: */ |