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