OSDN Git Service

updated codes.
[putex/putex.git] / src / dvisourc / dvitiff.c
1 /* Copyright 1994,1995,1996,1997,1998,1999 Y&Y, Inc.\r
2    Copyright 2007 TeX Users Group\r
3    Copyright 2014 Clerk Ma\r
4 \r
5    This program is free software; you can redistribute it and/or modify\r
6    it under the terms of the GNU General Public License as published by\r
7    the Free Software Foundation; either version 2 of the License, or\r
8    (at your option) any later version.\r
9 \r
10    This program is distributed in the hope that it will be useful, but\r
11    WITHOUT ANY WARRANTY; without even the implied warranty of\r
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
13    General Public License for more details.\r
14 \r
15    You should have received a copy of the GNU General Public License\r
16    along with this program; if not, write to the Free Software\r
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\r
18    02110-1301 USA.  */\r
19 \r
20 \r
21 /****************************************************************************/\r
22 /* Make PS code from TIFF image file 1, 2, 4, 8 bit pixels only */\r
23 /* Support palette color images => expands to RGB */\r
24 /* Support 24 bit color images converts RBG to gray if colorimage not avail */\r
25 /* Supports: input side - no compression, TIFF_CCITT, LZW, and PACK_BITS */\r
26 /* Does not support BitsPerSample other than power of 2 */\r
27 /* Does not support compression schemes 3 and 4 (CCITT) */\r
28 /* Supports: output side - no compression, ASCII85, LZW, and PACK_BITS */\r
29 /****************************************************************************/\r
30 \r
31 /* Also, code for some other DVIWindo \specials */\r
32 \r
33 #include "dvipsone.h"\r
34 #include "dvispeci.h"\r
35 \r
36 #define DEBUGTIFF         /* to get in extra tracing code */\r
37 \r
38 /* #define DEBUGBMP */\r
39 \r
40 /* #define DEBUGLZWENCODE */\r
41 \r
42 /* #define DEBUGRUNLENGTH */\r
43 \r
44 /* #define DEBUGCLEANUP */\r
45 \r
46 #define PSLEVEL2\r
47 \r
48 #define LZWCOMPRESSION\r
49 \r
50 #define MAXCOLUMNHEX 72\r
51 \r
52 #define MAXCOLUMNASCII 75\r
53 \r
54 #ifdef TIFF\r
55 \r
56 /* constants for LZW compression/decompression tables */\r
57 \r
58 #define MAXCODES  4096 /* to deal with up to 12 bit codes */\r
59 #define MAXCHR    256  /* 2^8 possible bytes */\r
60 #define CLEAR     256  /* clear string table code */\r
61 #define EOD       257  /* end of data code */\r
62 #define FIRSTCODE 258  /* first code available - new string */\r
63 \r
64 #ifdef PSLEVEL2\r
65   int bRunLengthFlag;   /* Use RunLengthDecode filter 96/Dec/24 */\r
66   #ifdef LZWCOMPRESSION\r
67   int bLZWFlag;         /* Use LZWDecode filter 96/Dec/30 */\r
68   #endif\r
69 /*  can have either of the above set, or none, but not both */\r
70 #endif\r
71 \r
72 unsigned char *StripData;  /* address of Strip Buffer */\r
73 \r
74 unsigned int StripDataLen; /* length of Strip Buffer */\r
75 \r
76 long InStripLen;        /* length of Strip in file 96/Nov/17 */\r
77 \r
78 typedef int BOOL;\r
79 \r
80 char infilename[FILENAME_MAX] = "";\r
81 \r
82 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
83 \r
84 /* using definitions in dvispeci.h */\r
85 \r
86 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
87 \r
88 /* #define MAXIMAGE 4096 */   /* maximum rows & columns - sanity check */\r
89 \r
90 #define MAXIMAGE 65536    /* maximum rows & columns - sanity check */\r
91 \r
92 BOOL bInvertImage   = 0;  /* should gray levels be inverted ? */\r
93 BOOL bColorImage    = 0;  /* is it a color image ? */\r
94                           /* i.e. RGB or color palette */\r
95 BOOL bExpandColor   = 0;  /* color palette image - expand to 24 bit */\r
96                           /* set when ColorMapPtr non-NULL */\r
97 BOOL bCompressColor = 0;  /* compress 24 bit color to one byte */\r
98                           /* for non-color PS output device ? */\r
99                           /* and for BMP with gray palette */\r
100 BOOL bExpandGray    = 0;  /* has Palette, but Palette is gray */\r
101 BOOL bGrayFlag      = 0;  /* non-zero if Palette is gray BMP palette */\r
102 BOOL bLinearFlag    = 0;  /* non-zero if palette is linear BMP palette */\r
103 int PaletteSize     = 0;  /* number of entries in palette */\r
104 \r
105 /* For Windows NT could declare USESHORTINT since 16 bit quantities */\r
106 \r
107 /* #define USESHORTINT */\r
108 \r
109 #ifdef USESHORTINT\r
110 unsigned short int *Palette = NULL; /* pointer to palette */\r
111 #else\r
112 unsigned int *Palette = NULL;       /* pointer to palette */\r
113 #endif\r
114 \r
115 /* char *eps_magic = "\\r
116 currentscreen pop\n\\r
117 {1 add 180 mul cos 1 0.08 add mul exch 2 add 180 mul cos 1 0.08 sub\n\\r
118 mul add 2 div} bind setscreen % Copyright (C) Y&Y 1989\n\\r
119 "; */\r
120 \r
121 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
122 \r
123 /* set to 0.0 0.0 0.0 at top of page ? */\r
124 \r
125 int bTextColor=0;\r
126 \r
127 double textred=0.0;     /* color of text */\r
128 double textgreen=0.0;\r
129 double textblue=0.0;\r
130 \r
131 int bRuleColor=0;\r
132 \r
133 double rulered=0.0;     /* color of rules */\r
134 double rulegreen=0.0;\r
135 double ruleblue=0.0;\r
136 \r
137 int bFigureColor=0;     /* figure color has been specified */\r
138 \r
139 double figurered=0.0;   /* foreground of figure */\r
140 double figuregreen=0.0;\r
141 double figureblue=0.0;\r
142 \r
143 double backred=1.0;     /* background of figure */\r
144 double backgreen=1.0;\r
145 double backblue=1.0;\r
146 \r
147 int bReverseVideo=0;\r
148 \r
149 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
150 \r
151 /* Some code imported from DVIWindo winspeci.c */\r
152 \r
153 /* Stuff for reading simple uncompressed TIFF files (& PackBits compressed) */\r
154 \r
155 unsigned int TIFFVersion;     /* TIFF version number */\r
156 unsigned int bLeastFirst=1;     /* least significant first */\r
157 unsigned int IFDCount;        /* number of items image file directory */\r
158 unsigned long IFDPosition;      /* position of image file directory */\r
159 \r
160 //#pragma optimize ("lge", off)\r
161 \r
162 /* static unsigned short int ureadtwo(FILE *input) {\r
163   unsigned short int c, d;\r
164   c = (unsigned short int) getc(input);\r
165   d = (unsigned short int) getc(input); \r
166   if (bLeastFirst != 0) return ((d << 8) | c);\r
167   else return ((c << 8) | d);\r
168 } */\r
169 \r
170 static unsigned int ureadtwo(FILE *input)\r
171 {\r
172   unsigned int c, d;\r
173   c = (unsigned int) getc(input);\r
174   d = (unsigned int) getc(input);\r
175   if (bLeastFirst != 0)\r
176     return ((d << 8) | c);\r
177   else\r
178     return ((c << 8) | d);\r
179 }\r
180 \r
181 static unsigned long ureadfour(FILE *input)\r
182 {\r
183   unsigned long c, d, e, f;\r
184   c = (unsigned long) getc(input);\r
185   d = (unsigned long) getc(input);\r
186   e = (unsigned long) getc(input);\r
187   f = (unsigned long) getc(input);\r
188   if (bLeastFirst != 0)\r
189     return ((((((f << 8) | e) << 8) | d) << 8) | c);\r
190   else\r
191     return ((((((c << 8) | d) << 8) | e) << 8) | f);\r
192 }\r
193 \r
194 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
195 \r
196 /* char *typename[6] = {"", "BYTE ", "ASCII", "SHORT", "LONG ", "RATIO"}; */\r
197 \r
198 int typesize[6] = {0, 1, 1, 2, 4, 8};   /* units of length/count */\r
199 \r
200 unsigned long TIFFOffset, TIFFLength;\r
201 \r
202 long PSOffset, PSLength, MetaOffset, MetaLength; /* not used ? */\r
203 \r
204 /* we are ignoring the possibility here that length > 1 and such ... */\r
205 \r
206 long indirectvalue (unsigned int type, long length, long offset, FILE *input)\r
207 {\r
208   long present, val=0;\r
209 \r
210 /*  UNUSED (length); */\r
211 #ifdef DEBUGTIFF\r
212   if (length > 1 && traceflag)\r
213   {\r
214     sprintf(logline, "Length %d\n", length);\r
215     showline(logline, 0);\r
216   }\r
217 #endif\r
218   present = ftell(input);     /* remember where we are */\r
219   if (fseek(input, (long) (offset + TIFFOffset), SEEK_SET) != 0)\r
220   {\r
221     sprintf(logline, " Error in seek %s\n", " to indirect value\n");\r
222     showline(logline, 1);\r
223   }\r
224   if (type == TYPE_LONG) val = (long) ureadfour(input);\r
225   else if (type == TYPE_SHORT) val = ureadtwo(input);\r
226   else if (type == TYPE_BYTE) val = getc(input);\r
227   else showline(" Invalid Indirect Value\n", 1);\r
228   fseek(input, present, SEEK_SET);  /* return to where we were */\r
229   return val;\r
230 }\r
231 \r
232 /* get value of a tag field in TIFF file */\r
233 \r
234 long extractvalue (unsigned int type, unsigned long length, long offset, FILE *input)\r
235 {\r
236   if (length == 0)\r
237     return 0;\r
238 \r
239   switch(type)\r
240   {\r
241     case TYPE_BYTE:\r
242       if (length <= 4)\r
243         return offset;\r
244       else\r
245         return indirectvalue(type, (long) length, (long) offset, input);\r
246     case TYPE_SHORT:\r
247       if (length <= 2)\r
248         return offset;\r
249       else\r
250         return indirectvalue(type, (long) length, (long) offset, input);\r
251     case TYPE_LONG:\r
252       if (length == 1)\r
253         return offset;\r
254       else\r
255         return indirectvalue(type, (long) length, (long) offset, input);\r
256     default:\r
257       return -1;\r
258   }\r
259 }\r
260 \r
261 int skipthisimage (FILE *input, unsigned long ifdpos)\r
262 {\r
263   int k, j;\r
264 \r
265   if(fseek(input, (long) ifdpos + TIFFOffset, SEEK_SET) != 0)\r
266   {\r
267     sprintf(logline, " Error in seek %s\n", " while skipping image\n");\r
268     showline(logline, 1);\r
269     return -1;\r
270   }\r
271   IFDCount = ureadtwo(input);     /* How many tags in this IFD */\r
272   for (k = 0; k < (int) IFDCount; k++)  /* read to end of IFD */\r
273   {\r
274     for (j = 0; j < 12; j++)\r
275       (void) getc(input);\r
276   }\r
277   IFDPosition = ureadfour(input);   /* get next IFD offset in file */\r
278   if (IFDPosition == 0) return -1;      /*  no more IFDs !!! */\r
279   else return 0;\r
280 }\r
281 \r
282 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
283 \r
284 /* Must have: ImageWidth, ImageLength, StripOffset, SamplesPerPixel, BitsPerSample */\r
285 \r
286 long ImageWidth;            /* vital ImageWidth */\r
287 long ImageLength;           /* vital ImageLength */\r
288 \r
289 int bytes;                /* total bytes per row output used ? */\r
290 \r
291 int SamplesPerPixel = 1;        /* vital (may be more than 1) */\r
292 int SamplesPerPixelX = 1;       /* SamplesPerPixel-ExtraSamples */\r
293 \r
294 int BitsPerSample = 1;          /* vital */\r
295 \r
296 int ExtraSamples = 0;         /* new 99/May/10 */\r
297 \r
298 unsigned int compression = 0;     /* vital */\r
299 int Orientation = 1;\r
300 int Predictor = 1;            /* for LZW only */\r
301                     /* 2 implies differencing applied */\r
302 long StripOffset = -1;          /* vital (first strip offset) */\r
303 long StripOffsetsPtr;\r
304 int StripOffsetsType;\r
305 int StripOffsetsLength;\r
306 \r
307 long StripByteCount = -1;       /* first StripByteCount */\r
308 long StripByteCountsPtr;\r
309 int StripByteCountsType;\r
310 int StripByteCountsLength;\r
311 \r
312 int RowsPerStrip = 0;\r
313 \r
314 int StripsPerImage;           /* computed from above */\r
315 \r
316 long ColorMapPtr = 0; /* pointer to map in case of Palette Color Images */\r
317 \r
318 int PhotometricInterpretation = 1;  /* default */\r
319 \r
320 int PlanarConfig=1;   /* cannot handle 2 ... */\r
321 \r
322 int BitsPerPixel;   /* BitsPerSample * SamplePerPixel */\r
323 int BitsPerPixelX;    /* BitsPerSample * (SamplePerPixel-ExtraSamples) */\r
324 \r
325 long InRowLength;     /* number of source bytes from file */\r
326 long InRowLengthX;    /* --- after ExtraSamples removed */\r
327 \r
328 long InRowRead;     /* bytes to read from input */\r
329 long BufferLength;    /* number of bytes of intermediate data */\r
330             /* length of lpBuffer allocated space */\r
331 long OutRowLength;    /* number of processed bytes for output */\r
332 \r
333 int CurrentStrip;   /* for debugging purposes */\r
334 \r
335 /* NOTE: MinSampleValue and MaxSampleValue should not affect appearance */\r
336 \r
337 /* int MinSampleValue, MaxSampleValue;  */    /* never used ? */\r
338 \r
339 int ResolutionUnit=2;   /* 1 no dimensions, 2 per inch, 3 per cm */\r
340 \r
341 /* long xresnum, xresden; */    /* x resolution */\r
342 /* long yresnum, yresden; */    /* y resolution */\r
343 \r
344 unsigned long xresnum, xresden;   /* x resolution */  /* 95/Oct/10 */\r
345 unsigned long yresnum, yresden;   /* y resolution */  /* 95/Oct/10 */\r
346 \r
347 int hptagflag=0;          /* non-zero if call from HPTAG */\r
348 /* may need something more elaborate hleft / hright and vhigh / vlow */\r
349 \r
350 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
351 \r
352 /* read the tag fields in the TIFF file, ignore ones we don't care about */\r
353 \r
354 int readfields (FILE *input, unsigned long ifdpos)\r
355 {\r
356   unsigned int k, tag, type;\r
357   unsigned long length, offset;\r
358   int c;\r
359 \r
360 #ifdef DEBUGTIFF\r
361   if (traceflag) showline("Now reading TIFF images fields\n", 0);\r
362 #endif\r
363 \r
364   if (fseek(input, (long) ifdpos + TIFFOffset, SEEK_SET) != 0)\r
365   {\r
366     sprintf(logline, " Error in seek %s\n", " while reading tags");\r
367     showline(logline, 1);\r
368     return -1;\r
369   }\r
370   IFDCount = ureadtwo(input);     /* How many tags in this IFD */\r
371   \r
372   ImageWidth = ImageLength = -1;\r
373   SamplesPerPixel = BitsPerSample = 1;\r
374   ExtraSamples = compression = 0;\r
375   Orientation = 1;\r
376   StripOffset = StripByteCount = -1;\r
377   RowsPerStrip = 0;\r
378   PhotometricInterpretation = 1;  /* default */\r
379   PlanarConfig = Predictor = 1;\r
380   ColorMapPtr = 0;  /* pointer to map in case of Palette Color Images */\r
381 /*  MinSampleValue = -1; MaxSampleValue = -1; */\r
382 /*  xresnum = yresnum = 72; */\r
383   xresnum = yresnum = nDefaultTIFFDPI;\r
384   xresden = yresden = 1;\r
385   ResolutionUnit = 2; \r
386 \r
387   for (k = 0; k < IFDCount; k++)\r
388   {\r
389     tag = ureadtwo(input);    /* tag - key */\r
390     type = ureadtwo(input);   /* value type */\r
391     if (tag == 0 && type == 0) {  /* invalid */\r
392       c = getc(input); ungetc(c, input);\r
393       sprintf(logline, " Tag: %u Type: %u (k %d c %d)\n",\r
394           tag, type, k, c);\r
395       showline(logline, 1);\r
396       break;\r
397     }\r
398     if (type > 5) {\r
399       c = getc(input); ungetc(c, input);\r
400 #ifdef DEBUGTIFF\r
401       if (traceflag)\r
402       {\r
403         sprintf(logline, " Tag: %u Type: %u (k %d c %d)\n", tag, type, k, c);\r
404         showline(logline, 1);\r
405       }\r
406 #endif\r
407 /*      break; */ /* removed 98/Sep/22 */\r
408     }\r
409     length = ureadfour(input);  /* `length' (better named `count') */\r
410     if (length == 1) {\r
411       if (type == TYPE_LONG) offset = ureadfour(input);\r
412       else if (type  == TYPE_SHORT) {\r
413         offset = ureadtwo(input);\r
414         (void) ureadtwo(input);   /* should be zero */\r
415       }\r
416       else if (type == TYPE_BYTE) {\r
417         offset = getc(input);\r
418         (void) getc(input);(void) getc(input);(void) getc(input);\r
419       }\r
420       else offset = ureadfour(input); /* for ratio e.g. */\r
421     }\r
422     else offset = ureadfour(input); /* value */\r
423 \r
424     switch (tag) {\r
425       case IMAGEWIDTH:\r
426         ImageWidth = extractvalue(type, length, (long) offset, input);\r
427         break;\r
428       case IMAGELENGTH:\r
429         ImageLength = extractvalue(type, length, (long) offset, input);\r
430         break;\r
431       case BITSPERSAMPLE:\r
432         BitsPerSample =\r
433               (int) extractvalue(type, length, (long) offset, input);\r
434         break;\r
435       case EXTRASAMPLES:            /* 1999/May/10 */\r
436         ExtraSamples =\r
437               (int) extractvalue(type, length, (long) offset, input);\r
438         break;        \r
439       case COMPRESSION:\r
440         compression =\r
441           (unsigned int) extractvalue(type, length, (long) offset, input);\r
442         break;\r
443       case PREDICTOR:\r
444         Predictor =\r
445           (int) extractvalue(type, length, (long) offset, input);\r
446         break;\r
447       case SAMPLESPERPIXEL:\r
448         SamplesPerPixel =\r
449           (int) extractvalue(type, length, (long) offset, input);\r
450         break;\r
451       case ROWSPERSTRIP:\r
452         RowsPerStrip =\r
453           (int) extractvalue(type, length, (long) offset, input);\r
454         break;\r
455       case STRIPOFFSETS:\r
456         StripOffsetsPtr = offset;\r
457           StripOffsetsType = type;\r
458           StripOffsetsLength = (int) length;\r
459         StripOffset = extractvalue(type, length, (long) offset, input);\r
460         break;\r
461       case STRIPBYTECOUNTS:\r
462         StripByteCountsPtr = offset;\r
463           StripByteCountsType = type;\r
464           StripByteCountsLength = (int) length;\r
465         StripByteCount = extractvalue(type, length, (long) offset, input);\r
466         break;\r
467       case ORIENTATION:\r
468         Orientation =\r
469           (int) extractvalue(type, length, (long) offset, input);\r
470         break;\r
471 /*      case MINSAMPLEVALUE:\r
472         MinSampleValue = (int) extractvalue(type, length, (long) offset, input); \r
473         break; */\r
474 /*      case MAXSAMPLEVALUE:\r
475         MaxSampleValue = (int) extractvalue(type, length, (long) offset, input);\r
476         break; */\r
477       case XRESOLUTION:\r
478         xresnum = indirectvalue(TYPE_LONG, 1, (long) offset, input); \r
479         xresden = indirectvalue(TYPE_LONG, 1, (long) offset+4, input); \r
480         break; \r
481       case YRESOLUTION:\r
482         yresnum = indirectvalue(TYPE_LONG, 1, (long) offset, input); \r
483         yresden = indirectvalue(TYPE_LONG, 1, (long) offset+4, input); \r
484         break; \r
485       case RESOLUTIONUNIT:\r
486         ResolutionUnit = (int) extractvalue(type, length, (long) offset, input); \r
487         break; \r
488       case PHOTOMETRICINTERPRETATION:\r
489         PhotometricInterpretation = \r
490           (int) extractvalue(type, length, (long) offset, input);\r
491         break;\r
492       case PLANARCONFIG:\r
493          PlanarConfig = \r
494           (int) extractvalue(type, length, (long) offset, input);\r
495         break;\r
496       case COLORMAP:\r
497 /*        ColorMap = extractvalue(type, length, (long) offset, input); */\r
498         ColorMapPtr = offset;\r
499 /*    Assume the type is SHORT (16 bit per entry) */\r
500 /*    Assume the length is 3 * 2 ^ BitsPerSample - 1 */\r
501         break;\r
502       default:              /* ignore unknown tags */\r
503         break;\r
504     }\r
505   }\r
506   return 0;\r
507 }\r
508 \r
509 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
510 \r
511 int computeheader(void);\r
512 void writepsheader(FILE *, long, long);\r
513 void writepstrailer(FILE *);\r
514 int readpackbits(unsigned char *lpBuffer, FILE *input, int RowLength);\r
515 int huffmanrow(unsigned char *lpBuffer, FILE *input, int width);\r
516 int DecodeLZW(FILE *output, FILE *input, unsigned char *lpBuffer);\r
517 void expandcolor(unsigned char *s, long width);\r
518 void expandgray(unsigned char *s, long width);\r
519 void compresscolor(unsigned char *s, long width);\r
520 int writearow(FILE *output, unsigned char *s, unsigned long width);\r
521 \r
522 #ifdef PSLEVEL2\r
523 void ASCIIinitfilter(FILE *output);\r
524 void ASCIIflushfilter(FILE *output);\r
525 void RUNinitfilter(FILE *output);\r
526 void RUNflushfilter(FILE *output);\r
527 #ifdef LZWCOMPRESSION\r
528 void LZWinitfilter(FILE *output);\r
529 void LZWflushfilter(FILE *output);\r
530 void LZWput(int, FILE *);\r
531 #endif\r
532 #endif\r
533 \r
534 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
535 \r
536 /* Remember to deallocate at end */ /* Read color map from TIFF image */\r
537 \r
538 /* do we need to use unsigned short for NT ? */\r
539 \r
540 int ReadColorMap (FILE *input, long ColorMapPtr, int BitsPerSample)\r
541 {\r
542   long present;\r
543   int k, n, nint;\r
544 \r
545 /*  should make all these unsigned short int instead for NT */\r
546 #ifdef USESHORTINT\r
547   unsigned short int *PalettePtr;\r
548 #else\r
549   unsigned int *PalettePtr;\r
550 #endif\r
551 \r
552 #ifdef DEBUGTIFF\r
553 #ifdef USESHORTINT\r
554   unsigned short int *PaletteRed;\r
555   unsigned short int *PaletteGreen;\r
556   unsigned short int *PaletteBlue;\r
557 #else\r
558   unsigned int *PaletteRed;\r
559   unsigned int *PaletteGreen;\r
560   unsigned int *PaletteBlue;\r
561 #endif\r
562 #endif\r
563 \r
564 /*  need three tables each of 2 ^ BitsPerSample integers */\r
565   n = 1 << BitsPerSample;   /* integers per table */\r
566   PaletteSize = n;      /* remember for later */\r
567   nint = n * 3;       /* total number of integers */\r
568 #ifdef DEBUGTIFF\r
569   if (traceflag)\r
570   {\r
571     sprintf(logline, "Reading Color Map of size %d\n", n);\r
572     showline(logline, 1);\r
573   }\r
574 #endif\r
575 /*  check following allocation in NT ? should we use short int ? */\r
576 #ifdef USESHORTINT\r
577   Palette = (unsigned short int *)\r
578         malloc(nint * sizeof(unsigned short int));\r
579 #else\r
580 /*  Palette = (unsigned int *) malloc(nint * 2); */ /* bytes */\r
581   Palette = (unsigned int *) malloc(nint * sizeof(unsigned int));\r
582 #endif\r
583   if (Palette == NULL)\r
584   {\r
585     showline(" ERROR: Unable to allocate memory\n", 1);\r
586     checkexit(1);\r
587 //    or more serious exit(1) ???\r
588   }\r
589   present = ftell(input);\r
590 #ifdef DEBUGTIFF\r
591   if (traceflag)\r
592   {\r
593     sprintf(logline, "Going to ColorMap at %ld + %lu\n",\r
594          ColorMapPtr, TIFFOffset);\r
595     showline(logline, 1);\r
596   }\r
597 #endif\r
598   if (fseek (input, (long) ColorMapPtr + TIFFOffset, SEEK_SET) != 0)\r
599   {\r
600     sprintf(logline, " Error in seek %s\n", " to ColorMap");\r
601     showline(logline, 1);\r
602   }\r
603   PalettePtr = Palette;\r
604 /*  Following shoud work in NT even if we use int instead of short */\r
605   for (k = 0; k < nint; k++) *PalettePtr++ = ureadtwo (input);\r
606   fseek (input, present, SEEK_SET);\r
607 /*  return 0; */\r
608 \r
609   PaletteRed = Palette;\r
610   PaletteGreen = PaletteRed + PaletteSize;\r
611   PaletteBlue = PaletteGreen + PaletteSize;\r
612 \r
613   bGrayFlag = 1;    // non-zero if palette is all grays\r
614   for (k = 0; k < n; k++)\r
615   {\r
616     if (PaletteRed[k] != PaletteGreen[k] ||\r
617         PaletteGreen[k] != PaletteBlue[k])\r
618     {\r
619       bGrayFlag = 0;\r
620       break;\r
621     }\r
622   }         // bGrayFlag presently not used\r
623 \r
624   bLinearFlag = 0;  // non-zero if Palette is simply linear\r
625   if (bGrayFlag) {\r
626     bLinearFlag = 1;\r
627     for (k = 0; k < n; k++)\r
628     {\r
629       if (PaletteRed[k] != (unsigned int) (k * 255 / (n-1))) {\r
630         bLinearFlag = 0;\r
631         break;\r
632       }\r
633     }\r
634   }         // bLinearFlag presently not used\r
635 \r
636 //  bGrayFlag and bLinearFlag could be used to produce smaller output files\r
637 \r
638 #ifdef DEBUGTIFF\r
639   if (traceflag)\r
640   {\r
641     PaletteRed = Palette;\r
642     PaletteGreen = PaletteRed + PaletteSize;\r
643     PaletteBlue = PaletteGreen + PaletteSize;\r
644     for (k = 0; k < n; k++) {\r
645       if (traceflag) {\r
646         sprintf(logline, "INX %d\tR %u\tG %u\tB %u\n",\r
647              k, PaletteRed[k], PaletteGreen[k], PaletteBlue[k]);\r
648         showline(logline, 0);\r
649       }\r
650     }\r
651   }\r
652 #endif\r
653   return 0;\r
654 }\r
655 \r
656 /* returns -1 if output error */    /* given InRowLengthX */\r
657 /* expand color if needed - or expand gray if needed */\r
658 /* compress color if needed */\r
659 /* write out a row of image */\r
660 \r
661 int ProcessRow (FILE *output, unsigned char *lpBuffer, long InRowLengthX,\r
662   long BufferLength, long OutRowLength)\r
663 {\r
664 /*  if (traceflag)\r
665     printf("ProcessRow InRowLengthX %d\n", InRowLengthX); */ /* DEBUGGING */\r
666 /*  if (traceflag)\r
667     printf("bExpandColor %d bExpandGray %d bCompressColor %d\n",\r
668        bExpandColor, bExpandGray, bCompressColor); */ /* DEBUGGING */\r
669 #ifndef _WINDOWS\r
670   if (traceflag) fflush(stdout);    /* DEBUGGING ONLY */\r
671 #endif\r
672   if (bExpandColor) expandcolor(lpBuffer, InRowLengthX);\r
673   else if (bExpandGray) expandgray(lpBuffer, InRowLengthX);\r
674   if (bCompressColor) compresscolor(lpBuffer, BufferLength);\r
675 #ifdef DEBUGTIFF\r
676   if (traceflag) {      /* DEBUGGING */\r
677     sprintf(logline, "ProcessRow OutRowLength %d\n", OutRowLength);\r
678     showline(logline, 0);\r
679   }\r
680 #endif\r
681   if (writearow(output, lpBuffer, OutRowLength) != 0) return -1;\r
682   else return 0;\r
683 }\r
684 \r
685 /* Throw out ExtraSamples in SamplesPerPixel */\r
686 /* IMPORTANT NOTE: assume for the moment samples are one byte */\r
687 \r
688 int RemoveExtraSamples (unsigned char *lpBuffer, int InRowLength)\r
689 {\r
690   unsigned char *s = lpBuffer;\r
691   unsigned char *t = lpBuffer;\r
692   int i, k, n = InRowLength / SamplesPerPixel;\r
693 \r
694 #ifdef DEBUGTIFF\r
695   if (traceflag)\r
696   {\r
697     sprintf(logline, "RemoveExtraSamples InRowLength %d\n", InRowLength);\r
698     showline(logline, 1);\r
699   }\r
700 #endif\r
701   if (ExtraSamples == 0) return InRowLength;\r
702 /*  check that BitsPerSample == 8 ??? */  \r
703   for (k = 0; k < n; k++) {\r
704     for (i = 0; i < SamplesPerPixelX; i++) *t++ = *s++;\r
705     s += ExtraSamples;\r
706   }\r
707   return (int) (t - lpBuffer);\r
708 }\r
709 \r
710 /* readflag != 0 when reading file only to get tag fields */\r
711 \r
712 int readTIFFfile (FILE *output, FILE *input,\r
713   long dwidth, long dheight, int nifd, int readflag)\r
714 {\r
715 /*  int i, j, flag; */\r
716   int i, flag;\r
717 /*  long present; */\r
718 /*  int k, color, n; */\r
719   unsigned long ImageSize;\r
720   unsigned int nread;\r
721   unsigned char *lpBuffer=NULL;\r
722   int nLen;\r
723 \r
724   TIFFVersion = ureadtwo(input);\r
725   if (TIFFVersion != TIFF_VERSION)\r
726   {\r
727     sprintf(logline, " Incorrect TIFF version code %d\n", TIFFVersion);\r
728     showline(logline, 1);\r
729     return -1;    /* bad version number for TIFF file */\r
730   }\r
731   \r
732 /*  Skip to desired image (if not first in file) */\r
733 \r
734   IFDPosition = ureadfour(input);   /* get first IFD offset in file */\r
735   while (nifd-- > 1) {\r
736     if (skipthisimage(input, IFDPosition) < 0)\r
737     {\r
738       sprintf(logline, " ERROR: Subimage %d not found", nifd);\r
739       showline(logline, 1);\r
740       return -1;\r
741     }\r
742   }\r
743 \r
744 /*  Now at desired image */\r
745   (void) readfields(input, IFDPosition);  /* read tag fields in TIFF file */\r
746 \r
747   IFDPosition = ureadfour(input);   /* get next IFD offset in file */\r
748 \r
749 /*  if (readflag == 0) return -1; */  /*  only scanning for width & height */\r
750   if (readflag != 0) return -1; /*  only scanning for width & height */\r
751 \r
752   bColorImage = 0;      /* if image is RGB or Palette color */\r
753   bExpandColor = 0;     /* comes on if Palette color image */\r
754   bExpandGray = 0;      /* comes on if Palette is gray */\r
755   bCompressColor = 0;     /* if image is colored and not `colorimage'  */\r
756   if (ColorMapPtr) {      /* is it a palette color image ? */\r
757     (void) ReadColorMap(input, ColorMapPtr, BitsPerSample);\r
758     bExpandColor = 1;\r
759     bColorImage = 1;\r
760   }\r
761 \r
762 #ifdef DEBUGTIFF\r
763   if (traceflag)\r
764   {\r
765     sprintf(logline, "Width %ld, Height %ld, BitsPerSample %d, SamplesPerPixel %d\n", \r
766        ImageWidth, ImageLength, BitsPerSample, SamplesPerPixel);\r
767     showline(logline, 1);\r
768   }\r
769 #endif\r
770 \r
771 #ifdef DEBUGTIFF\r
772   if (traceflag)\r
773   {\r
774     sprintf(logline, "Compression %u PhotometricInterpretation %d\n",\r
775      compression, PhotometricInterpretation);\r
776     showline(logline, 1);\r
777   }\r
778 #endif\r
779 \r
780 #ifdef DEBUGTIFF\r
781   if (traceflag && Predictor != 1)\r
782   {\r
783     sprintf(logline, "Predictor %d\n", Predictor);\r
784     showline(logline, 1);\r
785   }\r
786 #endif\r
787 \r
788   if (ExtraSamples > 0) SamplesPerPixelX = SamplesPerPixel-ExtraSamples;\r
789   else SamplesPerPixelX = SamplesPerPixel;\r
790   \r
791   BitsPerPixel = BitsPerSample * SamplesPerPixel;\r
792   if (ExtraSamples > 0) BitsPerPixelX = BitsPerSample * SamplesPerPixelX;\r
793   else BitsPerPixelX = BitsPerPixel;\r
794 \r
795   InRowLength = (ImageWidth * BitsPerPixel + 7) / 8;  /* row length file */\r
796   if (ExtraSamples > 0)InRowLengthX = (ImageWidth * BitsPerPixelX + 7) / 8;\r
797   else InRowLengthX = InRowLength;\r
798 \r
799   if (RowsPerStrip > 0)\r
800     StripsPerImage = (int) ((ImageLength + RowsPerStrip - 1) / RowsPerStrip);\r
801   else StripsPerImage = 1;\r
802 \r
803   if (bExpandColor) BufferLength = ImageWidth * 3;\r
804   else if (bExpandGray) BufferLength = ImageWidth;\r
805   else BufferLength = InRowLength;\r
806 \r
807 /*  do compression of 24 bit color if use of `colorimage' not allowed */\r
808 /*  if (bitsperpixel == 24 && bCompressFlag != 0 && forceice == 0) */\r
809 /*  if (BitsPerPixel == 24 && bCompressFlag != 0) */\r
810 /*  if ((BitsPerPixel == 24 || bExpandColor) && bAllowColor == 0)  */\r
811   if ((BitsPerPixelX == 24 || bExpandColor) && ! bAllowColor)\r
812   {\r
813     sprintf(logline, " color image (bits %d expand %d): use `*c' flag?",\r
814          BitsPerPixelX, bExpandColor);  /* 96/Aug/15 */\r
815 //    showline(logline, 1);\r
816     showline(logline, 0);     // reduce severity 2000 March 16\r
817     bCompressColor = 1;\r
818     OutRowLength = BufferLength / 3;\r
819   }\r
820   else OutRowLength = BufferLength;\r
821 \r
822 #ifdef DEBUGTIFF\r
823   if (traceflag)\r
824   {\r
825     sprintf(logline, "InRowLength %ld BufferLength %ld OutRowLength %ld\n",\r
826       InRowLength, BufferLength, OutRowLength);\r
827     showline(logline, 1);\r
828   }\r
829 #endif\r
830 \r
831 /*  deal with GhostScript TIFF file format with gaps */   /* 94/Dec/16 */\r
832 /*  shouldn't this only kick in if we are not using (LZW) compression ? */\r
833   if (bGhostHackFlag) {       /*  made conditional 95/Nov/10 */\r
834     if (InRowLength + 1 == StripByteCount)\r
835     {\r
836       InRowLength++;        /* a hack */\r
837     }\r
838   }\r
839 /*  should also increase BufferLength allocation ? 95/Nov/10 */\r
840 \r
841 #ifdef PSLEVEL2\r
842   bRunLengthFlag = 0;\r
843   if (bAllowCompression) {\r
844 /*    Use runlength encoding if monochrome *or* if original uses it */\r
845 /*    if (BitsPerSample == 1 && SamplesPerPixel == 1) */\r
846     if (BitsPerSample == 1 && SamplesPerPixelX == 1)\r
847       bRunLengthFlag = 1;\r
848     if (compression == PACK_BITS) bRunLengthFlag = 1;\r
849 #ifdef LZWCOMPRESSION\r
850     bLZWFlag = 0;\r
851 /*    Use LZW if runlength encoding not chosen */\r
852     if (bRunLengthFlag == 0)\r
853     {\r
854 //      if (compression == LZW_COMPRESSION) bLZWFlag = 1;\r
855 //      else; bLZWFlag = 1          /* otherwise use LZW */\r
856       bLZWFlag = 1;\r
857     }\r
858 #endif\r
859   }\r
860 #endif\r
861 \r
862   if (computeheader() != 0) return -1;  /* noticed format not supported? */\r
863 \r
864   writepsheader(output, dwidth, dheight);\r
865 \r
866 /*  following should already be taken care of in `computeheader' */\r
867 /*  if (compression > 1 && compression != PACK_BITS) */\r
868   if (compression > TIFF_CCITT && compression != LZW_COMPRESSION &&\r
869     compression != PACK_BITS)\r
870   {\r
871     sprintf(logline, " ERROR: Unknown compression scheme (%d)", compression);\r
872     showline(logline, 1);\r
873     return -1;\r
874   }\r
875 \r
876 /*  ImageSize = (unsigned long) InRowLength * ImageLength; */\r
877   ImageSize = (unsigned long) InRowLengthX * ImageLength;\r
878 /*  check whether values reasonable */\r
879   if (ImageSize == 0)\r
880   {\r
881     sprintf(logline, " ERROR: Zero image size, %d %d (%s)",\r
882         InRowLengthX, ImageLength, "readTIFFfile");\r
883     showline(logline, 1);\r
884     return -1;\r
885   }\r
886   if (ImageWidth > MAXIMAGE || ImageLength > MAXIMAGE ||  /* bad data ? */\r
887     ImageSize > 67108864) { /* arbitrary limits (to catch bad files) */\r
888     sprintf(logline,\r
889       " ERROR: image file too large\n(%ld x %ld (%d) => %ld bytes)",\r
890         ImageWidth, ImageLength, BitsPerPixel, ImageSize);\r
891     showline(logline, 1);\r
892     return -1;\r
893   }\r
894   if (ImageWidth < 0 || ImageLength < 0 ||    /* missing fields */\r
895         StripOffset < 0) {          /* missing fields */\r
896     showline(" ERROR: TIFF file missing required tags", 1);\r
897     return -1;\r
898   }\r
899 \r
900   if (fseek(input, (long) StripOffset + TIFFOffset, SEEK_SET) != 0)\r
901   {\r
902     sprintf(logline, " Error in seek %s\n", " to StripOffset\n");\r
903     showline(logline, 1);\r
904     return -1;\r
905   }\r
906 \r
907 /*  Maybe use far memory ? */ /* lot of changes if we do this ... */\r
908 /*  Maybe don't use if LZW compression ? */\r
909 /*  if (compression != LZW_COMPRESSION)  */\r
910 /*  if ((lpBuffer = malloc((int) BufferLength)) == NULL) {  */\r
911 /*  Accomodate GhostScript gap bug work around ... just in case 95/Nov/10 */\r
912 /*  nLen = BufferLength + 1; */\r
913   nLen = (int) ((BufferLength + 3) / 4) * 4;\r
914   if ((lpBuffer = malloc(nLen)) == NULL)\r
915   {\r
916     sprintf(logline, " ERROR: Unable to allocate %d bytes\n", nLen);\r
917     showline(logline, 1);\r
918     checkexit(1);         /* 1995/July/15 ? */\r
919 //    or more serious exit(1) ???\r
920   }\r
921 \r
922 /*  in case minsamplevalue and maxsamplevalue not given in tags */\r
923 /*  if (MinSampleValue < 0 || MaxSampleValue < 0 ||\r
924       MinSampleValue == MaxSampleValue) {\r
925     MinSampleValue = 0; MaxSampleValue = (1 << BitsPerSample) - 1;\r
926   } */  /* never used */\r
927 \r
928 /*  Actually go and read the file now ! */\r
929 \r
930 /*  following should already be taken care of in `computeheader' */\r
931 \r
932   if (compression > TIFF_CCITT && compression != LZW_COMPRESSION &&\r
933     compression != PACK_BITS)\r
934   {\r
935     sprintf(logline, " ERROR: Unknown compression scheme (%d)", compression);\r
936     showline(logline, 1);\r
937     return -1;\r
938   }\r
939 #ifdef DEBUGTIFF\r
940   if (traceflag)\r
941   {\r
942     if (compression == PACK_BITS) sprintf(logline, "Using PACK_BITS\n");\r
943     else if (compression == TIFF_CCITT) sprintf(logline, "Using TIFF_CCITT\n");\r
944     else if (compression == LZW_COMPRESSION) sprintf(logline, "Using LZW\n");\r
945     showline(logline, 1);\r
946   }\r
947 #endif\r
948 \r
949   flag = 0;               /* flag gets set if EOF hit */\r
950 \r
951 #ifdef PSLEVEL2\r
952   if (bLevel2)\r
953   {\r
954     ASCIIinitfilter(output);            /* 96/Dec/20 */\r
955     if (bRunLengthFlag) RUNinitfilter(output);    /* 96/Dec/24 */\r
956 #ifdef LZWCOMPRESSION\r
957     else if (bLZWFlag) LZWinitfilter(output);   /* 96/Dec/28 */\r
958 #endif\r
959   }\r
960 #endif\r
961 \r
962 /*  LZW needs to be done by strips, the others can be done by row */\r
963 \r
964   if (compression == LZW_COMPRESSION) DecodeLZW(output, input, lpBuffer);\r
965 \r
966   else {    /* else not LZW compression */\r
967 \r
968     for (i = 0; i < (int) ImageLength; i++) { /* read image lines */\r
969 \r
970       if (compression == PACK_BITS) {   /* compressed binary file */\r
971         if (readpackbits (lpBuffer, input, (int) InRowLength) != 0) {\r
972           flag = -1;\r
973           break;\r
974         }\r
975       }\r
976       else if (compression == TIFF_CCITT) { /* CCITT 1D compression */\r
977         if (huffmanrow (lpBuffer, input, (int) ImageWidth) != 0) {\r
978           flag = -1;\r
979           break;\r
980         }\r
981       }\r
982       else {                /* uncompressed file */\r
983         nread = fread(lpBuffer, 1, (unsigned int) InRowLength, input);\r
984         if (nread != (unsigned int) InRowLength) {  /* read a row */\r
985           flag = -1;\r
986           showline("Premature EOF ", 1);  /* ??? */\r
987           break;\r
988         } \r
989       }\r
990 #ifdef DEBUGTIFF\r
991       if (traceflag)\r
992       {\r
993         sprintf(logline, "readTIFFFile InRowLength %d\n", InRowLength);\r
994         showline(logline, 1);\r
995       }\r
996 #endif\r
997       if (ExtraSamples > 0)\r
998         (void) RemoveExtraSamples(lpBuffer, InRowLength); /* 99/May/10 */\r
999 \r
1000 #ifdef DEBUGTIFF\r
1001       if (traceflag)\r
1002       {\r
1003         sprintf(logline, "readTIFFFile OutRowLength %d BufferLength %d\n",\r
1004              OutRowLength, BufferLength);\r
1005         showline(logline, 1);\r
1006       }\r
1007 #endif\r
1008 \r
1009 /*      if (ProcessRow (output, lpBuffer, InRowLength, BufferLength, */\r
1010       if (ProcessRow (output, lpBuffer, InRowLengthX, BufferLength,\r
1011         OutRowLength) != 0)\r
1012       {\r
1013         showline("\n", 0);\r
1014         showline("ERROR: Output error ", 1);\r
1015         perrormod((outputfile != NULL) ? outputfile : "");\r
1016         break;\r
1017       }\r
1018 /*      if (flag != 0) break; *//* hit EOF or other error */\r
1019 /*      check on abort flag here somewhere also ? */\r
1020     } /* end of this row */\r
1021   } /* end of not LZW compression */\r
1022 \r
1023 //  Have to flush filters in reverse order\r
1024 #ifdef PSLEVEL2\r
1025   if (bLevel2)\r
1026   {\r
1027     if (bRunLengthFlag) RUNflushfilter(output); /* 96/Dec/24 */\r
1028 #ifdef LZWCOMPRESSION\r
1029     else if (bLZWFlag) LZWflushfilter(output);  /* 96/Dec/28 */\r
1030 #endif\r
1031     ASCIIflushfilter(output);       /* 96/Dec/20 */\r
1032   }\r
1033 #endif\r
1034   \r
1035 /* now finished reading */  /* maybe use far memory for lpBuffer ? */\r
1036 \r
1037   if (lpBuffer != NULL) {\r
1038     free(lpBuffer);\r
1039     lpBuffer = NULL;\r
1040   }\r
1041   if (Palette != NULL) {\r
1042     free(Palette);\r
1043     Palette = NULL;\r
1044   }\r
1045   writepstrailer(output);\r
1046   return flag;\r
1047 }    /* end of readTIFFfile(...) */\r
1048 \r
1049 /**********************************************************************/\r
1050 \r
1051 /* following is from windef.h */\r
1052 \r
1053 typedef unsigned long       DWORD;\r
1054 typedef int                 BOOL;\r
1055 typedef unsigned char       BYTE;\r
1056 typedef unsigned short      WORD;\r
1057 typedef float               FLOAT;\r
1058 typedef int                 INT;\r
1059 typedef unsigned int        UINT;\r
1060 \r
1061 typedef long        LONG;\r
1062 \r
1063 /* following is from wingdi.h */\r
1064 \r
1065 #ifndef _WINDOWS\r
1066 \r
1067 #define FAR\r
1068 \r
1069 #include <pshpack2.h>\r
1070 typedef struct tagBITMAPFILEHEADER {\r
1071   WORD    bfType;\r
1072   DWORD   bfSize;\r
1073   WORD    bfReserved1;\r
1074   WORD    bfReserved2;\r
1075   DWORD   bfOffBits;\r
1076 } BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;\r
1077 #include <poppack.h>\r
1078 \r
1079 typedef struct tagBITMAPINFOHEADER {\r
1080   DWORD      biSize;\r
1081   LONG       biWidth;\r
1082   LONG       biHeight;\r
1083   WORD       biPlanes;\r
1084   WORD       biBitCount;\r
1085   DWORD      biCompression;\r
1086   DWORD      biSizeImage;\r
1087   LONG       biXPelsPerMeter;\r
1088   LONG       biYPelsPerMeter;\r
1089   DWORD      biClrUsed;\r
1090   DWORD      biClrImportant;\r
1091 } BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;\r
1092 \r
1093 #include <pshpack1.h>\r
1094 typedef struct tagRGBTRIPLE {\r
1095   BYTE    rgbtBlue;\r
1096   BYTE    rgbtGreen;\r
1097   BYTE    rgbtRed;\r
1098 } RGBTRIPLE;\r
1099 #include <poppack.h>\r
1100 \r
1101 typedef struct tagRGBQUAD {\r
1102   BYTE    rgbBlue;\r
1103   BYTE    rgbGreen;\r
1104   BYTE    rgbRed;\r
1105   BYTE    rgbReserved;\r
1106 } RGBQUAD;\r
1107 typedef RGBQUAD FAR* LPRGBQUAD;\r
1108 \r
1109 #endif\r
1110 \r
1111 BITMAPFILEHEADER bmfh;\r
1112 \r
1113 BITMAPINFOHEADER bmih;\r
1114 \r
1115 /* RGBQUAD colortable[256]; */\r
1116 \r
1117 int dpifrom(int res)\r
1118 {\r
1119   double dres = (double) res * 25.4 / 1000.0;\r
1120   dres = (double) ((int) (dres * 10.0 + 0.5)) / 10.0;\r
1121   return (int) (dres + 0.5);\r
1122 }\r
1123 \r
1124 int colormaplength;   /* ??? */\r
1125 int mingrey, maxgrey; /* ??? */\r
1126 int nColors;      /* ??? */\r
1127 long OffBits;     /* ??? */\r
1128 long ImageSize;     /* ??? */\r
1129 \r
1130 /* readflag is non-zero in prescan */\r
1131 \r
1132 int readBMPfields (FILE *input, int readflag)\r
1133 {\r
1134   long nLen;\r
1135   double dw, dh;\r
1136 \r
1137   ImageWidth = ImageLength = -1;\r
1138   SamplesPerPixel = BitsPerSample = 1;\r
1139   ExtraSamples = 0;\r
1140   compression = 0; Orientation = 1;\r
1141   StripOffset = -1; StripByteCount = -1;\r
1142   PhotometricInterpretation = 1;  /* default */\r
1143   PlanarConfig = 1; Predictor = 1;\r
1144   ColorMapPtr = 0;  /* pointer to map in case of Palette Color Images */\r
1145   mingrey = -1; maxgrey = -1;\r
1146   xresnum = yresnum = nDefaultTIFFDPI;    /* 96/Apr/3 */  \r
1147   xresden = yresden = 1;        /* 93/Oct/20 */\r
1148   ResolutionUnit = 2;         /* default dpi */ /* 93/Oct/20 */\r
1149 \r
1150   fseek(input, 0, SEEK_END);\r
1151   nLen = ftell(input);        /* Length of file */\r
1152 //  fseek(input, 0, SEEK_SET);      /* rewind */\r
1153   rewind(input);\r
1154   fread(&bmfh, sizeof(bmfh), 1, input); /*  read file header */\r
1155   if (bmfh.bfType != (77 * 256 + 66)) {     /*  "BM" */\r
1156     sprintf(logline, "Not BMP file %X\n", bmfh.bfType);\r
1157     showline(logline, 1);\r
1158     return -1;\r
1159   }\r
1160 /* "Size of header %lu\n", bmih.biSize compare to nLen ? */\r
1161   OffBits = bmfh.bfOffBits;\r
1162 /* "Offset to image %lu\n", bmih.bfOffBits */\r
1163 #ifdef DEBUGBMP\r
1164   if (traceflag && sreadflag)\r
1165   {\r
1166     sprintf(logline, "\nnLen %ld bfSize %ld bfOffBits %ld ",\r
1167        nLen, bmfh.bfSize, bmfh.bfOffBits);\r
1168     showline(logline, 1);\r
1169   }\r
1170 #endif\r
1171 /*  bmfh.bfSize file size in words ? NO */\r
1172 /*  bmfh.bfOffBits offset from end of header ? NO */\r
1173 \r
1174   fread(&bmih, sizeof(bmih), 1, input); /*  read bitmap info header */\r
1175 \r
1176 /*  if (bmih.biClrUsed > 0) nColor = bmih.biClrUsed;\r
1177   else if (bmih.biBitCount < 24) nColor = 1 << bmih.biBitCount; */\r
1178   if (bmih.biClrUsed > 0) nColors = bmih.biClrUsed;\r
1179   else if (bmih.biBitCount < 24) nColors = 1 << bmih.biBitCount;\r
1180   else nColors = 0;\r
1181   ImageWidth = bmih.biWidth;\r
1182   ImageLength = bmih.biHeight;\r
1183   if (bmih.biBitCount < 24) {\r
1184     BitsPerSample = bmih.biBitCount;\r
1185     SamplesPerPixel = 1;\r
1186   }\r
1187   else {\r
1188     BitsPerSample = 8;\r
1189     SamplesPerPixel = 3;\r
1190   }\r
1191 #ifdef DEBUGBMP\r
1192   if (traceflag && readflag) {\r
1193     sprintf(logline, "\nBMIH: %d x %d bits %d x %d",\r
1194       ImageWidth, ImageLength, SamplesPerPixel, BitsPerSample);\r
1195     showline(logline, 1);\r
1196   }\r
1197   if (traceflag && readflag) {\r
1198     sprintf(logline, "\nBMIH: Size %ld Planes %d Compression %d SizeImage %ld ColorsUsed %d",\r
1199         bmih.biSize, bmih.biPlanes,\r
1200         bmih.biCompression, bmih.biSizeImage, bmih.biClrUsed);\r
1201     showline(logline, 1);\r
1202 \r
1203   }\r
1204 #endif\r
1205 \r
1206 /* "Number of image planes %u\n", bmih.biPlanes */\r
1207 /* "Compression %lu\n", bmih.biCompression */\r
1208 /* "Size of compressed image %lu\n", bmih.biSizeImage */\r
1209 /* "Number of colors used %lu %d\n", bmih.biClrUsed */\r
1210 \r
1211 /* "Horizontal pixel per meter %ld\n", bmih.biXPelsPerMeter */\r
1212   xresnum = dpifrom(bmih.biXPelsPerMeter);\r
1213   if (xresnum == 0) xresnum = nDefaultTIFFDPI;\r
1214   dw = (double) ImageWidth / xresnum;\r
1215 /* "%d dpi (horizontal)\twidth %lg inch\n", xresnum, dw */\r
1216 \r
1217 /* "Vertical pixel per meter %ld\n", bmih.biYPelsPerMeter */\r
1218   yresnum = dpifrom(bmih.biYPelsPerMeter);\r
1219   if (yresnum == 0) yresnum = nDefaultTIFFDPI;\r
1220   dh = (double) ImageLength / yresnum;\r
1221 /* "%d dpi (vertical)\theight %lg inch\n", yresnum, dh */\r
1222 \r
1223   compression = bmih.biCompression; /* save it */\r
1224   ColorMapPtr = 0;\r
1225   if (nColors > 0) {    /*  read color table unless 24 bit */\r
1226     if (nColors > 256) {\r
1227       sprintf(logline, " ERROR: too many colors: %d\n", nColors);\r
1228       showline(logline, 1);\r
1229       nColors = 256;\r
1230       return -1;\r
1231     }\r
1232     ColorMapPtr = ftell(input); /* color map starts here */\r
1233     TIFFOffset = 0;\r
1234     colormaplength = sizeof(RGBQUAD) * nColors;\r
1235 /*    fread(&colortable, sizeof(RGBQUAD), nColors, input); */\r
1236   }\r
1237 /*  ColorMapPtr should be zero for 24 bit RGB images */\r
1238   OffBits= sizeof(bmfh) + sizeof(bmih) + sizeof(RGBQUAD) * nColors;\r
1239   fseek(input, OffBits, SEEK_SET);\r
1240   if (bmih.biSizeImage > 0) ImageSize = bmih.biSizeImage;\r
1241   else ImageSize = nLen - OffBits;\r
1242 #ifdef DEBUGBMP\r
1243   if (traceflag && readflag)\r
1244   {\r
1245     sprintf(logline, "\nImage at %ld size %ld bytes ", OffBits, ImageSize);\r
1246     showline(logline, 1);\r
1247   }\r
1248 #endif\r
1249   return 0;\r
1250 }\r
1251 \r
1252 int readBMPPalette (FILE *input, long ColorMapPtr, int BitsPerSample)\r
1253 {\r
1254   long present;\r
1255   int k, n, nint;\r
1256   RGBQUAD rgb;\r
1257 /*  should make all these unsigned short int instead for NT */\r
1258 \r
1259 #ifdef USESHORTINT\r
1260   unsigned short int *PaletteRed;\r
1261   unsigned short int *PaletteGreen;\r
1262   unsigned short int *PaletteBlue;\r
1263 #else\r
1264   unsigned int *PaletteRed;\r
1265   unsigned int *PaletteGreen;\r
1266   unsigned int *PaletteBlue;\r
1267 #endif\r
1268 \r
1269 /*  need three tables each of 2 ^ BitsPerSample integers */\r
1270   n = 1 << BitsPerSample;   /* integers per table */\r
1271 #ifdef DEBUGBMP\r
1272   if (traceflag) {\r
1273     sprintf(logline, "Reading Color Map of size %d\n", n);\r
1274     showline(logline, 1);\r
1275   }\r
1276 #endif\r
1277   PaletteSize = n;      /* remember for later */\r
1278   nint = n * 3;       /* total number of integers */\r
1279 /*  check following allocation in NT ? should we use short int ? */\r
1280 #ifdef USESHORTINT\r
1281   Palette = (unsigned short int *)\r
1282         malloc(nint * sizeof(unsigned short int));\r
1283 #else\r
1284   Palette = (unsigned int *) malloc(nint * sizeof(unsigned int)); \r
1285 #endif\r
1286   if (Palette == NULL) {\r
1287     showline("Unable to allocate memory\n", 1);\r
1288     checkexit(1);\r
1289 //    or more serious exit(1) ???\r
1290   }\r
1291   PaletteRed = Palette;\r
1292   PaletteGreen = PaletteRed + PaletteSize;\r
1293   PaletteBlue = PaletteGreen + PaletteSize;\r
1294 \r
1295   present = ftell(input);\r
1296 #ifdef DEBUGBMP\r
1297   if (traceflag) {\r
1298     sprintf(logline, "Going to ColorMap at %ld\n", ColorMapPtr);\r
1299     showline(logline, 1);\r
1300   }\r
1301 #endif\r
1302   if (fseek (input, (long) ColorMapPtr, SEEK_SET) != 0)\r
1303   {\r
1304     sprintf(logline, " Error in seek %s\n", " to ColorMap\n");\r
1305     showline(logline, 1);\r
1306   }\r
1307   for (k = 0; k < n; k++) {\r
1308     fread (&rgb, sizeof(RGBQUAD), 1, input);\r
1309     PaletteRed[k] = rgb.rgbRed; \r
1310 /*    PaletteRed[k] = rgb.rgbRed << 8; */\r
1311     PaletteGreen[k] = rgb.rgbGreen; \r
1312 /*    PaletteGreen[k] = rgb.rgbGreen << 8; */\r
1313     PaletteBlue[k] = rgb.rgbBlue; \r
1314 /*    PaletteBlue[k] = rgb.rgbBlue << 8; */\r
1315   }\r
1316   bGrayFlag = 1;      /* non-zero if palette has only grays */\r
1317   for (k = 0; k < n; k++) {\r
1318     if (PaletteRed[k] != PaletteGreen[k] ||\r
1319       PaletteGreen[k] != PaletteBlue[k]) {\r
1320       bGrayFlag = 0;\r
1321       break;\r
1322     }\r
1323   }\r
1324   bLinearFlag = 0;    /* non-zero if Palette is simply linear */\r
1325   if (bGrayFlag) {\r
1326     bLinearFlag = 1;\r
1327     for (k = 0; k < n; k++) {\r
1328       if (PaletteRed[k] != (unsigned int) (k * 255 / (n-1))) {\r
1329 #ifdef DEBUGBMP\r
1330         if (traceflag) {\r
1331           sprintf(logline, "R[%d] = %d not %d\n",\r
1332             k, PaletteRed[k], (k * 255 / (n-1)));\r
1333           showline(logline, 1);\r
1334         }\r
1335 #endif\r
1336         bLinearFlag = 0;\r
1337         break;\r
1338       }\r
1339     }\r
1340   }\r
1341   \r
1342 /*  fseek (input, present, SEEK_SET); */\r
1343 #ifdef IGNORED\r
1344   if (traceflag) {    /* show palette */\r
1345     for (k = 0; k < n; k++) {\r
1346       sprintf(logline, "INX %d\tR %u\tG %u\tB %u\n",\r
1347         k, PaletteRed[k], PaletteGreen[k], PaletteBlue[k]);\r
1348       showline(logline, 1);\r
1349     }\r
1350   }\r
1351 #endif\r
1352   return 0; \r
1353 }\r
1354 \r
1355 /* readflag != 0 when prescanning to get fields */\r
1356 \r
1357 int readBMPfile (FILE *output, FILE *input,\r
1358          long dwidth, long dheight, int readflag)\r
1359 {\r
1360   unsigned char *lpBuffer=NULL;\r
1361   int i, flag;\r
1362   int nLen;\r
1363   unsigned int nread;\r
1364   unsigned char *s;\r
1365   int c, d, e=0;      /* keep compiler happy */\r
1366   int k, n;\r
1367   int evenflag=0;\r
1368   int nibble;\r
1369 \r
1370   (void) readBMPfields(input, readflag);  /* read tag fields in BMP file */\r
1371   BitsPerPixel = BitsPerSample * SamplesPerPixel; /* for bmp only */\r
1372   BitsPerPixelX = BitsPerPixel;\r
1373   if (readflag != 0) return 0;  /* if only reading for info */\r
1374   bColorImage = 0;      /* if image is RGB or Palette color */\r
1375   bExpandColor = 0;     /* comes on if Palette color image */\r
1376   bExpandGray = 0;      /* comes on if Palette is gray */\r
1377   bCompressColor = 0;     /* if image is colored and not `colorimage'  */\r
1378   if (ColorMapPtr > 0) {      /* do not read if 24 bit color */\r
1379     readBMPPalette (input, ColorMapPtr, BitsPerSample);\r
1380 /*    check on bGrayFlag and bLinearFlag here ... */\r
1381 #ifdef DEBUGBMP\r
1382     if (traceflag) {\r
1383       sprintf(logline, "bGrayFLag %d bLinearFlag %d\n",\r
1384           bGrayFlag, bLinearFlag);\r
1385       showline(logline, 1);\r
1386     }\r
1387 #endif\r
1388     if (bGrayFlag) bColorImage = 0;\r
1389     else bColorImage = 1;\r
1390     if (! bLinearFlag) {\r
1391       if (bGrayFlag) bExpandGray = 1;\r
1392       else bExpandColor = 1;\r
1393     }\r
1394     if (BitsPerPixel == 1 && bGrayFlag != 0) {\r
1395       bExpandGray = 0;    /*    treat as MonoChrome */\r
1396       if (bLinearFlag) bInvertImage = 0;\r
1397       else bInvertImage = 1;\r
1398     }\r
1399 /*    ??? check this */\r
1400   }\r
1401   else PaletteSize = 0; /* not Palette Color */\r
1402   if (bLinearFlag) PaletteSize = 0; /* no need to use Palette ??? */\r
1403 \r
1404 #ifdef DEBUGBMP\r
1405   if (traceflag) {\r
1406     sprintf(logline, \r
1407   "bColorImage %d bExpandColor %d bCompressColor %d PaletteSize %d\n", \r
1408          bColorImage, bExpandColor, bCompressColor, PaletteSize);\r
1409     showline(logline, 1);\r
1410   }\r
1411   if (traceflag) {\r
1412     sprintf(logline, "Width %ld, Height %ld, BitsPerSample %d, SamplesPerPixel %d\n", \r
1413          ImageWidth, ImageLength, BitsPerSample, SamplesPerPixel);\r
1414     showline(logline, 1);\r
1415   }\r
1416 #endif\r
1417 \r
1418 /* copied pretty much from readTIFF ... */\r
1419 \r
1420   SamplesPerPixelX = SamplesPerPixel;\r
1421   \r
1422   BitsPerPixel = BitsPerSample * SamplesPerPixel;   /* only BMP */\r
1423   BitsPerPixelX = BitsPerPixel;\r
1424   ExtraSamples = 0;\r
1425   InRowLength = (ImageWidth * BitsPerPixel + 7) / 8;  /* row length file */\r
1426 \r
1427   InRowRead = ((InRowLength + 3) / 4) * 4;  /* multiple of 4 bytes */\r
1428   if (bExpandColor) BufferLength = ImageWidth * 3;\r
1429   else if (bExpandGray) BufferLength = ImageWidth;\r
1430   else BufferLength = InRowLength;\r
1431   \r
1432   if ((BitsPerPixel == 24 || bExpandColor) && ! bAllowColor) {\r
1433     sprintf(logline, " color image (bits %d expand %d): use `*c' flag?",\r
1434          BitsPerPixel, bExpandColor); /* 96/Aug/15 */\r
1435     showline(logline, 1);\r
1436     bCompressColor = 1;\r
1437     OutRowLength = BufferLength / 3;\r
1438   }\r
1439   else OutRowLength = BufferLength;\r
1440 \r
1441 #ifdef DEBUGBMP\r
1442   if (traceflag)\r
1443   {\r
1444     sprintf(logline, "InRowLength %ld BufferLength %ld OutRowLength %ld\n",\r
1445          InRowLength, BufferLength, OutRowLength);\r
1446     showline(logline, 1);\r
1447   }\r
1448 #endif\r
1449   \r
1450 #ifdef PSLEVEL2\r
1451   bRunLengthFlag = 0;\r
1452   if (bAllowCompression) {\r
1453 /*    Use runlength encoding if monochrome *or* if original uses it */\r
1454 /*    if (BitsPerSample == 1 && SamplesPerPixel == 1) */\r
1455     if (BitsPerSample == 1 && SamplesPerPixelX == 1)\r
1456       bRunLengthFlag = 1;\r
1457     if (compression == PACK_BITS) bRunLengthFlag = 1;\r
1458 #ifdef LZWCOMPRESSION\r
1459     bLZWFlag = 0;\r
1460 /*    Use LZW if runlength encoding not chosen */\r
1461     if (bRunLengthFlag == 0) {\r
1462 //      if (compression == LZW_COMPRESSION) bLZWFlag = 1;\r
1463 //      else bLZWFlag = 1;          /* otherwise use LZW */\r
1464       bLZWFlag = 1;\r
1465     }\r
1466 #endif\r
1467   }\r
1468 #endif\r
1469 \r
1470   if (computeheader () != 0) return -1; /* noticed format not supported? */\r
1471 \r
1472   writepsheader(output, dwidth, dheight);\r
1473 \r
1474   ImageSize = (unsigned long) InRowLength * ImageLength; /* for bmp only */\r
1475 \r
1476 /*  check whether values reasonable */  \r
1477   if (ImageSize == 0) {\r
1478     sprintf(logline, " ERROR: Zero image size %d %d (%s)",\r
1479         InRowLength, ImageLength, "readBMPfile");\r
1480     showline(logline, 1);\r
1481     return -1;\r
1482   }\r
1483   if (ImageWidth > MAXIMAGE || ImageLength > MAXIMAGE ||  /* bad data ? */\r
1484     ImageSize > 67108864) { /* arbitrary limits (to catch bad files) */\r
1485     sprintf(logline,\r
1486         " ERROR: image file too large\n(%ld x %ld (%d) => %ld bytes)", \r
1487         ImageWidth, ImageLength, BitsPerPixel, ImageSize);\r
1488     showline(logline, 1);\r
1489     return -1;\r
1490   }\r
1491 \r
1492 #ifdef DEBUGBMP\r
1493   if (traceflag)\r
1494   {\r
1495     sprintf(logline, "Seeking to %ld\n", OffBits);\r
1496     showline(logline, 1);\r
1497   }\r
1498 #endif\r
1499   if (fseek(input, (long) OffBits, SEEK_SET) != 0)\r
1500   {\r
1501     sprintf(logline, " Error in seek %s\n", " to OffBits\n");\r
1502     showline(logline, 1);\r
1503     return -1;\r
1504   }\r
1505   nLen = (int) ((BufferLength + 3) / 4) * 4;\r
1506   lpBuffer = malloc(nLen);\r
1507   if (lpBuffer == NULL)\r
1508   {\r
1509     sprintf(logline, " ERROR: Unable to allocate %d bytes\n", nLen);\r
1510     showline(logline, 1);\r
1511     checkexit(1);\r
1512 //    or more serious exit(1) ???\r
1513   }\r
1514 \r
1515   flag = 0;               /* flag gets set if EOF hit */\r
1516 \r
1517 #ifdef PSLEVEL2\r
1518   if (bLevel2)\r
1519   {\r
1520     ASCIIinitfilter(output);            /* 96/Dec/20 */\r
1521     if (bRunLengthFlag) RUNinitfilter(output);    /* 96/Dec/24 */\r
1522 #ifdef LZWCOMPRESSION\r
1523     else if (bLZWFlag) LZWinitfilter(output);   /* 96/Dec/28 */\r
1524 #endif\r
1525   }\r
1526 #endif\r
1527 \r
1528   for (i = 0; i < (int) ImageLength; i++) { /* read image lines */\r
1529 \r
1530 /*    May need to uncompress here if compression != 0 */\r
1531 /*    nread = fread(lpBuffer, 1, (unsigned int) InRowLength, input); */\r
1532     if (compression == 0)\r
1533       nread = fread(lpBuffer, 1, (unsigned int) InRowRead, input);\r
1534     else if (BitsPerPixel == 4) { /* decompress, four bit images */\r
1535       evenflag = 1;       /* even nibble is next (output) */\r
1536       s = lpBuffer;\r
1537       while (s <= lpBuffer + InRowRead) {\r
1538         c = getc(input);\r
1539 #ifdef DEBUGBMP\r
1540         if (traceflag) {\r
1541           sprintf(logline, " %d", c);\r
1542           showline(logline, 1);\r
1543         }\r
1544 #endif\r
1545         if (c > 0) {      /* repeating group pixel count */\r
1546           d = getc(input);  /* pixel */\r
1547           e = d & 15;     /* decompose right nibble */\r
1548           d = d >> 4;     /* decompose left nibble */\r
1549 #ifdef DEBUGBMP\r
1550           if (traceflag) {\r
1551             sprintf(logline, " repeat %d %d", d, e);\r
1552             showline(logline, 1);\r
1553           }\r
1554 #endif\r
1555           for (k = 0; k < c; k++) {\r
1556             nibble = (k % 2 == 0) ? d : e;\r
1557 /*            now stuff nibble */\r
1558             if (evenflag) *s = (unsigned char) (nibble << 4);\r
1559 /*            else *s++ = *s | nibble; */\r
1560             else *s++ = (unsigned char) (*s | nibble);\r
1561             evenflag = 1 - evenflag;\r
1562           }\r
1563 #ifdef DEBUGBMP\r
1564           if (traceflag) {\r
1565             sprintf(logline, " buffered: %d,", s - lpBuffer);\r
1566             showline(logline, 1);\r
1567           }\r
1568 #endif\r
1569         }\r
1570         else {    /* c == 0 */\r
1571           c = getc(input);  /* pixel count */\r
1572 #ifdef DEBUGBMP\r
1573           if (traceflag) {\r
1574             sprintf(logline, " literal %d", c);\r
1575             showline(logline, 1);\r
1576           }\r
1577 #endif\r
1578           if (c > 2) {    /* literal group */\r
1579             for (k = 0; k < c; k++) {\r
1580               if (k % 2 == 0) {\r
1581                 d = getc(input);\r
1582                 e = d & 15;     /* decompose right nibble */\r
1583                 d = d >> 4;     /* decompose left nibble */\r
1584 #ifdef DEBUGBMP\r
1585                 if (traceflag) {\r
1586                   sprintf(logline, " %d %d", d, e);\r
1587                   showline(logline, 1);\r
1588                 }\r
1589 #endif\r
1590                 nibble = d;\r
1591               }\r
1592               else nibble = e;\r
1593 /*              now stuff nibble */\r
1594               if (evenflag) *s = (unsigned char) (nibble << 4);\r
1595 /*              else *s++ = *s | nibble; */\r
1596               else *s++ = (unsigned char) (*s | nibble);\r
1597               evenflag = 1 - evenflag;\r
1598             }\r
1599             n = 2 + (c+1)/2;    /* bytes read */\r
1600             if ((n % 2) != 0) {   /* padded out to even bytes */\r
1601               d = getc(input);\r
1602 #ifdef DEBUGBMP\r
1603               if (traceflag) {\r
1604                 sprintf(logline, " discard: %d", d);\r
1605                 showline(logline, 1);\r
1606               }\r
1607 #endif\r
1608             }\r
1609 #ifdef DEBUGBMP\r
1610             if (traceflag) {\r
1611               sprintf(logline, " buffered: %d,", s - lpBuffer);\r
1612               showline(logline, 1);\r
1613             }\r
1614 #endif\r
1615           }\r
1616           else if (c == 0) {\r
1617             if (evenflag++ == 0) s++; /* pad last nibble */\r
1618 #ifdef DEBUGBMP\r
1619             if (traceflag) {\r
1620               sprintf(logline, " EOL\n");\r
1621               showline(logline, 1);\r
1622             }\r
1623 #endif\r
1624             if (s < lpBuffer + InRowLength) {\r
1625               sprintf(logline, " Did not fill row %d %d\n",\r
1626                   s - lpBuffer, InRowLength);\r
1627               showline(logline, 1);\r
1628               while (s < lpBuffer + InRowLength) *s++ = '\0';\r
1629             }\r
1630             while (s < lpBuffer + InRowRead) *s++ = '\0';\r
1631             break;  /* end of row */\r
1632           }\r
1633           else if (c == 1) {\r
1634 #ifdef DEBUGBMP\r
1635             if (traceflag) {\r
1636               showline(" EOI\n", 0);\r
1637             }\r
1638 #endif\r
1639             if (i != (int) ImageLength - 1) {\r
1640 #ifdef DEBUGBMP\r
1641               if (traceflag) {\r
1642                 sprintf(logline, "i+1 %d ImageLength %d\n",\r
1643                     i+1, ImageLength);\r
1644                 showline(logline, 0);\r
1645               }\r
1646 #endif\r
1647               showline(" Premature end of image\n", 1);\r
1648             }\r
1649             break;  /* end of picture */\r
1650           }\r
1651           else if (c == 2) {  /* rats! */\r
1652             showline(" Skips not implemented\n", 1);\r
1653           }\r
1654         }\r
1655       }\r
1656       nread = s - lpBuffer;\r
1657     }\r
1658     else {  /* decompress, eight bit images only so far */\r
1659       s = lpBuffer;\r
1660       while (s <= lpBuffer + InRowRead) {\r
1661         c = getc(input);\r
1662 #ifdef DEBUGBMP\r
1663         if (traceflag) {\r
1664           sprintf(logline, " %d", c);\r
1665           showline(logline, 0);\r
1666         }\r
1667 #endif\r
1668         if (c > 0) {      /* repeating group */\r
1669           d = getc(input);  /* pixel */\r
1670 #ifdef DEBUGBMP\r
1671           if (traceflag) {\r
1672             sprintf(logline, " repeat: %d", d);\r
1673             showline(logline, 0);\r
1674           }\r
1675 #endif\r
1676 /*          for (k = 0; k < c; k++) *s++ = d; */\r
1677           for (k = 0; k < c; k++) *s++ = (unsigned char) d;\r
1678 #ifdef DEBUGBMP\r
1679           if (traceflag) {\r
1680             sprintf(logline, " buffered: %d,", s - lpBuffer);\r
1681             showline(logline, 0);\r
1682           }\r
1683 #endif\r
1684         }\r
1685         else {\r
1686 #ifdef DEBUGBMP\r
1687           if (traceflag) {\r
1688             sprintf(logline, " buffered: %d,", s - lpBuffer);\r
1689             showline(logline, 0);\r
1690           }\r
1691 #endif\r
1692           c = getc(input);  /* pixel count */\r
1693 #ifdef DEBUGBMP\r
1694           if (traceflag) {\r
1695             sprintf(logline, " %d", c);\r
1696             showline(logline, 0);\r
1697           }\r
1698 #endif\r
1699           if (c > 2) {    /* literal group */\r
1700             for (k = 0; k < c; k++) {\r
1701               d = getc(input);\r
1702               *s++ = (unsigned char) d;\r
1703 #ifdef DEBUGBMP\r
1704               if (traceflag) {\r
1705                 sprintf(logline, " %d", d);\r
1706                 showline(logline, 0);\r
1707               }\r
1708 #endif\r
1709             }\r
1710             if ((c % 2) != 0) {   /* padded out to even bytes */\r
1711               d = getc(input);\r
1712 #ifdef DEBUGBMP\r
1713               if (traceflag) {\r
1714                 sprintf(logline, " %d", d);\r
1715                 showline(logline, 0);\r
1716               }\r
1717 #endif\r
1718             }\r
1719           }\r
1720           else if (c == 0) {\r
1721             if (evenflag++ == 0) *s++ = '\0'; /* pad last byte */\r
1722 #ifdef DEBUGBMP\r
1723             if (traceflag) {\r
1724               sprintf(logline, " EOL\n");\r
1725               showline(logline, 0);\r
1726             }\r
1727 #endif\r
1728             if (s < lpBuffer + InRowLength) {\r
1729               sprintf(logline, " Did not fill row %d %d\n",\r
1730                    s - lpBuffer, InRowLength);\r
1731               showline(logline, 1);\r
1732               while (s < lpBuffer + InRowLength) *s++ = '\0';\r
1733             }\r
1734             while (s < lpBuffer + InRowRead) *s++ = '\0';\r
1735             break;  /* end of row EOL */\r
1736           }\r
1737           else if (c == 1) {\r
1738             if (evenflag++ == 0) *s++ = '\0';;    /* pad last byte */\r
1739 #ifdef DEBUGBMP\r
1740             if (traceflag) showline(" EOI\n", 0);\r
1741 #endif\r
1742             if (i != (int) ImageLength - 1) {\r
1743               showline(" Premature end of image\n", 1);\r
1744             }\r
1745             break;  /* end of picture EOF */\r
1746           }\r
1747           else if (c == 2) {  /* rats! */\r
1748             showline(" Skips not implemented\n", 1);\r
1749           }\r
1750         }\r
1751       }\r
1752       nread = s - lpBuffer;\r
1753     }\r
1754 /*    if (nread != (unsigned int) InRowLength) */\r
1755     if (nread != (unsigned int) InRowRead) {\r
1756       flag = -1;\r
1757 #ifdef DEBUGBMP\r
1758       if (traceflag) {\r
1759         sprintf(logline, "nread %d InRowRead %d\n", nread, InRowRead);\r
1760         showline(logline, 1);\r
1761       }\r
1762 #endif\r
1763       showline(" ERROR: Premature EOF\n", 1);\r
1764       break;\r
1765     } \r
1766 \r
1767     if (ProcessRow (output, lpBuffer, InRowLength, BufferLength,\r
1768             OutRowLength) != 0) {\r
1769       showline(" Output error\n", 1);     /* BMP */\r
1770       perrormod((outputfile != NULL) ? outputfile : "");\r
1771       break;\r
1772     }\r
1773 /*      if (flag != 0) break; *//* hit EOF or other error */\r
1774 /*      check on abort flag here somewhere also ? */\r
1775   } /* end of this row */\r
1776 \r
1777 //  Have to flush filters in reverse order\r
1778 #ifdef PSLEVEL2\r
1779   if (bLevel2) {\r
1780     if (bRunLengthFlag) RUNflushfilter(output); /* 96/Dec/24 */\r
1781 #ifdef LZWCOMPRESSION\r
1782     else if (bLZWFlag) LZWflushfilter(output);  /* 96/Dec/28 */\r
1783 #endif\r
1784     ASCIIflushfilter(output);       /* 96/Dec/20 */\r
1785   }\r
1786 #endif\r
1787 \r
1788 /* now finished reading */  /* maybe use far memory for lpBuffer ? */\r
1789 \r
1790   if (lpBuffer != NULL) {\r
1791     free(lpBuffer);\r
1792     lpBuffer = NULL;\r
1793   }\r
1794   if (Palette != NULL) {\r
1795     free(Palette);\r
1796     Palette = NULL;\r
1797   }\r
1798   writepstrailer(output);\r
1799   return flag;\r
1800 /*  UNDER CONSTRUCTION !!! */\r
1801 }    /* end of readBMPfile(...) */\r
1802   \r
1803 \r
1804 /**********************************************************************/\r
1805 \r
1806 /* Try and see whether EPSF file and read header info if so: */\r
1807 /* fills in TIFFOffset and PSOffset and MetaOffset and lengths */\r
1808 /* returns zero if not an EPSF file */ /* file position is end of EPSF head */\r
1809 \r
1810 int readepsfhead (FILE *special)\r
1811 {\r
1812   int c, d, e, f;\r
1813 \r
1814   PSOffset = 0;       /* redundant */\r
1815   MetaOffset = 0;       /* redundant */\r
1816   TIFFOffset = 0;       /* redundant */\r
1817 \r
1818   c = getc(special); d = getc(special);\r
1819   e = getc(special); f = getc(special);\r
1820   if (c == 'E' + 128 && d == 'P' + 128 &&\r
1821     e == 'S' + 128 && f == 'F' + 128) {\r
1822     bLeastFirst = 1;\r
1823     PSOffset = (long) ureadfour(special); /* read PS start offset */ \r
1824     PSLength = (long) ureadfour(special); /* read PS length */\r
1825     MetaOffset = (long) ureadfour(special); /* read MF start offset */\r
1826     MetaLength = (long) ureadfour(special); /* read MF length */\r
1827     TIFFOffset = (long) ureadfour(special); /* read TIFF start offset */\r
1828     TIFFLength = (long) ureadfour(special); /* read TIFF length */\r
1829     (void) ureadtwo(special);     /* should be 255, 255 */\r
1830     return -1;\r
1831   }\r
1832   else return 0;              /* not an EPSF file */\r
1833 }\r
1834 \r
1835 int BMPflag=0;    /* non-zero while processing BMP image */\r
1836 \r
1837 int readimagefilesub (FILE *output, FILE *special,\r
1838   long dwidth, long dheight, int nifd, int readflag)\r
1839 {\r
1840 /*  long present; */\r
1841   int c, d; \r
1842 \r
1843   TIFFOffset = 0;       /* normally beginning of file */\r
1844   PSOffset = 0;\r
1845   MetaOffset = 0;\r
1846   BMPflag=0;\r
1847 \r
1848   c = getc(special);\r
1849   (void) ungetc(c, special);\r
1850   if (c > 128) {        /* see whether perhaps EPSF file */\r
1851     if (readepsfhead(special) != 0) {     /* is it EPSF file ? */\r
1852 /*    If valid EPSF header with pointer to TIFF we get here */\r
1853     if (TIFFOffset == 0 || TIFFLength == 0) {\r
1854         showline(" ERROR: Zero TIFF offset or length\n", 1);\r
1855         return -1;\r
1856       }\r
1857       if (fseek(special, TIFFOffset, SEEK_SET) != 0)\r
1858       {\r
1859         sprintf(logline, " Error in seek %s\n", "to TIFFOffset\n");\r
1860         showline(logline, 1);\r
1861         return -1;\r
1862       }\r
1863     }\r
1864     else {\r
1865       showline(" ERROR: Not a valid EPSF or TIFF file\n", 1);\r
1866       return -1;\r
1867     }\r
1868   }             /* end of c > 128 (EPSF file) */\r
1869 \r
1870 /*  Try and deal with PostScript ASCII stuff */\r
1871 /*  Or may meet TIFF / BMP preamble */ \r
1872   c = getc(special); d = getc(special);\r
1873   if (c == '%' && d == '!') {   /* ordinary PS file ? */\r
1874     showline(" ERROR: Ordinary PS file, not TIFF\n", 1);\r
1875     return -1;\r
1876   }\r
1877   else if (c == 'I' && d == 'I') bLeastFirst = 1; /* PC style TIFF file */\r
1878   else if (c == 'M' && d == 'M') bLeastFirst = 0; /* Mac style TIFF file */\r
1879   else if (c == 'B' && d == 'M') BMPflag = 1;   /* BMP 98/Jun/28 */\r
1880   else {\r
1881     showline(" ERROR: Not a valid EPSF, TIFF or BMP file\n", 1);\r
1882     return -1;    /* not a TIFF subfile !!! */\r
1883   }\r
1884 \r
1885 /*  now have decided that this is a TIFF file (or TIFF preview) or BMP */\r
1886   if (BMPflag)\r
1887     (void) readBMPfile(output, special, dwidth, dheight, readflag);\r
1888   else\r
1889     (void) readTIFFfile(output, special, dwidth, dheight, nifd, readflag);\r
1890   return 0;\r
1891 }\r
1892 \r
1893 /*  In prescan to read TIFF tags, readflag = 1 */\r
1894 /*  Later, when actually using the file, readflag = 0 */\r
1895 /*  Prescan only happens if dheight and dwidth are not already given */\r
1896 /*  Returns -1 if file not found */\r
1897 \r
1898 int readimagefile (FILE *output, char *filename,\r
1899   long dwidth, long dheight, int nifd, int readflag)\r
1900 {\r
1901 /*  char infilename[FILENAME_MAX]; */ /* make global */\r
1902   FILE *special;\r
1903 /*  long present;  */\r
1904   int flag;\r
1905 \r
1906   strcpy(infilename, filename);\r
1907 /*  if ((special = findepsfile(infilename, -1, "tif")) == NULL) { */\r
1908 /*  if ((special = findepsfile(infilename, "tif", 1, readflag)) == NULL) */\r
1909 /*  1996/Mar/2 don't warn during prescan when readflag = 1 ??? */\r
1910   if ((special = findepsfile(infilename, "tif", !readflag, readflag)) == NULL)\r
1911     return -1;          \r
1912 \r
1913 #ifdef DEBUGTIFF\r
1914   if (traceflag)\r
1915   {\r
1916     sprintf(logline, "\nManaged to open file %s\n", infilename);\r
1917     showline(logline, 0);\r
1918   }\r
1919 #endif\r
1920   flag = readimagefilesub (output, special, dwidth, dheight, nifd, readflag);\r
1921   fclose(special);\r
1922   return flag;\r
1923 }\r
1924 \r
1925 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
1926 \r
1927 int column;\r
1928 \r
1929 /* Bitspersample can be 1, 2, 4, 8 for ease of conversion to PS */\r
1930 /* Each row takes an integral number of bytes */\r
1931 \r
1932 /* Expand palette color image into full RGB color image */\r
1933 /* Presently only set up for 8 bit palettes ... !!! */\r
1934 \r
1935 void expandcolor (unsigned char *lpBuffer, long width)\r
1936 {\r
1937   int k, n, ns;\r
1938 #ifdef USESHORTINT\r
1939   unsigned short int *PaletteRed;\r
1940   unsigned short int *PaletteGreen;\r
1941   unsigned short int *PaletteBlue;\r
1942 #else\r
1943   unsigned int *PaletteRed;\r
1944   unsigned int *PaletteGreen;\r
1945   unsigned int *PaletteBlue;\r
1946 #endif\r
1947   unsigned char *s;\r
1948   unsigned char *t;\r
1949   unsigned int red=0, green=0, blue=0;\r
1950   int PaletteIndex, Mask;\r
1951   int Byte = 0, BitsLeft = 0;\r
1952 \r
1953 #ifdef DEBUGTIFF\r
1954 /*  if (traceflag) printf("Palette Color => Color "); */\r
1955 #endif\r
1956 \r
1957   if (Palette == NULL)\r
1958   {\r
1959     showline(" ERROR: missing palette information\n", 1);\r
1960     return;\r
1961   }\r
1962   PaletteRed = Palette;\r
1963   PaletteGreen = PaletteRed + PaletteSize;\r
1964   PaletteBlue = PaletteGreen + PaletteSize;\r
1965   Mask = (1 << BitsPerSample) - 1;\r
1966 \r
1967 /*  First slide input data upwards to top of buffer area */\r
1968 \r
1969   n = (int) width;          /* InRowLengthX */\r
1970   ns = (int) ImageWidth;        /* samples per row */\r
1971 \r
1972 /*  if (BufferLength <= InRowLength) */\r
1973   if (BufferLength <= InRowLengthX) {\r
1974     showline(" ERROR: buffer overflow\n", 1);\r
1975     return;\r
1976   }\r
1977 \r
1978 /*  possibly use InRowLengthX ? in next two places */\r
1979 \r
1980   for (k = n-1; k >= 0; k--)  /* move it up to end of lpBuffer space */\r
1981 /*    lpBuffer[k + BufferLength - InRowLength] = lpBuffer[k]; */\r
1982     lpBuffer[k + BufferLength - InRowLengthX] = lpBuffer[k];\r
1983   \r
1984 /*  s = lpBuffer + BufferLength - InRowLength; */ /* start of input data */\r
1985   s = lpBuffer + BufferLength - InRowLengthX; /* start of input data */\r
1986   if (BitsPerSample != 8) {         /* nibble code init */\r
1987     Byte = 0; BitsLeft = 0;\r
1988   }\r
1989   t = lpBuffer;               /* start of output data */\r
1990   for (k = 0; k < ns; k++) {\r
1991     if (BitsPerSample != 8) {       /* slow, but inefficient ! */\r
1992       if (BitsLeft <= 0) {\r
1993         Byte = *s++; BitsLeft = 8;\r
1994       }\r
1995       BitsLeft -= BitsPerSample;\r
1996 /*      PaletteIndex = Byte >> (BitsPerSample - BitsLeft); */\r
1997       PaletteIndex = Byte >> BitsLeft;\r
1998       PaletteIndex = PaletteIndex & Mask;\r
1999 /*      BitsLeft -= BitsPerSample; */\r
2000     }\r
2001     else PaletteIndex = *s++;\r
2002     if (PaletteIndex < PaletteSize) {\r
2003       red = PaletteRed[PaletteIndex];\r
2004       green = PaletteGreen[PaletteIndex];\r
2005       blue = PaletteBlue[PaletteIndex];\r
2006     }\r
2007     else {\r
2008       sprintf(logline, " ERROR: Bad Palette Index %d >= %d\n",\r
2009           PaletteIndex, PaletteSize);\r
2010       showline(logline, 1);\r
2011     }\r
2012 #ifdef DEBUGTIFF\r
2013     if (traceflag) {\r
2014       sprintf(logline, "INX %d\tR %u\tG %u\tB %u\n",\r
2015                 PaletteIndex, red, green, blue); \r
2016       showline(logline, 0);\r
2017     }\r
2018 #endif\r
2019     if (BMPflag) {        /* BMP */\r
2020       *t++ = (unsigned char) red; \r
2021       *t++ = (unsigned char) green; \r
2022       *t++ = (unsigned char) blue;\r
2023     }\r
2024     else {            /* TIFF */\r
2025       *t++ = (unsigned char) (red >> 8); \r
2026       *t++ = (unsigned char) (green >> 8); \r
2027       *t++ = (unsigned char) (blue >> 8);\r
2028     }\r
2029   } \r
2030 }\r
2031 \r
2032 /* This is called for BMP image when palette is used, but it is gray */\r
2033 /* (i.e. R=G=B) and it is *not* linear (i.e. Palette[k] == k) */\r
2034 \r
2035 void expandgray (unsigned char *lpBuffer, long width)\r
2036 {\r
2037   int k, n, ns;\r
2038 #ifdef USESHORTINT\r
2039   unsigned short int *PaletteRed;\r
2040   unsigned short int *PaletteGreen;\r
2041   unsigned short int *PaletteBlue;\r
2042 #else\r
2043   unsigned int *PaletteRed;\r
2044   unsigned int *PaletteGreen;\r
2045   unsigned int *PaletteBlue;\r
2046 #endif\r
2047   unsigned char *s;\r
2048   unsigned char *t;\r
2049   unsigned int red, green, blue;\r
2050   int PaletteIndex, Mask;\r
2051   int Byte = 0, BitsLeft = 0;\r
2052 \r
2053 #ifdef DEBUGBMP\r
2054 /*  if (traceflag) printf("Palette Gray => Gray ");  */\r
2055 #endif\r
2056 \r
2057   if (Palette == NULL)\r
2058   {\r
2059     showline(" ERROR: missing palette information\n", 1);\r
2060     return;\r
2061   }\r
2062   PaletteRed = Palette;\r
2063   PaletteGreen = PaletteRed + PaletteSize;\r
2064   PaletteBlue = PaletteGreen + PaletteSize;\r
2065   Mask = (1 << BitsPerSample) - 1;\r
2066 \r
2067 /*  First slide input data upwards to top of buffer area */\r
2068 \r
2069   n = (int) width;          /* InRowLength */\r
2070   ns = (int) ImageWidth;        /* samples per row */\r
2071 \r
2072 /*  if (BufferLength <= InRowLength) */\r
2073   if (BufferLength <= InRowLengthX)\r
2074   {\r
2075     showline(" ERROR: buffer overflow\n", 1);\r
2076     return;\r
2077   }\r
2078 \r
2079   for (k = n-1; k >= 0; k--)\r
2080 /*    lpBuffer[k + BufferLength - InRowLength] = lpBuffer[k]; */\r
2081     lpBuffer[k + BufferLength - InRowLengthX] = lpBuffer[k];\r
2082 \r
2083 /*  s = lpBuffer + BufferLength - InRowLength; */ /* start of input data */\r
2084   s = lpBuffer + BufferLength - InRowLengthX;   /* start of input data */\r
2085   if (BitsPerSample != 8) {         /* nibble code init */\r
2086     Byte = 0; BitsLeft = 0;\r
2087   }\r
2088   t = lpBuffer;               /* start of output data */\r
2089   for (k = 0; k < ns; k++) {\r
2090     if (BitsPerSample != 8) {       /* slow, but inefficient ! */\r
2091       if (BitsLeft <= 0) {\r
2092         Byte = *s++; BitsLeft = 8;\r
2093       }\r
2094       BitsLeft -= BitsPerSample;\r
2095 /*      PaletteIndex = Byte >> (BitsPerSample - BitsLeft); */\r
2096       PaletteIndex = Byte >> BitsLeft;\r
2097       PaletteIndex = PaletteIndex & Mask;\r
2098 /*      BitsLeft -= BitsPerSample; */\r
2099     }\r
2100     else PaletteIndex = *s++;\r
2101     if (PaletteIndex < PaletteSize) {\r
2102       red = PaletteRed[PaletteIndex];\r
2103       green = PaletteGreen[PaletteIndex];   /* not used */\r
2104       blue = PaletteBlue[PaletteIndex];   /* not used */\r
2105     }\r
2106     else {\r
2107       sprintf(logline, " ERROR: Bad Palette Index %d >= %d\n",\r
2108            PaletteIndex, PaletteSize);\r
2109       showline(logline, 1);\r
2110       red = green = blue = 0;         /* keep compiler happy */\r
2111     }\r
2112 #ifdef DEBUGTIFF\r
2113 /*    if (traceflag) printf("Index %d red %u green %u blue %u\n", */\r
2114     if (traceflag) {\r
2115       sprintf(logline, "INX %d\tR %u\tG %u\tB %u\n",\r
2116           PaletteIndex, red, green, blue); \r
2117       showline(logline, 0);\r
2118     }\r
2119 #endif\r
2120     if (BMPflag) *t++ = (unsigned char) red; /* BMP */\r
2121     else *t++ = (unsigned char) (red >> 8);  /* TIFF */\r
2122   } \r
2123 }\r
2124 \r
2125 /* gray = 0.3 * red + 0.59 * green + 0.11 * blue */\r
2126 \r
2127 void compresscolor (unsigned char *lpBuffer, long width)\r
2128 {\r
2129   int k, n;\r
2130   unsigned char *s;\r
2131   unsigned char *t;\r
2132   unsigned int red, green, blue, gray;\r
2133 \r
2134 #ifdef DEBUGTIFF\r
2135   if (traceflag) showline("Color => Gray ", 0);\r
2136 #endif\r
2137   s = lpBuffer; t = lpBuffer;\r
2138   n = (int) (width / 3);\r
2139   for (k = 0; k < n; k++) {\r
2140     red = *s++; green = *s++; blue = *s++;\r
2141     gray = (int) (((long) blue * 28 + (long) red * 77 + (long) green * 151)\r
2142       >> 8);\r
2143     *t++ = (unsigned char) gray;\r
2144   } \r
2145\r
2146 \r
2147 /*****************************************************************************/\r
2148 \r
2149 #ifdef PSLEVEL2\r
2150 \r
2151 //#pragma optimize ("lge", on)    /* 2000 June 17 */\r
2152 \r
2153 /* use ASCII85Encode if bLevel2 enabled */\r
2154 \r
2155 /* ASCII85 encoding (b1 b2 b3 b4) => (c1 c2 c3 c4 c5) */\r
2156 \r
2157 /* b1 * 256^3 + b2 * 256^2 + b3 * 256  + b4 = \r
2158    c1 * 85^4  + c2 * 85^3  + c3 * 85^2 + c4 * 85 + c5 */\r
2159 \r
2160 /* Add `!' =  33 to make ASCII code. ! represents 0, u represent 84. */\r
2161 \r
2162 /* If all five digits are zero, use z instead of !!!!! - special case. */\r
2163 \r
2164 /* At end, given n = 1, 2, 3 bytes of binary data, append 4 - n zeros.\r
2165    Encode this in usual way (but *without* z special case). \r
2166    Write first (n+1) bytes.  Follow by -> (EOD) */\r
2167 \r
2168 unsigned long asciinum = 0;   /* accumulated so far up to four bytes */\r
2169 int asciicount = 0;       /* how many bytes accumulated so far */  \r
2170 \r
2171 /* Output 4 bytes --- 32 bit unsigned int --- as 5 ASCII 85 bytes */\r
2172 /* nbytes is number of bytes accumulated, which is 4 until the last time */\r
2173 /* Move this inline for speed ? */\r
2174 \r
2175 void ASCIIlong (FILE *output, unsigned long n, int nbytes)\r
2176 {\r
2177   unsigned int c[5];\r
2178   int k;\r
2179 \r
2180 //  sprintf(logline, "ASCIIlong %08X %d ", n, nbytes);\r
2181 //  showline(logline, 0);   // debugging only\r
2182   if (nbytes == 0) nbytes--;      /* nothing to do at end - avoid ! */\r
2183   if (n == 0 && nbytes == 4) {    /* special case !!!!! => z */\r
2184     PSputc('z', output);      /* shorthand for !!!!! */\r
2185     column++;\r
2186     if (column >= MAXCOLUMNASCII) {\r
2187       PSputc('\n', output);\r
2188       column = 0;\r
2189     }\r
2190     return;\r
2191   }\r
2192   for (k = 4; k >= 0; k--) {    /* get base 85 digits reverse order */\r
2193     c[k] = (unsigned int) (n % 85);\r
2194     n = n / 85;\r
2195   }\r
2196   for (k = 0; k < 5; k++) {   /* spit them out in correct order */\r
2197     if (nbytes-- < 0) {         /* last one, finish with EOD */\r
2198       if (column+1 >= MAXCOLUMNASCII) { /* see if space for ~> */\r
2199         PSputc('\n', output);\r
2200         column = 0;\r
2201       }\r
2202       PSputs("~>\n", output); /* EOD */\r
2203       column = 0;\r
2204       return;\r
2205     }\r
2206     PSputc((char) (c[k] + '!'), output);\r
2207     column++;\r
2208     if (column >= MAXCOLUMNASCII) {\r
2209       PSputc('\n', output);\r
2210       column = 0;\r
2211     }\r
2212   } /* end of for k = 0; k < 5; k++ */\r
2213 }\r
2214 \r
2215 /* Output single byte (accumulate until four seen, then call ASCIIlong) */\r
2216 /* Move this inline for speed ? */\r
2217 \r
2218 void ASCIIout (FILE *output, unsigned int x)\r
2219 {\r
2220 //  sprintf(logline, "ASCII %d ", x);\r
2221 //  showline(logline, 0);     // debugging only\r
2222   if (x > 255) x = x & 255;   // sanity check ???\r
2223   asciinum = (asciinum << 8) | x;\r
2224   asciicount++;\r
2225   if (asciicount >= 4) {\r
2226     ASCIIlong(output, asciinum, asciicount);\r
2227     asciinum = 0;\r
2228     asciicount = 0;\r
2229   }\r
2230 }\r
2231 \r
2232 /* initialize ASCII85 filter */\r
2233 \r
2234 void ASCIIinitfilter (FILE *output)   /* 96/Dec/20 */\r
2235 {\r
2236 //  showline("ASCIIinitfilter ", 0);  // debugging only\r
2237   asciinum = 0;\r
2238   asciicount = 0;\r
2239   column = 0;     /* ??? */\r
2240 }\r
2241 \r
2242 void RUNinitfilter (FILE *output)    /* 95/Dec/24 */\r
2243 {\r
2244 /*  apparently nothing special to do */\r
2245 }\r
2246 \r
2247 /* flush out anything left in ASCII85 filter */\r
2248 \r
2249 void ASCIIflushfilter (FILE *output)  /* 96/Dec/20 */\r
2250 {\r
2251   int k;\r
2252 //  showline("ASCIIflushfilter ", 0); // debugging only\r
2253   for (k = asciicount; k < 4; k++) {\r
2254     asciinum = (asciinum << 8);   /* append n-4 zeros */\r
2255   }\r
2256   ASCIIlong(output, asciinum, asciicount);\r
2257   asciinum = 0;\r
2258   asciicount = 0;\r
2259 }\r
2260 \r
2261 void RUNflushfilter (FILE *output)\r
2262 {\r
2263   ASCIIout(output, 128);          /* EOD */\r
2264 }\r
2265 \r
2266 /*****************************************************************************/\r
2267 \r
2268 /* write a row in ASCII85 format */\r
2269 \r
2270 void writearowASCII (FILE *output, unsigned char *s, unsigned long width)\r
2271 {\r
2272   unsigned int c;\r
2273   int k, n, i;\r
2274   unsigned long num;\r
2275 \r
2276   n = (int) width;\r
2277   k = 0;\r
2278   if (asciicount > 0) { /* finish off group of four bytes first */\r
2279     for (i = asciicount; i < 4; i++) {\r
2280       ASCIIout(output, *s++);\r
2281       k++;\r
2282       if (k >= n) break;  /* in case of miniscule width! */\r
2283     }\r
2284   }\r
2285   while (k < n-3) {   /* then do groups of four bytes */\r
2286     num = 0;\r
2287     for (i = 0; i < 4; i++) {\r
2288       c = *s++;\r
2289       num = (num << 8) | c;\r
2290     }\r
2291     ASCIIlong(output, num, 4);\r
2292     k += 4;\r
2293   }\r
2294   while (k < n) {     /* then do remaining bytes at tail of row */\r
2295     ASCIIout(output, *s++);\r
2296     k++;\r
2297   }\r
2298 }\r
2299 \r
2300 /**************************************************************************/\r
2301 \r
2302 #if (defined(DEBUGLZWENCODE) || defined(DEBUGRUNLENGTH))\r
2303 int debugflag=1;      /* debugging output */\r
2304 #endif\r
2305 \r
2306 /* Do run encoding per row (rather than image) --- easier, if not optimal */\r
2307 \r
2308 void dumprun(FILE *output, int nlen, int previous)\r
2309 {\r
2310 #ifdef DEBUGRUNLENGTH\r
2311   int i;\r
2312   if (nlen <= 0) {\r
2313     sprintf(logline, "Zero length run %d ", nlen);\r
2314     showline(logline, 0);\r
2315     return;\r
2316   }\r
2317   else if (nlen < 3) {\r
2318     sprintf(logline, " ERROR: run %d < 3\n", nlen);\r
2319     showline(logline, 1);\r
2320   }\r
2321   else if (nlen > 128) {\r
2322     sprintf(logline, " ERROR: run %d > 128", nlen);\r
2323     showline(logline, 1);\r
2324   }\r
2325   for (i = 0; i < nlen; i++) {\r
2326     sprintf(logline, "%02X", previous);\r
2327     showline(logline, 1);\r
2328   }\r
2329 #endif\r
2330   ASCIIout(output, 257 - nlen);\r
2331   ASCIIout(output, previous);\r
2332 }\r
2333 \r
2334 void dumpnonrun(FILE *output, int nlen, unsigned char *buffer)\r
2335 {\r
2336   int i;\r
2337   unsigned char *s;\r
2338 \r
2339 #ifdef DEBUGRUNLENGTH\r
2340   if (nlen <= 0) {\r
2341     sprintf(logline, "Zero length nonrun %d ", nlen);\r
2342     showline(logline, 0);\r
2343     return;\r
2344   }\r
2345   if (nlen > 128) {\r
2346     sprintf(logline, " ERROR: nonrun %d > 128", nlen);\r
2347     showline(logline, 1);\r
2348   }\r
2349   if (debugflag) {\r
2350     s = buffer;\r
2351     for (i = 0; i < nlen; i++) {\r
2352       int c;\r
2353       c = *s++;\r
2354       sprintf(logline, "%02X", c);\r
2355       showline(logline, 1);\r
2356     }\r
2357   }\r
2358 #endif\r
2359   ASCIIout(output, nlen - 1);\r
2360   s = buffer;\r
2361   for (i = 0; i < nlen; i++) ASCIIout(output, *s++);\r
2362 }\r
2363 \r
2364 /* RunLengthEncode filter */\r
2365 \r
2366 /* This basically has two states: */\r
2367 /* (1) accumulating non-run (runflag == 0) */\r
2368 /* (2) accumulating run (runflag != 0) */\r
2369 /* Here (1) is the starting state */\r
2370 /* Dumps out when (i) state changes (ii) 128 bytes seen (iii) end input */\r
2371 \r
2372 void writearowrun (FILE *output, unsigned char *s, unsigned long width)\r
2373 {\r
2374   int runflag;      /* non-zero if in accumulating run state */\r
2375   int previous;     /* character that appears to be repeating */\r
2376   int repeat;       /* how many times we have seen previous */\r
2377   int bcount;       /* count of bytes buffered up (s-new) */\r
2378   unsigned char *new;   /* points to part of string not yet dumped */\r
2379   int n, k, c;\r
2380 \r
2381   n = (int) width;\r
2382   k = 0;\r
2383   bcount = 0;       /* non run length accumulated */\r
2384   new = s;        /* points to first byte not yet output */\r
2385   previous = -1;      /* previous character in a run */\r
2386   repeat = 0;       /* how many repetetions of previous */\r
2387   runflag = 0;      /* start in non run state */\r
2388 \r
2389   while (k < n) {\r
2390     c = *s;       /* grab next byte */\r
2391     if (runflag) {        /* accumulating a run ? */\r
2392       if (repeat >= 128) {  /* run too long ? */\r
2393         dumprun(output, repeat, previous);\r
2394         new = s;\r
2395         previous = c;\r
2396         repeat = 1;\r
2397         bcount = 1;\r
2398         runflag = 0;      /* switch back to non run state */\r
2399       }\r
2400       else if (c == previous) { /* continue the run ? */\r
2401         repeat++;\r
2402       }\r
2403       else {            /* c != previous --- end of a run */\r
2404         dumprun(output, repeat, previous);\r
2405         new = s;\r
2406         previous = c;\r
2407         repeat = 1;\r
2408         bcount = 1;\r
2409         runflag = 0;      /* switch back to non run state */\r
2410       }\r
2411     }\r
2412     else {            /* runflag == 0 accumulating a non run */\r
2413       if (bcount >= 128) {  /* accumulated too much ? */\r
2414         dumpnonrun(output, bcount, new);\r
2415         new = s;\r
2416         previous = c;\r
2417         bcount = 1;\r
2418         repeat = 1;\r
2419 /*        and stay in non run mode */\r
2420       }\r
2421       else if (c == previous) {\r
2422         repeat++;\r
2423         if (repeat >= 4) {  /* end of non-run */\r
2424           if (bcount+1 > repeat)\r
2425             dumpnonrun(output, bcount-repeat+1, new);\r
2426           bcount = 0;         /* needed ? */\r
2427           runflag = 1;  /* switch to accumulating run state */\r
2428 /*          don't change previous, repeat */\r
2429         }\r
2430         if (runflag == 0) bcount++;\r
2431       }\r
2432       else {\r
2433         bcount++;\r
2434         previous = c;\r
2435 /*        don't change new, bcount */\r
2436         repeat = 1;\r
2437       }\r
2438     }\r
2439     s++;\r
2440     k++;\r
2441   } /* end of while loop */\r
2442 #ifdef DEBUGRUNLENGTH\r
2443 /*  if (debugflag) showline("EOL ", 0); */\r
2444 #endif\r
2445   if (runflag) dumprun(output, repeat, previous);\r
2446   else if (repeat >= bcount  && repeat > 1)\r
2447     dumprun(output, repeat, previous);\r
2448   else dumpnonrun(output, bcount, new);\r
2449 #ifdef DEBUGRUNLENGTH\r
2450   if (debugflag) showline("\n", 0);\r
2451 #endif\r
2452 }\r
2453 \r
2454 /**************************************************************************/\r
2455 \r
2456 /* code for LZW compression on OUTPUT side  LZWcompress rewrite 2000 June 17 */\r
2457 \r
2458 #ifdef LZWCOMPRESSION\r
2459 \r
2460 struct NODE {\r
2461   int chr;      // byte to get to this node --- or -1\r
2462 //  NODE nextinlist;  // next in list at this level ptr\r
2463   int nextinlist;   // next in list at this level\r
2464 //  NODE nextlevel;   // first at next level ptr\r
2465   int nextlevel;    // first at next level\r
2466 };\r
2467 \r
2468 // May get some added performance by making the last two components be\r
2469 // pointers rather than indeces...\r
2470 \r
2471 struct NODE *node=NULL;   // array of nodes --- allocated\r
2472 \r
2473 int currentnode;  // code of node currently at\r
2474 int nextnode;   // code of next node to be used\r
2475 int codelength;   // how many bits needed for code at this stage 9, 10, 11, 12\r
2476 \r
2477 void DeAllocStringsOut (void) // called from dvibody() in dvipsone.c\r
2478 {\r
2479   if (node != NULL) {\r
2480     free(node);\r
2481     node = NULL;\r
2482   }\r
2483 }\r
2484 \r
2485 void CleanOut (FILE *output, int n)\r
2486 {\r
2487   int k;\r
2488 \r
2489 //  sprintf(logline, "CLEANOUT %d\n", n);\r
2490 //  showline(logline, 0);\r
2491 \r
2492 //  0 to MAXCHR, and CLEAR and EOD\r
2493   for (k = 0; k < FIRSTCODE; k++) {\r
2494     node[k].chr = -1;\r
2495     node[k].nextinlist = -1;\r
2496     node[k].nextlevel = -1;\r
2497   }\r
2498   LZWput(CLEAR, output);    // using current code length\r
2499   nextnode = FIRSTCODE;   // next node available\r
2500   currentnode = n;      // string in progress\r
2501   codelength = 9;       // reset code length now\r
2502 }\r
2503 \r
2504 int SetupNodes (FILE *output)\r
2505 {\r
2506   int nlen;\r
2507 \r
2508   if (node == NULL) {\r
2509     nlen = MAXCODES * sizeof(struct NODE);  // 49,152 bytes\r
2510     if (traceflag) {\r
2511       sprintf(logline, "Allocating %d bytes\n", nlen);  // debugging only\r
2512       showline(logline, 0);\r
2513     }\r
2514     node = (struct NODE *) malloc(nlen);\r
2515     if (node == NULL) {\r
2516       sprintf(logline, "Unable to allocate %d bytes for NODE table\n", nlen);\r
2517       showline(logline, 1);\r
2518       checkexit(1);\r
2519     }\r
2520   }\r
2521 //  LZWput(CLEAR, output);      // do separately\r
2522 //  nextnode = FIRSTCODE;\r
2523 //  currentnode = -1;\r
2524   codelength = 9;         // need to initialize\r
2525 //  CleanOut(output, -1);     // do separately\r
2526   return 0;\r
2527 }\r
2528 \r
2529 #ifdef IGNORED\r
2530 // We are at node n and adding a new branch for byte chr -- NOT USED\r
2531 void AddaNode (FILE *output, int n, int chr, int previous)\r
2532 {\r
2533   int k, klast;\r
2534 //  if (nextnode < 0 || nextnode >= MAXCODES) showline("TABLE OVERFLOW", 1);\r
2535 //  Is there already a node at the next level ?\r
2536   k = node[n].nextlevel;\r
2537   if (k < 0) {    // no, start next level list\r
2538     node[n].nextlevel = nextnode; // link to new node\r
2539   }\r
2540   else {                // yes, link to end of that list\r
2541 //    k = node[n].nextlevel;\r
2542 //    find end of linked list\r
2543     while (k >= 0) {\r
2544       klast = k;\r
2545       k = node[klast].nextinlist;\r
2546     }\r
2547     node[klast].nextinlist = nextnode;  // link new node to end of list\r
2548   }\r
2549 //  set up new node being added\r
2550 //  node[nextnode].code = nextnode;\r
2551   node[nextnode].chr = chr;\r
2552   node[nextnode].nextinlist = -1;\r
2553   node[nextnode].nextlevel = -1;\r
2554   nextnode++;\r
2555   if (nextnode == 512 || nextnode == 1024 || nextnode == 2048) {\r
2556 //    sprintf(logline, "CODELENGTH %d ", codelength);\r
2557 //    showline(logline, 0);\r
2558     codelength++;\r
2559   }\r
2560   else if (nextnode == 4096) CleanOut(output, chr);\r
2561 }\r
2562 #endif\r
2563 \r
2564 // We are adding a new node for byte chr\r
2565 \r
2566 void NewNode (FILE *output, int chr, int previous) {\r
2567   if (nextnode < 0 || nextnode >= MAXCODES) showline("TABLE OVERFLOW", 1);\r
2568 //  set up new node being added\r
2569 //  node[nextnode].code = nextnode;\r
2570 //  sprintf(logline, "NEW NODE %d %d\n", chr, previous);\r
2571 //  showline(logline, 1);\r
2572 //  sprintf(logline, "NEW NODE %d for %d from %d ", nextnode, chr, previous);\r
2573 //  showline(logline, 1);   // debugging only\r
2574   node[nextnode].chr = chr;\r
2575   node[nextnode].nextinlist = -1;\r
2576   node[nextnode].nextlevel = -1;\r
2577   nextnode++;\r
2578   if (nextnode == 512 || nextnode == 1024 || nextnode == 2048) {\r
2579 //    sprintf(logline, "CODELENGTH %d ", codelength);\r
2580 //    showline(logline, 0);\r
2581     codelength++;\r
2582   }\r
2583   else if (nextnode == 4096) CleanOut(output, chr);\r
2584 }\r
2585 \r
2586 // Process next incoming byte\r
2587 \r
2588 void DoNextByte (FILE *output, int chr) { // called from  writearowLZW\r
2589   int k, klast;\r
2590 //  sprintf(logline, "(%d) ", chr);   // debugging only\r
2591 //  showline(logline, 0);\r
2592   if (currentnode < 0) {  // starting from scratch ? (empty string)\r
2593     currentnode = chr;\r
2594     return;\r
2595   }\r
2596   k = node[currentnode].nextlevel;\r
2597   if (k < 0) {  // does next level exist ?\r
2598 //    AddaNode(currentnode, n);\r
2599     LZWput(currentnode, output);    // new string NOT in table\r
2600     node[currentnode].nextlevel = nextnode; // NEXT LEVEL\r
2601 //    sprintf(logline, "NEW LEVEL %d %d %d ", currentnode, nextnode, chr);\r
2602 //    showline(logline, 0);       // debugging only\r
2603     NewNode(output, chr, currentnode);  // new node at nextnode\r
2604     currentnode = chr;          // string of one byte\r
2605     return;\r
2606   }\r
2607 //  there is a list at the next level --- search it\r
2608 //  k = node[currentnode].nextlevel;\r
2609   while (k >= 0 && node[k].chr != chr) {\r
2610     klast = k;\r
2611     k = node[klast].nextinlist;\r
2612   }\r
2613   if (k < 0) {              // hit end of list ?\r
2614 //    AddaNode(currentnode, n);\r
2615     LZWput(currentnode, output);    // new string NOT in table\r
2616     node[klast].nextinlist = nextnode;  // NEXT IN LIST\r
2617 //    sprintf(logline, "NEW ELEM %d (%d) %d %d ", currentnode, klast, nextnode, chr);\r
2618 //    showline(logline, 0);       // debugging only\r
2619     NewNode(output, chr, currentnode);  // new node at nextnode\r
2620     currentnode = chr;          // string of one byte\r
2621     return;\r
2622   }\r
2623 //  we did find this string in the table\r
2624 //  if (k < 0 || k >= MAXCODES) showline("ERROR ", 0);  // debugging only\r
2625   currentnode = k;  // it IS in table, no output\r
2626 }\r
2627 \r
2628 #ifdef IGNORED\r
2629 void DoCleanup (FILE *output)  // not used - see LZWflushfilter\r
2630 {\r
2631   if (currentnode >= 0) LZWput(currentnode, output);\r
2632 //  LZWput(CLEAR, output);\r
2633 //  nextnode = FIRSTCODE;\r
2634 //  currentnode = -1;\r
2635 //  codelength = 9;\r
2636   CleanOut(output, -1);\r
2637 }\r
2638 #endif\r
2639 \r
2640 /***************************************************************************/\r
2641 \r
2642 int perrow = 100;\r
2643 \r
2644 long leftover;    /* byte accumulated so far - need up to 12 + 12 bits */\r
2645 int bitsused;   /* bits used so far */\r
2646 \r
2647 /* stuff codelength bits of c into output stream */\r
2648 /* may produce one or two bytes ready to spit out */\r
2649 /* bitsused is always < 8 before and always < 8 after this */\r
2650 \r
2651 void LZWput (int code, FILE *output)\r
2652 {\r
2653   int c;\r
2654 \r
2655 //  if (bitsused < 0 || bitsused >= 8) showline("ERROR ", 1);\r
2656 #ifdef DEBUGLZWENCODE\r
2657   if (debugflag)\r
2658   {\r
2659     if (code >= (1 << codelength))\r
2660     sprintf(logline, "code %d too long for code length %d\n",\r
2661         code, codelength);\r
2662     showline(logline, 1);\r
2663   }\r
2664 #endif\r
2665 //  sprintf(logline, "LEFT %08X USED %d ", leftover, bitsused);\r
2666 //  showline(logline, 0);   // debugging only\r
2667   leftover = (leftover << codelength) | code;\r
2668   bitsused += codelength;\r
2669   if (bitsused >= 16) {\r
2670     c = (int) (leftover >> (bitsused - 8)); /* get left most 8 bits */\r
2671     ASCIIout(output, c & 255);      // expand ?\r
2672     bitsused -= 8;\r
2673   }\r
2674   c = (int) (leftover >> (bitsused - 8)); /* get left most 8 bits */\r
2675   ASCIIout(output, c & 255);        // expand ?\r
2676   bitsused -= 8;\r
2677 //  if (bitsused < 0 || bitsused >= 8) showline("ERROR ", 1);\r
2678 }\r
2679 \r
2680 void LZWputinit (FILE *output) {  /* called from LZWinitfilter */\r
2681 //  showline("LZWputinit ", 0); // debugging only\r
2682   leftover = 0;\r
2683   bitsused = 0;\r
2684 }\r
2685 \r
2686 void LZWputflush (FILE *output)\r
2687 {\r
2688   int c;\r
2689 //  showline("LZWputflush ", 0);  // debugging only\r
2690   if (bitsused == 0) return;    /* nothing left to push out */\r
2691   c = (int) (leftover << (8 - bitsused));\r
2692 /*  c = (int) (leftover >> (bitsused - 8)); */  /* same thing ? */\r
2693   ASCIIout(output, c & 255);      /* fill last byte with zeros */\r
2694 /*  leftover = 0; */\r
2695 /*  bitsused = 0; */\r
2696 }\r
2697 \r
2698 void LZWinitfilter (FILE *output) /*  initialization  */\r
2699 {\r
2700 //  showline("LZWinitfilter ", 0);    // debugging only\r
2701   LZWputinit(output);\r
2702 //  LZWput(CLEAR, output);  /* write CLEAR */\r
2703   SetupNodes(output);\r
2704   CleanOut(output, -1);\r
2705 /*  codelength = 9; */\r
2706 }\r
2707 \r
2708 void LZWflushfilter (FILE *output) /* termination */\r
2709 {\r
2710 //  showline("LZWflushfilter ", 0);   // debugging only\r
2711   if (currentnode >= 0) {\r
2712     LZWput(currentnode, output);\r
2713 #ifdef DEBUGLZWENCODE\r
2714     if (debugflag > 1) showcode(currentnode);\r
2715 #endif\r
2716   }\r
2717   LZWput(EOD, output);\r
2718 #ifdef DEBUGLZWENCODE\r
2719   if (debugflag) showline("EOD ", 1);\r
2720   if (debugflag) {\r
2721     sprintf(logline, "%d entries ", nextnode);\r
2722     showline(logline, 1);\r
2723   }\r
2724 #endif\r
2725   LZWputflush(output);\r
2726 /*  CleanOut(output, -1); */\r
2727 }\r
2728 \r
2729 /* Basic LZW encoding for output */ /* encode width bytes starting at *s */\r
2730 /* Initialization and Termination taken care of elsewhere */\r
2731 /* int code; */ /* code of the string matched so far to input */\r
2732 /* int last; */ /* last character of input string */\r
2733 \r
2734 int writearowLZW (FILE *output, unsigned char *s, unsigned long width)\r
2735 {\r
2736   unsigned char *send = s + width;\r
2737 \r
2738 /*  This picks up unfinished business --- currentnode >= 0 */\r
2739   while (s < send) {\r
2740     DoNextByte(output, *s++);\r
2741   }\r
2742   return 0;\r
2743 /*  This may leave unfinished business --- currentnode >= 0 */\r
2744 }\r
2745 \r
2746 #endif /* end of ifdef LZWCOMPRESSION */\r
2747 \r
2748 /*************************************************************************/\r
2749 \r
2750 //#pragma optimize ("lge", off)\r
2751 \r
2752 #endif /* end of ifdef PSLEVEL2 */\r
2753 \r
2754 /* write row in hex format */\r
2755 \r
2756 void writearowhex (FILE *output, unsigned char *s, unsigned long width)\r
2757 {\r
2758   unsigned int c, d;\r
2759   int k, n;\r
2760 \r
2761   n = (int) width;\r
2762   column = 0;\r
2763   for (k = 0; k < n; k++) {\r
2764     if (column >= MAXCOLUMNHEX) {\r
2765 //      putc('\n', output);\r
2766       PSputc('\n', output);\r
2767       column = 0;\r
2768     }\r
2769     c = *s++;\r
2770     d = c & 15;\r
2771     c = c >> 4;\r
2772     if (c > 9) {\r
2773 //      putc(c + 'A' - 10, output);\r
2774       PSputc((char) (c + 'A' - 10), output);\r
2775     }\r
2776     else {\r
2777 //      putc(c + '0', output);\r
2778       PSputc((char) (c + '0'), output);\r
2779     }\r
2780     column++;\r
2781     if (d > 9) {\r
2782 //      putc(d + 'A' - 10, output);\r
2783       PSputc((char) (d + 'A' - 10), output);\r
2784     }\r
2785     else {\r
2786 //      putc(d + '0', output);\r
2787       PSputc((char) (d + '0'), output);\r
2788     }\r
2789     column++;\r
2790   }\r
2791 //  putc('\n', output);   /* also start each image row on new line */\r
2792   PSputc('\n', output);   /* also start each image row on new line */\r
2793   column = 0;\r
2794 }\r
2795 \r
2796 /* returns -1 if output error */  /* write a row of data in hex */\r
2797 \r
2798 int writearow (FILE *output, unsigned char *s, unsigned long width)\r
2799 {\r
2800 #ifdef PSLEVEL2\r
2801   if (bLevel2) {\r
2802     if (bRunLengthFlag) writearowrun(output, s, width);\r
2803 #ifdef LZWCOMPRESSION\r
2804     else if (bLZWFlag) writearowLZW(output, s, width);\r
2805 #endif\r
2806     else writearowASCII(output, s, width);\r
2807   }\r
2808   else writearowhex(output, s, width);\r
2809 #else\r
2810   writearowhex(output, s, width);\r
2811 #endif\r
2812 \r
2813 //  if (ferror(output)) \r
2814   if (output != NULL && ferror(output))\r
2815   {\r
2816     showline(" ERROR: Output error\n", 1);\r
2817     perrormod((outputfile != NULL) ? outputfile : "");\r
2818     return -1;\r
2819   }\r
2820   if (bAbort) abortjob();   /* 97/Mar/1 ? */\r
2821   if (abortflag) return -1;\r
2822   return 0;\r
2823 }\r
2824 \r
2825 int computeheader (void) {\r
2826 /*  int changeflag= 0; */\r
2827 \r
2828 #ifdef DEBUGTIFF\r
2829   if (traceflag) showline("Now computing header information\n", 0);\r
2830 #endif\r
2831 \r
2832 /*  Now for some sanity checks */\r
2833   if (PlanarConfig != 1) {\r
2834     showline(" ERROR: Multiple color planes not supported\n", 1);\r
2835     return -1; \r
2836   }\r
2837   if (BitsPerSample > 8) {\r
2838     sprintf(logline, " ERROR: Maximum of 8 bits per sample (%d)\n",\r
2839       BitsPerSample);\r
2840     showline(logline, 1);\r
2841     return -1;\r
2842   }\r
2843   if ((BitsPerSample & (BitsPerSample-1)) != 0) {\r
2844     sprintf(logline, " ERROR: Bits per sample must be power of two (%d)\n",\r
2845       BitsPerSample);\r
2846     showline(logline, 1);\r
2847     return -1;\r
2848   }\r
2849   if (compression > TIFF_CCITT && compression != LZW_COMPRESSION &&\r
2850     compression != PACK_BITS ) {\r
2851     sprintf(logline,  " ERROR: Unknown compression scheme (%d)", compression);\r
2852     showline(logline, 1);\r
2853     return -1;\r
2854   }\r
2855 \r
2856   if (PhotometricInterpretation == 3) { /* that is palette color */\r
2857 /*    if (SamplesPerPixel != 1) */\r
2858     if (SamplesPerPixelX != 1) {\r
2859       showline(" ERROR: Palette color must have one sample per pixel", 1);\r
2860       return -1;\r
2861     }\r
2862   }\r
2863 /*  check whether need to use `colorimage' operator instead of `image' */\r
2864 /*  if (SamplesPerPixel != 1) */\r
2865   if (SamplesPerPixelX != 1) {\r
2866 //    if (PhotometricInterpretation != 2)\r
2867     if (PhotometricInterpretation != 2 && PhotometricInterpretation != 5)\r
2868 //      showline(" More than one sample per pixel, but not RGB?", 1);\r
2869       showline(" More than one sample per pixel, but not RGB or CMYK?", 1);\r
2870     bColorImage = 1;\r
2871     if (! bAllowColor) {\r
2872       sprintf(logline, " WARNING: More than one sample per pixel (%d) use `*c' flag?",\r
2873         SamplesPerPixel);\r
2874       showline(logline, 0);\r
2875 /*      return -1; */\r
2876       bCompressColor = 1;     /* then need to compress colors */\r
2877     }\r
2878   }\r
2879 /*  if (verboseflag && PhotometricInterpretation > 3) {\r
2880     printf("Photometricinterpretation %d\n", PhotometricInterpretation);\r
2881   }  */\r
2882 /*  0 => 0 will be white and 2^n-1 black */\r
2883 /*  1 => 0 will be black and 2^n-1 white (default) */\r
2884 /*  2 => RGB model */\r
2885 /*  3 => palette color */\r
2886 /*  4 => transparency mask */\r
2887 /*  Fix this one later */\r
2888 /*  if (PhotometricInterpretation == 3) bColorImage = 1;  */\r
2889 /*  if (ColorMapPtr != 0)   bColorImage = 1; */\r
2890   if (PhotometricInterpretation == 3 && ColorMapPtr == 0) {\r
2891     showline(" ERROR: Palette Color Image must have Palette!\n", 1);\r
2892     return -1;\r
2893   }\r
2894   if (PhotometricInterpretation == 2)\r
2895   {\r
2896 /*    if (SamplesPerPixel == 1)  */\r
2897     if (SamplesPerPixelX == 1)\r
2898     {\r
2899       sprintf(logline, " %s, but not more than one sample per pixel?\n", "RGB");\r
2900       showline(logline, 1);\r
2901     }\r
2902     if (! bAllowColor)\r
2903     {\r
2904       sprintf(logline, " WARNING: %s color image (%d) use `*c' flag?", "RGB", SamplesPerPixel);\r
2905 //      showline(logline, 1);\r
2906       showline(logline, 0);\r
2907       bCompressColor = 1;\r
2908     }\r
2909     bColorImage = 1;\r
2910   }\r
2911   if (PhotometricInterpretation == 5) { // 2000 May 27\r
2912 /*    if (SamplesPerPixel == 1)  */\r
2913     if (SamplesPerPixelX == 1)\r
2914     {\r
2915       sprintf(logline, " %s, but not more than one sample per pixel?\n", "CMYK");\r
2916       showline(logline, 1);\r
2917     }\r
2918     if (! bAllowColor)\r
2919     {\r
2920       sprintf(logline, " WARNING: %s color image (%d) use `*c' flag?", "CMYK", SamplesPerPixel);\r
2921 //      showline(logline, 1);\r
2922       showline(logline, 0);\r
2923       bCompressColor = 1;\r
2924     }\r
2925     bColorImage = 1;\r
2926   }\r
2927 /*  0 => 0 will be white and 2^n-1 black */\r
2928 /*  1 => 0 will be black and 2^n-1 white (default) */\r
2929 \r
2930   if (PhotometricInterpretation == 0)\r
2931   {\r
2932 #ifdef DEBUGTIFF\r
2933     if (traceflag) showline("Image grey levels will be inverted\n", 0); \r
2934 #endif\r
2935     bInvertImage = 1;\r
2936   }\r
2937   else bInvertImage = 0;\r
2938 \r
2939 #ifdef DEBUGTIFF\r
2940   if (traceflag)\r
2941   {\r
2942     sprintf(logline, "ExpandColor %d CompressColor %d InvertImage %d\n",\r
2943       bExpandColor, bCompressColor, bInvertImage);\r
2944     showline(logline, 0);\r
2945   }\r
2946 #endif\r
2947 \r
2948 /*  compute bytes per row (both input and output?) */\r
2949 /*  if (bColorImage)bytes = (int) (((long) ImageWidth * BitsPerPixel + 7) / 8);\r
2950   else bytes = (int) (((long) ImageWidth * BitsPerSample + 7) / 8); */\r
2951 /*  Following only correct if no expansion or contraction of color images */\r
2952 /*  bytes = (int) (((long) ImageWidth * BitsPerPixel + 7) / 8); */\r
2953   bytes = (int) OutRowLength;     /* ever used ? */\r
2954 #ifdef DEBUGTIFF\r
2955   if (traceflag) {\r
2956     sprintf(logline, "%d bytes per row\n", bytes);\r
2957     showline(logline, 0);\r
2958   }\r
2959 #endif\r
2960   return 0;\r
2961 }\r
2962 \r
2963 /* long xll=0, yll=0, xur=0, yur=0;  */\r
2964 \r
2965 /*  {1 exch sub} settransfer */\r
2966 /*  currenttranser {1 exch sub 0 exec} exch 4 put bind */\r
2967 /*  char *invertgray=\r
2968   "[{1 exch sub} /exec load currentransfer /exec load] cvx settransfer\n"; */\r
2969 \r
2970 /* compress some of this code into DVIPREAM.PS ? */\r
2971 \r
2972 void writepsheader (FILE *output, long dwidth, long dheight)\r
2973 {\r
2974   int bits=1;         /* bits per pixel in image */\r
2975   int samples=3;        /* samples per pixel 96/July/7 */\r
2976   int bMonoChrome=0;      /* if need to use image mask */\r
2977 /*  int paintback=0; */     /* if need to paint background */\r
2978 /*  long XOffset, YOffset; */\r
2979   long YOffset;\r
2980 \r
2981 #ifdef DEBUGTIFF\r
2982   if (traceflag) showline("Now writing out header information\n", 0);\r
2983 #endif\r
2984 /*  if (BitsPerSample == 1) bMonoChrome = 1; */ /* use image mask */\r
2985 \r
2986   if (bExpandColor) bits = 8;\r
2987   else if (bExpandGray) bits = 8;\r
2988   else bits = BitsPerSample;\r
2989 \r
2990   if (bits == 1) bMonoChrome = 1;       /* use image mask */\r
2991 \r
2992   if (bExpandColor) samples = 3;\r
2993   else if (bExpandGray) samples = 1;\r
2994 /*  else samples = SamplesPerPixel; */      /* 96/July/7 */\r
2995   else samples = SamplesPerPixelX;\r
2996 \r
2997 //  fprintf(output, "\nsave\n");\r
2998 //  putc('\n', output);\r
2999   PSputc('\n', output);\r
3000 //  fputs("save ", output);\r
3001   PSputs("save ", output);\r
3002   if (stripcomment == 0) {\r
3003     sprintf(logline, "%% %s\n", infilename);  /* 98/Jul/12 */\r
3004     PSputs(logline, output);\r
3005   }\r
3006   else {\r
3007 //    putc('\n', output);\r
3008     PSputc('\n', output);\r
3009   }\r
3010   if (! bColorImage) {    /* only use screen for B/W */\r
3011 /*    if (bInvertImage) fputs("invert\n", output); */\r
3012     if (bInvertImage && !bMonoChrome) {\r
3013 //      fputs("invert\n", output);\r
3014       PSputs("invert\n", output);\r
3015     }\r
3016 /*    if (wantmagic)  fputs(eps_magic, output); */\r
3017 /*    fprintf(output, "currentscreen pop dviscreen\n"); */\r
3018     if (wantmagictiff) {\r
3019       if (frequency > 0) {  /* did user specified frequency & angle ? */\r
3020         sprintf(logline, "%d %d dviscreen\n", frequency, angle);\r
3021         PSputs(logline, output);\r
3022       }\r
3023       else {\r
3024 //        fputs("currentscreen pop dviscreen\n", output);\r
3025         PSputs("currentscreen pop dviscreen\n", output);\r
3026       }\r
3027     }\r
3028   }\r
3029 /*  for monochrome, paint background first, then use imagemask */\r
3030 /*  if (BitsPerSample == 1) {\r
3031     if (bFigureColor) \r
3032       fprintf(output, "%lg %lg %lg rgb\n",\r
3033         figurered, figuregreen, figureblue); \r
3034     else if (bTextColor) fputs("black\n", output);\r
3035     paintback = 1;\r
3036   } */\r
3037 /*  create the string before or after the `save' ? */\r
3038 /*  fprintf(output, "/picstr %d string def\n", bytes);  */\r
3039 /*  string not needed if using ASCII85Decode filter 96/Dec/20 */\r
3040   if (! bLevel2) {\r
3041     sprintf(logline, "/picstr %d string def\n", bytes);\r
3042     PSputs(logline, output);\r
3043   }\r
3044 //  fprintf(output, "%d %d translate ", xll, yll);\r
3045 //  fputs("currentpoint translate ", output);\r
3046   PSputs("currentpoint translate ", output);\r
3047   if (dwidth == 0 || dheight == 0) {\r
3048     showline(" Zero width or height ", 1);\r
3049   }\r
3050 #ifdef ALLOWSCALE\r
3051   if (outscaleflag) {\r
3052     sprintf(logline, "%.9lg %.9lg scale\n",\r
3053       (double) dwidth / outscale, (double)  dheight / outscale);\r
3054   }\r
3055   else {\r
3056     sprintf(logline, "%ld %ld scale\n", dwidth, dheight);\r
3057   }\r
3058 #else\r
3059   sprintf(logline, "%ld %ld scale\n", dwidth, dheight);\r
3060 #endif\r
3061   PSputs(logline, output);\r
3062 \r
3063 /*  if (bFigureColor && paintback) { */   /* need to paint background */\r
3064 /*  proper support for \special{figurecolor: . . . . . .} 94/Mar/14 */\r
3065   if (BitsPerSample == 1) {       /* need to paint background ? */\r
3066 /*    fputs("gsave\n", output); */    /* not needed */\r
3067 /*    paint background here in background color */\r
3068 /*    if (backred != 1.0 || backgreen != 1.0 || backblue != 1.0)  */\r
3069     if (bFigureColor) {\r
3070       sprintf(logline, "%lg %lg %lg rgb\n",\r
3071         backred, backgreen, backblue);    /* color for background */\r
3072       PSputs(logline, output);\r
3073     }\r
3074     else {\r
3075 //      fputs("white\n", output);\r
3076       PSputs("white\n", output);\r
3077     }\r
3078 /*  now paint background in this color *//* use `box' in preamble ? */\r
3079     if (bSuppressBack == 0) {\r
3080 //      fputs("0 0 moveto 1 0 lineto ", output);\r
3081       PSputs("0 0 moveto 1 0 lineto ", output);\r
3082 /*      fputs("0 0 moveto 1 0 lineto 1 -1 lineto 0 -1 lineto closepath fill\n", output); */\r
3083 /*      background seems to be painted above not on image 95/Dec/31 */\r
3084 /*      fputs("0 0 moveto 1 0 lineto 1 1 lineto 0 1 lineto closepath fill\n", output); */\r
3085       if (hptagflag != 0) {\r
3086 //        fputs("1 1 lineto 0 1 lineto ", output);\r
3087         PSputs("1 1 lineto 0 1 lineto ", output);\r
3088       }\r
3089 /*      background seems to be painted below not on image 96/May/6 */\r
3090       else {\r
3091 //        fputs("1 -1 lineto 0 -1 lineto ", output);\r
3092         PSputs("1 -1 lineto 0 -1 lineto ", output);\r
3093       }\r
3094 //      fputs("closepath fill\n", output);\r
3095       PSputs("closepath fill\n", output);\r
3096     }\r
3097     if (bFigureColor) {\r
3098       sprintf(logline, "%lg %lg %lg rgb\n",\r
3099         figurered, figuregreen, figureblue); /* color for foreground */\r
3100       PSputs(logline, output);\r
3101     }\r
3102     else {\r
3103 //      fputs("black\n", output);\r
3104       PSputs("black\n", output);\r
3105     }\r
3106 /*    fputs("grestore\n", output); */   /* not needed */\r
3107   }\r
3108 //  fprintf(output, "%ld %ld %d\n", ImageWidth, ImageLength, bits);\r
3109   sprintf(logline, "%ld %ld ", ImageWidth, ImageLength);\r
3110   PSputs(logline, output);\r
3111   if (bMonoChrome) {\r
3112     if (bInvertImage) {\r
3113 //      fputs("true\n", output);\r
3114       PSputs("true\n", output);\r
3115     }\r
3116     else {\r
3117 //      fputs("false\n", output);\r
3118       PSputs("false\n", output);\r
3119     }\r
3120   }\r
3121   else {\r
3122     sprintf(logline, "%d\n", bits);       /* not monochrome */\r
3123     PSputs(logline, output);\r
3124   }\r
3125   if (BMPflag) {              /* new mode 98/Jul/9 */\r
3126     sprintf(logline, "[%ld 0 0 %ld 0 %ld]\n",\r
3127                 ImageWidth, -ImageLength, 0);\r
3128     PSputs(logline, output);\r
3129   }\r
3130   else {\r
3131     if (hptagflag != 0) YOffset = 0;\r
3132     else YOffset = ImageLength;\r
3133     sprintf(logline, "[%ld 0 0 %ld 0 %ld]\n",\r
3134         ImageWidth, ImageLength, YOffset);\r
3135     PSputs(logline, output);\r
3136   }\r
3137 /*  fputs("{currentfile picstr readhexstring pop} bind\n", output); */\r
3138   if (bLevel2) {\r
3139 //    fputs("currentfile", output);\r
3140     PSputs("currentfile", output);\r
3141 //    fputs(" /ASCII85Decode filter", output);\r
3142     PSputs(" /ASCII85Decode filter", output);\r
3143     if (bRunLengthFlag) {\r
3144 //      fputs(" /RunLengthDecode filter", output);\r
3145       PSputs(" /RunLengthDecode filter", output);\r
3146     }\r
3147 #ifdef LZWCOMPRESSION\r
3148     else if (bLZWFlag) {\r
3149 //      fputs(" /LZWDecode filter", output);\r
3150       PSputs(" /LZWDecode filter", output);\r
3151     }\r
3152 #endif\r
3153 //    putc('\n', output);\r
3154     PSputc('\n', output);\r
3155   }\r
3156   else {\r
3157 //    fputs("{currentfile picstr readhexstring pop} bind\n", output);\r
3158     PSputs("{currentfile picstr readhexstring pop} bind\n", output);\r
3159   }\r
3160 /*  samples per pixel better be 1 (grey), 3 (RGB) or 4 (CMYK) */\r
3161   if (bColorImage && bAllowColor) {\r
3162 //    fprintf(output, "false %d colorimage\n", SamplesPerPixel); \r
3163     sprintf(logline, "false %d colorimage", samples); /* 96/July/7 */\r
3164     PSputs(logline, output);\r
3165   }\r
3166 /*  else if (bCompressColor) fputs("image\n", output); */\r
3167   else if (bMonoChrome) {\r
3168 //    fputs("imagemask", output); /* monochrome */\r
3169     PSputs("imagemask", output);  /* monochrome */\r
3170   }\r
3171   else {\r
3172 //    fputs("image", output); /* either not color, or color compressed */\r
3173     PSputs("image", output);  /* either not color, or color compressed */\r
3174   }\r
3175 //  putc('\n', output);\r
3176   PSputc('\n', output);\r
3177 /*  image data must follow right away */\r
3178 }\r
3179 \r
3180 void writepstrailer (FILE *output)\r
3181 {\r
3182 #ifdef DEBUGTIFF\r
3183   if (traceflag) showline("Now writing trailer\n", 0);\r
3184 #endif\r
3185 /*  if (BitsPerSample == 1) {\r
3186     if (bTextColor) fprintf(output, "%lg %lg %lg rgb\n",\r
3187           Textred, Textgreen, Textblue);\r
3188     else if(bFigureColor) fputs("black\n");\r
3189   } */              /* monochrome - not needed */\r
3190 //  fputs("restore\n", output);\r
3191   PSputs("restore\n", output);\r
3192 }\r
3193 \r
3194 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
3195 \r
3196 /* Read a row using PACK_BITS compression scheme */\r
3197 /* returns non-zero if problems encountered */\r
3198 \r
3199 int readpackbits (unsigned char *lpBuffer, FILE *input, int RowLength)\r
3200 {\r
3201   unsigned char *u=lpBuffer;\r
3202   int c, k, n, total=0, flag=0;\r
3203   \r
3204   for(;;) {\r
3205     if ((n = getc(input)) < 0) {  /* premature EOF */\r
3206       showline(" Premature EOF", 1);\r
3207       flag = -1;\r
3208       break;  \r
3209     }\r
3210     else if (n < 128) {     /* use next (n+1) bytes as is */\r
3211       for (k=0; k < n+1; k++) *u++ = (char) getc(input);  \r
3212       total += n+1;\r
3213     }\r
3214     else if (n > 128) {     /* repeat next byte (257 - n) times */\r
3215       c = getc(input);\r
3216       for (k=0; k < (257 - n); k++) *u++ = (char) c;   \r
3217       total += (257 - n);\r
3218     }\r
3219 /*    and n == 128 is a NOP */\r
3220     if (total == RowLength) break;  /* enough bytes yet ? */\r
3221     if (total > RowLength) {    /* too many bytes ? */\r
3222       showline(" Too many bytes in compressed row\n", 1);\r
3223       flag = -1;\r
3224       break;\r
3225     }\r
3226   }\r
3227   return flag;\r
3228 }\r
3229 \r
3230 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
3231 \r
3232 /* Implement 1d CCITT Huffman code decompression (minus EOL) */\r
3233 /* ==> implies BitsPerSample == 1 */\r
3234 /* white runs = 0, black runs = 1 */\r
3235 /* normal PhotometricInterpretation == 0 */\r
3236 /* invert black/white if PhotometricInterpretation == 1 */\r
3237 \r
3238 int bytex, bitsleft;        /* input buffering in splitting bits */\r
3239 \r
3240 int getbit (FILE *input)\r
3241 {\r
3242   if (bitsleft-- <= 0) {\r
3243     if ((bytex = getc(input)) == EOF) {\r
3244       sprintf(logline, " Unexpected EOF (%s)\n", "getbit TIFF");\r
3245       showline(logline, 0);\r
3246 /*      checkexit(1); */      /* Wait for it to create bad code */\r
3247     }\r
3248     bitsleft = 7;\r
3249   }\r
3250   bytex = bytex << 1;\r
3251 #ifdef DEBUGTIFF\r
3252   if (traceflag) {\r
3253     sprintf(logline, "%d", (bytex & 256) ? 1 : 0);\r
3254     showline(logline, 0);\r
3255   }\r
3256 #endif\r
3257   if (bytex & 256) return 1;\r
3258   else return 0;\r
3259 }\r
3260 \r
3261 //#pragma optimize ("lge", on)\r
3262 \r
3263 /* It's the Huffman code stuff that wants to be not optimized */\r
3264 \r
3265 //#pragma optimize ("lge", off)\r
3266 \r
3267 /* Actually commonmake may be OK with compiler optimizations ON */\r
3268 \r
3269 int commonmake (FILE *input) /* common black/white make up codes (7 zeros) */\r
3270 {\r
3271 #ifdef DEBUGTIFF\r
3272   if (traceflag) {\r
3273     showline("commonmake entry ", 0);\r
3274   }\r
3275 #endif\r
3276   if (getbit(input)) {  /* 00000001 */\r
3277     if (getbit(input)) {  /* 000000011 */\r
3278       if (getbit(input)) {  /* 0000000111 */\r
3279         if (getbit(input)) {  /* 00000001111 */\r
3280           if (getbit(input)) {  /* 000000011111 */\r
3281             return 2560;\r
3282           }\r
3283           else { /* 000000011110 */\r
3284             return 2496;\r
3285           }\r
3286         }\r
3287         else { /* 00000001110 */\r
3288           if (getbit(input)) {  /* 000000011101 */\r
3289             return 2432;\r
3290           }\r
3291           else { /* 000000011100 */\r
3292             return 2368;\r
3293           }\r
3294         }\r
3295       }\r
3296       else { /* 0000000110 */\r
3297         if (getbit(input)) {  /* 00000001101 */\r
3298           return 1920;\r
3299         }\r
3300         else { /* 00000001100 */\r
3301           return 1856;\r
3302         }\r
3303       }\r
3304     }\r
3305     else { /* 000000010 */\r
3306       if (getbit(input)) {  /* 0000000101 */\r
3307         if (getbit(input)) {  /* 00000001011 */\r
3308           if (getbit(input)) {  /* 000000010111 */\r
3309             return 2304;\r
3310           }\r
3311           else { /* 000000010110 */\r
3312             return 2240;\r
3313           }\r
3314         }\r
3315         else { /* 00000001010 */\r
3316           if (getbit(input)) {  /* 000000010101 */\r
3317             return 2176;\r
3318           }\r
3319           else { /* 000000010100 */\r
3320             return 2112;\r
3321           }\r
3322         }\r
3323       }\r
3324       else { /* 0000000100 */\r
3325         if (getbit(input)) {  /* 00000001001 */\r
3326           if (getbit(input)) {  /* 000000010011 */\r
3327             return 2048;\r
3328           }\r
3329           else { /* 000000010010 */\r
3330             return 1984;\r
3331           }\r
3332         }\r
3333         else { /* 00000001000 */\r
3334           return 1792;\r
3335         }\r
3336       }\r
3337     }\r
3338   }\r
3339   else { /* 00000000 */\r
3340 /*  Actually, EOL code is not supposed to be used in TIFF compression 2 */\r
3341     if (!getbit(input)) { /* 000000000 */\r
3342       if (!getbit(input)) { /* 0000000000 */\r
3343         if (!getbit(input)) { /* 00000000000 */\r
3344           if (getbit(input)) { /* 000000000001 */\r
3345             showline("EOL ", 1);\r
3346             return 0;       /* ??? */\r
3347           }\r
3348         }\r
3349       }\r
3350     }\r
3351   }\r
3352   showline(" Impossible make-up run\n", 1);\r
3353   return -1;  /* error */\r
3354 }\r
3355 \r
3356 /* Compiler screws up the following code if optimizations turned on */\r
3357 \r
3358 int whiterun (FILE *input)\r
3359 {\r
3360 #ifdef DEBUGTIFF\r
3361   if (traceflag)\r
3362   {\r
3363     showline("whiterun entry ", 0);\r
3364   }\r
3365 #endif\r
3366   if (getbit(input)) {  /* 1 */\r
3367     if (getbit(input)) {  /* 11 */\r
3368       if (getbit(input)) {  /* 111 */\r
3369         if (getbit(input)) {  /* 1111 */\r
3370           return 7;\r
3371         }\r
3372         else {      /* 1110 */\r
3373           return 6;\r
3374         }\r
3375       }\r
3376       else {      /* 110 */\r
3377         if (getbit(input)) {  /* 1101 */\r
3378           if (getbit(input)) { /* 11011 */\r
3379             return 64;    /* make up */\r
3380           }\r
3381           else {      /* 11010 */\r
3382             if (getbit(input)) { /* 110101 */\r
3383               return 15;\r
3384             }\r
3385             else {      /* 110100 */\r
3386               return 14;\r
3387             }\r
3388           }\r
3389         }\r
3390         else {      /* 1100 */\r
3391           return 5;\r
3392         }\r
3393       }\r
3394     }\r
3395     else {      /* 10 */\r
3396       if (getbit(input)) {  /* 101 */\r
3397         if (getbit(input)) {  /* 1011 */\r
3398           return 4;\r
3399         }\r
3400         else {      /* 1010 */\r
3401           if (getbit(input)) { /* 10101 */\r
3402             if (getbit(input)) { /* 101011 */\r
3403               return 17;\r
3404             }\r
3405             else {      /* 101010 */\r
3406               return 16;\r
3407             }\r
3408           }\r
3409           else {      /* 10100 */\r
3410             return 9;\r
3411           }\r
3412         }\r
3413       }\r
3414       else {      /* 100 */\r
3415         if (getbit(input)) {  /* 1001 */\r
3416           if (getbit(input)) { /* 10011 */\r
3417             return 8;\r
3418           }\r
3419           else {      /* 10010 */\r
3420             return 128; /* make up */\r
3421           }\r
3422         }\r
3423         else {      /* 1000 */\r
3424           return 3;\r
3425         }\r
3426       }\r
3427     }\r
3428   }\r
3429   else {      /* 0 */\r
3430     if (getbit(input)) {  /* 01 */\r
3431       if (getbit(input)) {  /* 011 */\r
3432         if (getbit(input)) {  /* 0111 */\r
3433           return 2;\r
3434         }\r
3435         else {      /* 0110 */\r
3436           if (getbit(input)) { /* 01101 */\r
3437             if (getbit(input)) { /* 011011 */\r
3438               if (getbit(input)) { /* 0110111 */\r
3439                 return 256; /* make up */\r
3440               }\r
3441               else {      /* 0110110 */\r
3442                 if (getbit(input)) {  /* 01101101 */\r
3443                   if (getbit(input)) {  /* 011011011 */\r
3444                     return 1408;  /* make up */\r
3445                   }\r
3446                   else { /*  011011010 */\r
3447                     return 1344;  /* make up */\r
3448                   }\r
3449                 }\r
3450                 else {      /* 01101100 */\r
3451                   if (getbit(input)) {  /* 011011001 */\r
3452                     return 1280;  /* make up */\r
3453                   }\r
3454                   else { /* 011011000 */\r
3455                     return 1216;  /* make up */\r
3456                   }\r
3457                 }\r
3458               }\r
3459             }\r
3460             else { /* 011010 */\r
3461               if (getbit(input)) { /* 0110101 */\r
3462                 if (getbit(input)) { /* 01101011 */\r
3463                   if (getbit(input)) { /* 011010111 */\r
3464                     return 1152;  /* make up */\r
3465                   }\r
3466                   else {      /* 011010110 */\r
3467                     return 1088;  /* make up */\r
3468                   }\r
3469                 }\r
3470                 else { /* 01101010 */\r
3471                   if (getbit(input)) { /* 011010101 */\r
3472                     return 1024;  /* make up */\r
3473                   }\r
3474                   else { /* 011010100 */\r
3475                     return 960; /* make up */\r
3476                   }\r
3477                 }\r
3478               }\r
3479               else { /* 0110100 */\r
3480                 if (getbit(input)) { /* 01101001 */\r
3481                   if (getbit(input)) { /* 011010011 */\r
3482                     return 896; /* make up */\r
3483                   }\r
3484                   else { /* 011010010 */\r
3485                     return 832; /* make up */\r
3486                   }\r
3487                 }\r
3488                 else { /* 01101000 */\r
3489                   return 576; /* make up */\r
3490                 }\r
3491               }\r
3492             }\r
3493           }\r
3494           else { /* 01100 */\r
3495             if (getbit(input)) { /* 011001 */\r
3496               if (getbit(input)) { /* 0110011 */\r
3497                 if (getbit(input)) { /* 01100111 */\r
3498                   return 640; /* make up */\r
3499                 }\r
3500                 else { /* 01100110 */\r
3501                   if (getbit(input)) { /* 011001101 */\r
3502                     return 768; /* make up */\r
3503                   }\r
3504                   else { /* 011001100 */\r
3505                     return 704; /* make up */\r
3506                   }\r
3507                 }\r
3508               }\r
3509               else { /* 0110010 */\r
3510                 if (getbit(input)) { /* 01100101 */\r
3511                   return 512; /* make up */\r
3512                 }\r
3513                 else { /* 01100100 */\r
3514                   return 448; /* make up */\r
3515                 }\r
3516               }\r
3517             }\r
3518             else { /* 011000 */\r
3519               return 1664;  /* make up */\r
3520             }\r
3521           }\r
3522         }\r
3523       }\r
3524       else {      /* 010 */\r
3525         if (getbit(input)) {  /* 0101 */\r
3526           if (getbit(input)) { /* 01011 */\r
3527             if (getbit(input)) { /* 010111 */\r
3528               return 192;   /* make up */\r
3529             }\r
3530             else { /* 010110 */\r
3531               if (getbit(input)) { /* 0101101 */\r
3532                 if (getbit(input)) { /* 01011011 */\r
3533                   return 58;\r
3534                 }\r
3535                 else { /* 01011010 */\r
3536                   return 57;\r
3537                 }\r
3538               }\r
3539               else { /* 0101100 */\r
3540                 if (getbit(input)) { /* 01011001 */\r
3541                   return 56;\r
3542                 }\r
3543                 else { /* 01011000 */\r
3544                   return 55;\r
3545                 }\r
3546               }\r
3547             }\r
3548           }\r
3549           else {      /* 01010 */\r
3550             if (getbit(input)) { /* 010101 */\r
3551               if (getbit(input)) { /* 0101011 */\r
3552                 return 25;\r
3553               }\r
3554               else {      /* 0101010 */\r
3555                 if (getbit(input)) { /* 01010101 */\r
3556                   return 52;\r
3557                 }\r
3558                 else { /* 01010100 */\r
3559                   return 51;\r
3560                 }\r
3561               }\r
3562             }\r
3563             else {      /* 010100 */\r
3564               if (getbit(input)) { /* 0101001 */\r
3565                 if (getbit(input)) { /* 01010011 */\r
3566                   return 50;\r
3567                 }\r
3568                 else { /* 01010010 */\r
3569                   return 49;\r
3570                 }\r
3571               }\r
3572               else {      /* 0101000 */\r
3573                 return 24;\r
3574               }\r
3575             }\r
3576           }\r
3577         }\r
3578         else {      /* 0100 */\r
3579           if (getbit(input)) {  /* 01001 */\r
3580             if (getbit(input)) { /* 010011 */\r
3581               if (getbit(input)) { /* 0100111 */\r
3582                 return 18;\r
3583               }\r
3584               else {      /* 0100110 */\r
3585                 if (getbit(input)) {  /* 01001101 */\r
3586                   if (getbit(input)) {  /* 010011011 */\r
3587                     return 1728;  /* make up */\r
3588                   }\r
3589                   else { /* 010011010 */\r
3590                     return 1600;  /* make up */\r
3591                   }\r
3592                 }\r
3593                 else { /* 01001100 */\r
3594                   if (getbit(input)) {  /* 010011001 */\r
3595                     return 1536;  /* make up */\r
3596                   }\r
3597                   else { /* 010011000 */\r
3598                     return 1472;  /* make up */\r
3599                   }\r
3600                 }\r
3601               }\r
3602             }\r
3603             else {      /* 010010 */\r
3604               if (getbit(input)) { /* 0100101 */\r
3605                 if (getbit(input)) { /* 01001011 */\r
3606                   return 60;\r
3607                 }\r
3608                 else { /* 01001010 */\r
3609                   return 59;\r
3610                 }\r
3611               }\r
3612               else {      /* 0100100 */\r
3613                 return 27;\r
3614               }\r
3615             }\r
3616           }\r
3617           else {      /* 01000 */\r
3618             return 11;\r
3619           }\r
3620         }\r
3621       }\r
3622     }\r
3623     else {      /* 00 */\r
3624       if (getbit(input)) {  /* 001 */\r
3625         if (getbit(input)) {  /* 0011 */\r
3626           if (getbit(input)) {  /* 00111 */\r
3627             return 10;\r
3628           }\r
3629           else {      /* 00110 */\r
3630             if (getbit(input)) { /* 001101 */\r
3631               if (getbit(input)) { /* 0011011 */\r
3632                 if (getbit(input)) {  /* 0110111 */\r
3633                   return 384; /* make up */\r
3634                 }\r
3635                 else { /* 0110110 */\r
3636                   return 320; /* make up */\r
3637                 }\r
3638               }\r
3639               else { /* 0011010 */\r
3640                 if (getbit(input)) { /* 00110101 */\r
3641                   return 0;\r
3642                 }\r
3643                 else { /* 00110100 */\r
3644                   return 63;\r
3645                 }\r
3646               }\r
3647             }\r
3648             else {      /* 001100 */\r
3649               if (getbit(input)) { /* 0011001 */\r
3650                 if (getbit(input)) { /* 00110011 */\r
3651                   return 62;\r
3652                 }\r
3653                 else { /* 00110010 */\r
3654                   return 61;\r
3655                 }\r
3656               }\r
3657               else {      /* 0011000 */\r
3658                 return 28;\r
3659               }\r
3660             }\r
3661           }\r
3662         }\r
3663         else {      /* 0010 */\r
3664           if (getbit(input)) { /* 00101 */\r
3665             if (getbit(input)) { /* 001011 */\r
3666               if (getbit(input)) { /* 0010111 */\r
3667                 return 21;\r
3668               }\r
3669               else {      /* 0010110 */\r
3670                 if (getbit(input)) { /* 00101101 */\r
3671                   return 44;\r
3672                 }\r
3673                 else { /* 00101100 */\r
3674                   return 43;\r
3675                 }\r
3676               }\r
3677             }\r
3678             else {      /* 001010 */\r
3679               if (getbit(input)) { /* 0010101 */\r
3680                 if (getbit(input)) { /* 00101011 */\r
3681                   return 42;\r
3682                 }\r
3683                 else { /* 00101010 */\r
3684                   return 41;\r
3685                 }\r
3686               }\r
3687               else { /* 0010100 */\r
3688                 if (getbit(input)) { /* 00101001 */\r
3689                   return 40;\r
3690                 }\r
3691                 else { /* 00101000 */\r
3692                   return 39;\r
3693                 }\r
3694               }\r
3695             }\r
3696           }\r
3697           else {      /* 00100 */\r
3698             if (getbit(input)) { /* 001001 */\r
3699               if (getbit(input)) { /* 0010011 */\r
3700                 return 26;\r
3701               }\r
3702               else {      /* 0010010 */\r
3703                 if (getbit(input)) { /* 00100101 */\r
3704                   return 54;\r
3705                 }\r
3706                 else { /* 00100100 */\r
3707                   return 53;\r
3708                 }\r
3709               }\r
3710             }\r
3711             else {      /* 001000 */\r
3712               return 12;\r
3713             }\r
3714           }\r
3715         }\r
3716       }\r
3717       else {    /* 000 */\r
3718         if (getbit(input)) {  /* 0001 */\r
3719           if (getbit(input)) {  /* 00011 */\r
3720             if (getbit(input)) { /* 000111 */\r
3721               return 1;\r
3722             }\r
3723             else {      /* 000110 */\r
3724               if (getbit(input)) { /* 0001101 */\r
3725                 if (getbit(input)) { /* 00011011 */\r
3726                   return 32;\r
3727                 }\r
3728                 else { /* 00011010 */\r
3729                   return 31;\r
3730                 }\r
3731               }\r
3732               else {    /* 0001100 */\r
3733                 return 19;\r
3734               }\r
3735             }\r
3736           }\r
3737           else {    /* 00010 */\r
3738             if (getbit(input)) { /* 000101 */\r
3739               if (getbit(input)) { /* 0001011 */\r
3740                 if (getbit(input)) { /* 00010111 */\r
3741                   return 38;\r
3742                 }\r
3743                 else { /* 00010110 */\r
3744                   return 37;\r
3745                 }\r
3746               }\r
3747               else { /* 0001010 */\r
3748                 if (getbit(input)) { /* 00010101 */\r
3749                   return 36;\r
3750                 }\r
3751                 else { /* 00010100 */\r
3752                   return 35;\r
3753                 }\r
3754               }\r
3755             }\r
3756             else {      /* 000100 */\r
3757               if (getbit(input)) { /* 0001001 */\r
3758                 if (getbit(input)) { /* 00010011 */\r
3759                   return 34;\r
3760                 }\r
3761                 else { /* 00010010 */\r
3762                   return 33;\r
3763                 }\r
3764               }\r
3765               else {      /* 0001000 */\r
3766                 return 20;\r
3767               }\r
3768             }\r
3769           }\r
3770         }\r
3771         else {    /* 0000 */\r
3772           if (getbit(input)) { /* 00001 */\r
3773             if (getbit(input)) { /* 000011 */\r
3774               return 13;\r
3775             }\r
3776             else {      /* 000010 */\r
3777               if (getbit(input)) { /* 0000101 */\r
3778                 if (getbit(input)) { /* 00001011 */\r
3779                   return 48;\r
3780                 }\r
3781                 else { /* 00001010 */\r
3782                   return 47;\r
3783                 }\r
3784               }\r
3785               else {      /* 0000100 */\r
3786                 return 23;\r
3787               }\r
3788             }\r
3789           }\r
3790           else {    /* 00000 */\r
3791             if (getbit(input)) { /* 000001 */\r
3792               if (getbit(input)) { /* 0000011 */\r
3793                 return 22;\r
3794               }\r
3795               else {      /* 0000010 */\r
3796                 if (getbit(input)) { /* 00000101 */\r
3797                   return 46;\r
3798                 }\r
3799                 else { /* 00000100 */\r
3800                   return 45;\r
3801                 }\r
3802               }\r
3803             }\r
3804             else {      /* 000000 */\r
3805               if (getbit(input)) { /* 0000001 */\r
3806                 if (getbit(input)) { /* 00000011 */\r
3807                   return 30;\r
3808                 }\r
3809                 else { /* 00000010 */\r
3810                   return 29;\r
3811                 }\r
3812               }\r
3813               else { /* 0000000 */\r
3814                 return commonmake(input); /* seven zeros */\r
3815               }\r
3816             }\r
3817           }\r
3818         }\r
3819       }\r
3820     }\r
3821   }\r
3822   showline(" Impossible white run\n", 1);\r
3823   return -1;  /* error */\r
3824 }\r
3825 \r
3826 /* Compiler screws up the following code if optimizations turned on */\r
3827 \r
3828 int blackzero (FILE *input)   /* black run code starts with four zeros */\r
3829 {\r
3830 #ifdef DEBUGTIFF\r
3831   if (traceflag) showline (" blackzero entry ", 0);\r
3832 #endif\r
3833   if (getbit(input)) { /* 00001 */\r
3834     if (getbit(input)) { /* 000011 */\r
3835       if (getbit(input)) { /* 0000111 */\r
3836         return 12;\r
3837       }\r
3838       else {      /* 0000110 */\r
3839         if (getbit(input)) {  /* 00001101 */\r
3840           if (getbit(input)) { /* 000011011 */\r
3841             if (getbit(input)) { /* 0000110111 */\r
3842               return 0;\r
3843             }\r
3844             else {      /* 0000110110 */\r
3845               if (getbit(input)) { /* 00001101101 */\r
3846                 if (getbit(input)) { /* 000011011011 */\r
3847                   return 43;\r
3848                 }\r
3849                 else {      /* 000011011010 */\r
3850                   return 42;\r
3851                 }\r
3852               }\r
3853               else {      /* 00001101100 */\r
3854                 return 21;\r
3855               }\r
3856             }\r
3857           }\r
3858           else {      /* 000011010 */\r
3859             if (getbit(input)) { /* 0000110101 */\r
3860               if (getbit(input)) { /* 00001101011 */\r
3861                 if (getbit(input)) { /* 000011010111 */\r
3862                   return 39;\r
3863                 }\r
3864                 else {      /* 000011010110 */\r
3865                   return 38;\r
3866                 }\r
3867               }\r
3868               else {      /* 00001101010 */\r
3869                 if (getbit(input)) { /* 000011010101 */\r
3870                   return 37;\r
3871                 }\r
3872                 else {      /* 000011010100 */\r
3873                   return 36;\r
3874                 }\r
3875               }\r
3876             }\r
3877             else {      /* 0000110100 */\r
3878               if (getbit(input)) { /* 00001101001 */\r
3879                 if (getbit(input)) { /* 000011010011 */\r
3880                   return 35;\r
3881                 }\r
3882                 else { /* 000011010010 */\r
3883                   return 34;\r
3884                 }\r
3885               }\r
3886               else {      /* 00001101000 */\r
3887                 return 20;\r
3888               }\r
3889             }\r
3890           }\r
3891         }\r
3892         else {      /* 00001100 */\r
3893           if (getbit(input)) {  /* 000011001 */\r
3894             if (getbit(input)) { /* 0000110011 */\r
3895               if (getbit(input)) { /* 00001100111 */\r
3896                 return 19;\r
3897               }\r
3898               else {      /* 00001100110 */\r
3899                 if (getbit(input)) { /* 000011001101 */\r
3900                   return 29;\r
3901                 }\r
3902                 else {      /* 000011001100 */\r
3903                   return 28;\r
3904                 }\r
3905               }\r
3906             }\r
3907             else {      /* 0000110010 */\r
3908               if (getbit(input)) { /* 00001100101 */\r
3909                 if (getbit(input)) { /* 000011001011 */\r
3910                   return 27;\r
3911                 }\r
3912                 else {      /* 000011001010 */\r
3913                   return 26;\r
3914                 }\r
3915               }\r
3916               else {      /* 00001100100 */\r
3917                 if (getbit(input)) { /* 000011001001 */\r
3918                   return 192; /* make up */\r
3919                 }\r
3920                 else {      /* 000011001000 */\r
3921                   return 128; /* make up */\r
3922                 }\r
3923               }\r
3924             }\r
3925           }\r
3926           else {      /* 000011000 */\r
3927             return 15;\r
3928           }\r
3929         }\r
3930       }\r
3931     }\r
3932     else {      /* 000010 */\r
3933       if (getbit(input)) { /* 0000101 */\r
3934         return 11;\r
3935       }\r
3936       else {      /* 0000100 */\r
3937         return 10;\r
3938       }\r
3939     }\r
3940   }\r
3941   else {    /* 00000 */\r
3942     if (getbit(input)) { /* 000001 */\r
3943       if (getbit(input)) { /* 0000011 */\r
3944         if (getbit(input)) {  /* 00000111 */\r
3945           return 14;\r
3946         }\r
3947         else {      /* 00000110 */\r
3948           if (getbit(input)) { /* 000001101 */\r
3949             if (getbit(input)) { /* 0000011011 */\r
3950               if (getbit(input)) { /* 00000110111 */\r
3951                 return 22;\r
3952               }\r
3953               else {      /* 00000110110 */\r
3954                 if (getbit(input)) { /* 000001101101 */\r
3955                   return 41;\r
3956                 }\r
3957                 else {      /* 000001101100 */\r
3958                   return 40;\r
3959                 }\r
3960               }\r
3961             }\r
3962             else {      /* 0000011010 */\r
3963               if (getbit(input)) {  /* 00000110101 */\r
3964                 if (getbit(input)) { /* 000001101011 */\r
3965                   return 33;\r
3966                 }\r
3967                 else {      /* 000001101010 */\r
3968                   return 32;\r
3969                 }\r
3970               }\r
3971               else {      /* 00000110100 */\r
3972                 if (getbit(input)) { /* 000001101001 */\r
3973                   return 31;\r
3974                 }\r
3975                 else {      /* 000001101000 */\r
3976                   return 30;\r
3977                 }\r
3978               }\r
3979             }\r
3980           }\r
3981           else {      /* 000001100 */\r
3982             if (getbit(input)) { /* 0000011001 */\r
3983               if (getbit(input)) { /* 00000110011 */\r
3984                 if (getbit(input)) { /* 000001100111 */\r
3985                   return 63;\r
3986                 }\r
3987                 else {      /* 000001100110 */\r
3988                   return 62;\r
3989                 }\r
3990               }\r
3991               else {      /* 00000110010 */\r
3992                 if (getbit(input)) { /* 000001100101 */\r
3993                   return 49;\r
3994                 }\r
3995                 else {      /* 000001100100 */\r
3996                   return 48;\r
3997                 }\r
3998               }\r
3999             }\r
4000             else {      /* 0000011000 */\r
4001               return 17;\r
4002             }\r
4003           }\r
4004         }\r
4005       }\r
4006       else {      /* 0000010 */\r
4007         if (getbit(input)) {  /* 00000101 */\r
4008           if (getbit(input)) { /* 000001011 */\r
4009             if (getbit(input)) { /* 0000010111 */\r
4010               return 16;\r
4011             }\r
4012             else {      /* 0000010110 */\r
4013               if (getbit(input)) { /* 00000101101 */\r
4014                 if (getbit(input)) { /* 000001011011 */\r
4015                   return 256;   /* make up */\r
4016                 }\r
4017                 else {      /* 000001011010 */\r
4018                   return 61;\r
4019                 }\r
4020               }\r
4021               else {      /* 00000101100 */\r
4022                 if (getbit(input)) { /* 000001011001 */\r
4023                   return 58;\r
4024                 }\r
4025                 else {      /* 000001011000 */\r
4026                   return 57;\r
4027                 }\r
4028               }\r
4029             }\r
4030           }\r
4031           else {      /* 000001010 */\r
4032             if (getbit(input)) { /* 0000010101 */\r
4033               if (getbit(input)) { /* 00000101011 */\r
4034                 if (getbit(input)) { /* 000001010111 */\r
4035                   return 47;\r
4036                 }\r
4037                 else {      /* 000001010110 */\r
4038                   return 46;\r
4039                 }\r
4040               }\r
4041               else {      /* 00000101010 */\r
4042                 if (getbit(input)) { /* 000001010101 */\r
4043                   return 45;\r
4044                 }\r
4045                 else {      /* 000001010100 */\r
4046                   return 44;\r
4047                 }\r
4048               }\r
4049             }\r
4050             else {      /* 0000010100 */\r
4051               if (getbit(input)) { /* 00000101001 */\r
4052                 if (getbit(input)) { /* 000001010011 */\r
4053                   return 51;\r
4054                 }\r
4055                 else {      /* 000001010010 */\r
4056                   return 50;\r
4057                 }\r
4058               }\r
4059               else {      /* 00000101000 */\r
4060                 return 23;\r
4061               }\r
4062             }\r
4063           }\r
4064         }\r
4065         else {      /* 00000100 */\r
4066           return 13;\r
4067         }\r
4068       }\r
4069     }\r
4070     else {      /* 000000 */\r
4071       if (getbit(input)) { /* 0000001 */\r
4072         if (getbit(input)) { /* 00000011 */\r
4073           if (getbit(input)) { /* 000000111 */\r
4074             if (getbit(input)) { /* 0000001111 */\r
4075               return 64;  /* make up */\r
4076             }\r
4077             else {      /* 0000001110 */\r
4078               if (getbit(input)) { /* 00000011101 */\r
4079                 if (getbit(input)) { /* 000000111011 */\r
4080                   if (getbit(input)) { /* 0000001110111 */\r
4081                     return 1216;\r
4082                   }\r
4083                   else {      /* 0000001110110 */\r
4084                     return 1152;\r
4085                   }\r
4086                 }\r
4087                 else {      /* 000000111010 */\r
4088                   if (getbit(input)) { /* 0000001110101 */\r
4089                     return 1088;\r
4090                   }\r
4091                   else {      /* 0000001110100 */\r
4092                     return 1024;\r
4093                   }\r
4094 \r
4095                 }\r
4096               }\r
4097               else {      /* 00000011100 */\r
4098                 if (getbit(input)) { /* 000000111001 */\r
4099                   if (getbit(input)) { /* 0000001110011 */\r
4100                     return 960;\r
4101                   }\r
4102                   else {      /* 0000001110010 */\r
4103                     return 896;\r
4104                   }\r
4105                 }\r
4106                 else {      /* 000000111000 */\r
4107                   return 54;\r
4108                 }\r
4109               }\r
4110             }\r
4111           }\r
4112           else {      /* 000000110 */\r
4113             if (getbit(input)) { /* 0000001101 */\r
4114               if (getbit(input)) { /* 00000011011 */\r
4115                 if (getbit(input)) { /* 000000110111 */\r
4116                   return 53;\r
4117                 }\r
4118                 else {      /* 000000110110 */\r
4119                   if (getbit(input)) { /* 0000001101101 */\r
4120                     return 576; /*make up */\r
4121                   }\r
4122                   else {      /* 0000001101100 */\r
4123                     return 512; /* make up */\r
4124                   }\r
4125                 }\r
4126               }\r
4127               else {      /* 00000011010 */\r
4128                 if (getbit(input)) { /* 000000110101 */\r
4129                   return 448; /* make up */\r
4130                 }\r
4131                 else {      /* 000000110100 */\r
4132                   return 384; /* make up */\r
4133                 }\r
4134               }\r
4135             }\r
4136             else {      /* 0000001100 */\r
4137               if (getbit(input)) { /* 00000011001 */\r
4138                 if (getbit(input)) { /* 000000110011 */\r
4139                   return 320; /* make up */\r
4140                 }\r
4141                 else {      /* 000000110010 */\r
4142                   if (getbit(input)) { /* 0000001100101 */\r
4143                     return 1728;\r
4144                   }\r
4145                   else {      /* 0000001100100 */\r
4146                     return 1664;\r
4147                   }\r
4148                 }\r
4149               }\r
4150               else {      /* 00000011000 */\r
4151                 return 25;\r
4152               }\r
4153             }\r
4154           }\r
4155         }\r
4156         else { /* 00000010 */\r
4157           if (getbit(input)) { /* 000000101 */\r
4158             if (getbit(input)) { /* 0000001011 */\r
4159               if (getbit(input)) { /* 00000010111 */\r
4160                 return 24;\r
4161               }\r
4162               else {      /* 00000010110 */\r
4163                 if (getbit(input)) { /* 000000101101 */\r
4164                   if (getbit(input)) { /* 0000001011011 */\r
4165                     return 1600;\r
4166                   }\r
4167                   else {      /* 0000001011010 */\r
4168                     return 1536;\r
4169                   }\r
4170                 }\r
4171                 else {      /* 000000101100 */\r
4172                   return 60;\r
4173                 }\r
4174               }\r
4175             }\r
4176             else {      /* 0000001010 */\r
4177               if (getbit(input)) { /* 00000010101 */\r
4178                 if (getbit(input)) { /* 000000101011 */\r
4179                   return 59;\r
4180                 }\r
4181                 else {      /* 000000101010 */\r
4182                   if (getbit(input)) { /* 0000001010101 */\r
4183                     return 1472;\r
4184                   }\r
4185                   else {      /* 0000001010100 */\r
4186                     return 1408;\r
4187                   }\r
4188                 }\r
4189               }\r
4190               else {      /* 00000010100 */\r
4191                 if (getbit(input)) { /* 000000101001 */\r
4192                   if (getbit(input)) { /* 0000001010011 */\r
4193                     return 1344;\r
4194                   }\r
4195                   else {      /* 0000001010010 */\r
4196                     return 1280;\r
4197                   }\r
4198                 }\r
4199                 else {      /* 000000101000 */\r
4200                   return 56;\r
4201                 }\r
4202               }\r
4203             }\r
4204           }\r
4205           else {      /* 000000100 */\r
4206             if (getbit(input)) { /* 0000001001 */\r
4207               if (getbit(input)) { /* 00000010011 */\r
4208                 if (getbit(input)) { /* 000000100111 */\r
4209                   return 55;\r
4210                 }\r
4211                 else {      /* 000000100110 */\r
4212                   if (getbit(input)) { /* 0000001001101 */\r
4213                     return 832;\r
4214                   }\r
4215                   else {      /* 0000001001100 */\r
4216                     return 768;\r
4217                   }\r
4218                 }\r
4219               }\r
4220               else {      /* 00000010010 */\r
4221                 if (getbit(input)) { /* 000000100101 */\r
4222                   if (getbit(input)) { /* 0000001001011 */\r
4223                     return 704;\r
4224                   }\r
4225                   else {      /* 0000001001010 */\r
4226                     return 640;\r
4227                   }\r
4228                 }\r
4229                 else {      /* 000000100100 */\r
4230                   return 52;\r
4231                 }\r
4232               }\r
4233             }\r
4234             else {      /* 0000001000 */\r
4235               return 18;\r
4236             }\r
4237           }\r
4238         }\r
4239       }\r
4240       else { /* 0000000 */\r
4241         return commonmake(input); /* seven zeros */\r
4242       }\r
4243     }\r
4244   }\r
4245   showline(" Impossible black run", 1);\r
4246   showline(" (starting with four zeros)\n", 1);\r
4247   return -1;  /* error */\r
4248 }\r
4249 \r
4250 /* blackrun may actually be OK with compiler optimizations turned on */\r
4251 \r
4252 int blackrun (FILE *input)\r
4253 {\r
4254 #ifdef DEBUGTIFF\r
4255   if (traceflag)\r
4256   {\r
4257     showline ("blackrun entry ", 0);\r
4258   }\r
4259 #endif\r
4260   if (getbit(input)) {  /* 1 */\r
4261     if (getbit(input)) {  /* 11 */\r
4262       return 2;\r
4263     }\r
4264     else {      /* 10 */\r
4265       return 3;\r
4266     }\r
4267   }\r
4268   else {      /* 0 */\r
4269     if (getbit(input)) {  /* 01 */\r
4270       if (getbit(input)) {  /* 011 */\r
4271         return 4;\r
4272       }\r
4273       else {      /* 010 */\r
4274         return 1;\r
4275       }\r
4276     }\r
4277     else {      /* 00 */\r
4278       if (getbit(input)) {  /* 001 */\r
4279         if (getbit(input)) {  /* 0011 */\r
4280           return 5;\r
4281         }\r
4282         else {      /* 0010 */\r
4283           return 6;\r
4284         }\r
4285       }\r
4286       else {    /* 000 */\r
4287         if (getbit(input)) {  /* 0001 */\r
4288           if (getbit(input)) {  /* 00011 */\r
4289             return 7;\r
4290           }\r
4291           else {    /* 00010 */\r
4292             if (getbit(input)) { /* 000101 */\r
4293               return 8;\r
4294             }\r
4295             else {      /* 000100 */\r
4296               return 9;\r
4297             }\r
4298           }\r
4299         }\r
4300         else {    /* 0000 */\r
4301           return blackzero(input);  /* four zeros */\r
4302         }\r
4303       }\r
4304     }\r
4305   }\r
4306   showline(" ERROR: Impossible black run", 1);\r
4307   showline("\n", 0);\r
4308   return -1;  /* error */\r
4309 }\r
4310 \r
4311 //#pragma optimize ("lge", on)\r
4312 \r
4313 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
4314 \r
4315 /* FOLLOWING IS EXPERIMENT 97/OCT/21 */\r
4316 \r
4317 //#pragma optimize ("lge", off)\r
4318 \r
4319 int index, bitinx;  /* index into row of bytes and bits within them */\r
4320 \r
4321 int total;      /* maybe long ? */\r
4322 \r
4323 /* Following could be speeded up some ... */\r
4324 \r
4325 int writewhite (unsigned char *lpBuffer, int run, int width)\r
4326 {\r
4327   if (run == 0) return 0;     /* nothing to do */\r
4328   if (run < 0) return -1;     /* hit invalid run */\r
4329   total += run;\r
4330 #ifdef DEBUGTIFF\r
4331   if (traceflag) {\r
4332     sprintf(logline, "run %d total %d\n", run, total);\r
4333     showline(logline, 0);\r
4334   }\r
4335 #endif\r
4336   if (total > width) return -1; /* error */\r
4337 /*  just advance pointers */\r
4338   while (run > 0) {\r
4339     if (bitinx == 0) {\r
4340       while (run >= 8) {  \r
4341         index++;\r
4342 #ifdef DEBUGTIFF\r
4343         if (traceflag) {\r
4344           sprintf(logline, "index %d run %d ", index, run);\r
4345           showline(logline, 0);\r
4346         }\r
4347 #endif\r
4348 /*        *(lpBuffer+index) = 0; */ /* already zeroed out */\r
4349         run -= 8;\r
4350       }\r
4351     }\r
4352     if (run > 0) {\r
4353       if (bitinx-- <=  0) {\r
4354         index++; bitinx = 7;\r
4355       }\r
4356 #ifdef DEBUGTIFF\r
4357       if (traceflag) {\r
4358         sprintf(logline, "index %d bitinx %d ", index, bitinx);\r
4359         showline(logline, 0);\r
4360       }\r
4361 #endif\r
4362 /*      *(lpBuffer + index) &= ~(1 << bitinx); */\r
4363       run--;\r
4364     }\r
4365   }\r
4366   if (total == width) return 1; /* EOL */\r
4367   else return 0;\r
4368 }\r
4369 \r
4370 int writeblack (unsigned char *lpBuffer, int run, int width)\r
4371 {\r
4372   if (run == 0) return 0;     /* nothing to do */\r
4373   if (run < 0) return -1;     /* hit invalid run */\r
4374   total += run;\r
4375 #ifdef DEBUGTIFF\r
4376   if (traceflag) {\r
4377     sprintf(logline, "run %d total %d\n", run, total);\r
4378     showline(logline, 0);\r
4379   }\r
4380 #endif\r
4381   if (total > width) return -1; /* error */\r
4382   while (run > 0) {\r
4383     if (bitinx == 0) {\r
4384       while (run >= 8) {  \r
4385         index++;\r
4386 #ifdef DEBUGTIFF\r
4387         if (traceflag) {\r
4388           sprintf(logline, "index %d run %d ", index, run);\r
4389           showline(logline, 0);\r
4390         }\r
4391 #endif\r
4392         *(lpBuffer+index) = 255;  /* write a byte at a time */\r
4393         run -= 8;\r
4394       }\r
4395     }\r
4396     if (run > 0) {\r
4397       if (bitinx-- <=  0) {\r
4398         index++; bitinx = 7;\r
4399       }\r
4400 #ifdef DEBUGTIFF\r
4401       if (traceflag) {\r
4402         sprintf(logline, "index %d bitinx %d ", index, bitinx);\r
4403         showline(logline, 0);\r
4404       }\r
4405 #endif\r
4406       *(lpBuffer + index) |= (1 << bitinx); /* write a bit at a time */\r
4407       run--;\r
4408     }\r
4409   }\r
4410   if (total == width) return 1; /* EOL */\r
4411   else return 0;\r
4412 }\r
4413 \r
4414 /* make width long ? */\r
4415 \r
4416 int huffmanrow (unsigned char *lpBuffer, FILE *input, int width)\r
4417 {\r
4418   int k, bytes;\r
4419   int run;\r
4420 /*  int total = 0; */             /* long total ? */\r
4421 \r
4422 /*  if (lpBuffer == NULL) {\r
4423     showline(" Bad buffer pointer\n", 1);\r
4424     return -1;\r
4425   } */\r
4426   total = 0;\r
4427   index = -1; bitinx = 0;   /* output buffering */\r
4428   bytex = 0; bitsleft = 0;    /* input buffering */\r
4429 \r
4430   bytes = (width + 7) / 8;  /* preset with zeros */\r
4431 #ifdef DEBUGTIFF\r
4432   if (traceflag) {\r
4433     sprintf(logline, "Cleaning out %d bytes\n", bytes);\r
4434     showline(logline, 0);\r
4435   }\r
4436 #endif\r
4437   for (k = 0; k < bytes; k++) lpBuffer[k] = 0;\r
4438 \r
4439   for (;;) {\r
4440 #ifdef DEBUGTIFF\r
4441     if (traceflag) {\r
4442       sprintf(logline, "Looking for white run\n");\r
4443       showline(logline, 0);\r
4444     }\r
4445 #endif\r
4446     while ((run = whiterun (input)) >= 64) {\r
4447 #ifdef DEBUGTIFF\r
4448       if (traceflag) {\r
4449         sprintf(logline, " W %d ", run);\r
4450         showline(logline, 0);\r
4451       }\r
4452 #endif\r
4453       if (writewhite(lpBuffer, run, width) < 0) break;\r
4454     }\r
4455     if (total >= width) break;\r
4456 #ifdef DEBUGTIFF\r
4457     if (traceflag) {\r
4458       sprintf(logline, " W %d\n", run);\r
4459       showline(logline, 0);\r
4460     }\r
4461 #endif\r
4462     if (writewhite(lpBuffer, run, width) != 0) break;  /* terminal run */\r
4463 \r
4464 #ifdef DEBUGTIFF\r
4465     if (traceflag) {\r
4466       sprintf(logline, "Looking for black run\n");\r
4467       showline(logline, 0);\r
4468     }\r
4469 #endif\r
4470     while ((run = blackrun (input)) >= 64) {\r
4471 #ifdef DEBUGTIFF\r
4472       if (traceflag) {\r
4473         sprintf(logline, " B %d ", run);\r
4474         showline(logline, 0);\r
4475       }\r
4476 #endif\r
4477       if (writeblack(lpBuffer, run, width) < 0) break;\r
4478     }\r
4479     if (total >= width) break;\r
4480 #ifdef DEBUGTIFF\r
4481     if (traceflag) {\r
4482       sprintf(logline, " B %d\n", run);\r
4483       showline(logline, 0);\r
4484     }\r
4485 #endif\r
4486     if (writeblack(lpBuffer, run, width) != 0) break;  /* terminal run */\r
4487   }\r
4488   if (total != width) {\r
4489     sprintf(logline, " Sum of runs %d not equal width %d\n", total, width);\r
4490     showline(logline, 1);\r
4491     return -1;\r
4492   }\r
4493 #ifdef DEBUGTIFF\r
4494   else if (traceflag ) {\r
4495     sprintf(logline, "Sum of runs equal to width %d\n", width);\r
4496     showline(logline, 0);\r
4497   }\r
4498 #endif\r
4499   return 0;\r
4500 }\r
4501 \r
4502 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
4503 \r
4504 //#pragma optimize ("lge", on)    /* experiment 2000 June 17 */\r
4505 \r
4506 /* Here is the code for LZW (compression scheme number 5) input side */\r
4507 \r
4508 char *StringByte=NULL;      /* contains last byte of string */\r
4509 \r
4510 char *StringFirst=NULL;     /* contains first byte of string */\r
4511                     /* to speed up processing ... */\r
4512 \r
4513 #ifdef USESHORTINT\r
4514 short int *StringPrevious=NULL; /* points to previous char of string */\r
4515 short int *StringLength=NULL;   /* length of string */\r
4516                     /* to speed up processing ... */\r
4517 #else\r
4518 int *StringPrevious=NULL;     /* points to previous char of string */\r
4519 int *StringLength=NULL;     /* length of string */\r
4520                     /* to speed up processing ... */\r
4521 #endif\r
4522 \r
4523 int TableIndex=FIRSTCODE;         /* index into above String Tables */\r
4524                     /* next available string entry */\r
4525 \r
4526 int CodeLength=9;           /* current code length INPUT */\r
4527 \r
4528 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
4529 \r
4530 /* following is never called ? now called from dvipsone.c when exiting */\r
4531 \r
4532 void DeAllocStringsIn (void)   /* remember to do this at end */\r
4533 {\r
4534 /*  if (Memory != NULL) {\r
4535     free(Memory); Memory = NULL;\r
4536   } */\r
4537   if (StringByte != NULL) {\r
4538     free(StringByte); StringByte = NULL;\r
4539   }\r
4540   if (StringFirst != NULL) {\r
4541     free(StringFirst); StringFirst = NULL;\r
4542   }\r
4543   if (StringPrevious != NULL) {\r
4544     free(StringPrevious); StringPrevious = NULL;\r
4545   }\r
4546   if (StringLength != NULL) {\r
4547     free(StringLength); StringLength = NULL;\r
4548   }\r
4549 }\r
4550 \r
4551 /* worry here about allocation in NT ? sizeof(int) */\r
4552 \r
4553 int AllocStringsIn (void)\r
4554 {\r
4555 /*  if (Memory == NULL) {\r
4556     Memory = (char *) malloc(INIMEMORY);\r
4557     MemorySize = INIMEMORY;\r
4558   } */ /* memory for strings in string table */\r
4559   if (StringByte == NULL) { /* allocate string table indeces */\r
4560     StringByte = (char *) malloc(MAXCODES * sizeof(char));\r
4561   }\r
4562   if (StringFirst == NULL) {  /* allocate string table indeces */\r
4563     StringFirst = (char *) malloc(MAXCODES * sizeof(char));\r
4564   }\r
4565 /*  should this be short int in NT ? */\r
4566 #ifdef USESHORTINT\r
4567   if (StringPrevious == NULL) { /* allocate string table lengths */\r
4568     StringPrevious = (short int *)\r
4569              malloc(MAXCODES * sizeof(short int));\r
4570   }\r
4571   if (StringLength == NULL) { /* allocate string table lengths */\r
4572     StringLength = (short int *)\r
4573              malloc(MAXCODES * sizeof(short int));\r
4574   }\r
4575 #else\r
4576   if (StringPrevious == NULL) { /* allocate string table lengths */\r
4577     StringPrevious = (int *) malloc(MAXCODES * sizeof(int));\r
4578   }\r
4579   if (StringLength == NULL) { /* allocate string table lengths */\r
4580     StringLength = (int *) malloc(MAXCODES * sizeof(int));\r
4581   }\r
4582 #endif\r
4583 /*  if (Memory == NULL || StringTable == NULL ||  StringLength == NULL) { */\r
4584   if (StringByte == NULL || StringFirst == NULL ||\r
4585     StringPrevious == NULL || StringLength == NULL) {\r
4586     showline("Unable to allocate memory\n", 1);\r
4587     checkexit(1);\r
4588 //    or more serious exit(1) ???\r
4589   }\r
4590   return 0;\r
4591 }\r
4592 \r
4593 void InitializeStringTable (void)  /* set up string table initially */\r
4594 {\r
4595   int k;\r
4596 \r
4597   AllocStringsIn();         /* grab memory for tables if needed */\r
4598 //  What if it failed ???\r
4599   for (k = 0; k < MAXCHR; k++) {  /* 256 single byte strings */\r
4600     StringByte[k] = (char) k;\r
4601     StringFirst[k] = (char) k;\r
4602     StringPrevious[k] = -1;   /* indicate beginning of string */\r
4603     StringLength[k] = 1;\r
4604   }\r
4605 /*  FreeIndex = MAXCHR; */\r
4606   TableIndex = FIRSTCODE;\r
4607   CodeLength = 9;         /* initial code length */\r
4608 }\r
4609 \r
4610 void ResetStringTable (int quietflag) /* clear string table */\r
4611 {\r
4612 /*  int k; */\r
4613 \r
4614 #ifdef DEBUGTIFF\r
4615   if (!quietflag)\r
4616   {\r
4617     if (traceflag) showline("CLEAR ", 0);\r
4618     if (traceflag) showline("\n", 0);\r
4619     if (traceflag && TableIndex > FIRSTCODE)\r
4620     {\r
4621 /*      printf("TableIndex %d FreeIndex %u CodeLength %d\n",\r
4622         TableIndex, FreeIndex, CodeLength); */\r
4623       sprintf(logline, "TableIndex %d CodeLength %d\n", TableIndex, CodeLength);\r
4624       showline(logline, 0);\r
4625     }\r
4626   } \r
4627 #endif\r
4628 /*  following not really needed */\r
4629 /*  for (k = FIRSTCODE; k < TableIndex; k++) {\r
4630     StringTable[k] = 0;\r
4631     StringLength[k] = 0;\r
4632   } */\r
4633 /*  FreeIndex = MAXCHR; */\r
4634   TableIndex = FIRSTCODE;\r
4635   CodeLength = 9;\r
4636 }\r
4637 \r
4638 #ifdef USESHORTINT\r
4639 void AddNewEntry (short int OldCode, short int Code)\r
4640 {\r
4641 #else\r
4642 void AddNewEntry (int OldCode, int Code)\r
4643 {\r
4644 #endif\r
4645 /*  char *s; */\r
4646 /*  char *t; */\r
4647 /*  int k; */\r
4648 \r
4649 #ifdef DEBUGLZW\r
4650   if (traceflag)\r
4651   {\r
4652     sprintf(logline, "Add string TableIndex %4d (%d)\n",\r
4653          TableIndex, StringLength[OldCode] + 1);\r
4654     showline(logline, 0);\r
4655   }\r
4656 #endif\r
4657 \r
4658 /*  This is where we enter new one in table */\r
4659 /*  StringTable[TableIndex] = FreeIndex; */\r
4660 /*  StringLength[TableIndex] = len; */\r
4661   StringByte[TableIndex] = StringFirst[Code];\r
4662   StringFirst[TableIndex] = StringFirst[OldCode];\r
4663   StringPrevious[TableIndex] = OldCode;\r
4664 #ifdef USESHORTINT\r
4665   StringLength[TableIndex] =\r
4666         (unsigned short int) (StringLength[OldCode] + 1);\r
4667 #else\r
4668   StringLength[TableIndex] = StringLength[OldCode] + 1;\r
4669 #endif\r
4670   TableIndex++;\r
4671 /*  s = Memory + FreeIndex; */\r
4672 /*  t = Memory + StringTable[OldCode]; */\r
4673 /*  for (k = 0; k < len-1; k++) *s++ = *t++; */\r
4674 /*  t = Memory + StringTable[Code];  */\r
4675 /*  *s = *t; */         /* last byte comes from next code string */\r
4676 /*  FreeIndex += len; */\r
4677 \r
4678   if (TableIndex == 511 || TableIndex == 1023 || TableIndex == 2047)\r
4679   {\r
4680     CodeLength++;\r
4681 #ifdef DEBUGTIFF\r
4682     if (traceflag)\r
4683     {\r
4684       sprintf(logline, "LENGTH %d (%d)\n", TableIndex, CodeLength);\r
4685       showline(logline, 0);\r
4686     }\r
4687 #endif\r
4688   }\r
4689 \r
4690   if (TableIndex > MAXCODES)\r
4691   {\r
4692     showline(" ERROR: Table overflow\n", 1);\r
4693     checkexit(1);\r
4694   }\r
4695 }\r
4696 \r
4697 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
4698 \r
4699 int IsInTable (int Code)  /* is code already in table ? */\r
4700 {\r
4701   return (Code >= 0 && Code < TableIndex);\r
4702 }\r
4703 \r
4704 /* copy string from table by code number */\r
4705 \r
4706 unsigned char *WriteString (unsigned char *buffer, int Code)\r
4707 {\r
4708 /*  int k; */\r
4709   int n, len=0;\r
4710   unsigned char *s;\r
4711   unsigned char *t;\r
4712 \r
4713 /*  s = buffer; */\r
4714 /*  t = Memory + StringTable[Code]; */\r
4715 //  if (Code < TableIndex)\r
4716   len = StringLength[Code];\r
4717   t = buffer + len;         /* byte after last one to copy */\r
4718   if (t > StripData + StripDataLen) {\r
4719 /*    special case kludge if terminates right after code length switch */\r
4720     if (((unsigned int) (buffer - StripData) == StripDataLen) &&\r
4721 // kludge to try and deal with lack of code length increase just before EOI\r
4722         ((Code == (EOD*2)) || (Code == (EOD*4))))  // 2000/Feb/4\r
4723     {\r
4724       return buffer;\r
4725     } /* 98/Sep/22 */\r
4726 /*    showline(" ERROR: ran off end of Strip Buffer\n", 1); */\r
4727     sprintf(logline, \r
4728       "ERROR: Strip Buffer len %d code %d EOD %d CodeLength %d TableIndex %d",\r
4729         len, Code, EOD, CodeLength, TableIndex);\r
4730     showline(logline, 0);\r
4731     if (traceflag) {\r
4732       sprintf(logline,\r
4733       "code %d len %d buffer %ld buffer + len %ld stripdatalen %ld\n",\r
4734          Code, len, buffer-StripData, t-StripData, StripDataLen);\r
4735       showline(logline, 0);\r
4736     }\r
4737     return buffer;\r
4738   }\r
4739   s = t - 1;              /* last byte to copy */\r
4740 /*  for (k = 0; k < len; k++) *s++ = *t++; */\r
4741   n = Code;\r
4742 /*  for (k = 0; k < len; k++) */\r
4743 /*  for (k = len; k > 0; k--) */\r
4744   while (n >= 0) {\r
4745 /*    if (k != StringLength[n])\r
4746       printf("k %d <> len %d ", k, StringLength[n]); */ /* check */\r
4747     *s-- = StringByte[n];           /* copy the byte */\r
4748 /*    if (StringPrevious[n] < 0 && k != 1)\r
4749       printf("k %d n %d Code %d ", k, n, Code); */\r
4750     n = StringPrevious[n];\r
4751 /*    if (n < 0) break; */            /* termination */\r
4752   }\r
4753   if ((s + 1) != buffer) {            /* sanity check */\r
4754     int err;\r
4755     if ((s+1) > buffer) err = (s+1) - buffer;\r
4756     else err = buffer - (s+1);\r
4757     sprintf(logline, "Off by %d (len %d Code %d)\n", err, len, Code);\r
4758     showline(logline, 1);\r
4759   }\r
4760 /*  s = buffer;\r
4761   while (s < t) {\r
4762     if (*s++ != 0) putc('1', stdout);\r
4763     else putc('0', stdout);\r
4764     if (counter++ % 1024 == 0) putc('\n', stdout);\r
4765   }\r
4766   return buffer; */                 /* TESTING HACK! */\r
4767   return t;\r
4768 }\r
4769 \r
4770 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
4771 \r
4772 unsigned long OldByte=0;    /* cadaver being eaten */\r
4773 int OldBitsLeft=0;        /* how many bits left in OldByte */\r
4774 \r
4775 #ifdef USESHORTINT\r
4776 short int GetNextCode (FILE *input) /* get next LZW code number from input  */\r
4777 {\r
4778 #else\r
4779 int GetNextCode (FILE *input) /* get next LZW code number from input  */\r
4780 {\r
4781 #endif\r
4782   int bits;\r
4783   int c;\r
4784   unsigned long k;\r
4785 \r
4786   bits = OldBitsLeft;         /*  how many bits do we have */\r
4787   k = OldByte;            /*  start with old bits */\r
4788 \r
4789   while (bits < CodeLength) {     /* need more bits ? */\r
4790     if (InStripLen-- <= 0) {    /* treat as EOD 96/Nov/17 */\r
4791       if (traceflag) {\r
4792         sprintf(logline, " No EOD at end of strip %d ", CurrentStrip);\r
4793         showline(logline, 1);\r
4794       }\r
4795       return EOD;\r
4796     }\r
4797     if ((c = getc(input)) == EOF)\r
4798     {\r
4799       sprintf(logline, " Unexpected EOF (%s)\n", "getnextcode");\r
4800       showline(logline, 1);\r
4801       checkexit(1);\r
4802 //      finish = -1;\r
4803 //      return -1;          /* EOF serious error ... */\r
4804     } \r
4805     k = (k << 8) | c;\r
4806     bits += 8;\r
4807   }\r
4808   OldByte = k;\r
4809   OldBitsLeft = bits - CodeLength;    /* extra bits not used */\r
4810 /*  OldByte = OldByte & ((1 << OldBitsLeft) - 1); *//* redundant */\r
4811   k = k >> OldBitsLeft;         /* shift out extra bits */\r
4812   k = k & ((1 << CodeLength) - 1);    /* mask out high order */\r
4813 #ifdef DEBUGLZW\r
4814   if (traceflag) {\r
4815     sprintf(logline, "CODE %4d ", k);\r
4816     showline(logline, 0);\r
4817   }\r
4818 #endif\r
4819 #ifdef USESHORTINT\r
4820   return (short int) k;\r
4821 #else\r
4822   return (int) k;\r
4823 #endif\r
4824 }\r
4825 \r
4826 void LZWdecompress (unsigned char *StripData, FILE *input)\r
4827 {\r
4828 #ifdef USESHORTINT\r
4829   short int Code, OldCode;\r
4830 #else\r
4831   int Code, OldCode;\r
4832 #endif\r
4833   unsigned int nlen;\r
4834   unsigned char *s = StripData;\r
4835 \r
4836   OldCode = 0;            /* to keep compiler happy */\r
4837 /*  InitializeStringTable(); */     /* assume already done once */\r
4838 /*  ResetStringTable(1); */       /* not needed - first code CLEAR */\r
4839   while ((Code = GetNextCode(input)) != EOD) {\r
4840     if (Code == -1) {       // error check only\r
4841       showline(" ERROR: Premature end of LZW", 1);\r
4842       showline("\n", 0);\r
4843       return;\r
4844     }\r
4845 // #ifdef DEBUGLZW\r
4846 //    if (traceflag) {\r
4847 //      sprintf(logline, "%4d ", Code);       /* debugging */\r
4848 //      showline(logline, 0);\r
4849 //    }\r
4850 // #endif\r
4851     if (Code == CLEAR) {\r
4852       ResetStringTable(0);\r
4853       Code = GetNextCode(input);\r
4854       if (traceflag) showline("\n", 0);\r
4855       if (Code == -1) {     // error check only\r
4856         showline(" ERROR: Premature end of LZW", 1);\r
4857         showline(" (after CLEAR)", 0);\r
4858         showline("\n", 0);\r
4859         return;\r
4860       }\r
4861       if (Code == EOD) break;\r
4862       s = WriteString(s, Code);\r
4863       OldCode = Code;\r
4864     }               /* end of CLEAR case */\r
4865     else {\r
4866 //      if (IsInTable(Code)) {\r
4867       if (Code >= 0 && Code < TableIndex) {\r
4868 /*        AddTableEntry(StringTable(OldCode)\r
4869           + FirstChar(StringFromCode(Code);)); */\r
4870         AddNewEntry(OldCode, Code);\r
4871         s = WriteString(s, Code);\r
4872         OldCode = Code;\r
4873       }             /* end of Code in Table case */\r
4874       else {            /* Code is *not* in table */\r
4875 /*        OutString = StringFromCode (OldCode) +\r
4876           + FirstChar(StringFromCode(Code);)); */\r
4877         if (Code > TableIndex) {\r
4878 // kludge to try and deal with lack of code length increase just before EOI\r
4879           Code = Code / 2;\r
4880           OldBitsLeft++;\r
4881 //          CodeLength--;\r
4882           if (traceflag) {\r
4883             sprintf(logline,\r
4884               " Code (%d) > TableIndex (%d) CodeLength %d ",\r
4885               Code, TableIndex, CodeLength);\r
4886             showline(logline, 1);\r
4887           }\r
4888 //          break;      /* ugh! */\r
4889         }         // error check only\r
4890 /*        strcpy(Omega, StringFromCode(OldCode));\r
4891         ConcatOneChar(Omega, StringFromCode(OldCode));\r
4892         WriteString(Omega, output);\r
4893         AddTableEntry(Omega); */\r
4894         AddNewEntry(OldCode, OldCode); \r
4895         s = WriteString(s, Code);\r
4896         OldCode = Code;\r
4897       } /* end of Code *not* in Table case */\r
4898     } /* end of *not* CLEAR case */\r
4899   } /* end of not EOD loop */\r
4900 \r
4901 /*  if (bExpandColor) nlen = StripDataLen / 3;\r
4902   else nlen = StripDataLen; */ /* ??? */\r
4903   if (traceflag) {  /*  NOTE: mismatch on last strip is OK */\r
4904     if (CurrentStrip < StripsPerImage-1) {        /* 96/Nov/17 */\r
4905       if (bExpandColor) nlen = StripDataLen / 3;\r
4906       else nlen = StripDataLen;\r
4907       if ((unsigned int) (s - StripData) != nlen) {\r
4908         sprintf(logline,\r
4909         " Strip data mismatch %u < %u bytes (Strip %d of %ld)\n",\r
4910             (s - StripData), nlen, CurrentStrip, StripsPerImage);\r
4911         showline(logline, 1);\r
4912       }\r
4913     }\r
4914   } \r
4915 \r
4916 /*  if (verboseflag) printf("EOD "); */\r
4917 /*  reset table for next one */\r
4918   ResetStringTable(0);\r
4919 #ifdef DEBUGTIFF\r
4920   if (traceflag)\r
4921   {\r
4922     sprintf(logline, "Now at byte %ld in file\n", ftell(input));\r
4923     showline(logline, 0);\r
4924   }\r
4925 #endif\r
4926 }\r
4927 \r
4928 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***  */\r
4929 \r
4930 /* Set up StripOffset & StripByteCount for strip number k */\r
4931 /* and go to start of data for strip number k */\r
4932 /* First one was already set up - don't disturb in case not indirect */\r
4933 /* In practice, strips are usually contiguous, but no guarantee... */\r
4934 \r
4935 long SetupStrip (FILE *input, int k)      /* 96/Nov/17 */\r
4936 {\r
4937   if (k > 0) {\r
4938     StripOffset = indirectvalue(StripOffsetsType, 1,\r
4939       StripOffsetsPtr + k * typesize[StripOffsetsType], input);\r
4940     StripByteCount = indirectvalue(StripByteCountsType, 1,\r
4941       StripByteCountsPtr + k * typesize[StripByteCountsType], input);\r
4942   }\r
4943 #ifdef DEBUGTIFF\r
4944   if (traceflag) {\r
4945     sprintf(logline, "Strip %d Offset %ld ByteCount %ld\n",\r
4946     k, StripOffset, StripByteCount);\r
4947     showline(logline, 0);\r
4948   }\r
4949 #endif\r
4950   if (fseek (input, StripOffset, SEEK_SET))\r
4951   {\r
4952     showline("Error in seek to StripOffset", 1);  /* ??? */\r
4953     finish = -1;\r
4954     return -1;\r
4955   }\r
4956   if (k == 0 && StripByteCount < 0)\r
4957     StripByteCount = 0XFFFFFF;    // kludge if missing 2000/Apr/13\r
4958   return StripByteCount;            /* 96/Nov/17 */\r
4959 }\r
4960 \r
4961 /* Copy a row from far space used by LZW to near space used for output */\r
4962 \r
4963 void CopyRow (unsigned char *lpBuffer, unsigned char *StripData,\r
4964     long InRowLength)\r
4965 {\r
4966   int k, n;\r
4967   unsigned char *s=lpBuffer;\r
4968   unsigned char *t=StripData;\r
4969   n = (int) InRowLength;    /* assuming row not longer than 32k */\r
4970 /*  if (InRowLength > BufferLength) { */ /* DEBUGGING 95/Nov/10 */\r
4971   if (InRowLength > BufferLength+1) {  /* DEBUGGING 95/Nov/10 */\r
4972     sprintf(logline, " ERROR: InRowLength %ld > BufferLength %ld\n",\r
4973         InRowLength, BufferLength);\r
4974     showline(logline, 1);\r
4975 /*    return; */\r
4976     n = (int) BufferLength;      /* prevent heap corruption */\r
4977   }\r
4978   for (k = 0; k < n; k++) *s++ = *t++; \r
4979 }\r
4980 \r
4981 /* A whole strip is treated as one unit for LZW encoding ... */\r
4982 /* So need to do once per strip and need memory for strip output */\r
4983 \r
4984 int DecodeLZW (FILE *output, FILE *input, unsigned char *lpBuffer)\r
4985 {\r
4986   int k, row = 0, i, j, n, m, flag = 0;\r
4987 /*  unsigned char *StripData; */\r
4988   long nlen;\r
4989 \r
4990   nlen = (long) BufferLength * RowsPerStrip;\r
4991 #ifdef IGNORED\r
4992 /*  is this 65535U limit still valid in NT ? malloc limitation ? */\r
4993   if (nlen > 65535U) {\r
4994     sprintf(logline, " Cannot handle Strip Buffer of %lu bytes\n", nlen);\r
4995     showline(logline, 1);\r
4996 /*    nlen = 30000U;  */        /* TESTING HACK! */\r
4997     checkexit(1); \r
4998   }\r
4999 #endif\r
5000   StripDataLen = (unsigned int) nlen;\r
5001 #ifdef DEBUGTIFF\r
5002   if (traceflag) {            /* debugging */\r
5003     sprintf(logline, " Allocating %u bytes for Strip Buffer\n", StripDataLen);\r
5004     showline(logline, 0);\r
5005   }\r
5006 #endif\r
5007   StripData = (unsigned char *) malloc(StripDataLen);\r
5008 /*    malloc((unsigned int) (InRowLength * RowsPerStrip)); */\r
5009 /*    malloc((unsigned int) (BufferLength * RowsPerStrip)); */\r
5010   if (StripData == NULL) {\r
5011 //    showline(" ", 0);\r
5012     showline(" Unable to allocate memory\n", 1);  /* 1995/July/15 */\r
5013     checkexit(1);\r
5014 //    or more serious exit(1) ???\r
5015   }\r
5016   InitializeStringTable(); \r
5017 /*  checkheap("AFTER INITIALIZE", 0); */  /* debugging only 1995/Nov/10 */\r
5018   row = 0;\r
5019   for (k = 0; k < StripsPerImage; k++) {\r
5020     CurrentStrip = k;         /* global for debug output */\r
5021 /*    SetupStrip(input, k); */\r
5022     InStripLen = SetupStrip(input, k);  /* save GetNextCode 96/Nov/17 */\r
5023     OldByte = 0;  OldBitsLeft = 0;\r
5024     ResetStringTable(1);      /* redundant ? */\r
5025     LZWdecompress(StripData, input);\r
5026     n = RowsPerStrip;\r
5027     if (row + n > ImageLength) n = (int) (ImageLength - row);\r
5028     for (i = 0; i < n; i++) {\r
5029       CopyRow(lpBuffer, StripData + i * InRowLength, InRowLength);\r
5030 /*      Following new 1996/Sep/9 */\r
5031       if (Predictor == 2) {   /* only applies to LZW images */\r
5032 /*        We will assume here that BitsPerSample == 8 ... */\r
5033 /*        if (SamplesPerPixel == 1) */      /* gray level */\r
5034         if (SamplesPerPixelX == 1) {      /* gray level */\r
5035           for (j = 1; j < InRowLength; j++)\r
5036 /*            lpBuffer[j] += lpBuffer[j-1]; */\r
5037             lpBuffer[j] = (unsigned char) (lpBuffer[j] + lpBuffer[j-1]);\r
5038         }\r
5039         else {                /* RGB (3) or CMYK (4) */\r
5040 /*          for (j = SamplesPerPixel; j < InRowLength; j++) */\r
5041           for (j = SamplesPerPixelX; j < InRowLength; j++)\r
5042 /*            lpBuffer[j] += lpBuffer[j-SamplesPerPixel]; */\r
5043             lpBuffer[j] =\r
5044 /*              (unsigned char) (lpBuffer[j] + lpBuffer[j-SamplesPerPixel]); */\r
5045               (unsigned char) (lpBuffer[j] + lpBuffer[j-SamplesPerPixelX]);\r
5046         }\r
5047       }   \r
5048       if (ExtraSamples > 0)\r
5049         (void) RemoveExtraSamples(lpBuffer, InRowLength); /* 99/May/10 */\r
5050 /*      if (ProcessRow (output, lpBuffer, InRowLength, BufferLength, */\r
5051       if (ProcessRow (output, lpBuffer, InRowLengthX, BufferLength,\r
5052         OutRowLength) != 0) break;  /* break if output error */\r
5053 /*      if (bCompressColor)\r
5054         compresscolorfar(StripData + i * BufferLength, InRowLength);\r
5055       if (writearowfar (output, StripData + i * BufferLength,\r
5056         OutRowLength) != 0) {\r
5057         flag = 1;\r
5058         break;\r
5059       }\r
5060       if (flag) break; */\r
5061     }\r
5062     row += n;\r
5063   }\r
5064   ResetStringTable(1);      /* redundant ? */\r
5065 #ifdef DEBUGTIFF\r
5066   if (traceflag) {          /* debugging */\r
5067     sprintf(logline, " Freeing %u bytes Strip Buffer\n", StripDataLen);\r
5068     showline(logline, 0);\r
5069   }\r
5070 #endif\r
5071   free(StripData);\r
5072   StripData = NULL;       /* debugging 95/Nov/10 */\r
5073   if (traceflag) { /* debugging code added */ /* should work also in NT */\r
5074     if ((m = _heapchk ()) != _HEAPOK) {     /* 1995/Nov/10 */\r
5075       sprintf(logline, " ERROR: heap corrupted (%d)\n", m);\r
5076 /*      sprintf(logline, " ERROR: __near heap corrupted (%d)\n", m); */\r
5077       showline(logline, 1);\r
5078 /*      checkexit(9); */\r
5079       exit(9);      /* terminate with extreme prejudice */\r
5080     }\r
5081   }\r
5082   return flag;\r
5083 }\r
5084 \r
5085 /* InitializeStringTable AllocString - may need to DeAllocString eventually */\r
5086 \r
5087 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
5088 \r
5089 /* change long => int where sensible */\r
5090 \r
5091 /* complain if samplesperpixel other than one */ /* no color support */\r
5092 /* quit early (before writing header) if 24 bit image */\r
5093 \r
5094 /* implement CCIT Huffman decompression also OK */\r
5095 /* implement LZW decompression also */ /* need Predictor also ? */\r
5096 \r
5097 /* implement gray scale response curve ? */ /* although ignored by some apps */\r
5098 \r
5099 /* II* or MM* followed by four byte offset to first IFD (often == 8) */\r
5100 \r
5101 /* IFD: 2 byte count of fields, followed by 12 byte tag fields */\r
5102 /* after that, four byte offset to next IFD (or zero) (or junk!) */\r
5103 \r
5104 /* Field entries sorted in ascending order on tag: */\r
5105 \r
5106 /* Byte 0 & 1: tag */\r
5107 /* Byte 2 & 3: type */\r
5108 /* Byte 4 - 7: `length' (better called `count') */\r
5109 /* Byte 8 -11: value offset -- always even  (or value itself if it fits) */\r
5110 \r
5111 /* if bAllowColor is false, maybe just use green component and `image' */\r
5112 \r
5113 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */\r
5114 \r
5115 BOOL bTIFFAllow=1;\r
5116 \r
5117 /* x * (numer / denom) 1995/Oct/12 */\r
5118 /* or use MulDiv ??? */\r
5119 \r
5120 long MulRatio (long x, unsigned long numer, unsigned long denom)\r
5121 {\r
5122   long result;\r
5123   if (denom == 0 || numer == 0) return 0;\r
5124   if ((numer % denom) == 0) {\r
5125     numer = numer / denom;\r
5126     denom = 1;\r
5127   }\r
5128   if ((denom % numer) == 0) {\r
5129     denom = denom / numer;\r
5130     numer = 1;\r
5131   }\r
5132   while (denom > 65536 || numer > 65536) {\r
5133     denom = denom >> 1;\r
5134     numer = numer >> 1;\r
5135   }\r
5136   result = x / denom * numer;\r
5137   return result;    \r
5138 }\r
5139 \r
5140 // long MulRatio (long x, unsigned long numer, unsigned long denom) {\r
5141 //  if (denom == 0 || numer == 0) return 0;\r
5142 //  else return(MulDiv(x, numer, denom));\r
5143 // }\r
5144 \r
5145 /* actually insert the TIFF figure here */\r
5146 /* negative nifd indicates figure missing - draw box and filename only */\r
5147 /* if dheight == 0 => calculate dheight from dwidth based on aspect ratio */\r
5148 /* if dwidth == 0 => calculate dwidth & dheight from xres and yres */\r
5149 \r
5150 /* actually insert the TIFF figure here */\r
5151 /* negative nifd indicates figure missing - draw box and filename only */\r
5152 /* if dheight == 0 => calculate dheight from dwidth based on aspect ratio */\r
5153 \r
5154 int showtiffhere (FILE *output, char *filename, long dwidth, long dheight,\r
5155          double xscale, double yscale,  int nifd)\r
5156 {\r
5157   int flag;\r
5158   if (bTIFFAllow != 0) {\r
5159 /*    if (dheight == 0) { */  /* need aspect ratio from TIFF file */\r
5160     if (dheight == 0 || dwidth == 0) {\r
5161       if (traceflag) {\r
5162         sprintf(logline, " Prescanning %s\n", filename);\r
5163         showline(logline, 0);\r
5164       }\r
5165       flag = readimagefile(output, filename, dwidth, dheight, nifd, 1);\r
5166 /*      if (flag < 0) return; */  /* was unable to find file 96/Dec/27 */\r
5167 /*      if (traceflag) printf("FLAG %d\n", flag); */\r
5168       if (flag == 0) {      /* 96/Dec/27 */\r
5169         if (dwidth == 0 && dheight == 0) {      /* fix 95/Oct/12 */\r
5170 /* convert information in image to scaled points */\r
5171 /*          dwidth = (ImageWidth * xresden / xresnum) << 16; */\r
5172 /*          dheight = (ImageLength * yresden / yresnum) << 16; */\r
5173 /*          if (traceflag)\r
5174             printf(" ImageWidth %ld (%lu / %lu) ImageLength %ld (%lu / %lu)\n",\r
5175             ImageWidth, xresnum, xresden, ImageLength, yresnum, yresden); */\r
5176           if (xresnum == 0 || yresnum == 0) {   /* 96/Apr/4 */\r
5177             sprintf(logline,\r
5178                 " xres %lu / %lu yres %lu / %lu unit %d\n",\r
5179                 xresnum, xresden, yresnum, yresden, ResolutionUnit);\r
5180             showline(logline, 1);\r
5181 /*            xresnum = yresnum = 72; */ /* 96/Apr/3 */\r
5182             xresnum = yresnum = nDefaultTIFFDPI;\r
5183 /*            return; */          /* 96/Apr/4 */\r
5184           }\r
5185 \r
5186 /*          dwidth = (ImageWidth << 16) / xresnum * xresden; */\r
5187           dwidth = MulRatio(ImageWidth << 16, xresden, xresnum);\r
5188 /*          dheight = (ImageLength << 16) / yresnum * yresden; */\r
5189           dheight = MulRatio(ImageLength << 16, yresden, yresnum);\r
5190 /*          if (traceflag)\r
5191             printf(" dwidth %ld dheight %ld\n", dwidth, dheight); */\r
5192           if (ResolutionUnit == 1) {      /* what to do ? */\r
5193             showline(" resolution == 1", 1);\r
5194           }\r
5195           else if (ResolutionUnit == 2) {   /* 72.27 pt per in */\r
5196             dwidth = dwidth / 100 * 7227;\r
5197             dheight = dheight / 100 * 7227;\r
5198           }\r
5199           else if (ResolutionUnit == 3) {   /* 28.45 pt per cm */\r
5200             dwidth = dwidth / 100 * 2845;\r
5201             dheight = dheight / 100 * 2845;\r
5202           }\r
5203         }\r
5204 /* adjusted order of mul and div to avoid potential overflow 94/Dec/16 */\r
5205 /* or use MulDiv ??? */ /* switched to MulRatio 98/Jul/9 */\r
5206         else if (dheight == 0) {\r
5207           if (ImageWidth != 0) \r
5208 /*            dheight = (ImageLength * dwidth) / ImageWidth; */\r
5209 /*            dheight = (dwidth / ImageWidth) * ImageLength;  */\r
5210             dheight = MulRatio(dwidth, ImageLength, ImageWidth);\r
5211         }\r
5212         else if (dwidth == 0) {\r
5213           if (ImageLength != 0)\r
5214 /*            dwidth = (ImageWidth * dheight) / ImageLength; */\r
5215 /*            dwidth = (dheight / ImageLength) * ImageWidth; */\r
5216             dwidth = MulRatio(dheight, ImageWidth, ImageLength); \r
5217         }\r
5218 /*      added 99/July/2 */\r
5219         if (xscale != 0.0) dwidth = (long) ((double) dwidth * xscale);\r
5220         if (yscale != 0.0) dheight = (long) ((double) dheight * yscale);\r
5221 #ifdef DEBUGTIFF\r
5222         if (traceflag) {\r
5223           sprintf(logline, " dwidth %ld dheight %ld", dwidth, dheight);\r
5224           showline(logline, 0);\r
5225         }\r
5226 #endif\r
5227     }\r
5228 /*    xll = mapx(dvi_h); yll = mapy(dvi_v); */\r
5229 /*    xll = dvi_h; yll = dvi_v; */\r
5230 /*    xur = mapx(dvi_h + dwidth); yur = mapy(dvi_v - dheight); */\r
5231 /*    xur = dvi_h + dwidth; yur = dvi_v - dheight; */\r
5232     }     /* 96/Dec/27 */\r
5233 /*    if (nifd >= 0) readimagefile(output, filename, dwidth, dheight, nifd, 1); */\r
5234     if (nifd >= 0)\r
5235       flag = readimagefile(output, filename, dwidth, dheight, nifd, 0);\r
5236     \r
5237   }\r
5238   return 0;\r
5239 }\r
5240 \r
5241 /* have the \special in line at this point - entry point from dvispeci.c */\r
5242 \r
5243 /*  else if (strcmp(line, "textcolor") == 0 ||\r
5244     strcmp(line, "rulecolor") == 0 ||\r
5245     strcmp(line, "figurecolor") == 0 ||\r
5246     strcmp(line, "reversevideo") == 0 ||\r
5247     strcmp(line, "button") == 0 ||\r
5248     strcmp(line, "mark") == 0 ||      \r
5249     strcmp(line, "viewrule") == 0 ||\r
5250     strcmp(line, "viewtext") == 0 ||\r
5251     strcmp(line, "insertimage") == 0) { */\r
5252 \r
5253 /* made common to save string space */\r
5254 \r
5255 void dontunderline (void)\r
5256 {\r
5257 //  showline(" ERROR: don't understand ", 1);\r
5258 //  showline(line, 1);\r
5259   sprintf(logline, " ERROR: don't understand: %s", line);\r
5260   showline(logline, 1);\r
5261 }\r
5262 \r
5263 /* name => buffer convert \ to / and change : to / and so on */\r
5264 \r
5265 void platformindependent (char *buffer, char *name) { /* 96/Mar/3 */\r
5266   char *s;\r
5267   strcpy(buffer, name);\r
5268 /*  avoid trouble with file names that contain spaces - truncate 'em! */\r
5269   if ((s = strchr(buffer, ' ')) != NULL) *s = '\0';\r
5270 /*  if ((s = strchr(buffer, ':')) != NULL) { */\r
5271   if ((s = strchr(buffer, ':')) != NULL &&\r
5272     *(s+1) != '\\' && *(s+1) != '/') {      /* 98/Jun/30 */\r
5273     *s = '/';\r
5274     memmove(buffer+1, buffer, strlen(buffer)+1);\r
5275     *buffer = '/';\r
5276   }\r
5277 /*  which is not really much use unless it is a relative file name ... */\r
5278 /*  while ((s = strchr(buffer, '\\')) != NULL) *s = '/'; */\r
5279   s = buffer;           /* now convert \ to / */\r
5280   while ((s = strchr(s, '\\')) != NULL) *s = '/';\r
5281 }\r
5282 \r
5283 /* clean up hyper-text mark name for PostScript Distiller 95/Feb/25 */\r
5284 \r
5285 /* Remove characters from name to make it valid PS name */\r
5286 /* Valid name may not contain white space or delimiters (pgs 30, 27 PS bible) */\r
5287 /* White space is null (0), tab (9), linefeed (10), formfeed (12), */\r
5288 /* return (13), and space (32) */\r
5289 /* Delimiters are () <> [] {} / % */\r
5290 /* Note: some question about allowing \ here, since in a *string* */\r
5291 /* backslash is used as an escape - so if name converted to string ... */\r
5292 \r
5293 /* Implementation limit on name length is 127 (Appendix B.1 in PS reference) */\r
5294 /* Implementation limit on file name length is 100 */\r
5295 \r
5296 /* #define MAXPSNAME 32 */  /* old limit */\r
5297 #define MAXPSNAME 63  /* 98/Jul/16 */\r
5298 \r
5299 /* This removes punctuation also . , : ; ! ? etc  NOT ANYMORE! 97/Feb/23 */\r
5300 /* Removes white space and delimiters - limits to MAXPSNAME char */\r
5301 /* NOTE: must use cleanupname *both* in mark: and button: */\r
5302 /* and URL calls with named destinations 97/Feb/23 ! */\r
5303 \r
5304 /* what if the string is quoted ? */ /* \b is not strictly forbidden */\r
5305 \r
5306 /* what about #?  not allowed in PDF name. but we want to pass it here? */\r
5307 \r
5308 /* char *badcharinname=" \t\n\r\f()<>[]{}/%"; */\r
5309 char *badcharinname=" \b\t\n\f\r()<>[]{}/%";\r
5310 \r
5311 void cleanupname (char *name)\r
5312 {\r
5313   char *s;\r
5314 #ifdef DEBUGCLEANUP\r
5315   if (traceflag)\r
5316   {\r
5317     sprintf(logline, " CLEANUPNAME: %s", name);     /* debugging */\r
5318     showline(logline, 0);\r
5319   }\r
5320 #endif\r
5321   if (*name == '\0')\r
5322   {\r
5323     showline(" ERROR: empty mark or button", 1);\r
5324   }\r
5325   s = name;\r
5326   while ((s = strpbrk(s, badcharinname)) != NULL)\r
5327     strcpy(s, s+1);\r
5328   if (strlen(name) > MAXPSNAME) *(name+MAXPSNAME) = '\0'; /* 96/Aug/12 */\r
5329 #ifdef DEBUGCLEANUP\r
5330   if (traceflag)\r
5331   {\r
5332     sprintf(logline, " CLEANEXIT: %s", name);   /* debugging */\r
5333     showline(logline, 0);\r
5334   }\r
5335 #endif\r
5336   if (*name == '\0') showline(" ERROR: empty mark or button", 1);\r
5337 }\r
5338 \r
5339 /* support for old textcolor / rulecolor specials */\r
5340 \r
5341 int oldcolor (FILE *output, FILE  *input)\r
5342 {\r
5343   char *s;\r
5344   int n;\r
5345 /*  old text color support */\r
5346   if (strcmp(line, "textcolor") == 0) {\r
5347     (void) scan_special (input, line, MAXLINE);\r
5348     if (traceflag) {\r
5349       sprintf(logline, " %s ", line);\r
5350       showline(logline, 0);\r
5351     }\r
5352     if (!bKeepBlack) {\r
5353       if (strstr(line, "revert") != NULL) {\r
5354         textred = 0.0; textgreen = 0.0; textblue = 0.0;\r
5355 //        fputs("\nblack\n", output);\r
5356         PSputs("\nblack\n", output);\r
5357         bTextColor = 0;\r
5358       }\r
5359       else if (sscanf(line, "%lg %lg %lg",\r
5360             &textred, &textgreen, &textblue) == 3) {\r
5361 /*        see whether floating point or not */\r
5362         if ((s = strchr(line, '.')) == NULL || *(s+1) < '0') {\r
5363           textred = textred / 255.0;\r
5364           textgreen = textgreen / 255.0;\r
5365           textblue = textblue / 255.0;\r
5366         }\r
5367         if (textred == 0.0 && textgreen == 0.0 && textblue == 0.0) {\r
5368 //          fputs("\nblack\n", output);\r
5369           PSputs("\nblack\n", output);\r
5370           bTextColor = 0;\r
5371         }   /* treat 0 0 0 same as revert ? */\r
5372         else {\r
5373           sprintf(logline, "\n%lg %lg %lg rgb\n",\r
5374               textred, textgreen, textblue);\r
5375           PSputs(logline, output);\r
5376           bTextColor = 1;\r
5377         }\r
5378       }\r
5379       else {\r
5380         dontunderline();\r
5381         return 1;\r
5382       }\r
5383 //      fprintf(output, "\n%lg %lg %lg setrgbcolor\n",\r
5384     }\r
5385     return 1;\r
5386   }\r
5387   /*  old rule color support */\r
5388   else if (strcmp(line, "rulecolor") == 0) {\r
5389     (void) scan_special (input, line, MAXLINE);\r
5390 #ifdef DEBUGTIFF\r
5391     if (traceflag) {\r
5392       sprintf(logline, " %s ", line);\r
5393       showline(logline, 0);\r
5394     }\r
5395 #endif\r
5396     if (!bKeepBlack) {\r
5397       if (strstr(line, "revert") != NULL) {\r
5398         rulered = 0.0; rulegreen = 0.0; ruleblue = 0.0;\r
5399         bRuleColor = 0;\r
5400       }\r
5401       else if (sscanf(line, "%lg %lg %lg", &rulered, &rulegreen, &ruleblue) == 3) {\r
5402 /* see whether floating point or not */\r
5403         if ((s = strchr(line, '.')) == NULL || *(s+1) < '0') {\r
5404           rulered = rulered / 255.0;\r
5405           rulegreen = rulegreen / 255.0;\r
5406           ruleblue = ruleblue / 255.0;\r
5407         }\r
5408         if (rulered == 0.0 && rulegreen == 0.0 && ruleblue == 0.0)\r
5409           bRuleColor = 0;\r
5410         else bRuleColor = 1; \r
5411       }\r
5412       else {\r
5413         dontunderline();\r
5414         return 1;\r
5415       }\r
5416     }\r
5417     return 1;\r
5418   }\r
5419 /*  old figurecolor support */\r
5420   else if (strcmp(line, "figurecolor") == 0) {\r
5421     (void) scan_special (input, line, MAXLINE);\r
5422 #ifdef DEBUGTIFF\r
5423     if (traceflag) {\r
5424       sprintf(logline, " %s ", line);\r
5425       showline(logline, 0);\r
5426     }\r
5427 #endif\r
5428     if (!bKeepBlack) {\r
5429       if (strstr(line, "revert") != NULL) {\r
5430         figurered = 0.0; figuregreen = 0.0; figureblue = 0.0;\r
5431         backred = 1.0; backgreen = 1.0; backblue = 1.0;\r
5432         bFigureColor = 0;\r
5433       }\r
5434       else if ((n = sscanf(line, "%lg %lg %lg %lg %lg %lg",\r
5435                &figurered, &figuregreen, &figureblue,\r
5436                &backred, &backgreen, &backblue)) >= 3) {\r
5437         bFigureColor = 1;\r
5438 /* see whether floating point or not */\r
5439         if ((s = strchr(line, '.')) == NULL || *(s+1) < '0') {\r
5440           figurered = figurered / 255.0;\r
5441           figuregreen = figuregreen / 255.0;\r
5442           figureblue = figureblue / 255.0;\r
5443           if (n == 6) {\r
5444             backred = backred / 255.0;\r
5445             backgreen = backgreen / 255.0;\r
5446             backblue = backblue / 255.0;\r
5447           }\r
5448         }\r
5449         if (n < 6) {      /* default background color */\r
5450           backred = 1.0; backgreen = 1.0; backblue = 1.0;\r
5451         }\r
5452 \r
5453         if (figurered == 0.0 && figuregreen == 0.0 && figureblue == 0.0 \r
5454           && backred == 1.0 && backgreen == 1.0 && backblue == 1.0) \r
5455           bFigureColor = 0; \r
5456         else bFigureColor = 1;\r
5457       }       /* end of three or more numbers found case */\r
5458       else {\r
5459         dontunderline();\r
5460         return 1;\r
5461       }\r
5462     }\r
5463     return 1;\r
5464   }\r
5465 /*  old reverse video support */\r
5466   else if (strcmp(line, "reversevideo") == 0) {\r
5467     (void) scan_special (input, line, MAXLINE);\r
5468 #ifdef DEBUGTIFF\r
5469     if (traceflag) {\r
5470       sprintf(logline, " %s ", line);\r
5471       showline(logline, 0);\r
5472     }\r
5473 #endif\r
5474     if (!bKeepBlack) {\r
5475       if (strstr(line, "on") != NULL) bReverseVideo = 1;\r
5476       else if (strstr(line, "off") != NULL) bReverseVideo = 0;\r
5477       else if (strstr(line, "toggle") != NULL)\r
5478       bReverseVideo = ~bReverseVideo;\r
5479 /*        ignore reversevideo for the moment ??? */\r
5480       if (bReverseVideo) {\r
5481 //        fputs("{1 exch sub} settransfer\n", output);\r
5482         PSputs("{1 exch sub} settransfer\n", output);\r
5483       }\r
5484       else {\r
5485 //        fputs("{} settransfer\n", output);\r
5486         PSputs("{} settransfer\n", output);\r
5487       }\r
5488     }\r
5489     return 1;\r
5490   }\r
5491   else dontunderline();\r
5492   return 0;\r
5493 }\r
5494 \r
5495 /* new to allow quoted file names with spaces 98/Jul/9 */\r
5496 \r
5497 char *scaninsert(char *line, char *filename)\r
5498 {\r
5499   char *s = line;\r
5500   char *t = filename;\r
5501 \r
5502   *filename = '\0';\r
5503 \r
5504   while (*s <= ' ' && *s != '\0') s++;  /* step over white space */\r
5505 \r
5506   if (*s == '\0') return 0;\r
5507 \r
5508   if (*s == '\"') {     /* is it quoted file name ? */\r
5509     s++;          /* step over initial " */\r
5510     while (*s != '\"' && *s != '\0') *t++ = *s++;\r
5511     if (*s != '\0') s++;          /* step over final " */\r
5512   }\r
5513   else {            /* normal file name */\r
5514     while (*s > ' ' && *s != '\0') *t++ = *s++;\r
5515   }\r
5516   *t = '\0';\r
5517   if (*s <= ' ' && *s != '\0') s++; /* step over white space after name */\r
5518 /*  special hack to convert ## to # */\r
5519   if ((t = strstr(filename, "##")) != NULL) strcpy(t, t+1);\r
5520   if (traceflag) {\r
5521     sprintf(logline, "line: %s filename: %s\n",\r
5522               line, filename);\r
5523     showline(logline, 0);\r
5524   }\r
5525   return s;\r
5526 }\r
5527 \r
5528 /* returns zero if *not* one of our DVIWindo \specials */\r
5529 \r
5530 int newspecials (FILE *output, FILE *input)\r
5531 {\r
5532   int nifd=1;\r
5533   long dheight, dwidth;\r
5534   char filename[FILENAME_MAX];\r
5535   char *sname=NULL;\r
5536   char *sfile=NULL;\r
5537   char *slaunch=NULL;\r
5538   char *sparams=NULL;\r
5539   char *spage=NULL;           /* 96/May/4 */\r
5540   char *s, *t;\r
5541   int npage=0, noffset=0;         /* 96/May/4 */\r
5542   int n, np=0;\r
5543   int URLflag=0;              /* 97/Jan/7 */\r
5544   double xscale, yscale;\r
5545 \r
5546 #ifdef DEBUGTIFF\r
5547   if (traceflag)\r
5548   {\r
5549     sprintf(logline, " %s:", line);\r
5550     showline(logline, 0);\r
5551   }\r
5552 #endif\r
5553 \r
5554 /*  insert TIFF or BMP image */\r
5555   if (strcmp(line, "insertimage") == 0)\r
5556   {\r
5557 /*    (void) scan_special (input, line, MAXLINE); */\r
5558     (void) scan_special_raw (input, line, MAXLINE);\r
5559 #ifdef DEBUGTIFF\r
5560     if (traceflag)\r
5561     {\r
5562       sprintf(logline, " %s ", line);\r
5563       showline(logline, 0);\r
5564     }\r
5565 #endif\r
5566     nifd = 1;         /* n-th (sub-)image in TIFF file */\r
5567     dwidth = dheight = 0;   /* NEW - use all info from file */\r
5568     xscale = yscale = 0.0;    /* 99/July/2 */\r
5569 /*    if (sscanf(line, "%s %ld %ld %d", filename, &dwidth, &dheight, &nifd) */\r
5570     s = scaninsert(line, filename);\r
5571     if ((t = strstr(s, "scaled")) == NULL)\r
5572     {\r
5573       sscanf(s, "%ld %ld %d", &dwidth, &dheight, &nifd);  /* normal */\r
5574     }\r
5575     else {  /* new case 99/July/2 */\r
5576       sscanf(t+7, "%lg %lg", &xscale, &yscale);\r
5577       if (xscale > 33.33) xscale = xscale / 1000.0;\r
5578       if (yscale > 33.33) yscale = yscale / 1000.0;\r
5579       if (xscale != 0.0 && yscale == 0.0) yscale = xscale;\r
5580       if (xscale == 0.0) xscale = 1.0;\r
5581       if (yscale == 0.0) yscale = 1.0;\r
5582     }\r
5583     if (*filename != '\0') {  /* need at least file name */\r
5584 //      clock_t sclock, eclock;\r
5585 //      sclock = clock();\r
5586       hptagflag = 0;\r
5587       showtiffhere(output, filename, dwidth, dheight, xscale, yscale, nifd);\r
5588 //      eclock = clock();\r
5589 //      sprintf(logline, " TIFF %lg sec\n", (double) (eclock - sclock) / CLOCKS_PER_SEC);\r
5590 //      showline(logline, 0); // debugging only\r
5591     }\r
5592     else dontunderline();\r
5593     return 1;\r
5594   }\r
5595 \r
5596 /*  old textcolor, rulecolor \specials{...}s */\r
5597   else if (strstr(line, "color") != NULL ||\r
5598        strstr(line, "video") != NULL)\r
5599     return oldcolor(output, input);\r
5600 \r
5601 /*  mark: name --- mark: "<File Open>" */ /* turn into named destination */\r
5602   else if (strcmp(line, "mark") == 0) {\r
5603     if (bPDFmarks == 0) {\r
5604       flush_special(input);\r
5605       return 1;   /* we recognize it, but ignore it */\r
5606     }\r
5607 /*    (void) scan_special (input, line, MAXLINE);  */\r
5608     (void) scan_special_raw (input, line, MAXLINE); /* fix 97/Nov/11 */\r
5609     if (traceflag) {\r
5610       sprintf(logline, " %s ", line);\r
5611       showline(logline, 0);\r
5612     }\r
5613 /*    deal with <FOO BAR> style --- flush all < and > and ' ' in string */\r
5614     if (usealtGoToR == 0)\r
5615       cleanupname(line);    /* should only contain mark name */\r
5616                   /* and nothing after the mark */\r
5617 //    putc('\n', output);   /* ??? */\r
5618     PSputc('\n', output);   /* ??? */\r
5619     if (*line < ' ') {\r
5620       showline(" ERROR: empty destination %s ", 1);\r
5621       showline(line, 1);\r
5622     }\r
5623 /*    need alternate form of /Dest ? */\r
5624 /*    fprintf(stdout, "[ /Dest /%s\n", line); */\r
5625     sprintf(logline, "[ /Dest /%s\n", line);\r
5626     PSputs(logline, output);\r
5627 /*    need to find current position in *default* user space */\r
5628 /*    move up 20 point, ignore x component --- i.e. keep the old x (null) */\r
5629 /*    keep original zoom (null) */ /* 20 point is arbitrary */\r
5630 //    fputs(\r
5631     PSputs(\r
5632 "  /View [ /XYZ gsave revscl currentpoint grestore 20 add exch pop null exch null]\n",\r
5633         output);  /* revscl ? */\r
5634 //    fputs("/DEST pdfmark\n", output);\r
5635     PSputs("/DEST pdfmark\n", output);\r
5636     return 1;\r
5637   }\r
5638 \r
5639 /*  button: <width> <height> name --- button: 1138360 433848 "<DVIfile>" */\r
5640 /*  we are ignoring for the moment file: ... and launch: ... */\r
5641   else if (strcmp(line, "button") == 0) {\r
5642     if (bPDFmarks == 0) {\r
5643       flush_special(input);\r
5644       return 1;   /* we recognize it, but ignore it */\r
5645     }\r
5646 /*    (void) scan_special (input, line, MAXLINE); */\r
5647     (void) scan_special_raw (input, line, MAXLINE); \r
5648     if (traceflag) {\r
5649       sprintf(logline, " %s ", line);\r
5650       showline(logline, 0);\r
5651     }\r
5652     if (sscanf(line, "%ld %ld%n", &dwidth, &dheight, &n) < 2) {\r
5653       showline(" ERROR: button ", 1); /* error output */\r
5654       showline(line, 1);\r
5655       flush_special(input);\r
5656       return 1;   /* it does not have required width and height ! */\r
5657     }\r
5658 /*    if (strstr(line, "launch:") != NULL) {\r
5659       flush_special(input);\r
5660       return 1;\r
5661     } */\r
5662     sname = line + n;         /* now after width and height */\r
5663     while (*sname == ' ') sname++;    /* step over white space */\r
5664 /*    catch case where no mark given, only file: , launch: or page: ... */\r
5665 /*    if ((strncmp(sname, "file:", 5) == 0)) sname = NULL; */\r
5666 /*    if ((strncmp(sname, "launch:", 7) == 0)) sname = NULL; */\r
5667 /*    if (strncmp(sname, "file:", 5) == 0 || */ /* avoid file://... */\r
5668     if ((strncmp(sname, "file:", 5) == 0 && *(sname+5) != '/') ||\r
5669       strncmp(sname, "launch:", 7) == 0 ||\r
5670       strncmp(sname, "execute:", 8) == 0 ||\r
5671       strncmp(sname, "page:", 5) == 0) sname = NULL;\r
5672 /*    check whether page number is given 96/May/12 */\r
5673     if ((spage = strstr(line, "page:")) != NULL) {\r
5674       noffset = 0;\r
5675       npage = 0;\r
5676       if (sscanf(spage+5, "%d+%d", &npage, &noffset) < 2) {\r
5677         if (sscanf(spage+5, "%d", &npage) < 1) {\r
5678           sprintf(logline, " ERROR: %s ", spage); /* error output */\r
5679           showline(logline, 1);\r
5680         }\r
5681       }\r
5682 /*      if (traceflag)  printf("npage %d noffset %d spage-line %d\n",\r
5683            npage, noffset, spage-line); */\r
5684     }\r
5685 /*    check whether file: given */\r
5686 /*    if ((sfile = strstr(line, "file:")) != NULL) { */ /* avoid file:// */\r
5687     if ((sfile = strstr(line, "file:")) != NULL && *(sfile+5) != '/') {\r
5688       sfile = sfile+5;\r
5689       while (*sfile == ' ') sfile++;\r
5690 /*      if (traceflag) printf("sfile-line %d\n", sfile-line); */\r
5691       if (sscanf(sfile, "-p=%d%n", &np, &n) == 1) { /* 98/Dec/8 */\r
5692         spage = sfile+3;\r
5693 /*        what if npage has already been set ? */\r
5694         npage = np;\r
5695         sfile += n;\r
5696         while (*sfile == ' ') sfile++;  \r
5697 /*        if (traceflag)\r
5698           printf("npage %d sfile-line %d\n", npage, sfile-line); */\r
5699       }\r
5700     }\r
5701 /*    check whether launch: given */\r
5702     if ((slaunch = strstr(line, "launch:")) != NULL) {\r
5703       slaunch = slaunch+7;\r
5704       while (*slaunch == ' ') slaunch++;\r
5705     }\r
5706     if (sfile != NULL) slaunch = NULL;    /* can do only one ??? */\r
5707 //    putc('\n', output);   /* ??? */\r
5708     PSputc('\n', output);   /* ??? */\r
5709 //    fprintf(output,\r
5710     sprintf(logline,\r
5711         "[ /Rect [currentpoint 2 copy exch %ld add exch %ld sub]\n",\r
5712         dwidth, dheight);\r
5713     PSputs(logline, output);\r
5714 /*    Note: default is /Action /GoTo */\r
5715     if (sname != NULL) {    /* was a named destination given ? */\r
5716       if ((s = strchr(sname, ',')) != NULL) *s = '\0';\r
5717 /*      should we make a new case for this http: action: PDF: ? */\r
5718 /*      special case `named destination' http:// ... */\r
5719 /*      This form of URL link supported under Acrobat 2.1 and later */\r
5720 /*      use http://www.adobe.com/test.pdf#name for named destination */\r
5721       if (strncmp(sname, "http:", 5) == 0 ||\r
5722         strncmp(sname, "ftp:", 4) == 0 ||\r
5723         strncmp(sname, "news:", 5) == 0 ||\r
5724         strncmp(sname, "mailto:", 7) == 0 ||\r
5725 /*        strncmp(sname, "file://localhost", 16) == 0 || */\r
5726 /*        strncmp(sname, "file:///|c/...", 16) == 0 || */\r
5727         strncmp(sname, "file://", 7) == 0 ||\r
5728         strncmp(sname, "gopher:", 7) == 0\r
5729          ) {  /* 1996/July/4 */\r
5730 /*  Now deal with *relative* URL given as http: pdf_from.pdf e.g. 97/May/3 */\r
5731 /*  Assumes base URL set via \special{PDF: base http://www.YandY.com}% */\r
5732         if ((s = strchr(sname, ':')) != NULL && *(s+1) == ' ') {\r
5733           sname = s+1;\r
5734           while (*sname == ' ') sname++;\r
5735         }\r
5736 /*        TeX changes # => ## so change back ## => # 97/Jan/8 */\r
5737         if ((s = strstr(sname, "##")) != NULL) strcpy(s, s+1);\r
5738         if ((s = strchr(sname, '#')) != NULL) { /* 97/Feb/23 */\r
5739           if (usealtGoToR == 0)\r
5740             cleanupname(s+1); /* clean up named destination */\r
5741         }\r
5742         sprintf(logline, "  /Action << /Subtype /URI /URI (%s) >>\n",\r
5743             sname);\r
5744         PSputs(logline, output);\r
5745       }\r
5746       else {          /* not a URL type of thing */\r
5747 /*  terminate the mark name - in case file: after - 97/Apr/23 */\r
5748 /*  but avoid truncating a destination that happens to include a : */\r
5749         if ((s = strchr(sname, ':')) != NULL) {\r
5750           while (s > sname && *s > ' ') s--;\r
5751           if (s > sname)      /* fix 97/Nov/11 */\r
5752             *s = '\0';      /* terminate the mark name */\r
5753         }\r
5754         if (usealtGoToR == 0)\r
5755           cleanupname(sname);   /* clean up the destination */\r
5756         if (*sname < ' ') {\r
5757           sprintf(logline, " ERROR: empty destination %s ", sname);\r
5758           showline(logline, 1);\r
5759         }\r
5760 /*        fprintf(stdout, "  /Dest /%s\n", sname); */\r
5761         if (! usealtGoToR) {\r
5762           sprintf(logline, "  /Dest /%s\n", sname);\r
5763           PSputs(logline, output);\r
5764         }\r
5765       }\r
5766     } /* end of named destination given */\r
5767 /*    97/Jan/7 Acrobat 3.0 wants page number in GoToR ? 97/Jan/7 */\r
5768     if (sfile != NULL && spage == NULL) {\r
5769       npage = 1; noffset = 0; /* go to page 1 as default */\r
5770       spage = sfile;      /* pretend there was a number */\r
5771     }\r
5772     if (spage != NULL) {    /* was a page number given ? 96/May/12 */\r
5773       if (noffset != 0) npage += noffset;\r
5774 /*      fprintf(output, "  /Page %d\n", npage + nPDFoffset); */\r
5775       sprintf(logline, "  /Page %d\n", npage);\r
5776       PSputs(logline, output);\r
5777 //      fputs("  /View [ /XYZ -4 PageHeight 4 add null]\n", output);\r
5778       PSputs("  /View [ /XYZ -4 PageHeight 4 add null]\n", output);\r
5779     }\r
5780 /*    case where a file or URL is specified */\r
5781     if (sfile != NULL) {\r
5782       URLflag = 0;\r
5783 /*      check whether the `file' specified is a URL */\r
5784       if (strncmp(sfile, "http:", 5) == 0 ||\r
5785         strncmp(sfile, "ftp:", 4) == 0 ||\r
5786         strncmp(sfile, "news:", 5) == 0 ||\r
5787         strncmp(sfile, "mailto:", 7) == 0 ||\r
5788 /*        strncmp(sfile, "file://localhost", 16) == 0 || */\r
5789 /*        strncmp(sfile, "file:///|c/...", 16) == 0 || */\r
5790         strncmp(sfile, "file://", 7) == 0 ||\r
5791         strncmp(sfile, "gopher:", 7) == 0\r
5792          ) URLflag=1; /* treat URL style things different 97/Jan/7 */\r
5793       if (usealtGoToR == 0) {     /* for now */\r
5794 //        fputs("  /Action /GoToR\n", output);\r
5795         PSputs("  /Action /GoToR\n", output);\r
5796         if ((s = strchr(sfile, ',')) != NULL) *s = '\0';  /* 96/May/4 */\r
5797         if (URLflag == 0) {   /* don't mess with extension if URL ? */ \r
5798 /*          remove extension if any (typically .dvi) use .pdf instead */\r
5799 /*          be  careful about ../foo if there is no extension 97/Jan/7 */\r
5800           if ((s = strrchr(sfile, '.')) != NULL &&\r
5801             ((t = strrchr(sfile, '/')) == NULL || s > t) &&\r
5802             ((t = strrchr(sfile, '\\')) == NULL || s > t))\r
5803             *s = '\0';\r
5804           strcat(sfile, ".pdf");  /* default extension in PS output */\r
5805         } /* end of if URLflag == 0 */\r
5806 /*        massage into Acrobat `platform independent' format */\r
5807         platformindependent (filename, sfile);  /* reuse filename */\r
5808         sprintf(logline, "  /File (%s)\n", filename);\r
5809         PSputs(logline, output);\r
5810 //        fprintf(output, "  /DosFile (%s)\n", sfile); \r
5811         sprintf(logline, "  /DOSFile (%s)\n", sfile); /* 98/Jun/20 */\r
5812         PSputs(logline, output);\r
5813       }\r
5814       else {  /* use alternative format */\r
5815         sprintf(logline, " /Action << /S /GoToR /D (%s) /F (%s) >>/n",\r
5816             sname, sfile);  /* ??? 98/Jun/30 */\r
5817         PSputs(logline, output);\r
5818       }\r
5819     }\r
5820     if (slaunch != NULL) {\r
5821       if ((s = strchr(slaunch, ',')) != NULL) *s = '\0';\r
5822 //      fputs("  /Action /Launch\n", output);\r
5823       PSputs("  /Action /Launch\n", output);\r
5824 /*      massage into Acrobat `platform independent' format */\r
5825       platformindependent (filename, slaunch);\r
5826 /*      do special things for Windows call ... */\r
5827       sprintf(logline, "  /File (%s)\n", filename);\r
5828       PSputs(logline, output);\r
5829       if ((s = strchr(slaunch, ' ')) != NULL) {\r
5830         *s = '\0';\r
5831         sparams = s+1;\r
5832       }\r
5833 /*      Acrobat Reader uses Windows ShellExecute(...) */\r
5834       sprintf(logline, "  /WinFile (%s)\n", slaunch);\r
5835       PSputs(logline, output);\r
5836       if (sparams != NULL) {\r
5837         sprintf(logline, "  /Params (%s)\n", sparams);\r
5838         PSputs(logline, output);\r
5839       }\r
5840 /*      optional key /Dir (current directory) */\r
5841 /*      optional key /Op  (open or print) */\r
5842     }\r
5843 \r
5844 /*    Default border is [0 0 1] - we want it to be invisible instead */\r
5845 //    fputs("  /Border [ 0 0 0]\n", output);\r
5846     PSputs("  /Border [ 0 0 0]\n", output);\r
5847 //    fputs("  /Subtype /Link\n", output);\r
5848     PSputs("  /Subtype /Link\n", output);\r
5849 //    fputs("/ANN pdfmark\n", output);\r
5850     PSputs("/ANN pdfmark\n", output);\r
5851     return 1;\r
5852   }\r
5853   else if (strcmp(line, "viewrule") == 0 || /* 95/Mar/27 */\r
5854        strcmp(line, "viewtext") == 0) { /* 95/Mar/27 */\r
5855      flush_special(input);\r
5856      return 1;    /* we recognize it, but ignore it */\r
5857   }\r
5858 #ifdef DEBUGTIFF\r
5859   else if (traceflag) showline(line, 1);\r
5860 #endif\r
5861   return 0;       /* not a DVIWindo special */\r
5862 }\r
5863 \r
5864 #endif\r
5865 \r
5866 /* proper support for figurecolor \special / bilevel images 1994/March/14 */\r
5867 \r
5868 /* \special{tiff:/mount/mktpub_d1/users/temp_jobs/59625100nl/procroms.tif\r
5869    lib=control.glb xmag=1 ymag=1 hleft vhigh  bclip=0.000000 lclip=0.000000\r
5870    rclip=0.000000 tclip=0.000000 nostrip */\r
5871 /* New stuff for HPTAG */ /* 95/Oct/12 */\r
5872 \r
5873 int dohptag (FILE *output, FILE *input)\r
5874 {\r
5875 /*  double bclip=0, lclip=0, rclip=0, tclip=0; */\r
5876 /*  int hleft=1, hright=0, vhigh=1, vlow=0; */\r
5877 /*  double xmag=1, ymag=1; */\r
5878 /*  int nostrip=1; */\r
5879   char *s, *t;\r
5880   char filename[FILENAME_MAX];\r
5881 \r
5882   (void) scan_special (input, line, MAXLINE);\r
5883   if ((s = strchr(line, ' ')) != NULL) *s = '\0';\r
5884   if ((t = strrchr(line, '/')) != NULL) strcpy(filename, t+1);\r
5885   else if (strlen(line) < sizeof(filename)) strcpy(filename, line);\r
5886   else return 0;              /* failure */\r
5887 /*  now analyze the rest of the line starting at s+1 */\r
5888 /*  showtiffhere(output, filename, dwidth, dheight, 0, 0, nifd); */\r
5889   hptagflag = 1;\r
5890   BMPflag = 0;\r
5891   showtiffhere(output, filename, 0, 0, 0, 0, 1);\r
5892   return 1;               /* success */\r
5893 }\r
5894 \r
5895 /* for setting hyper-text buttons we want the *real* underlying PS */\r
5896 /* (not what we would have seen had mag = 1000 */\r
5897 /* hence use revscl, *not* revsclx */\r
5898 \r
5899 /* #pragma optimize ("lge", on) */\r
5900 \r
5901 /* END OF EXPERIMENT */\r
5902 \r
5903 /* int WINAPI MulDiv(int nNumber, int nNumerator, int nDenominator); */\r