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
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
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
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
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
31 /* Also, code for some other DVIWindo \specials */
\r
33 #include "dvipsone.h"
\r
34 #include "dvispeci.h"
\r
36 #define DEBUGTIFF /* to get in extra tracing code */
\r
38 /* #define DEBUGBMP */
\r
40 /* #define DEBUGLZWENCODE */
\r
42 /* #define DEBUGRUNLENGTH */
\r
44 /* #define DEBUGCLEANUP */
\r
48 #define LZWCOMPRESSION
\r
50 #define MAXCOLUMNHEX 72
\r
52 #define MAXCOLUMNASCII 75
\r
56 /* constants for LZW compression/decompression tables */
\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
65 int bRunLengthFlag; /* Use RunLengthDecode filter 96/Dec/24 */
\r
66 #ifdef LZWCOMPRESSION
\r
67 int bLZWFlag; /* Use LZWDecode filter 96/Dec/30 */
\r
69 /* can have either of the above set, or none, but not both */
\r
72 unsigned char *StripData; /* address of Strip Buffer */
\r
74 unsigned int StripDataLen; /* length of Strip Buffer */
\r
76 long InStripLen; /* length of Strip in file 96/Nov/17 */
\r
80 char infilename[FILENAME_MAX] = "";
\r
82 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
84 /* using definitions in dvispeci.h */
\r
86 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
88 /* #define MAXIMAGE 4096 */ /* maximum rows & columns - sanity check */
\r
90 #define MAXIMAGE 65536 /* maximum rows & columns - sanity check */
\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
105 /* For Windows NT could declare USESHORTINT since 16 bit quantities */
\r
107 /* #define USESHORTINT */
\r
110 unsigned short int *Palette = NULL; /* pointer to palette */
\r
112 unsigned int *Palette = NULL; /* pointer to palette */
\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
121 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
123 /* set to 0.0 0.0 0.0 at top of page ? */
\r
127 double textred=0.0; /* color of text */
\r
128 double textgreen=0.0;
\r
129 double textblue=0.0;
\r
133 double rulered=0.0; /* color of rules */
\r
134 double rulegreen=0.0;
\r
135 double ruleblue=0.0;
\r
137 int bFigureColor=0; /* figure color has been specified */
\r
139 double figurered=0.0; /* foreground of figure */
\r
140 double figuregreen=0.0;
\r
141 double figureblue=0.0;
\r
143 double backred=1.0; /* background of figure */
\r
144 double backgreen=1.0;
\r
145 double backblue=1.0;
\r
147 int bReverseVideo=0;
\r
149 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
151 /* Some code imported from DVIWindo winspeci.c */
\r
153 /* Stuff for reading simple uncompressed TIFF files (& PackBits compressed) */
\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
160 //#pragma optimize ("lge", off)
\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
170 static unsigned int ureadtwo(FILE *input)
\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
178 return ((c << 8) | d);
\r
181 static unsigned long ureadfour(FILE *input)
\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
191 return ((((((c << 8) | d) << 8) | e) << 8) | f);
\r
194 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
196 /* char *typename[6] = {"", "BYTE ", "ASCII", "SHORT", "LONG ", "RATIO"}; */
\r
198 int typesize[6] = {0, 1, 1, 2, 4, 8}; /* units of length/count */
\r
200 unsigned long TIFFOffset, TIFFLength;
\r
202 long PSOffset, PSLength, MetaOffset, MetaLength; /* not used ? */
\r
204 /* we are ignoring the possibility here that length > 1 and such ... */
\r
206 long indirectvalue (unsigned int type, long length, long offset, FILE *input)
\r
208 long present, val=0;
\r
210 /* UNUSED (length); */
\r
212 if (length > 1 && traceflag)
\r
214 sprintf(logline, "Length %d\n", length);
\r
215 showline(logline, 0);
\r
218 present = ftell(input); /* remember where we are */
\r
219 if (fseek(input, (long) (offset + TIFFOffset), SEEK_SET) != 0)
\r
221 sprintf(logline, " Error in seek %s\n", " to indirect value\n");
\r
222 showline(logline, 1);
\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
232 /* get value of a tag field in TIFF file */
\r
234 long extractvalue (unsigned int type, unsigned long length, long offset, FILE *input)
\r
245 return indirectvalue(type, (long) length, (long) offset, input);
\r
250 return indirectvalue(type, (long) length, (long) offset, input);
\r
255 return indirectvalue(type, (long) length, (long) offset, input);
\r
261 int skipthisimage (FILE *input, unsigned long ifdpos)
\r
265 if(fseek(input, (long) ifdpos + TIFFOffset, SEEK_SET) != 0)
\r
267 sprintf(logline, " Error in seek %s\n", " while skipping image\n");
\r
268 showline(logline, 1);
\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
274 for (j = 0; j < 12; j++)
\r
275 (void) getc(input);
\r
277 IFDPosition = ureadfour(input); /* get next IFD offset in file */
\r
278 if (IFDPosition == 0) return -1; /* no more IFDs !!! */
\r
282 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
284 /* Must have: ImageWidth, ImageLength, StripOffset, SamplesPerPixel, BitsPerSample */
\r
286 long ImageWidth; /* vital ImageWidth */
\r
287 long ImageLength; /* vital ImageLength */
\r
289 int bytes; /* total bytes per row output used ? */
\r
291 int SamplesPerPixel = 1; /* vital (may be more than 1) */
\r
292 int SamplesPerPixelX = 1; /* SamplesPerPixel-ExtraSamples */
\r
294 int BitsPerSample = 1; /* vital */
\r
296 int ExtraSamples = 0; /* new 99/May/10 */
\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
307 long StripByteCount = -1; /* first StripByteCount */
\r
308 long StripByteCountsPtr;
\r
309 int StripByteCountsType;
\r
310 int StripByteCountsLength;
\r
312 int RowsPerStrip = 0;
\r
314 int StripsPerImage; /* computed from above */
\r
316 long ColorMapPtr = 0; /* pointer to map in case of Palette Color Images */
\r
318 int PhotometricInterpretation = 1; /* default */
\r
320 int PlanarConfig=1; /* cannot handle 2 ... */
\r
322 int BitsPerPixel; /* BitsPerSample * SamplePerPixel */
\r
323 int BitsPerPixelX; /* BitsPerSample * (SamplePerPixel-ExtraSamples) */
\r
325 long InRowLength; /* number of source bytes from file */
\r
326 long InRowLengthX; /* --- after ExtraSamples removed */
\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
333 int CurrentStrip; /* for debugging purposes */
\r
335 /* NOTE: MinSampleValue and MaxSampleValue should not affect appearance */
\r
337 /* int MinSampleValue, MaxSampleValue; */ /* never used ? */
\r
339 int ResolutionUnit=2; /* 1 no dimensions, 2 per inch, 3 per cm */
\r
341 /* long xresnum, xresden; */ /* x resolution */
\r
342 /* long yresnum, yresden; */ /* y resolution */
\r
344 unsigned long xresnum, xresden; /* x resolution */ /* 95/Oct/10 */
\r
345 unsigned long yresnum, yresden; /* y resolution */ /* 95/Oct/10 */
\r
347 int hptagflag=0; /* non-zero if call from HPTAG */
\r
348 /* may need something more elaborate hleft / hright and vhigh / vlow */
\r
350 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
352 /* read the tag fields in the TIFF file, ignore ones we don't care about */
\r
354 int readfields (FILE *input, unsigned long ifdpos)
\r
356 unsigned int k, tag, type;
\r
357 unsigned long length, offset;
\r
361 if (traceflag) showline("Now reading TIFF images fields\n", 0);
\r
364 if (fseek(input, (long) ifdpos + TIFFOffset, SEEK_SET) != 0)
\r
366 sprintf(logline, " Error in seek %s\n", " while reading tags");
\r
367 showline(logline, 1);
\r
370 IFDCount = ureadtwo(input); /* How many tags in this IFD */
\r
372 ImageWidth = ImageLength = -1;
\r
373 SamplesPerPixel = BitsPerSample = 1;
\r
374 ExtraSamples = compression = 0;
\r
376 StripOffset = StripByteCount = -1;
\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
387 for (k = 0; k < IFDCount; k++)
\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
395 showline(logline, 1);
\r
399 c = getc(input); ungetc(c, input);
\r
403 sprintf(logline, " Tag: %u Type: %u (k %d c %d)\n", tag, type, k, c);
\r
404 showline(logline, 1);
\r
407 /* break; */ /* removed 98/Sep/22 */
\r
409 length = ureadfour(input); /* `length' (better named `count') */
\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
416 else if (type == TYPE_BYTE) {
\r
417 offset = getc(input);
\r
418 (void) getc(input);(void) getc(input);(void) getc(input);
\r
420 else offset = ureadfour(input); /* for ratio e.g. */
\r
422 else offset = ureadfour(input); /* value */
\r
426 ImageWidth = extractvalue(type, length, (long) offset, input);
\r
429 ImageLength = extractvalue(type, length, (long) offset, input);
\r
431 case BITSPERSAMPLE:
\r
433 (int) extractvalue(type, length, (long) offset, input);
\r
435 case EXTRASAMPLES: /* 1999/May/10 */
\r
437 (int) extractvalue(type, length, (long) offset, input);
\r
441 (unsigned int) extractvalue(type, length, (long) offset, input);
\r
445 (int) extractvalue(type, length, (long) offset, input);
\r
447 case SAMPLESPERPIXEL:
\r
449 (int) extractvalue(type, length, (long) offset, input);
\r
453 (int) extractvalue(type, length, (long) offset, input);
\r
456 StripOffsetsPtr = offset;
\r
457 StripOffsetsType = type;
\r
458 StripOffsetsLength = (int) length;
\r
459 StripOffset = extractvalue(type, length, (long) offset, input);
\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
469 (int) extractvalue(type, length, (long) offset, input);
\r
471 /* case MINSAMPLEVALUE:
\r
472 MinSampleValue = (int) extractvalue(type, length, (long) offset, input);
\r
474 /* case MAXSAMPLEVALUE:
\r
475 MaxSampleValue = (int) extractvalue(type, length, (long) offset, input);
\r
478 xresnum = indirectvalue(TYPE_LONG, 1, (long) offset, input);
\r
479 xresden = indirectvalue(TYPE_LONG, 1, (long) offset+4, input);
\r
482 yresnum = indirectvalue(TYPE_LONG, 1, (long) offset, input);
\r
483 yresden = indirectvalue(TYPE_LONG, 1, (long) offset+4, input);
\r
485 case RESOLUTIONUNIT:
\r
486 ResolutionUnit = (int) extractvalue(type, length, (long) offset, input);
\r
488 case PHOTOMETRICINTERPRETATION:
\r
489 PhotometricInterpretation =
\r
490 (int) extractvalue(type, length, (long) offset, input);
\r
494 (int) extractvalue(type, length, (long) offset, input);
\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
502 default: /* ignore unknown tags */
\r
509 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\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
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
534 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
536 /* Remember to deallocate at end */ /* Read color map from TIFF image */
\r
538 /* do we need to use unsigned short for NT ? */
\r
540 int ReadColorMap (FILE *input, long ColorMapPtr, int BitsPerSample)
\r
545 /* should make all these unsigned short int instead for NT */
\r
547 unsigned short int *PalettePtr;
\r
549 unsigned int *PalettePtr;
\r
554 unsigned short int *PaletteRed;
\r
555 unsigned short int *PaletteGreen;
\r
556 unsigned short int *PaletteBlue;
\r
558 unsigned int *PaletteRed;
\r
559 unsigned int *PaletteGreen;
\r
560 unsigned int *PaletteBlue;
\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
571 sprintf(logline, "Reading Color Map of size %d\n", n);
\r
572 showline(logline, 1);
\r
575 /* check following allocation in NT ? should we use short int ? */
\r
577 Palette = (unsigned short int *)
\r
578 malloc(nint * sizeof(unsigned short int));
\r
580 /* Palette = (unsigned int *) malloc(nint * 2); */ /* bytes */
\r
581 Palette = (unsigned int *) malloc(nint * sizeof(unsigned int));
\r
583 if (Palette == NULL)
\r
585 showline(" ERROR: Unable to allocate memory\n", 1);
\r
587 // or more serious exit(1) ???
\r
589 present = ftell(input);
\r
593 sprintf(logline, "Going to ColorMap at %ld + %lu\n",
\r
594 ColorMapPtr, TIFFOffset);
\r
595 showline(logline, 1);
\r
598 if (fseek (input, (long) ColorMapPtr + TIFFOffset, SEEK_SET) != 0)
\r
600 sprintf(logline, " Error in seek %s\n", " to ColorMap");
\r
601 showline(logline, 1);
\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
609 PaletteRed = Palette;
\r
610 PaletteGreen = PaletteRed + PaletteSize;
\r
611 PaletteBlue = PaletteGreen + PaletteSize;
\r
613 bGrayFlag = 1; // non-zero if palette is all grays
\r
614 for (k = 0; k < n; k++)
\r
616 if (PaletteRed[k] != PaletteGreen[k] ||
\r
617 PaletteGreen[k] != PaletteBlue[k])
\r
622 } // bGrayFlag presently not used
\r
624 bLinearFlag = 0; // non-zero if Palette is simply linear
\r
627 for (k = 0; k < n; k++)
\r
629 if (PaletteRed[k] != (unsigned int) (k * 255 / (n-1))) {
\r
634 } // bLinearFlag presently not used
\r
636 // bGrayFlag and bLinearFlag could be used to produce smaller output files
\r
641 PaletteRed = Palette;
\r
642 PaletteGreen = PaletteRed + PaletteSize;
\r
643 PaletteBlue = PaletteGreen + PaletteSize;
\r
644 for (k = 0; k < n; k++) {
\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
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
661 int ProcessRow (FILE *output, unsigned char *lpBuffer, long InRowLengthX,
\r
662 long BufferLength, long OutRowLength)
\r
665 printf("ProcessRow InRowLengthX %d\n", InRowLengthX); */ /* DEBUGGING */
\r
667 printf("bExpandColor %d bExpandGray %d bCompressColor %d\n",
\r
668 bExpandColor, bExpandGray, bCompressColor); */ /* DEBUGGING */
\r
670 if (traceflag) fflush(stdout); /* DEBUGGING ONLY */
\r
672 if (bExpandColor) expandcolor(lpBuffer, InRowLengthX);
\r
673 else if (bExpandGray) expandgray(lpBuffer, InRowLengthX);
\r
674 if (bCompressColor) compresscolor(lpBuffer, BufferLength);
\r
676 if (traceflag) { /* DEBUGGING */
\r
677 sprintf(logline, "ProcessRow OutRowLength %d\n", OutRowLength);
\r
678 showline(logline, 0);
\r
681 if (writearow(output, lpBuffer, OutRowLength) != 0) return -1;
\r
685 /* Throw out ExtraSamples in SamplesPerPixel */
\r
686 /* IMPORTANT NOTE: assume for the moment samples are one byte */
\r
688 int RemoveExtraSamples (unsigned char *lpBuffer, int InRowLength)
\r
690 unsigned char *s = lpBuffer;
\r
691 unsigned char *t = lpBuffer;
\r
692 int i, k, n = InRowLength / SamplesPerPixel;
\r
697 sprintf(logline, "RemoveExtraSamples InRowLength %d\n", InRowLength);
\r
698 showline(logline, 1);
\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
707 return (int) (t - lpBuffer);
\r
710 /* readflag != 0 when reading file only to get tag fields */
\r
712 int readTIFFfile (FILE *output, FILE *input,
\r
713 long dwidth, long dheight, int nifd, int readflag)
\r
715 /* int i, j, 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
724 TIFFVersion = ureadtwo(input);
\r
725 if (TIFFVersion != TIFF_VERSION)
\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
732 /* Skip to desired image (if not first in file) */
\r
734 IFDPosition = ureadfour(input); /* get first IFD offset in file */
\r
735 while (nifd-- > 1) {
\r
736 if (skipthisimage(input, IFDPosition) < 0)
\r
738 sprintf(logline, " ERROR: Subimage %d not found", nifd);
\r
739 showline(logline, 1);
\r
744 /* Now at desired image */
\r
745 (void) readfields(input, IFDPosition); /* read tag fields in TIFF file */
\r
747 IFDPosition = ureadfour(input); /* get next IFD offset in file */
\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
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
765 sprintf(logline, "Width %ld, Height %ld, BitsPerSample %d, SamplesPerPixel %d\n",
\r
766 ImageWidth, ImageLength, BitsPerSample, SamplesPerPixel);
\r
767 showline(logline, 1);
\r
774 sprintf(logline, "Compression %u PhotometricInterpretation %d\n",
\r
775 compression, PhotometricInterpretation);
\r
776 showline(logline, 1);
\r
781 if (traceflag && Predictor != 1)
\r
783 sprintf(logline, "Predictor %d\n", Predictor);
\r
784 showline(logline, 1);
\r
788 if (ExtraSamples > 0) SamplesPerPixelX = SamplesPerPixel-ExtraSamples;
\r
789 else SamplesPerPixelX = SamplesPerPixel;
\r
791 BitsPerPixel = BitsPerSample * SamplesPerPixel;
\r
792 if (ExtraSamples > 0) BitsPerPixelX = BitsPerSample * SamplesPerPixelX;
\r
793 else BitsPerPixelX = BitsPerPixel;
\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
799 if (RowsPerStrip > 0)
\r
800 StripsPerImage = (int) ((ImageLength + RowsPerStrip - 1) / RowsPerStrip);
\r
801 else StripsPerImage = 1;
\r
803 if (bExpandColor) BufferLength = ImageWidth * 3;
\r
804 else if (bExpandGray) BufferLength = ImageWidth;
\r
805 else BufferLength = InRowLength;
\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
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
820 else OutRowLength = BufferLength;
\r
825 sprintf(logline, "InRowLength %ld BufferLength %ld OutRowLength %ld\n",
\r
826 InRowLength, BufferLength, OutRowLength);
\r
827 showline(logline, 1);
\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
836 InRowLength++; /* a hack */
\r
839 /* should also increase BufferLength allocation ? 95/Nov/10 */
\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
851 /* Use LZW if runlength encoding not chosen */
\r
852 if (bRunLengthFlag == 0)
\r
854 // if (compression == LZW_COMPRESSION) bLZWFlag = 1;
\r
855 // else; bLZWFlag = 1 /* otherwise use LZW */
\r
862 if (computeheader() != 0) return -1; /* noticed format not supported? */
\r
864 writepsheader(output, dwidth, dheight);
\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
871 sprintf(logline, " ERROR: Unknown compression scheme (%d)", compression);
\r
872 showline(logline, 1);
\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
881 sprintf(logline, " ERROR: Zero image size, %d %d (%s)",
\r
882 InRowLengthX, ImageLength, "readTIFFfile");
\r
883 showline(logline, 1);
\r
886 if (ImageWidth > MAXIMAGE || ImageLength > MAXIMAGE || /* bad data ? */
\r
887 ImageSize > 67108864) { /* arbitrary limits (to catch bad files) */
\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
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
900 if (fseek(input, (long) StripOffset + TIFFOffset, SEEK_SET) != 0)
\r
902 sprintf(logline, " Error in seek %s\n", " to StripOffset\n");
\r
903 showline(logline, 1);
\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
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
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
928 /* Actually go and read the file now ! */
\r
930 /* following should already be taken care of in `computeheader' */
\r
932 if (compression > TIFF_CCITT && compression != LZW_COMPRESSION &&
\r
933 compression != PACK_BITS)
\r
935 sprintf(logline, " ERROR: Unknown compression scheme (%d)", compression);
\r
936 showline(logline, 1);
\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
949 flag = 0; /* flag gets set if EOF hit */
\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
962 /* LZW needs to be done by strips, the others can be done by row */
\r
964 if (compression == LZW_COMPRESSION) DecodeLZW(output, input, lpBuffer);
\r
966 else { /* else not LZW compression */
\r
968 for (i = 0; i < (int) ImageLength; i++) { /* read image lines */
\r
970 if (compression == PACK_BITS) { /* compressed binary file */
\r
971 if (readpackbits (lpBuffer, input, (int) InRowLength) != 0) {
\r
976 else if (compression == TIFF_CCITT) { /* CCITT 1D compression */
\r
977 if (huffmanrow (lpBuffer, input, (int) ImageWidth) != 0) {
\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
986 showline("Premature EOF ", 1); /* ??? */
\r
993 sprintf(logline, "readTIFFFile InRowLength %d\n", InRowLength);
\r
994 showline(logline, 1);
\r
997 if (ExtraSamples > 0)
\r
998 (void) RemoveExtraSamples(lpBuffer, InRowLength); /* 99/May/10 */
\r
1003 sprintf(logline, "readTIFFFile OutRowLength %d BufferLength %d\n",
\r
1004 OutRowLength, BufferLength);
\r
1005 showline(logline, 1);
\r
1009 /* if (ProcessRow (output, lpBuffer, InRowLength, BufferLength, */
\r
1010 if (ProcessRow (output, lpBuffer, InRowLengthX, BufferLength,
\r
1011 OutRowLength) != 0)
\r
1013 showline("\n", 0);
\r
1014 showline("ERROR: Output error ", 1);
\r
1015 perrormod((outputfile != NULL) ? outputfile : "");
\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
1023 // Have to flush filters in reverse order
\r
1027 if (bRunLengthFlag) RUNflushfilter(output); /* 96/Dec/24 */
\r
1028 #ifdef LZWCOMPRESSION
\r
1029 else if (bLZWFlag) LZWflushfilter(output); /* 96/Dec/28 */
\r
1031 ASCIIflushfilter(output); /* 96/Dec/20 */
\r
1035 /* now finished reading */ /* maybe use far memory for lpBuffer ? */
\r
1037 if (lpBuffer != NULL) {
\r
1041 if (Palette != NULL) {
\r
1045 writepstrailer(output);
\r
1047 } /* end of readTIFFfile(...) */
\r
1049 /**********************************************************************/
\r
1051 /* following is from windef.h */
\r
1053 typedef unsigned long DWORD;
\r
1055 typedef unsigned char BYTE;
\r
1056 typedef unsigned short WORD;
\r
1057 typedef float FLOAT;
\r
1059 typedef unsigned int UINT;
\r
1061 typedef long LONG;
\r
1063 /* following is from wingdi.h */
\r
1069 #include <pshpack2.h>
\r
1070 typedef struct tagBITMAPFILEHEADER {
\r
1076 } BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
\r
1077 #include <poppack.h>
\r
1079 typedef struct tagBITMAPINFOHEADER {
\r
1085 DWORD biCompression;
\r
1086 DWORD biSizeImage;
\r
1087 LONG biXPelsPerMeter;
\r
1088 LONG biYPelsPerMeter;
\r
1090 DWORD biClrImportant;
\r
1091 } BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
\r
1093 #include <pshpack1.h>
\r
1094 typedef struct tagRGBTRIPLE {
\r
1099 #include <poppack.h>
\r
1101 typedef struct tagRGBQUAD {
\r
1107 typedef RGBQUAD FAR* LPRGBQUAD;
\r
1111 BITMAPFILEHEADER bmfh;
\r
1113 BITMAPINFOHEADER bmih;
\r
1115 /* RGBQUAD colortable[256]; */
\r
1117 int dpifrom(int res)
\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
1124 int colormaplength; /* ??? */
\r
1125 int mingrey, maxgrey; /* ??? */
\r
1126 int nColors; /* ??? */
\r
1127 long OffBits; /* ??? */
\r
1128 long ImageSize; /* ??? */
\r
1130 /* readflag is non-zero in prescan */
\r
1132 int readBMPfields (FILE *input, int readflag)
\r
1137 ImageWidth = ImageLength = -1;
\r
1138 SamplesPerPixel = BitsPerSample = 1;
\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
1150 fseek(input, 0, SEEK_END);
\r
1151 nLen = ftell(input); /* Length of file */
\r
1152 // fseek(input, 0, SEEK_SET); /* rewind */
\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
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
1164 if (traceflag && sreadflag)
\r
1166 sprintf(logline, "\nnLen %ld bfSize %ld bfOffBits %ld ",
\r
1167 nLen, bmfh.bfSize, bmfh.bfOffBits);
\r
1168 showline(logline, 1);
\r
1171 /* bmfh.bfSize file size in words ? NO */
\r
1172 /* bmfh.bfOffBits offset from end of header ? NO */
\r
1174 fread(&bmih, sizeof(bmih), 1, input); /* read bitmap info header */
\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
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
1188 BitsPerSample = 8;
\r
1189 SamplesPerPixel = 3;
\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
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
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
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
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
1223 compression = bmih.biCompression; /* save it */
\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
1232 ColorMapPtr = ftell(input); /* color map starts here */
\r
1234 colormaplength = sizeof(RGBQUAD) * nColors;
\r
1235 /* fread(&colortable, sizeof(RGBQUAD), nColors, input); */
\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
1243 if (traceflag && readflag)
\r
1245 sprintf(logline, "\nImage at %ld size %ld bytes ", OffBits, ImageSize);
\r
1246 showline(logline, 1);
\r
1252 int readBMPPalette (FILE *input, long ColorMapPtr, int BitsPerSample)
\r
1257 /* should make all these unsigned short int instead for NT */
\r
1259 #ifdef USESHORTINT
\r
1260 unsigned short int *PaletteRed;
\r
1261 unsigned short int *PaletteGreen;
\r
1262 unsigned short int *PaletteBlue;
\r
1264 unsigned int *PaletteRed;
\r
1265 unsigned int *PaletteGreen;
\r
1266 unsigned int *PaletteBlue;
\r
1269 /* need three tables each of 2 ^ BitsPerSample integers */
\r
1270 n = 1 << BitsPerSample; /* integers per table */
\r
1273 sprintf(logline, "Reading Color Map of size %d\n", n);
\r
1274 showline(logline, 1);
\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
1284 Palette = (unsigned int *) malloc(nint * sizeof(unsigned int));
\r
1286 if (Palette == NULL) {
\r
1287 showline("Unable to allocate memory\n", 1);
\r
1289 // or more serious exit(1) ???
\r
1291 PaletteRed = Palette;
\r
1292 PaletteGreen = PaletteRed + PaletteSize;
\r
1293 PaletteBlue = PaletteGreen + PaletteSize;
\r
1295 present = ftell(input);
\r
1298 sprintf(logline, "Going to ColorMap at %ld\n", ColorMapPtr);
\r
1299 showline(logline, 1);
\r
1302 if (fseek (input, (long) ColorMapPtr, SEEK_SET) != 0)
\r
1304 sprintf(logline, " Error in seek %s\n", " to ColorMap\n");
\r
1305 showline(logline, 1);
\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
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
1324 bLinearFlag = 0; /* non-zero if Palette is simply linear */
\r
1327 for (k = 0; k < n; k++) {
\r
1328 if (PaletteRed[k] != (unsigned int) (k * 255 / (n-1))) {
\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
1342 /* fseek (input, present, SEEK_SET); */
\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
1355 /* readflag != 0 when prescanning to get fields */
\r
1357 int readBMPfile (FILE *output, FILE *input,
\r
1358 long dwidth, long dheight, int readflag)
\r
1360 unsigned char *lpBuffer=NULL;
\r
1363 unsigned int nread;
\r
1365 int c, d, e=0; /* keep compiler happy */
\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
1383 sprintf(logline, "bGrayFLag %d bLinearFlag %d\n",
\r
1384 bGrayFlag, bLinearFlag);
\r
1385 showline(logline, 1);
\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
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
1399 /* ??? check this */
\r
1401 else PaletteSize = 0; /* not Palette Color */
\r
1402 if (bLinearFlag) PaletteSize = 0; /* no need to use Palette ??? */
\r
1407 "bColorImage %d bExpandColor %d bCompressColor %d PaletteSize %d\n",
\r
1408 bColorImage, bExpandColor, bCompressColor, PaletteSize);
\r
1409 showline(logline, 1);
\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
1418 /* copied pretty much from readTIFF ... */
\r
1420 SamplesPerPixelX = SamplesPerPixel;
\r
1422 BitsPerPixel = BitsPerSample * SamplesPerPixel; /* only BMP */
\r
1423 BitsPerPixelX = BitsPerPixel;
\r
1425 InRowLength = (ImageWidth * BitsPerPixel + 7) / 8; /* row length file */
\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
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
1439 else OutRowLength = BufferLength;
\r
1444 sprintf(logline, "InRowLength %ld BufferLength %ld OutRowLength %ld\n",
\r
1445 InRowLength, BufferLength, OutRowLength);
\r
1446 showline(logline, 1);
\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
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
1470 if (computeheader () != 0) return -1; /* noticed format not supported? */
\r
1472 writepsheader(output, dwidth, dheight);
\r
1474 ImageSize = (unsigned long) InRowLength * ImageLength; /* for bmp only */
\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
1483 if (ImageWidth > MAXIMAGE || ImageLength > MAXIMAGE || /* bad data ? */
\r
1484 ImageSize > 67108864) { /* arbitrary limits (to catch bad files) */
\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
1495 sprintf(logline, "Seeking to %ld\n", OffBits);
\r
1496 showline(logline, 1);
\r
1499 if (fseek(input, (long) OffBits, SEEK_SET) != 0)
\r
1501 sprintf(logline, " Error in seek %s\n", " to OffBits\n");
\r
1502 showline(logline, 1);
\r
1505 nLen = (int) ((BufferLength + 3) / 4) * 4;
\r
1506 lpBuffer = malloc(nLen);
\r
1507 if (lpBuffer == NULL)
\r
1509 sprintf(logline, " ERROR: Unable to allocate %d bytes\n", nLen);
\r
1510 showline(logline, 1);
\r
1512 // or more serious exit(1) ???
\r
1515 flag = 0; /* flag gets set if EOF hit */
\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
1528 for (i = 0; i < (int) ImageLength; i++) { /* read image lines */
\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
1537 while (s <= lpBuffer + InRowRead) {
\r
1541 sprintf(logline, " %d", c);
\r
1542 showline(logline, 1);
\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
1551 sprintf(logline, " repeat %d %d", d, e);
\r
1552 showline(logline, 1);
\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
1565 sprintf(logline, " buffered: %d,", s - lpBuffer);
\r
1566 showline(logline, 1);
\r
1570 else { /* c == 0 */
\r
1571 c = getc(input); /* pixel count */
\r
1574 sprintf(logline, " literal %d", c);
\r
1575 showline(logline, 1);
\r
1578 if (c > 2) { /* literal group */
\r
1579 for (k = 0; k < c; k++) {
\r
1582 e = d & 15; /* decompose right nibble */
\r
1583 d = d >> 4; /* decompose left nibble */
\r
1586 sprintf(logline, " %d %d", d, e);
\r
1587 showline(logline, 1);
\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
1599 n = 2 + (c+1)/2; /* bytes read */
\r
1600 if ((n % 2) != 0) { /* padded out to even bytes */
\r
1604 sprintf(logline, " discard: %d", d);
\r
1605 showline(logline, 1);
\r
1611 sprintf(logline, " buffered: %d,", s - lpBuffer);
\r
1612 showline(logline, 1);
\r
1616 else if (c == 0) {
\r
1617 if (evenflag++ == 0) s++; /* pad last nibble */
\r
1620 sprintf(logline, " EOL\n");
\r
1621 showline(logline, 1);
\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
1630 while (s < lpBuffer + InRowRead) *s++ = '\0';
\r
1631 break; /* end of row */
\r
1633 else if (c == 1) {
\r
1636 showline(" EOI\n", 0);
\r
1639 if (i != (int) ImageLength - 1) {
\r
1642 sprintf(logline, "i+1 %d ImageLength %d\n",
\r
1643 i+1, ImageLength);
\r
1644 showline(logline, 0);
\r
1647 showline(" Premature end of image\n", 1);
\r
1649 break; /* end of picture */
\r
1651 else if (c == 2) { /* rats! */
\r
1652 showline(" Skips not implemented\n", 1);
\r
1656 nread = s - lpBuffer;
\r
1658 else { /* decompress, eight bit images only so far */
\r
1660 while (s <= lpBuffer + InRowRead) {
\r
1664 sprintf(logline, " %d", c);
\r
1665 showline(logline, 0);
\r
1668 if (c > 0) { /* repeating group */
\r
1669 d = getc(input); /* pixel */
\r
1672 sprintf(logline, " repeat: %d", d);
\r
1673 showline(logline, 0);
\r
1676 /* for (k = 0; k < c; k++) *s++ = d; */
\r
1677 for (k = 0; k < c; k++) *s++ = (unsigned char) d;
\r
1680 sprintf(logline, " buffered: %d,", s - lpBuffer);
\r
1681 showline(logline, 0);
\r
1688 sprintf(logline, " buffered: %d,", s - lpBuffer);
\r
1689 showline(logline, 0);
\r
1692 c = getc(input); /* pixel count */
\r
1695 sprintf(logline, " %d", c);
\r
1696 showline(logline, 0);
\r
1699 if (c > 2) { /* literal group */
\r
1700 for (k = 0; k < c; k++) {
\r
1702 *s++ = (unsigned char) d;
\r
1705 sprintf(logline, " %d", d);
\r
1706 showline(logline, 0);
\r
1710 if ((c % 2) != 0) { /* padded out to even bytes */
\r
1714 sprintf(logline, " %d", d);
\r
1715 showline(logline, 0);
\r
1720 else if (c == 0) {
\r
1721 if (evenflag++ == 0) *s++ = '\0'; /* pad last byte */
\r
1724 sprintf(logline, " EOL\n");
\r
1725 showline(logline, 0);
\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
1734 while (s < lpBuffer + InRowRead) *s++ = '\0';
\r
1735 break; /* end of row EOL */
\r
1737 else if (c == 1) {
\r
1738 if (evenflag++ == 0) *s++ = '\0';; /* pad last byte */
\r
1740 if (traceflag) showline(" EOI\n", 0);
\r
1742 if (i != (int) ImageLength - 1) {
\r
1743 showline(" Premature end of image\n", 1);
\r
1745 break; /* end of picture EOF */
\r
1747 else if (c == 2) { /* rats! */
\r
1748 showline(" Skips not implemented\n", 1);
\r
1752 nread = s - lpBuffer;
\r
1754 /* if (nread != (unsigned int) InRowLength) */
\r
1755 if (nread != (unsigned int) InRowRead) {
\r
1759 sprintf(logline, "nread %d InRowRead %d\n", nread, InRowRead);
\r
1760 showline(logline, 1);
\r
1763 showline(" ERROR: Premature EOF\n", 1);
\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
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
1777 // Have to flush filters in reverse order
\r
1780 if (bRunLengthFlag) RUNflushfilter(output); /* 96/Dec/24 */
\r
1781 #ifdef LZWCOMPRESSION
\r
1782 else if (bLZWFlag) LZWflushfilter(output); /* 96/Dec/28 */
\r
1784 ASCIIflushfilter(output); /* 96/Dec/20 */
\r
1788 /* now finished reading */ /* maybe use far memory for lpBuffer ? */
\r
1790 if (lpBuffer != NULL) {
\r
1794 if (Palette != NULL) {
\r
1798 writepstrailer(output);
\r
1800 /* UNDER CONSTRUCTION !!! */
\r
1801 } /* end of readBMPfile(...) */
\r
1804 /**********************************************************************/
\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
1810 int readepsfhead (FILE *special)
\r
1814 PSOffset = 0; /* redundant */
\r
1815 MetaOffset = 0; /* redundant */
\r
1816 TIFFOffset = 0; /* redundant */
\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
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
1832 else return 0; /* not an EPSF file */
\r
1835 int BMPflag=0; /* non-zero while processing BMP image */
\r
1837 int readimagefilesub (FILE *output, FILE *special,
\r
1838 long dwidth, long dheight, int nifd, int readflag)
\r
1840 /* long present; */
\r
1843 TIFFOffset = 0; /* normally beginning of file */
\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
1857 if (fseek(special, TIFFOffset, SEEK_SET) != 0)
\r
1859 sprintf(logline, " Error in seek %s\n", "to TIFFOffset\n");
\r
1860 showline(logline, 1);
\r
1865 showline(" ERROR: Not a valid EPSF or TIFF file\n", 1);
\r
1868 } /* end of c > 128 (EPSF file) */
\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
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
1881 showline(" ERROR: Not a valid EPSF, TIFF or BMP file\n", 1);
\r
1882 return -1; /* not a TIFF subfile !!! */
\r
1885 /* now have decided that this is a TIFF file (or TIFF preview) or BMP */
\r
1887 (void) readBMPfile(output, special, dwidth, dheight, readflag);
\r
1889 (void) readTIFFfile(output, special, dwidth, dheight, nifd, readflag);
\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
1898 int readimagefile (FILE *output, char *filename,
\r
1899 long dwidth, long dheight, int nifd, int readflag)
\r
1901 /* char infilename[FILENAME_MAX]; */ /* make global */
\r
1903 /* long present; */
\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
1916 sprintf(logline, "\nManaged to open file %s\n", infilename);
\r
1917 showline(logline, 0);
\r
1920 flag = readimagefilesub (output, special, dwidth, dheight, nifd, readflag);
\r
1925 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\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
1932 /* Expand palette color image into full RGB color image */
\r
1933 /* Presently only set up for 8 bit palettes ... !!! */
\r
1935 void expandcolor (unsigned char *lpBuffer, long width)
\r
1938 #ifdef USESHORTINT
\r
1939 unsigned short int *PaletteRed;
\r
1940 unsigned short int *PaletteGreen;
\r
1941 unsigned short int *PaletteBlue;
\r
1943 unsigned int *PaletteRed;
\r
1944 unsigned int *PaletteGreen;
\r
1945 unsigned int *PaletteBlue;
\r
1949 unsigned int red=0, green=0, blue=0;
\r
1950 int PaletteIndex, Mask;
\r
1951 int Byte = 0, BitsLeft = 0;
\r
1954 /* if (traceflag) printf("Palette Color => Color "); */
\r
1957 if (Palette == NULL)
\r
1959 showline(" ERROR: missing palette information\n", 1);
\r
1962 PaletteRed = Palette;
\r
1963 PaletteGreen = PaletteRed + PaletteSize;
\r
1964 PaletteBlue = PaletteGreen + PaletteSize;
\r
1965 Mask = (1 << BitsPerSample) - 1;
\r
1967 /* First slide input data upwards to top of buffer area */
\r
1969 n = (int) width; /* InRowLengthX */
\r
1970 ns = (int) ImageWidth; /* samples per row */
\r
1972 /* if (BufferLength <= InRowLength) */
\r
1973 if (BufferLength <= InRowLengthX) {
\r
1974 showline(" ERROR: buffer overflow\n", 1);
\r
1978 /* possibly use InRowLengthX ? in next two places */
\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
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
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
1995 BitsLeft -= BitsPerSample;
\r
1996 /* PaletteIndex = Byte >> (BitsPerSample - BitsLeft); */
\r
1997 PaletteIndex = Byte >> BitsLeft;
\r
1998 PaletteIndex = PaletteIndex & Mask;
\r
1999 /* BitsLeft -= BitsPerSample; */
\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
2008 sprintf(logline, " ERROR: Bad Palette Index %d >= %d\n",
\r
2009 PaletteIndex, PaletteSize);
\r
2010 showline(logline, 1);
\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
2019 if (BMPflag) { /* BMP */
\r
2020 *t++ = (unsigned char) red;
\r
2021 *t++ = (unsigned char) green;
\r
2022 *t++ = (unsigned char) blue;
\r
2025 *t++ = (unsigned char) (red >> 8);
\r
2026 *t++ = (unsigned char) (green >> 8);
\r
2027 *t++ = (unsigned char) (blue >> 8);
\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
2035 void expandgray (unsigned char *lpBuffer, long width)
\r
2038 #ifdef USESHORTINT
\r
2039 unsigned short int *PaletteRed;
\r
2040 unsigned short int *PaletteGreen;
\r
2041 unsigned short int *PaletteBlue;
\r
2043 unsigned int *PaletteRed;
\r
2044 unsigned int *PaletteGreen;
\r
2045 unsigned int *PaletteBlue;
\r
2049 unsigned int red, green, blue;
\r
2050 int PaletteIndex, Mask;
\r
2051 int Byte = 0, BitsLeft = 0;
\r
2054 /* if (traceflag) printf("Palette Gray => Gray "); */
\r
2057 if (Palette == NULL)
\r
2059 showline(" ERROR: missing palette information\n", 1);
\r
2062 PaletteRed = Palette;
\r
2063 PaletteGreen = PaletteRed + PaletteSize;
\r
2064 PaletteBlue = PaletteGreen + PaletteSize;
\r
2065 Mask = (1 << BitsPerSample) - 1;
\r
2067 /* First slide input data upwards to top of buffer area */
\r
2069 n = (int) width; /* InRowLength */
\r
2070 ns = (int) ImageWidth; /* samples per row */
\r
2072 /* if (BufferLength <= InRowLength) */
\r
2073 if (BufferLength <= InRowLengthX)
\r
2075 showline(" ERROR: buffer overflow\n", 1);
\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
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
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
2094 BitsLeft -= BitsPerSample;
\r
2095 /* PaletteIndex = Byte >> (BitsPerSample - BitsLeft); */
\r
2096 PaletteIndex = Byte >> BitsLeft;
\r
2097 PaletteIndex = PaletteIndex & Mask;
\r
2098 /* BitsLeft -= BitsPerSample; */
\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
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
2113 /* if (traceflag) printf("Index %d red %u green %u blue %u\n", */
\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
2120 if (BMPflag) *t++ = (unsigned char) red; /* BMP */
\r
2121 else *t++ = (unsigned char) (red >> 8); /* TIFF */
\r
2125 /* gray = 0.3 * red + 0.59 * green + 0.11 * blue */
\r
2127 void compresscolor (unsigned char *lpBuffer, long width)
\r
2132 unsigned int red, green, blue, gray;
\r
2135 if (traceflag) showline("Color => Gray ", 0);
\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
2143 *t++ = (unsigned char) gray;
\r
2147 /*****************************************************************************/
\r
2151 //#pragma optimize ("lge", on) /* 2000 June 17 */
\r
2153 /* use ASCII85Encode if bLevel2 enabled */
\r
2155 /* ASCII85 encoding (b1 b2 b3 b4) => (c1 c2 c3 c4 c5) */
\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
2160 /* Add `!' = 33 to make ASCII code. ! represents 0, u represent 84. */
\r
2162 /* If all five digits are zero, use z instead of !!!!! - special case. */
\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
2168 unsigned long asciinum = 0; /* accumulated so far up to four bytes */
\r
2169 int asciicount = 0; /* how many bytes accumulated so far */
\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
2175 void ASCIIlong (FILE *output, unsigned long n, int nbytes)
\r
2177 unsigned int c[5];
\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
2186 if (column >= MAXCOLUMNASCII) {
\r
2187 PSputc('\n', output);
\r
2192 for (k = 4; k >= 0; k--) { /* get base 85 digits reverse order */
\r
2193 c[k] = (unsigned int) (n % 85);
\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
2202 PSputs("~>\n", output); /* EOD */
\r
2206 PSputc((char) (c[k] + '!'), output);
\r
2208 if (column >= MAXCOLUMNASCII) {
\r
2209 PSputc('\n', output);
\r
2212 } /* end of for k = 0; k < 5; k++ */
\r
2215 /* Output single byte (accumulate until four seen, then call ASCIIlong) */
\r
2216 /* Move this inline for speed ? */
\r
2218 void ASCIIout (FILE *output, unsigned int x)
\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
2225 if (asciicount >= 4) {
\r
2226 ASCIIlong(output, asciinum, asciicount);
\r
2232 /* initialize ASCII85 filter */
\r
2234 void ASCIIinitfilter (FILE *output) /* 96/Dec/20 */
\r
2236 // showline("ASCIIinitfilter ", 0); // debugging only
\r
2239 column = 0; /* ??? */
\r
2242 void RUNinitfilter (FILE *output) /* 95/Dec/24 */
\r
2244 /* apparently nothing special to do */
\r
2247 /* flush out anything left in ASCII85 filter */
\r
2249 void ASCIIflushfilter (FILE *output) /* 96/Dec/20 */
\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
2256 ASCIIlong(output, asciinum, asciicount);
\r
2261 void RUNflushfilter (FILE *output)
\r
2263 ASCIIout(output, 128); /* EOD */
\r
2266 /*****************************************************************************/
\r
2268 /* write a row in ASCII85 format */
\r
2270 void writearowASCII (FILE *output, unsigned char *s, unsigned long width)
\r
2274 unsigned long num;
\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
2282 if (k >= n) break; /* in case of miniscule width! */
\r
2285 while (k < n-3) { /* then do groups of four bytes */
\r
2287 for (i = 0; i < 4; i++) {
\r
2289 num = (num << 8) | c;
\r
2291 ASCIIlong(output, num, 4);
\r
2294 while (k < n) { /* then do remaining bytes at tail of row */
\r
2295 ASCIIout(output, *s++);
\r
2300 /**************************************************************************/
\r
2302 #if (defined(DEBUGLZWENCODE) || defined(DEBUGRUNLENGTH))
\r
2303 int debugflag=1; /* debugging output */
\r
2306 /* Do run encoding per row (rather than image) --- easier, if not optimal */
\r
2308 void dumprun(FILE *output, int nlen, int previous)
\r
2310 #ifdef DEBUGRUNLENGTH
\r
2313 sprintf(logline, "Zero length run %d ", nlen);
\r
2314 showline(logline, 0);
\r
2317 else if (nlen < 3) {
\r
2318 sprintf(logline, " ERROR: run %d < 3\n", nlen);
\r
2319 showline(logline, 1);
\r
2321 else if (nlen > 128) {
\r
2322 sprintf(logline, " ERROR: run %d > 128", nlen);
\r
2323 showline(logline, 1);
\r
2325 for (i = 0; i < nlen; i++) {
\r
2326 sprintf(logline, "%02X", previous);
\r
2327 showline(logline, 1);
\r
2330 ASCIIout(output, 257 - nlen);
\r
2331 ASCIIout(output, previous);
\r
2334 void dumpnonrun(FILE *output, int nlen, unsigned char *buffer)
\r
2339 #ifdef DEBUGRUNLENGTH
\r
2341 sprintf(logline, "Zero length nonrun %d ", nlen);
\r
2342 showline(logline, 0);
\r
2346 sprintf(logline, " ERROR: nonrun %d > 128", nlen);
\r
2347 showline(logline, 1);
\r
2351 for (i = 0; i < nlen; i++) {
\r
2354 sprintf(logline, "%02X", c);
\r
2355 showline(logline, 1);
\r
2359 ASCIIout(output, nlen - 1);
\r
2361 for (i = 0; i < nlen; i++) ASCIIout(output, *s++);
\r
2364 /* RunLengthEncode filter */
\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
2372 void writearowrun (FILE *output, unsigned char *s, unsigned long width)
\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
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
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
2398 runflag = 0; /* switch back to non run state */
\r
2400 else if (c == previous) { /* continue the run ? */
\r
2403 else { /* c != previous --- end of a run */
\r
2404 dumprun(output, repeat, previous);
\r
2409 runflag = 0; /* switch back to non run state */
\r
2412 else { /* runflag == 0 accumulating a non run */
\r
2413 if (bcount >= 128) { /* accumulated too much ? */
\r
2414 dumpnonrun(output, bcount, new);
\r
2419 /* and stay in non run mode */
\r
2421 else if (c == previous) {
\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
2430 if (runflag == 0) bcount++;
\r
2435 /* don't change new, bcount */
\r
2441 } /* end of while loop */
\r
2442 #ifdef DEBUGRUNLENGTH
\r
2443 /* if (debugflag) showline("EOL ", 0); */
\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
2454 /**************************************************************************/
\r
2456 /* code for LZW compression on OUTPUT side LZWcompress rewrite 2000 June 17 */
\r
2458 #ifdef LZWCOMPRESSION
\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
2468 // May get some added performance by making the last two components be
\r
2469 // pointers rather than indeces...
\r
2471 struct NODE *node=NULL; // array of nodes --- allocated
\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
2477 void DeAllocStringsOut (void) // called from dvibody() in dvipsone.c
\r
2479 if (node != NULL) {
\r
2485 void CleanOut (FILE *output, int n)
\r
2489 // sprintf(logline, "CLEANOUT %d\n", n);
\r
2490 // showline(logline, 0);
\r
2492 // 0 to MAXCHR, and CLEAR and EOD
\r
2493 for (k = 0; k < FIRSTCODE; k++) {
\r
2495 node[k].nextinlist = -1;
\r
2496 node[k].nextlevel = -1;
\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
2504 int SetupNodes (FILE *output)
\r
2508 if (node == NULL) {
\r
2509 nlen = MAXCODES * sizeof(struct NODE); // 49,152 bytes
\r
2511 sprintf(logline, "Allocating %d bytes\n", nlen); // debugging only
\r
2512 showline(logline, 0);
\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
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
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
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
2540 else { // yes, link to end of that list
\r
2541 // k = node[n].nextlevel;
\r
2542 // find end of linked list
\r
2545 k = node[klast].nextinlist;
\r
2547 node[klast].nextinlist = nextnode; // link new node to end of list
\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
2555 if (nextnode == 512 || nextnode == 1024 || nextnode == 2048) {
\r
2556 // sprintf(logline, "CODELENGTH %d ", codelength);
\r
2557 // showline(logline, 0);
\r
2560 else if (nextnode == 4096) CleanOut(output, chr);
\r
2564 // We are adding a new node for byte chr
\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
2578 if (nextnode == 512 || nextnode == 1024 || nextnode == 2048) {
\r
2579 // sprintf(logline, "CODELENGTH %d ", codelength);
\r
2580 // showline(logline, 0);
\r
2583 else if (nextnode == 4096) CleanOut(output, chr);
\r
2586 // Process next incoming byte
\r
2588 void DoNextByte (FILE *output, int chr) { // called from writearowLZW
\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
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
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
2611 k = node[klast].nextinlist;
\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
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
2629 void DoCleanup (FILE *output) // not used - see LZWflushfilter
\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
2640 /***************************************************************************/
\r
2644 long leftover; /* byte accumulated so far - need up to 12 + 12 bits */
\r
2645 int bitsused; /* bits used so far */
\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
2651 void LZWput (int code, FILE *output)
\r
2655 // if (bitsused < 0 || bitsused >= 8) showline("ERROR ", 1);
\r
2656 #ifdef DEBUGLZWENCODE
\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
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
2674 c = (int) (leftover >> (bitsused - 8)); /* get left most 8 bits */
\r
2675 ASCIIout(output, c & 255); // expand ?
\r
2677 // if (bitsused < 0 || bitsused >= 8) showline("ERROR ", 1);
\r
2680 void LZWputinit (FILE *output) { /* called from LZWinitfilter */
\r
2681 // showline("LZWputinit ", 0); // debugging only
\r
2686 void LZWputflush (FILE *output)
\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
2698 void LZWinitfilter (FILE *output) /* initialization */
\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
2708 void LZWflushfilter (FILE *output) /* termination */
\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
2717 LZWput(EOD, output);
\r
2718 #ifdef DEBUGLZWENCODE
\r
2719 if (debugflag) showline("EOD ", 1);
\r
2721 sprintf(logline, "%d entries ", nextnode);
\r
2722 showline(logline, 1);
\r
2725 LZWputflush(output);
\r
2726 /* CleanOut(output, -1); */
\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
2734 int writearowLZW (FILE *output, unsigned char *s, unsigned long width)
\r
2736 unsigned char *send = s + width;
\r
2738 /* This picks up unfinished business --- currentnode >= 0 */
\r
2739 while (s < send) {
\r
2740 DoNextByte(output, *s++);
\r
2743 /* This may leave unfinished business --- currentnode >= 0 */
\r
2746 #endif /* end of ifdef LZWCOMPRESSION */
\r
2748 /*************************************************************************/
\r
2750 //#pragma optimize ("lge", off)
\r
2752 #endif /* end of ifdef PSLEVEL2 */
\r
2754 /* write row in hex format */
\r
2756 void writearowhex (FILE *output, unsigned char *s, unsigned long width)
\r
2758 unsigned int c, d;
\r
2763 for (k = 0; k < n; k++) {
\r
2764 if (column >= MAXCOLUMNHEX) {
\r
2765 // putc('\n', output);
\r
2766 PSputc('\n', output);
\r
2773 // putc(c + 'A' - 10, output);
\r
2774 PSputc((char) (c + 'A' - 10), output);
\r
2777 // putc(c + '0', output);
\r
2778 PSputc((char) (c + '0'), output);
\r
2782 // putc(d + 'A' - 10, output);
\r
2783 PSputc((char) (d + 'A' - 10), output);
\r
2786 // putc(d + '0', output);
\r
2787 PSputc((char) (d + '0'), output);
\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
2796 /* returns -1 if output error */ /* write a row of data in hex */
\r
2798 int writearow (FILE *output, unsigned char *s, unsigned long width)
\r
2802 if (bRunLengthFlag) writearowrun(output, s, width);
\r
2803 #ifdef LZWCOMPRESSION
\r
2804 else if (bLZWFlag) writearowLZW(output, s, width);
\r
2806 else writearowASCII(output, s, width);
\r
2808 else writearowhex(output, s, width);
\r
2810 writearowhex(output, s, width);
\r
2813 // if (ferror(output))
\r
2814 if (output != NULL && ferror(output))
\r
2816 showline(" ERROR: Output error\n", 1);
\r
2817 perrormod((outputfile != NULL) ? outputfile : "");
\r
2820 if (bAbort) abortjob(); /* 97/Mar/1 ? */
\r
2821 if (abortflag) return -1;
\r
2825 int computeheader (void) {
\r
2826 /* int changeflag= 0; */
\r
2829 if (traceflag) showline("Now computing header information\n", 0);
\r
2832 /* Now for some sanity checks */
\r
2833 if (PlanarConfig != 1) {
\r
2834 showline(" ERROR: Multiple color planes not supported\n", 1);
\r
2837 if (BitsPerSample > 8) {
\r
2838 sprintf(logline, " ERROR: Maximum of 8 bits per sample (%d)\n",
\r
2840 showline(logline, 1);
\r
2843 if ((BitsPerSample & (BitsPerSample-1)) != 0) {
\r
2844 sprintf(logline, " ERROR: Bits per sample must be power of two (%d)\n",
\r
2846 showline(logline, 1);
\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
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
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
2871 if (! bAllowColor) {
\r
2872 sprintf(logline, " WARNING: More than one sample per pixel (%d) use `*c' flag?",
\r
2874 showline(logline, 0);
\r
2876 bCompressColor = 1; /* then need to compress colors */
\r
2879 /* if (verboseflag && PhotometricInterpretation > 3) {
\r
2880 printf("Photometricinterpretation %d\n", PhotometricInterpretation);
\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
2894 if (PhotometricInterpretation == 2)
\r
2896 /* if (SamplesPerPixel == 1) */
\r
2897 if (SamplesPerPixelX == 1)
\r
2899 sprintf(logline, " %s, but not more than one sample per pixel?\n", "RGB");
\r
2900 showline(logline, 1);
\r
2902 if (! bAllowColor)
\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
2911 if (PhotometricInterpretation == 5) { // 2000 May 27
\r
2912 /* if (SamplesPerPixel == 1) */
\r
2913 if (SamplesPerPixelX == 1)
\r
2915 sprintf(logline, " %s, but not more than one sample per pixel?\n", "CMYK");
\r
2916 showline(logline, 1);
\r
2918 if (! bAllowColor)
\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
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
2930 if (PhotometricInterpretation == 0)
\r
2933 if (traceflag) showline("Image grey levels will be inverted\n", 0);
\r
2937 else bInvertImage = 0;
\r
2942 sprintf(logline, "ExpandColor %d CompressColor %d InvertImage %d\n",
\r
2943 bExpandColor, bCompressColor, bInvertImage);
\r
2944 showline(logline, 0);
\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
2956 sprintf(logline, "%d bytes per row\n", bytes);
\r
2957 showline(logline, 0);
\r
2963 /* long xll=0, yll=0, xur=0, yur=0; */
\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
2970 /* compress some of this code into DVIPREAM.PS ? */
\r
2972 void writepsheader (FILE *output, long dwidth, long dheight)
\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
2982 if (traceflag) showline("Now writing out header information\n", 0);
\r
2984 /* if (BitsPerSample == 1) bMonoChrome = 1; */ /* use image mask */
\r
2986 if (bExpandColor) bits = 8;
\r
2987 else if (bExpandGray) bits = 8;
\r
2988 else bits = BitsPerSample;
\r
2990 if (bits == 1) bMonoChrome = 1; /* use image mask */
\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
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
3007 // putc('\n', output);
\r
3008 PSputc('\n', output);
\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
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
3024 // fputs("currentscreen pop dviscreen\n", output);
\r
3025 PSputs("currentscreen pop dviscreen\n", output);
\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
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
3041 sprintf(logline, "/picstr %d string def\n", bytes);
\r
3042 PSputs(logline, output);
\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
3051 if (outscaleflag) {
\r
3052 sprintf(logline, "%.9lg %.9lg scale\n",
\r
3053 (double) dwidth / outscale, (double) dheight / outscale);
\r
3056 sprintf(logline, "%ld %ld scale\n", dwidth, dheight);
\r
3059 sprintf(logline, "%ld %ld scale\n", dwidth, dheight);
\r
3061 PSputs(logline, output);
\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
3075 // fputs("white\n", output);
\r
3076 PSputs("white\n", output);
\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
3089 /* background seems to be painted below not on image 96/May/6 */
\r
3091 // fputs("1 -1 lineto 0 -1 lineto ", output);
\r
3092 PSputs("1 -1 lineto 0 -1 lineto ", output);
\r
3094 // fputs("closepath fill\n", output);
\r
3095 PSputs("closepath fill\n", output);
\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
3103 // fputs("black\n", output);
\r
3104 PSputs("black\n", output);
\r
3106 /* fputs("grestore\n", output); */ /* not needed */
\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
3117 // fputs("false\n", output);
\r
3118 PSputs("false\n", output);
\r
3122 sprintf(logline, "%d\n", bits); /* not monochrome */
\r
3123 PSputs(logline, output);
\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
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
3137 /* fputs("{currentfile picstr readhexstring pop} bind\n", output); */
\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
3147 #ifdef LZWCOMPRESSION
\r
3148 else if (bLZWFlag) {
\r
3149 // fputs(" /LZWDecode filter", output);
\r
3150 PSputs(" /LZWDecode filter", output);
\r
3153 // putc('\n', output);
\r
3154 PSputc('\n', output);
\r
3157 // fputs("{currentfile picstr readhexstring pop} bind\n", output);
\r
3158 PSputs("{currentfile picstr readhexstring pop} bind\n", output);
\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
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
3172 // fputs("image", output); /* either not color, or color compressed */
\r
3173 PSputs("image", output); /* either not color, or color compressed */
\r
3175 // putc('\n', output);
\r
3176 PSputc('\n', output);
\r
3177 /* image data must follow right away */
\r
3180 void writepstrailer (FILE *output)
\r
3183 if (traceflag) showline("Now writing trailer\n", 0);
\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
3194 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
3196 /* Read a row using PACK_BITS compression scheme */
\r
3197 /* returns non-zero if problems encountered */
\r
3199 int readpackbits (unsigned char *lpBuffer, FILE *input, int RowLength)
\r
3201 unsigned char *u=lpBuffer;
\r
3202 int c, k, n, total=0, flag=0;
\r
3205 if ((n = getc(input)) < 0) { /* premature EOF */
\r
3206 showline(" Premature EOF", 1);
\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
3214 else if (n > 128) { /* repeat next byte (257 - n) times */
\r
3216 for (k=0; k < (257 - n); k++) *u++ = (char) c;
\r
3217 total += (257 - n);
\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
3230 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\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
3238 int bytex, bitsleft; /* input buffering in splitting bits */
\r
3240 int getbit (FILE *input)
\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
3250 bytex = bytex << 1;
\r
3253 sprintf(logline, "%d", (bytex & 256) ? 1 : 0);
\r
3254 showline(logline, 0);
\r
3257 if (bytex & 256) return 1;
\r
3261 //#pragma optimize ("lge", on)
\r
3263 /* It's the Huffman code stuff that wants to be not optimized */
\r
3265 //#pragma optimize ("lge", off)
\r
3267 /* Actually commonmake may be OK with compiler optimizations ON */
\r
3269 int commonmake (FILE *input) /* common black/white make up codes (7 zeros) */
\r
3273 showline("commonmake entry ", 0);
\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
3283 else { /* 000000011110 */
\r
3287 else { /* 00000001110 */
\r
3288 if (getbit(input)) { /* 000000011101 */
\r
3291 else { /* 000000011100 */
\r
3296 else { /* 0000000110 */
\r
3297 if (getbit(input)) { /* 00000001101 */
\r
3300 else { /* 00000001100 */
\r
3305 else { /* 000000010 */
\r
3306 if (getbit(input)) { /* 0000000101 */
\r
3307 if (getbit(input)) { /* 00000001011 */
\r
3308 if (getbit(input)) { /* 000000010111 */
\r
3311 else { /* 000000010110 */
\r
3315 else { /* 00000001010 */
\r
3316 if (getbit(input)) { /* 000000010101 */
\r
3319 else { /* 000000010100 */
\r
3324 else { /* 0000000100 */
\r
3325 if (getbit(input)) { /* 00000001001 */
\r
3326 if (getbit(input)) { /* 000000010011 */
\r
3329 else { /* 000000010010 */
\r
3333 else { /* 00000001000 */
\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
3352 showline(" Impossible make-up run\n", 1);
\r
3353 return -1; /* error */
\r
3356 /* Compiler screws up the following code if optimizations turned on */
\r
3358 int whiterun (FILE *input)
\r
3363 showline("whiterun entry ", 0);
\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
3377 if (getbit(input)) { /* 1101 */
\r
3378 if (getbit(input)) { /* 11011 */
\r
3379 return 64; /* make up */
\r
3381 else { /* 11010 */
\r
3382 if (getbit(input)) { /* 110101 */
\r
3385 else { /* 110100 */
\r
3396 if (getbit(input)) { /* 101 */
\r
3397 if (getbit(input)) { /* 1011 */
\r
3401 if (getbit(input)) { /* 10101 */
\r
3402 if (getbit(input)) { /* 101011 */
\r
3405 else { /* 101010 */
\r
3409 else { /* 10100 */
\r
3415 if (getbit(input)) { /* 1001 */
\r
3416 if (getbit(input)) { /* 10011 */
\r
3419 else { /* 10010 */
\r
3420 return 128; /* make up */
\r
3430 if (getbit(input)) { /* 01 */
\r
3431 if (getbit(input)) { /* 011 */
\r
3432 if (getbit(input)) { /* 0111 */
\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
3441 else { /* 0110110 */
\r
3442 if (getbit(input)) { /* 01101101 */
\r
3443 if (getbit(input)) { /* 011011011 */
\r
3444 return 1408; /* make up */
\r
3446 else { /* 011011010 */
\r
3447 return 1344; /* make up */
\r
3450 else { /* 01101100 */
\r
3451 if (getbit(input)) { /* 011011001 */
\r
3452 return 1280; /* make up */
\r
3454 else { /* 011011000 */
\r
3455 return 1216; /* make up */
\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
3466 else { /* 011010110 */
\r
3467 return 1088; /* make up */
\r
3470 else { /* 01101010 */
\r
3471 if (getbit(input)) { /* 011010101 */
\r
3472 return 1024; /* make up */
\r
3474 else { /* 011010100 */
\r
3475 return 960; /* make up */
\r
3479 else { /* 0110100 */
\r
3480 if (getbit(input)) { /* 01101001 */
\r
3481 if (getbit(input)) { /* 011010011 */
\r
3482 return 896; /* make up */
\r
3484 else { /* 011010010 */
\r
3485 return 832; /* make up */
\r
3488 else { /* 01101000 */
\r
3489 return 576; /* make up */
\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
3500 else { /* 01100110 */
\r
3501 if (getbit(input)) { /* 011001101 */
\r
3502 return 768; /* make up */
\r
3504 else { /* 011001100 */
\r
3505 return 704; /* make up */
\r
3509 else { /* 0110010 */
\r
3510 if (getbit(input)) { /* 01100101 */
\r
3511 return 512; /* make up */
\r
3513 else { /* 01100100 */
\r
3514 return 448; /* make up */
\r
3518 else { /* 011000 */
\r
3519 return 1664; /* make up */
\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
3530 else { /* 010110 */
\r
3531 if (getbit(input)) { /* 0101101 */
\r
3532 if (getbit(input)) { /* 01011011 */
\r
3535 else { /* 01011010 */
\r
3539 else { /* 0101100 */
\r
3540 if (getbit(input)) { /* 01011001 */
\r
3543 else { /* 01011000 */
\r
3549 else { /* 01010 */
\r
3550 if (getbit(input)) { /* 010101 */
\r
3551 if (getbit(input)) { /* 0101011 */
\r
3554 else { /* 0101010 */
\r
3555 if (getbit(input)) { /* 01010101 */
\r
3558 else { /* 01010100 */
\r
3563 else { /* 010100 */
\r
3564 if (getbit(input)) { /* 0101001 */
\r
3565 if (getbit(input)) { /* 01010011 */
\r
3568 else { /* 01010010 */
\r
3572 else { /* 0101000 */
\r
3579 if (getbit(input)) { /* 01001 */
\r
3580 if (getbit(input)) { /* 010011 */
\r
3581 if (getbit(input)) { /* 0100111 */
\r
3584 else { /* 0100110 */
\r
3585 if (getbit(input)) { /* 01001101 */
\r
3586 if (getbit(input)) { /* 010011011 */
\r
3587 return 1728; /* make up */
\r
3589 else { /* 010011010 */
\r
3590 return 1600; /* make up */
\r
3593 else { /* 01001100 */
\r
3594 if (getbit(input)) { /* 010011001 */
\r
3595 return 1536; /* make up */
\r
3597 else { /* 010011000 */
\r
3598 return 1472; /* make up */
\r
3603 else { /* 010010 */
\r
3604 if (getbit(input)) { /* 0100101 */
\r
3605 if (getbit(input)) { /* 01001011 */
\r
3608 else { /* 01001010 */
\r
3612 else { /* 0100100 */
\r
3617 else { /* 01000 */
\r
3624 if (getbit(input)) { /* 001 */
\r
3625 if (getbit(input)) { /* 0011 */
\r
3626 if (getbit(input)) { /* 00111 */
\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
3635 else { /* 0110110 */
\r
3636 return 320; /* make up */
\r
3639 else { /* 0011010 */
\r
3640 if (getbit(input)) { /* 00110101 */
\r
3643 else { /* 00110100 */
\r
3648 else { /* 001100 */
\r
3649 if (getbit(input)) { /* 0011001 */
\r
3650 if (getbit(input)) { /* 00110011 */
\r
3653 else { /* 00110010 */
\r
3657 else { /* 0011000 */
\r
3664 if (getbit(input)) { /* 00101 */
\r
3665 if (getbit(input)) { /* 001011 */
\r
3666 if (getbit(input)) { /* 0010111 */
\r
3669 else { /* 0010110 */
\r
3670 if (getbit(input)) { /* 00101101 */
\r
3673 else { /* 00101100 */
\r
3678 else { /* 001010 */
\r
3679 if (getbit(input)) { /* 0010101 */
\r
3680 if (getbit(input)) { /* 00101011 */
\r
3683 else { /* 00101010 */
\r
3687 else { /* 0010100 */
\r
3688 if (getbit(input)) { /* 00101001 */
\r
3691 else { /* 00101000 */
\r
3697 else { /* 00100 */
\r
3698 if (getbit(input)) { /* 001001 */
\r
3699 if (getbit(input)) { /* 0010011 */
\r
3702 else { /* 0010010 */
\r
3703 if (getbit(input)) { /* 00100101 */
\r
3706 else { /* 00100100 */
\r
3711 else { /* 001000 */
\r
3718 if (getbit(input)) { /* 0001 */
\r
3719 if (getbit(input)) { /* 00011 */
\r
3720 if (getbit(input)) { /* 000111 */
\r
3723 else { /* 000110 */
\r
3724 if (getbit(input)) { /* 0001101 */
\r
3725 if (getbit(input)) { /* 00011011 */
\r
3728 else { /* 00011010 */
\r
3732 else { /* 0001100 */
\r
3737 else { /* 00010 */
\r
3738 if (getbit(input)) { /* 000101 */
\r
3739 if (getbit(input)) { /* 0001011 */
\r
3740 if (getbit(input)) { /* 00010111 */
\r
3743 else { /* 00010110 */
\r
3747 else { /* 0001010 */
\r
3748 if (getbit(input)) { /* 00010101 */
\r
3751 else { /* 00010100 */
\r
3756 else { /* 000100 */
\r
3757 if (getbit(input)) { /* 0001001 */
\r
3758 if (getbit(input)) { /* 00010011 */
\r
3761 else { /* 00010010 */
\r
3765 else { /* 0001000 */
\r
3772 if (getbit(input)) { /* 00001 */
\r
3773 if (getbit(input)) { /* 000011 */
\r
3776 else { /* 000010 */
\r
3777 if (getbit(input)) { /* 0000101 */
\r
3778 if (getbit(input)) { /* 00001011 */
\r
3781 else { /* 00001010 */
\r
3785 else { /* 0000100 */
\r
3790 else { /* 00000 */
\r
3791 if (getbit(input)) { /* 000001 */
\r
3792 if (getbit(input)) { /* 0000011 */
\r
3795 else { /* 0000010 */
\r
3796 if (getbit(input)) { /* 00000101 */
\r
3799 else { /* 00000100 */
\r
3804 else { /* 000000 */
\r
3805 if (getbit(input)) { /* 0000001 */
\r
3806 if (getbit(input)) { /* 00000011 */
\r
3809 else { /* 00000010 */
\r
3813 else { /* 0000000 */
\r
3814 return commonmake(input); /* seven zeros */
\r
3822 showline(" Impossible white run\n", 1);
\r
3823 return -1; /* error */
\r
3826 /* Compiler screws up the following code if optimizations turned on */
\r
3828 int blackzero (FILE *input) /* black run code starts with four zeros */
\r
3831 if (traceflag) showline (" blackzero entry ", 0);
\r
3833 if (getbit(input)) { /* 00001 */
\r
3834 if (getbit(input)) { /* 000011 */
\r
3835 if (getbit(input)) { /* 0000111 */
\r
3838 else { /* 0000110 */
\r
3839 if (getbit(input)) { /* 00001101 */
\r
3840 if (getbit(input)) { /* 000011011 */
\r
3841 if (getbit(input)) { /* 0000110111 */
\r
3844 else { /* 0000110110 */
\r
3845 if (getbit(input)) { /* 00001101101 */
\r
3846 if (getbit(input)) { /* 000011011011 */
\r
3849 else { /* 000011011010 */
\r
3853 else { /* 00001101100 */
\r
3858 else { /* 000011010 */
\r
3859 if (getbit(input)) { /* 0000110101 */
\r
3860 if (getbit(input)) { /* 00001101011 */
\r
3861 if (getbit(input)) { /* 000011010111 */
\r
3864 else { /* 000011010110 */
\r
3868 else { /* 00001101010 */
\r
3869 if (getbit(input)) { /* 000011010101 */
\r
3872 else { /* 000011010100 */
\r
3877 else { /* 0000110100 */
\r
3878 if (getbit(input)) { /* 00001101001 */
\r
3879 if (getbit(input)) { /* 000011010011 */
\r
3882 else { /* 000011010010 */
\r
3886 else { /* 00001101000 */
\r
3892 else { /* 00001100 */
\r
3893 if (getbit(input)) { /* 000011001 */
\r
3894 if (getbit(input)) { /* 0000110011 */
\r
3895 if (getbit(input)) { /* 00001100111 */
\r
3898 else { /* 00001100110 */
\r
3899 if (getbit(input)) { /* 000011001101 */
\r
3902 else { /* 000011001100 */
\r
3907 else { /* 0000110010 */
\r
3908 if (getbit(input)) { /* 00001100101 */
\r
3909 if (getbit(input)) { /* 000011001011 */
\r
3912 else { /* 000011001010 */
\r
3916 else { /* 00001100100 */
\r
3917 if (getbit(input)) { /* 000011001001 */
\r
3918 return 192; /* make up */
\r
3920 else { /* 000011001000 */
\r
3921 return 128; /* make up */
\r
3926 else { /* 000011000 */
\r
3932 else { /* 000010 */
\r
3933 if (getbit(input)) { /* 0000101 */
\r
3936 else { /* 0000100 */
\r
3941 else { /* 00000 */
\r
3942 if (getbit(input)) { /* 000001 */
\r
3943 if (getbit(input)) { /* 0000011 */
\r
3944 if (getbit(input)) { /* 00000111 */
\r
3947 else { /* 00000110 */
\r
3948 if (getbit(input)) { /* 000001101 */
\r
3949 if (getbit(input)) { /* 0000011011 */
\r
3950 if (getbit(input)) { /* 00000110111 */
\r
3953 else { /* 00000110110 */
\r
3954 if (getbit(input)) { /* 000001101101 */
\r
3957 else { /* 000001101100 */
\r
3962 else { /* 0000011010 */
\r
3963 if (getbit(input)) { /* 00000110101 */
\r
3964 if (getbit(input)) { /* 000001101011 */
\r
3967 else { /* 000001101010 */
\r
3971 else { /* 00000110100 */
\r
3972 if (getbit(input)) { /* 000001101001 */
\r
3975 else { /* 000001101000 */
\r
3981 else { /* 000001100 */
\r
3982 if (getbit(input)) { /* 0000011001 */
\r
3983 if (getbit(input)) { /* 00000110011 */
\r
3984 if (getbit(input)) { /* 000001100111 */
\r
3987 else { /* 000001100110 */
\r
3991 else { /* 00000110010 */
\r
3992 if (getbit(input)) { /* 000001100101 */
\r
3995 else { /* 000001100100 */
\r
4000 else { /* 0000011000 */
\r
4006 else { /* 0000010 */
\r
4007 if (getbit(input)) { /* 00000101 */
\r
4008 if (getbit(input)) { /* 000001011 */
\r
4009 if (getbit(input)) { /* 0000010111 */
\r
4012 else { /* 0000010110 */
\r
4013 if (getbit(input)) { /* 00000101101 */
\r
4014 if (getbit(input)) { /* 000001011011 */
\r
4015 return 256; /* make up */
\r
4017 else { /* 000001011010 */
\r
4021 else { /* 00000101100 */
\r
4022 if (getbit(input)) { /* 000001011001 */
\r
4025 else { /* 000001011000 */
\r
4031 else { /* 000001010 */
\r
4032 if (getbit(input)) { /* 0000010101 */
\r
4033 if (getbit(input)) { /* 00000101011 */
\r
4034 if (getbit(input)) { /* 000001010111 */
\r
4037 else { /* 000001010110 */
\r
4041 else { /* 00000101010 */
\r
4042 if (getbit(input)) { /* 000001010101 */
\r
4045 else { /* 000001010100 */
\r
4050 else { /* 0000010100 */
\r
4051 if (getbit(input)) { /* 00000101001 */
\r
4052 if (getbit(input)) { /* 000001010011 */
\r
4055 else { /* 000001010010 */
\r
4059 else { /* 00000101000 */
\r
4065 else { /* 00000100 */
\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
4077 else { /* 0000001110 */
\r
4078 if (getbit(input)) { /* 00000011101 */
\r
4079 if (getbit(input)) { /* 000000111011 */
\r
4080 if (getbit(input)) { /* 0000001110111 */
\r
4083 else { /* 0000001110110 */
\r
4087 else { /* 000000111010 */
\r
4088 if (getbit(input)) { /* 0000001110101 */
\r
4091 else { /* 0000001110100 */
\r
4097 else { /* 00000011100 */
\r
4098 if (getbit(input)) { /* 000000111001 */
\r
4099 if (getbit(input)) { /* 0000001110011 */
\r
4102 else { /* 0000001110010 */
\r
4106 else { /* 000000111000 */
\r
4112 else { /* 000000110 */
\r
4113 if (getbit(input)) { /* 0000001101 */
\r
4114 if (getbit(input)) { /* 00000011011 */
\r
4115 if (getbit(input)) { /* 000000110111 */
\r
4118 else { /* 000000110110 */
\r
4119 if (getbit(input)) { /* 0000001101101 */
\r
4120 return 576; /*make up */
\r
4122 else { /* 0000001101100 */
\r
4123 return 512; /* make up */
\r
4127 else { /* 00000011010 */
\r
4128 if (getbit(input)) { /* 000000110101 */
\r
4129 return 448; /* make up */
\r
4131 else { /* 000000110100 */
\r
4132 return 384; /* make up */
\r
4136 else { /* 0000001100 */
\r
4137 if (getbit(input)) { /* 00000011001 */
\r
4138 if (getbit(input)) { /* 000000110011 */
\r
4139 return 320; /* make up */
\r
4141 else { /* 000000110010 */
\r
4142 if (getbit(input)) { /* 0000001100101 */
\r
4145 else { /* 0000001100100 */
\r
4150 else { /* 00000011000 */
\r
4156 else { /* 00000010 */
\r
4157 if (getbit(input)) { /* 000000101 */
\r
4158 if (getbit(input)) { /* 0000001011 */
\r
4159 if (getbit(input)) { /* 00000010111 */
\r
4162 else { /* 00000010110 */
\r
4163 if (getbit(input)) { /* 000000101101 */
\r
4164 if (getbit(input)) { /* 0000001011011 */
\r
4167 else { /* 0000001011010 */
\r
4171 else { /* 000000101100 */
\r
4176 else { /* 0000001010 */
\r
4177 if (getbit(input)) { /* 00000010101 */
\r
4178 if (getbit(input)) { /* 000000101011 */
\r
4181 else { /* 000000101010 */
\r
4182 if (getbit(input)) { /* 0000001010101 */
\r
4185 else { /* 0000001010100 */
\r
4190 else { /* 00000010100 */
\r
4191 if (getbit(input)) { /* 000000101001 */
\r
4192 if (getbit(input)) { /* 0000001010011 */
\r
4195 else { /* 0000001010010 */
\r
4199 else { /* 000000101000 */
\r
4205 else { /* 000000100 */
\r
4206 if (getbit(input)) { /* 0000001001 */
\r
4207 if (getbit(input)) { /* 00000010011 */
\r
4208 if (getbit(input)) { /* 000000100111 */
\r
4211 else { /* 000000100110 */
\r
4212 if (getbit(input)) { /* 0000001001101 */
\r
4215 else { /* 0000001001100 */
\r
4220 else { /* 00000010010 */
\r
4221 if (getbit(input)) { /* 000000100101 */
\r
4222 if (getbit(input)) { /* 0000001001011 */
\r
4225 else { /* 0000001001010 */
\r
4229 else { /* 000000100100 */
\r
4234 else { /* 0000001000 */
\r
4240 else { /* 0000000 */
\r
4241 return commonmake(input); /* seven zeros */
\r
4245 showline(" Impossible black run", 1);
\r
4246 showline(" (starting with four zeros)\n", 1);
\r
4247 return -1; /* error */
\r
4250 /* blackrun may actually be OK with compiler optimizations turned on */
\r
4252 int blackrun (FILE *input)
\r
4257 showline ("blackrun entry ", 0);
\r
4260 if (getbit(input)) { /* 1 */
\r
4261 if (getbit(input)) { /* 11 */
\r
4269 if (getbit(input)) { /* 01 */
\r
4270 if (getbit(input)) { /* 011 */
\r
4278 if (getbit(input)) { /* 001 */
\r
4279 if (getbit(input)) { /* 0011 */
\r
4287 if (getbit(input)) { /* 0001 */
\r
4288 if (getbit(input)) { /* 00011 */
\r
4291 else { /* 00010 */
\r
4292 if (getbit(input)) { /* 000101 */
\r
4295 else { /* 000100 */
\r
4301 return blackzero(input); /* four zeros */
\r
4306 showline(" ERROR: Impossible black run", 1);
\r
4307 showline("\n", 0);
\r
4308 return -1; /* error */
\r
4311 //#pragma optimize ("lge", on)
\r
4313 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
4315 /* FOLLOWING IS EXPERIMENT 97/OCT/21 */
\r
4317 //#pragma optimize ("lge", off)
\r
4319 int index, bitinx; /* index into row of bytes and bits within them */
\r
4321 int total; /* maybe long ? */
\r
4323 /* Following could be speeded up some ... */
\r
4325 int writewhite (unsigned char *lpBuffer, int run, int width)
\r
4327 if (run == 0) return 0; /* nothing to do */
\r
4328 if (run < 0) return -1; /* hit invalid run */
\r
4332 sprintf(logline, "run %d total %d\n", run, total);
\r
4333 showline(logline, 0);
\r
4336 if (total > width) return -1; /* error */
\r
4337 /* just advance pointers */
\r
4339 if (bitinx == 0) {
\r
4340 while (run >= 8) {
\r
4344 sprintf(logline, "index %d run %d ", index, run);
\r
4345 showline(logline, 0);
\r
4348 /* *(lpBuffer+index) = 0; */ /* already zeroed out */
\r
4353 if (bitinx-- <= 0) {
\r
4354 index++; bitinx = 7;
\r
4358 sprintf(logline, "index %d bitinx %d ", index, bitinx);
\r
4359 showline(logline, 0);
\r
4362 /* *(lpBuffer + index) &= ~(1 << bitinx); */
\r
4366 if (total == width) return 1; /* EOL */
\r
4370 int writeblack (unsigned char *lpBuffer, int run, int width)
\r
4372 if (run == 0) return 0; /* nothing to do */
\r
4373 if (run < 0) return -1; /* hit invalid run */
\r
4377 sprintf(logline, "run %d total %d\n", run, total);
\r
4378 showline(logline, 0);
\r
4381 if (total > width) return -1; /* error */
\r
4383 if (bitinx == 0) {
\r
4384 while (run >= 8) {
\r
4388 sprintf(logline, "index %d run %d ", index, run);
\r
4389 showline(logline, 0);
\r
4392 *(lpBuffer+index) = 255; /* write a byte at a time */
\r
4397 if (bitinx-- <= 0) {
\r
4398 index++; bitinx = 7;
\r
4402 sprintf(logline, "index %d bitinx %d ", index, bitinx);
\r
4403 showline(logline, 0);
\r
4406 *(lpBuffer + index) |= (1 << bitinx); /* write a bit at a time */
\r
4410 if (total == width) return 1; /* EOL */
\r
4414 /* make width long ? */
\r
4416 int huffmanrow (unsigned char *lpBuffer, FILE *input, int width)
\r
4420 /* int total = 0; */ /* long total ? */
\r
4422 /* if (lpBuffer == NULL) {
\r
4423 showline(" Bad buffer pointer\n", 1);
\r
4427 index = -1; bitinx = 0; /* output buffering */
\r
4428 bytex = 0; bitsleft = 0; /* input buffering */
\r
4430 bytes = (width + 7) / 8; /* preset with zeros */
\r
4433 sprintf(logline, "Cleaning out %d bytes\n", bytes);
\r
4434 showline(logline, 0);
\r
4437 for (k = 0; k < bytes; k++) lpBuffer[k] = 0;
\r
4442 sprintf(logline, "Looking for white run\n");
\r
4443 showline(logline, 0);
\r
4446 while ((run = whiterun (input)) >= 64) {
\r
4449 sprintf(logline, " W %d ", run);
\r
4450 showline(logline, 0);
\r
4453 if (writewhite(lpBuffer, run, width) < 0) break;
\r
4455 if (total >= width) break;
\r
4458 sprintf(logline, " W %d\n", run);
\r
4459 showline(logline, 0);
\r
4462 if (writewhite(lpBuffer, run, width) != 0) break; /* terminal run */
\r
4466 sprintf(logline, "Looking for black run\n");
\r
4467 showline(logline, 0);
\r
4470 while ((run = blackrun (input)) >= 64) {
\r
4473 sprintf(logline, " B %d ", run);
\r
4474 showline(logline, 0);
\r
4477 if (writeblack(lpBuffer, run, width) < 0) break;
\r
4479 if (total >= width) break;
\r
4482 sprintf(logline, " B %d\n", run);
\r
4483 showline(logline, 0);
\r
4486 if (writeblack(lpBuffer, run, width) != 0) break; /* terminal run */
\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
4494 else if (traceflag ) {
\r
4495 sprintf(logline, "Sum of runs equal to width %d\n", width);
\r
4496 showline(logline, 0);
\r
4502 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
4504 //#pragma optimize ("lge", on) /* experiment 2000 June 17 */
\r
4506 /* Here is the code for LZW (compression scheme number 5) input side */
\r
4508 char *StringByte=NULL; /* contains last byte of string */
\r
4510 char *StringFirst=NULL; /* contains first byte of string */
\r
4511 /* to speed up processing ... */
\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
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
4523 int TableIndex=FIRSTCODE; /* index into above String Tables */
\r
4524 /* next available string entry */
\r
4526 int CodeLength=9; /* current code length INPUT */
\r
4528 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
4530 /* following is never called ? now called from dvipsone.c when exiting */
\r
4532 void DeAllocStringsIn (void) /* remember to do this at end */
\r
4534 /* if (Memory != NULL) {
\r
4535 free(Memory); Memory = NULL;
\r
4537 if (StringByte != NULL) {
\r
4538 free(StringByte); StringByte = NULL;
\r
4540 if (StringFirst != NULL) {
\r
4541 free(StringFirst); StringFirst = NULL;
\r
4543 if (StringPrevious != NULL) {
\r
4544 free(StringPrevious); StringPrevious = NULL;
\r
4546 if (StringLength != NULL) {
\r
4547 free(StringLength); StringLength = NULL;
\r
4551 /* worry here about allocation in NT ? sizeof(int) */
\r
4553 int AllocStringsIn (void)
\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
4562 if (StringFirst == NULL) { /* allocate string table indeces */
\r
4563 StringFirst = (char *) malloc(MAXCODES * sizeof(char));
\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
4571 if (StringLength == NULL) { /* allocate string table lengths */
\r
4572 StringLength = (short int *)
\r
4573 malloc(MAXCODES * sizeof(short int));
\r
4576 if (StringPrevious == NULL) { /* allocate string table lengths */
\r
4577 StringPrevious = (int *) malloc(MAXCODES * sizeof(int));
\r
4579 if (StringLength == NULL) { /* allocate string table lengths */
\r
4580 StringLength = (int *) malloc(MAXCODES * sizeof(int));
\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
4588 // or more serious exit(1) ???
\r
4593 void InitializeStringTable (void) /* set up string table initially */
\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
4605 /* FreeIndex = MAXCHR; */
\r
4606 TableIndex = FIRSTCODE;
\r
4607 CodeLength = 9; /* initial code length */
\r
4610 void ResetStringTable (int quietflag) /* clear string table */
\r
4617 if (traceflag) showline("CLEAR ", 0);
\r
4618 if (traceflag) showline("\n", 0);
\r
4619 if (traceflag && TableIndex > FIRSTCODE)
\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
4628 /* following not really needed */
\r
4629 /* for (k = FIRSTCODE; k < TableIndex; k++) {
\r
4630 StringTable[k] = 0;
\r
4631 StringLength[k] = 0;
\r
4633 /* FreeIndex = MAXCHR; */
\r
4634 TableIndex = FIRSTCODE;
\r
4638 #ifdef USESHORTINT
\r
4639 void AddNewEntry (short int OldCode, short int Code)
\r
4642 void AddNewEntry (int OldCode, int Code)
\r
4652 sprintf(logline, "Add string TableIndex %4d (%d)\n",
\r
4653 TableIndex, StringLength[OldCode] + 1);
\r
4654 showline(logline, 0);
\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
4668 StringLength[TableIndex] = StringLength[OldCode] + 1;
\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
4678 if (TableIndex == 511 || TableIndex == 1023 || TableIndex == 2047)
\r
4684 sprintf(logline, "LENGTH %d (%d)\n", TableIndex, CodeLength);
\r
4685 showline(logline, 0);
\r
4690 if (TableIndex > MAXCODES)
\r
4692 showline(" ERROR: Table overflow\n", 1);
\r
4697 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
4699 int IsInTable (int Code) /* is code already in table ? */
\r
4701 return (Code >= 0 && Code < TableIndex);
\r
4704 /* copy string from table by code number */
\r
4706 unsigned char *WriteString (unsigned char *buffer, int Code)
\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
4726 /* showline(" ERROR: ran off end of Strip Buffer\n", 1); */
\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
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
4739 s = t - 1; /* last byte to copy */
\r
4740 /* for (k = 0; k < len; k++) *s++ = *t++; */
\r
4742 /* for (k = 0; k < len; k++) */
\r
4743 /* for (k = len; k > 0; k--) */
\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
4753 if ((s + 1) != buffer) { /* sanity check */
\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
4762 if (*s++ != 0) putc('1', stdout);
\r
4763 else putc('0', stdout);
\r
4764 if (counter++ % 1024 == 0) putc('\n', stdout);
\r
4766 return buffer; */ /* TESTING HACK! */
\r
4770 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
4772 unsigned long OldByte=0; /* cadaver being eaten */
\r
4773 int OldBitsLeft=0; /* how many bits left in OldByte */
\r
4775 #ifdef USESHORTINT
\r
4776 short int GetNextCode (FILE *input) /* get next LZW code number from input */
\r
4779 int GetNextCode (FILE *input) /* get next LZW code number from input */
\r
4786 bits = OldBitsLeft; /* how many bits do we have */
\r
4787 k = OldByte; /* start with old bits */
\r
4789 while (bits < CodeLength) { /* need more bits ? */
\r
4790 if (InStripLen-- <= 0) { /* treat as EOD 96/Nov/17 */
\r
4792 sprintf(logline, " No EOD at end of strip %d ", CurrentStrip);
\r
4793 showline(logline, 1);
\r
4797 if ((c = getc(input)) == EOF)
\r
4799 sprintf(logline, " Unexpected EOF (%s)\n", "getnextcode");
\r
4800 showline(logline, 1);
\r
4803 // return -1; /* EOF serious error ... */
\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
4815 sprintf(logline, "CODE %4d ", k);
\r
4816 showline(logline, 0);
\r
4819 #ifdef USESHORTINT
\r
4820 return (short int) k;
\r
4826 void LZWdecompress (unsigned char *StripData, FILE *input)
\r
4828 #ifdef USESHORTINT
\r
4829 short int Code, OldCode;
\r
4831 int Code, OldCode;
\r
4833 unsigned int nlen;
\r
4834 unsigned char *s = StripData;
\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
4845 // #ifdef DEBUGLZW
\r
4846 // if (traceflag) {
\r
4847 // sprintf(logline, "%4d ", Code); /* debugging */
\r
4848 // showline(logline, 0);
\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
4861 if (Code == EOD) break;
\r
4862 s = WriteString(s, Code);
\r
4864 } /* end of CLEAR case */
\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
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
4884 " Code (%d) > TableIndex (%d) CodeLength %d ",
\r
4885 Code, TableIndex, CodeLength);
\r
4886 showline(logline, 1);
\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
4897 } /* end of Code *not* in Table case */
\r
4898 } /* end of *not* CLEAR case */
\r
4899 } /* end of not EOD loop */
\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
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
4916 /* if (verboseflag) printf("EOD "); */
\r
4917 /* reset table for next one */
\r
4918 ResetStringTable(0);
\r
4922 sprintf(logline, "Now at byte %ld in file\n", ftell(input));
\r
4923 showline(logline, 0);
\r
4928 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\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
4935 long SetupStrip (FILE *input, int k) /* 96/Nov/17 */
\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
4945 sprintf(logline, "Strip %d Offset %ld ByteCount %ld\n",
\r
4946 k, StripOffset, StripByteCount);
\r
4947 showline(logline, 0);
\r
4950 if (fseek (input, StripOffset, SEEK_SET))
\r
4952 showline("Error in seek to StripOffset", 1); /* ??? */
\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
4961 /* Copy a row from far space used by LZW to near space used for output */
\r
4963 void CopyRow (unsigned char *lpBuffer, unsigned char *StripData,
\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
4976 n = (int) BufferLength; /* prevent heap corruption */
\r
4978 for (k = 0; k < n; k++) *s++ = *t++;
\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
4984 int DecodeLZW (FILE *output, FILE *input, unsigned char *lpBuffer)
\r
4986 int k, row = 0, i, j, n, m, flag = 0;
\r
4987 /* unsigned char *StripData; */
\r
4990 nlen = (long) BufferLength * RowsPerStrip;
\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
5000 StripDataLen = (unsigned int) nlen;
\r
5002 if (traceflag) { /* debugging */
\r
5003 sprintf(logline, " Allocating %u bytes for Strip Buffer\n", StripDataLen);
\r
5004 showline(logline, 0);
\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
5014 // or more serious exit(1) ???
\r
5016 InitializeStringTable();
\r
5017 /* checkheap("AFTER INITIALIZE", 0); */ /* debugging only 1995/Nov/10 */
\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
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
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
5044 /* (unsigned char) (lpBuffer[j] + lpBuffer[j-SamplesPerPixel]); */
\r
5045 (unsigned char) (lpBuffer[j] + lpBuffer[j-SamplesPerPixelX]);
\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
5060 if (flag) break; */
\r
5064 ResetStringTable(1); /* redundant ? */
\r
5066 if (traceflag) { /* debugging */
\r
5067 sprintf(logline, " Freeing %u bytes Strip Buffer\n", StripDataLen);
\r
5068 showline(logline, 0);
\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
5085 /* InitializeStringTable AllocString - may need to DeAllocString eventually */
\r
5087 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
5089 /* change long => int where sensible */
\r
5091 /* complain if samplesperpixel other than one */ /* no color support */
\r
5092 /* quit early (before writing header) if 24 bit image */
\r
5094 /* implement CCIT Huffman decompression also OK */
\r
5095 /* implement LZW decompression also */ /* need Predictor also ? */
\r
5097 /* implement gray scale response curve ? */ /* although ignored by some apps */
\r
5099 /* II* or MM* followed by four byte offset to first IFD (often == 8) */
\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
5104 /* Field entries sorted in ascending order on tag: */
\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
5111 /* if bAllowColor is false, maybe just use green component and `image' */
\r
5113 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
5115 BOOL bTIFFAllow=1;
\r
5117 /* x * (numer / denom) 1995/Oct/12 */
\r
5118 /* or use MulDiv ??? */
\r
5120 long MulRatio (long x, unsigned long numer, unsigned long denom)
\r
5123 if (denom == 0 || numer == 0) return 0;
\r
5124 if ((numer % denom) == 0) {
\r
5125 numer = numer / denom;
\r
5128 if ((denom % numer) == 0) {
\r
5129 denom = denom / numer;
\r
5132 while (denom > 65536 || numer > 65536) {
\r
5133 denom = denom >> 1;
\r
5134 numer = numer >> 1;
\r
5136 result = x / denom * numer;
\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
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
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
5154 int showtiffhere (FILE *output, char *filename, long dwidth, long dheight,
\r
5155 double xscale, double yscale, int nifd)
\r
5158 if (bTIFFAllow != 0) {
\r
5159 /* if (dheight == 0) { */ /* need aspect ratio from TIFF file */
\r
5160 if (dheight == 0 || dwidth == 0) {
\r
5162 sprintf(logline, " Prescanning %s\n", filename);
\r
5163 showline(logline, 0);
\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
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
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
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
5191 printf(" dwidth %ld dheight %ld\n", dwidth, dheight); */
\r
5192 if (ResolutionUnit == 1) { /* what to do ? */
\r
5193 showline(" resolution == 1", 1);
\r
5195 else if (ResolutionUnit == 2) { /* 72.27 pt per in */
\r
5196 dwidth = dwidth / 100 * 7227;
\r
5197 dheight = dheight / 100 * 7227;
\r
5199 else if (ResolutionUnit == 3) { /* 28.45 pt per cm */
\r
5200 dwidth = dwidth / 100 * 2845;
\r
5201 dheight = dheight / 100 * 2845;
\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
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
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
5223 sprintf(logline, " dwidth %ld dheight %ld", dwidth, dheight);
\r
5224 showline(logline, 0);
\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
5233 /* if (nifd >= 0) readimagefile(output, filename, dwidth, dheight, nifd, 1); */
\r
5235 flag = readimagefile(output, filename, dwidth, dheight, nifd, 0);
\r
5241 /* have the \special in line at this point - entry point from dvispeci.c */
\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
5253 /* made common to save string space */
\r
5255 void dontunderline (void)
\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
5263 /* name => buffer convert \ to / and change : to / and so on */
\r
5265 void platformindependent (char *buffer, char *name) { /* 96/Mar/3 */
\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
5274 memmove(buffer+1, buffer, strlen(buffer)+1);
\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
5283 /* clean up hyper-text mark name for PostScript Distiller 95/Feb/25 */
\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
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
5296 /* #define MAXPSNAME 32 */ /* old limit */
\r
5297 #define MAXPSNAME 63 /* 98/Jul/16 */
\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
5304 /* what if the string is quoted ? */ /* \b is not strictly forbidden */
\r
5306 /* what about #? not allowed in PDF name. but we want to pass it here? */
\r
5308 /* char *badcharinname=" \t\n\r\f()<>[]{}/%"; */
\r
5309 char *badcharinname=" \b\t\n\f\r()<>[]{}/%";
\r
5311 void cleanupname (char *name)
\r
5314 #ifdef DEBUGCLEANUP
\r
5317 sprintf(logline, " CLEANUPNAME: %s", name); /* debugging */
\r
5318 showline(logline, 0);
\r
5321 if (*name == '\0')
\r
5323 showline(" ERROR: empty mark or button", 1);
\r
5326 while ((s = strpbrk(s, badcharinname)) != NULL)
\r
5328 if (strlen(name) > MAXPSNAME) *(name+MAXPSNAME) = '\0'; /* 96/Aug/12 */
\r
5329 #ifdef DEBUGCLEANUP
\r
5332 sprintf(logline, " CLEANEXIT: %s", name); /* debugging */
\r
5333 showline(logline, 0);
\r
5336 if (*name == '\0') showline(" ERROR: empty mark or button", 1);
\r
5339 /* support for old textcolor / rulecolor specials */
\r
5341 int oldcolor (FILE *output, FILE *input)
\r
5345 /* old text color support */
\r
5346 if (strcmp(line, "textcolor") == 0) {
\r
5347 (void) scan_special (input, line, MAXLINE);
\r
5349 sprintf(logline, " %s ", line);
\r
5350 showline(logline, 0);
\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
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
5367 if (textred == 0.0 && textgreen == 0.0 && textblue == 0.0) {
\r
5368 // fputs("\nblack\n", output);
\r
5369 PSputs("\nblack\n", output);
\r
5371 } /* treat 0 0 0 same as revert ? */
\r
5373 sprintf(logline, "\n%lg %lg %lg rgb\n",
\r
5374 textred, textgreen, textblue);
\r
5375 PSputs(logline, output);
\r
5383 // fprintf(output, "\n%lg %lg %lg setrgbcolor\n",
\r
5387 /* old rule color support */
\r
5388 else if (strcmp(line, "rulecolor") == 0) {
\r
5389 (void) scan_special (input, line, MAXLINE);
\r
5392 sprintf(logline, " %s ", line);
\r
5393 showline(logline, 0);
\r
5396 if (!bKeepBlack) {
\r
5397 if (strstr(line, "revert") != NULL) {
\r
5398 rulered = 0.0; rulegreen = 0.0; ruleblue = 0.0;
\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
5408 if (rulered == 0.0 && rulegreen == 0.0 && ruleblue == 0.0)
\r
5410 else bRuleColor = 1;
\r
5419 /* old figurecolor support */
\r
5420 else if (strcmp(line, "figurecolor") == 0) {
\r
5421 (void) scan_special (input, line, MAXLINE);
\r
5424 sprintf(logline, " %s ", line);
\r
5425 showline(logline, 0);
\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
5434 else if ((n = sscanf(line, "%lg %lg %lg %lg %lg %lg",
\r
5435 &figurered, &figuregreen, &figureblue,
\r
5436 &backred, &backgreen, &backblue)) >= 3) {
\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
5444 backred = backred / 255.0;
\r
5445 backgreen = backgreen / 255.0;
\r
5446 backblue = backblue / 255.0;
\r
5449 if (n < 6) { /* default background color */
\r
5450 backred = 1.0; backgreen = 1.0; backblue = 1.0;
\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
5465 /* old reverse video support */
\r
5466 else if (strcmp(line, "reversevideo") == 0) {
\r
5467 (void) scan_special (input, line, MAXLINE);
\r
5470 sprintf(logline, " %s ", line);
\r
5471 showline(logline, 0);
\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
5485 // fputs("{} settransfer\n", output);
\r
5486 PSputs("{} settransfer\n", output);
\r
5491 else dontunderline();
\r
5495 /* new to allow quoted file names with spaces 98/Jul/9 */
\r
5497 char *scaninsert(char *line, char *filename)
\r
5500 char *t = filename;
\r
5504 while (*s <= ' ' && *s != '\0') s++; /* step over white space */
\r
5506 if (*s == '\0') return 0;
\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
5513 else { /* normal file name */
\r
5514 while (*s > ' ' && *s != '\0') *t++ = *s++;
\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
5521 sprintf(logline, "line: %s filename: %s\n",
\r
5523 showline(logline, 0);
\r
5528 /* returns zero if *not* one of our DVIWindo \specials */
\r
5530 int newspecials (FILE *output, FILE *input)
\r
5533 long dheight, dwidth;
\r
5534 char filename[FILENAME_MAX];
\r
5537 char *slaunch=NULL;
\r
5538 char *sparams=NULL;
\r
5539 char *spage=NULL; /* 96/May/4 */
\r
5541 int npage=0, noffset=0; /* 96/May/4 */
\r
5543 int URLflag=0; /* 97/Jan/7 */
\r
5544 double xscale, yscale;
\r
5549 sprintf(logline, " %s:", line);
\r
5550 showline(logline, 0);
\r
5554 /* insert TIFF or BMP image */
\r
5555 if (strcmp(line, "insertimage") == 0)
\r
5557 /* (void) scan_special (input, line, MAXLINE); */
\r
5558 (void) scan_special_raw (input, line, MAXLINE);
\r
5562 sprintf(logline, " %s ", line);
\r
5563 showline(logline, 0);
\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
5573 sscanf(s, "%ld %ld %d", &dwidth, &dheight, &nifd); /* normal */
\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
5583 if (*filename != '\0') { /* need at least file name */
\r
5584 // clock_t sclock, eclock;
\r
5585 // sclock = clock();
\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
5592 else dontunderline();
\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
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
5607 /* (void) scan_special (input, line, MAXLINE); */
\r
5608 (void) scan_special_raw (input, line, MAXLINE); /* fix 97/Nov/11 */
\r
5610 sprintf(logline, " %s ", line);
\r
5611 showline(logline, 0);
\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
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
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
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
5646 /* (void) scan_special (input, line, MAXLINE); */
\r
5647 (void) scan_special_raw (input, line, MAXLINE);
\r
5649 sprintf(logline, " %s ", line);
\r
5650 showline(logline, 0);
\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
5658 /* if (strstr(line, "launch:") != NULL) {
\r
5659 flush_special(input);
\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
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
5682 /* if (traceflag) printf("npage %d noffset %d spage-line %d\n",
\r
5683 npage, noffset, spage-line); */
\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
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
5693 /* what if npage has already been set ? */
\r
5696 while (*sfile == ' ') sfile++;
\r
5698 printf("npage %d sfile-line %d\n", npage, sfile-line); */
\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
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
5711 "[ /Rect [currentpoint 2 copy exch %ld add exch %ld sub]\n",
\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
5734 while (*sname == ' ') sname++;
\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
5742 sprintf(logline, " /Action << /Subtype /URI /URI (%s) >>\n",
\r
5744 PSputs(logline, output);
\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
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
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
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
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
5780 /* case where a file or URL is specified */
\r
5781 if (sfile != NULL) {
\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
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
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
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
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
5840 /* optional key /Dir (current directory) */
\r
5841 /* optional key /Op (open or print) */
\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
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
5859 else if (traceflag) showline(line, 1);
\r
5861 return 0; /* not a DVIWindo special */
\r
5866 /* proper support for figurecolor \special / bilevel images 1994/March/14 */
\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
5873 int dohptag (FILE *output, FILE *input)
\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
5880 char filename[FILENAME_MAX];
\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
5891 showtiffhere(output, filename, 0, 0, 0, 0, 1);
\r
5892 return 1; /* success */
\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
5899 /* #pragma optimize ("lge", on) */
\r
5901 /* END OF EXPERIMENT */
\r
5903 /* int WINAPI MulDiv(int nNumber, int nNumerator, int nDenominator); */
\r