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 /* Revised 1999 June 13 to run in DLL form */
\r
40 #include <windows.h>
\r
50 // We must define MYLIBAPI as __declspec(dllexport) before including
\r
51 // dvipsone.h, then dvipsone.h will see that we have already
\r
52 // defined MYLIBAPI and will not (re)define it as __declspec(dllimport)
\r
53 #define MYLIBAPI __declspec(dllexport)
\r
54 // #include "dvipsone.h"
\r
57 #include "dvipsone.h"
\r
60 #pragma warning(disable:4100) // unreferenced formal variable
\r
63 #pragma warning(disable:4996)
\r
64 #pragma warning(disable:4127) // conditional expression is constant
\r
70 #include "dvispeci.h"
\r
72 #define DEBUGTIFF /* to get in extra tracing code */
\r
74 /* #define DEBUGBMP */
\r
76 /* #define DEBUGLZWENCODE */
\r
78 /* #define DEBUGRUNLENGTH */
\r
80 /* #define DEBUGCLEANUP */
\r
84 #define LZWCOMPRESSION
\r
86 #define MAXCOLUMNHEX 72
\r
88 #define MAXCOLUMNASCII 75
\r
92 /* constants for LZW compression/decompression tables */
\r
94 #define MAXCODES 4096 /* to deal with up to 12 bit codes */
\r
95 #define MAXCHR 256 /* 2^8 possible bytes */
\r
96 #define CLEAR 256 /* clear string table code */
\r
97 #define EOD 257 /* end of data code */
\r
98 #define FIRSTCODE 258 /* first code available - new string */
\r
101 int bRunLengthFlag; /* Use RunLengthDecode filter 96/Dec/24 */
\r
102 #ifdef LZWCOMPRESSION
\r
103 int bLZWFlag; /* Use LZWDecode filter 96/Dec/30 */
\r
105 /* can have either of the above set, or none, but not both */
\r
108 unsigned char *StripData; /* address of Strip Buffer */
\r
110 unsigned int StripDataLen; /* length of Strip Buffer */
\r
112 long InStripLen; /* length of Strip in file 96/Nov/17 */
\r
116 char infilename[FILENAME_MAX] = "";
\r
118 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
120 /* using definitions in dvispeci.h */
\r
122 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
124 /* #define MAXIMAGE 4096 */ /* maximum rows & columns - sanity check */
\r
126 #define MAXIMAGE 65536 /* maximum rows & columns - sanity check */
\r
128 BOOL bInvertImage = 0; /* should gray levels be inverted ? */
\r
129 BOOL bColorImage = 0; /* is it a color image ? */
\r
130 /* i.e. RGB or color palette */
\r
131 BOOL bExpandColor = 0; /* color palette image - expand to 24 bit */
\r
132 /* set when ColorMapPtr non-NULL */
\r
133 BOOL bCompressColor = 0; /* compress 24 bit color to one byte */
\r
134 /* for non-color PS output device ? */
\r
135 /* and for BMP with gray palette */
\r
136 BOOL bExpandGray = 0; /* has Palette, but Palette is gray */
\r
137 BOOL bGrayFlag = 0; /* non-zero if Palette is gray BMP palette */
\r
138 BOOL bLinearFlag = 0; /* non-zero if palette is linear BMP palette */
\r
139 int PaletteSize = 0; /* number of entries in palette */
\r
141 /* For Windows NT could declare USESHORTINT since 16 bit quantities */
\r
143 /* #define USESHORTINT */
\r
146 unsigned short int *Palette = NULL; /* pointer to palette */
\r
148 unsigned int *Palette = NULL; /* pointer to palette */
\r
151 /* char *eps_magic = "\
\r
152 currentscreen pop\n\
\r
153 {1 add 180 mul cos 1 0.08 add mul exch 2 add 180 mul cos 1 0.08 sub\n\
\r
154 mul add 2 div} bind setscreen % Copyright (C) Y&Y 1989\n\
\r
157 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
159 /* set to 0.0 0.0 0.0 at top of page ? */
\r
163 double textred=0.0; /* color of text */
\r
164 double textgreen=0.0;
\r
165 double textblue=0.0;
\r
169 double rulered=0.0; /* color of rules */
\r
170 double rulegreen=0.0;
\r
171 double ruleblue=0.0;
\r
173 int bFigureColor=0; /* figure color has been specified */
\r
175 double figurered=0.0; /* foreground of figure */
\r
176 double figuregreen=0.0;
\r
177 double figureblue=0.0;
\r
179 double backred=1.0; /* background of figure */
\r
180 double backgreen=1.0;
\r
181 double backblue=1.0;
\r
183 int bReverseVideo=0;
\r
185 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
187 /* Some code imported from DVIWindo winspeci.c */
\r
189 /* Stuff for reading simple uncompressed TIFF files (& PackBits compressed) */
\r
191 unsigned int TIFFVersion; /* TIFF version number */
\r
192 unsigned int bLeastFirst=1; /* least significant first */
\r
193 unsigned int IFDCount; /* number of items image file directory */
\r
194 unsigned long IFDPosition; /* position of image file directory */
\r
196 //#pragma optimize ("lge", off)
\r
198 /* static unsigned short int ureadtwo(FILE *input) {
\r
199 unsigned short int c, d;
\r
200 c = (unsigned short int) getc(input);
\r
201 d = (unsigned short int) getc(input);
\r
202 if (bLeastFirst != 0) return ((d << 8) | c);
\r
203 else return ((c << 8) | d);
\r
206 static unsigned int ureadtwo(FILE *input)
\r
209 c = (unsigned int) getc(input);
\r
210 d = (unsigned int) getc(input);
\r
211 if (bLeastFirst != 0)
\r
212 return ((d << 8) | c);
\r
214 return ((c << 8) | d);
\r
217 static unsigned long ureadfour(FILE *input)
\r
219 unsigned long c, d, e, f;
\r
220 c = (unsigned long) getc(input);
\r
221 d = (unsigned long) getc(input);
\r
222 e = (unsigned long) getc(input);
\r
223 f = (unsigned long) getc(input);
\r
224 if (bLeastFirst != 0)
\r
225 return ((((((f << 8) | e) << 8) | d) << 8) | c);
\r
227 return ((((((c << 8) | d) << 8) | e) << 8) | f);
\r
230 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
232 /* char *typename[6] = {"", "BYTE ", "ASCII", "SHORT", "LONG ", "RATIO"}; */
\r
234 int typesize[6] = {0, 1, 1, 2, 4, 8}; /* units of length/count */
\r
236 unsigned long TIFFOffset, TIFFLength;
\r
238 long PSOffset, PSLength, MetaOffset, MetaLength; /* not used ? */
\r
240 /* we are ignoring the possibility here that length > 1 and such ... */
\r
242 long indirectvalue (unsigned int type, long length, long offset, FILE *input)
\r
244 long present, val=0;
\r
246 /* UNUSED (length); */
\r
248 if (length > 1 && traceflag)
\r
250 sprintf(logline, "Length %d\n", length);
\r
251 showline(logline, 0);
\r
254 present = ftell(input); /* remember where we are */
\r
255 if (fseek(input, (long) (offset + TIFFOffset), SEEK_SET) != 0)
\r
257 sprintf(logline, " Error in seek %s\n", " to indirect value\n");
\r
258 showline(logline, 1);
\r
260 if (type == TYPE_LONG) val = (long) ureadfour(input);
\r
261 else if (type == TYPE_SHORT) val = ureadtwo(input);
\r
262 else if (type == TYPE_BYTE) val = getc(input);
\r
263 else showline(" Invalid Indirect Value\n", 1);
\r
264 fseek(input, present, SEEK_SET); /* return to where we were */
\r
268 /* get value of a tag field in TIFF file */
\r
270 long extractvalue (unsigned int type, unsigned long length, long offset, FILE *input)
\r
281 return indirectvalue(type, (long) length, (long) offset, input);
\r
286 return indirectvalue(type, (long) length, (long) offset, input);
\r
291 return indirectvalue(type, (long) length, (long) offset, input);
\r
297 int skipthisimage (FILE *input, unsigned long ifdpos)
\r
301 if(fseek(input, (long) ifdpos + TIFFOffset, SEEK_SET) != 0)
\r
303 sprintf(logline, " Error in seek %s\n", " while skipping image\n");
\r
304 showline(logline, 1);
\r
307 IFDCount = ureadtwo(input); /* How many tags in this IFD */
\r
308 for (k = 0; k < (int) IFDCount; k++) /* read to end of IFD */
\r
310 for (j = 0; j < 12; j++)
\r
311 (void) getc(input);
\r
313 IFDPosition = ureadfour(input); /* get next IFD offset in file */
\r
314 if (IFDPosition == 0) return -1; /* no more IFDs !!! */
\r
318 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
320 /* Must have: ImageWidth, ImageLength, StripOffset, SamplesPerPixel, BitsPerSample */
\r
322 long ImageWidth; /* vital ImageWidth */
\r
323 long ImageLength; /* vital ImageLength */
\r
325 int bytes; /* total bytes per row output used ? */
\r
327 int SamplesPerPixel = 1; /* vital (may be more than 1) */
\r
328 int SamplesPerPixelX = 1; /* SamplesPerPixel-ExtraSamples */
\r
330 int BitsPerSample = 1; /* vital */
\r
332 int ExtraSamples = 0; /* new 99/May/10 */
\r
334 unsigned int compression = 0; /* vital */
\r
335 int Orientation = 1;
\r
336 int Predictor = 1; /* for LZW only */
\r
337 /* 2 implies differencing applied */
\r
338 long StripOffset = -1; /* vital (first strip offset) */
\r
339 long StripOffsetsPtr;
\r
340 int StripOffsetsType;
\r
341 int StripOffsetsLength;
\r
343 long StripByteCount = -1; /* first StripByteCount */
\r
344 long StripByteCountsPtr;
\r
345 int StripByteCountsType;
\r
346 int StripByteCountsLength;
\r
348 int RowsPerStrip = 0;
\r
350 int StripsPerImage; /* computed from above */
\r
352 long ColorMapPtr = 0; /* pointer to map in case of Palette Color Images */
\r
354 int PhotometricInterpretation = 1; /* default */
\r
356 int PlanarConfig=1; /* cannot handle 2 ... */
\r
358 int BitsPerPixel; /* BitsPerSample * SamplePerPixel */
\r
359 int BitsPerPixelX; /* BitsPerSample * (SamplePerPixel-ExtraSamples) */
\r
361 long InRowLength; /* number of source bytes from file */
\r
362 long InRowLengthX; /* --- after ExtraSamples removed */
\r
364 long InRowRead; /* bytes to read from input */
\r
365 long BufferLength; /* number of bytes of intermediate data */
\r
366 /* length of lpBuffer allocated space */
\r
367 long OutRowLength; /* number of processed bytes for output */
\r
369 int CurrentStrip; /* for debugging purposes */
\r
371 /* NOTE: MinSampleValue and MaxSampleValue should not affect appearance */
\r
373 /* int MinSampleValue, MaxSampleValue; */ /* never used ? */
\r
375 int ResolutionUnit=2; /* 1 no dimensions, 2 per inch, 3 per cm */
\r
377 /* long xresnum, xresden; */ /* x resolution */
\r
378 /* long yresnum, yresden; */ /* y resolution */
\r
380 unsigned long xresnum, xresden; /* x resolution */ /* 95/Oct/10 */
\r
381 unsigned long yresnum, yresden; /* y resolution */ /* 95/Oct/10 */
\r
383 int hptagflag=0; /* non-zero if call from HPTAG */
\r
384 /* may need something more elaborate hleft / hright and vhigh / vlow */
\r
386 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
388 /* read the tag fields in the TIFF file, ignore ones we don't care about */
\r
390 int readfields (FILE *input, unsigned long ifdpos)
\r
392 unsigned int k, tag, type;
\r
393 unsigned long length, offset;
\r
397 if (traceflag) showline("Now reading TIFF images fields\n", 0);
\r
400 if (fseek(input, (long) ifdpos + TIFFOffset, SEEK_SET) != 0)
\r
402 sprintf(logline, " Error in seek %s\n", " while reading tags");
\r
403 showline(logline, 1);
\r
406 IFDCount = ureadtwo(input); /* How many tags in this IFD */
\r
408 ImageWidth = ImageLength = -1;
\r
409 SamplesPerPixel = BitsPerSample = 1;
\r
410 ExtraSamples = compression = 0;
\r
412 StripOffset = StripByteCount = -1;
\r
414 PhotometricInterpretation = 1; /* default */
\r
415 PlanarConfig = Predictor = 1;
\r
416 ColorMapPtr = 0; /* pointer to map in case of Palette Color Images */
\r
417 /* MinSampleValue = -1; MaxSampleValue = -1; */
\r
418 /* xresnum = yresnum = 72; */
\r
419 xresnum = yresnum = nDefaultTIFFDPI;
\r
420 xresden = yresden = 1;
\r
421 ResolutionUnit = 2;
\r
423 for (k = 0; k < IFDCount; k++)
\r
425 tag = ureadtwo(input); /* tag - key */
\r
426 type = ureadtwo(input); /* value type */
\r
427 if (tag == 0 && type == 0) { /* invalid */
\r
428 c = getc(input); ungetc(c, input);
\r
429 sprintf(logline, " Tag: %u Type: %u (k %d c %d)\n",
\r
431 showline(logline, 1);
\r
435 c = getc(input); ungetc(c, input);
\r
439 sprintf(logline, " Tag: %u Type: %u (k %d c %d)\n", tag, type, k, c);
\r
440 showline(logline, 1);
\r
443 /* break; */ /* removed 98/Sep/22 */
\r
445 length = ureadfour(input); /* `length' (better named `count') */
\r
447 if (type == TYPE_LONG) offset = ureadfour(input);
\r
448 else if (type == TYPE_SHORT) {
\r
449 offset = ureadtwo(input);
\r
450 (void) ureadtwo(input); /* should be zero */
\r
452 else if (type == TYPE_BYTE) {
\r
453 offset = getc(input);
\r
454 (void) getc(input);(void) getc(input);(void) getc(input);
\r
456 else offset = ureadfour(input); /* for ratio e.g. */
\r
458 else offset = ureadfour(input); /* value */
\r
462 ImageWidth = extractvalue(type, length, (long) offset, input);
\r
465 ImageLength = extractvalue(type, length, (long) offset, input);
\r
467 case BITSPERSAMPLE:
\r
469 (int) extractvalue(type, length, (long) offset, input);
\r
471 case EXTRASAMPLES: /* 1999/May/10 */
\r
473 (int) extractvalue(type, length, (long) offset, input);
\r
477 (unsigned int) extractvalue(type, length, (long) offset, input);
\r
481 (int) extractvalue(type, length, (long) offset, input);
\r
483 case SAMPLESPERPIXEL:
\r
485 (int) extractvalue(type, length, (long) offset, input);
\r
489 (int) extractvalue(type, length, (long) offset, input);
\r
492 StripOffsetsPtr = offset;
\r
493 StripOffsetsType = type;
\r
494 StripOffsetsLength = (int) length;
\r
495 StripOffset = extractvalue(type, length, (long) offset, input);
\r
497 case STRIPBYTECOUNTS:
\r
498 StripByteCountsPtr = offset;
\r
499 StripByteCountsType = type;
\r
500 StripByteCountsLength = (int) length;
\r
501 StripByteCount = extractvalue(type, length, (long) offset, input);
\r
505 (int) extractvalue(type, length, (long) offset, input);
\r
507 /* case MINSAMPLEVALUE:
\r
508 MinSampleValue = (int) extractvalue(type, length, (long) offset, input);
\r
510 /* case MAXSAMPLEVALUE:
\r
511 MaxSampleValue = (int) extractvalue(type, length, (long) offset, input);
\r
514 xresnum = indirectvalue(TYPE_LONG, 1, (long) offset, input);
\r
515 xresden = indirectvalue(TYPE_LONG, 1, (long) offset+4, input);
\r
518 yresnum = indirectvalue(TYPE_LONG, 1, (long) offset, input);
\r
519 yresden = indirectvalue(TYPE_LONG, 1, (long) offset+4, input);
\r
521 case RESOLUTIONUNIT:
\r
522 ResolutionUnit = (int) extractvalue(type, length, (long) offset, input);
\r
524 case PHOTOMETRICINTERPRETATION:
\r
525 PhotometricInterpretation =
\r
526 (int) extractvalue(type, length, (long) offset, input);
\r
530 (int) extractvalue(type, length, (long) offset, input);
\r
533 /* ColorMap = extractvalue(type, length, (long) offset, input); */
\r
534 ColorMapPtr = offset;
\r
535 /* Assume the type is SHORT (16 bit per entry) */
\r
536 /* Assume the length is 3 * 2 ^ BitsPerSample - 1 */
\r
538 default: /* ignore unknown tags */
\r
545 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
547 int computeheader(void);
\r
548 void writepsheader(FILE *, long, long);
\r
549 void writepstrailer(FILE *);
\r
550 int readpackbits(unsigned char *lpBuffer, FILE *input, int RowLength);
\r
551 int huffmanrow(unsigned char *lpBuffer, FILE *input, int width);
\r
552 int DecodeLZW(FILE *output, FILE *input, unsigned char *lpBuffer);
\r
553 void expandcolor(unsigned char *s, long width);
\r
554 void expandgray(unsigned char *s, long width);
\r
555 void compresscolor(unsigned char *s, long width);
\r
556 int writearow(FILE *output, unsigned char *s, unsigned long width);
\r
559 void ASCIIinitfilter(FILE *output);
\r
560 void ASCIIflushfilter(FILE *output);
\r
561 void RUNinitfilter(FILE *output);
\r
562 void RUNflushfilter(FILE *output);
\r
563 #ifdef LZWCOMPRESSION
\r
564 void LZWinitfilter(FILE *output);
\r
565 void LZWflushfilter(FILE *output);
\r
566 void LZWput(int, FILE *);
\r
570 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
572 /* Remember to deallocate at end */ /* Read color map from TIFF image */
\r
574 /* do we need to use unsigned short for NT ? */
\r
576 int ReadColorMap (FILE *input, long ColorMapPtr, int BitsPerSample)
\r
581 /* should make all these unsigned short int instead for NT */
\r
583 unsigned short int *PalettePtr;
\r
585 unsigned int *PalettePtr;
\r
590 unsigned short int *PaletteRed;
\r
591 unsigned short int *PaletteGreen;
\r
592 unsigned short int *PaletteBlue;
\r
594 unsigned int *PaletteRed;
\r
595 unsigned int *PaletteGreen;
\r
596 unsigned int *PaletteBlue;
\r
600 /* need three tables each of 2 ^ BitsPerSample integers */
\r
601 n = 1 << BitsPerSample; /* integers per table */
\r
602 PaletteSize = n; /* remember for later */
\r
603 nint = n * 3; /* total number of integers */
\r
607 sprintf(logline, "Reading Color Map of size %d\n", n);
\r
608 showline(logline, 1);
\r
611 /* check following allocation in NT ? should we use short int ? */
\r
613 Palette = (unsigned short int *)
\r
614 malloc(nint * sizeof(unsigned short int));
\r
616 /* Palette = (unsigned int *) malloc(nint * 2); */ /* bytes */
\r
617 Palette = (unsigned int *) malloc(nint * sizeof(unsigned int));
\r
619 if (Palette == NULL)
\r
621 showline(" ERROR: Unable to allocate memory\n", 1);
\r
623 // or more serious exit(1) ???
\r
625 present = ftell(input);
\r
629 sprintf(logline, "Going to ColorMap at %ld + %lu\n",
\r
630 ColorMapPtr, TIFFOffset);
\r
631 showline(logline, 1);
\r
634 if (fseek (input, (long) ColorMapPtr + TIFFOffset, SEEK_SET) != 0)
\r
636 sprintf(logline, " Error in seek %s\n", " to ColorMap");
\r
637 showline(logline, 1);
\r
639 PalettePtr = Palette;
\r
640 /* Following shoud work in NT even if we use int instead of short */
\r
641 for (k = 0; k < nint; k++) *PalettePtr++ = ureadtwo (input);
\r
642 fseek (input, present, SEEK_SET);
\r
645 PaletteRed = Palette;
\r
646 PaletteGreen = PaletteRed + PaletteSize;
\r
647 PaletteBlue = PaletteGreen + PaletteSize;
\r
649 bGrayFlag = 1; // non-zero if palette is all grays
\r
650 for (k = 0; k < n; k++)
\r
652 if (PaletteRed[k] != PaletteGreen[k] ||
\r
653 PaletteGreen[k] != PaletteBlue[k])
\r
658 } // bGrayFlag presently not used
\r
660 bLinearFlag = 0; // non-zero if Palette is simply linear
\r
663 for (k = 0; k < n; k++)
\r
665 if (PaletteRed[k] != (unsigned int) (k * 255 / (n-1))) {
\r
670 } // bLinearFlag presently not used
\r
672 // bGrayFlag and bLinearFlag could be used to produce smaller output files
\r
677 PaletteRed = Palette;
\r
678 PaletteGreen = PaletteRed + PaletteSize;
\r
679 PaletteBlue = PaletteGreen + PaletteSize;
\r
680 for (k = 0; k < n; k++) {
\r
682 sprintf(logline, "INX %d\tR %u\tG %u\tB %u\n",
\r
683 k, PaletteRed[k], PaletteGreen[k], PaletteBlue[k]);
\r
684 showline(logline, 0);
\r
692 /* returns -1 if output error */ /* given InRowLengthX */
\r
693 /* expand color if needed - or expand gray if needed */
\r
694 /* compress color if needed */
\r
695 /* write out a row of image */
\r
697 int ProcessRow (FILE *output, unsigned char *lpBuffer, long InRowLengthX,
\r
698 long BufferLength, long OutRowLength)
\r
701 printf("ProcessRow InRowLengthX %d\n", InRowLengthX); */ /* DEBUGGING */
\r
703 printf("bExpandColor %d bExpandGray %d bCompressColor %d\n",
\r
704 bExpandColor, bExpandGray, bCompressColor); */ /* DEBUGGING */
\r
706 if (traceflag) fflush(stdout); /* DEBUGGING ONLY */
\r
708 if (bExpandColor) expandcolor(lpBuffer, InRowLengthX);
\r
709 else if (bExpandGray) expandgray(lpBuffer, InRowLengthX);
\r
710 if (bCompressColor) compresscolor(lpBuffer, BufferLength);
\r
712 if (traceflag) { /* DEBUGGING */
\r
713 sprintf(logline, "ProcessRow OutRowLength %d\n", OutRowLength);
\r
714 showline(logline, 0);
\r
717 if (writearow(output, lpBuffer, OutRowLength) != 0) return -1;
\r
721 /* Throw out ExtraSamples in SamplesPerPixel */
\r
722 /* IMPORTANT NOTE: assume for the moment samples are one byte */
\r
724 int RemoveExtraSamples (unsigned char *lpBuffer, int InRowLength)
\r
726 unsigned char *s = lpBuffer;
\r
727 unsigned char *t = lpBuffer;
\r
728 int i, k, n = InRowLength / SamplesPerPixel;
\r
733 sprintf(logline, "RemoveExtraSamples InRowLength %d\n", InRowLength);
\r
734 showline(logline, 1);
\r
737 if (ExtraSamples == 0) return InRowLength;
\r
738 /* check that BitsPerSample == 8 ??? */
\r
739 for (k = 0; k < n; k++) {
\r
740 for (i = 0; i < SamplesPerPixelX; i++) *t++ = *s++;
\r
743 return (int) (t - lpBuffer);
\r
746 /* readflag != 0 when reading file only to get tag fields */
\r
748 int readTIFFfile (FILE *output, FILE *input,
\r
749 long dwidth, long dheight, int nifd, int readflag)
\r
751 /* int i, j, flag; */
\r
753 /* long present; */
\r
754 /* int k, color, n; */
\r
755 unsigned long ImageSize;
\r
756 unsigned int nread;
\r
757 unsigned char *lpBuffer=NULL;
\r
760 TIFFVersion = ureadtwo(input);
\r
761 if (TIFFVersion != TIFF_VERSION)
\r
763 sprintf(logline, " Incorrect TIFF version code %d\n", TIFFVersion);
\r
764 showline(logline, 1);
\r
765 return -1; /* bad version number for TIFF file */
\r
768 /* Skip to desired image (if not first in file) */
\r
770 IFDPosition = ureadfour(input); /* get first IFD offset in file */
\r
771 while (nifd-- > 1) {
\r
772 if (skipthisimage(input, IFDPosition) < 0)
\r
774 sprintf(logline, " ERROR: Subimage %d not found", nifd);
\r
775 showline(logline, 1);
\r
780 /* Now at desired image */
\r
781 (void) readfields(input, IFDPosition); /* read tag fields in TIFF file */
\r
783 IFDPosition = ureadfour(input); /* get next IFD offset in file */
\r
785 /* if (readflag == 0) return -1; */ /* only scanning for width & height */
\r
786 if (readflag != 0) return -1; /* only scanning for width & height */
\r
788 bColorImage = 0; /* if image is RGB or Palette color */
\r
789 bExpandColor = 0; /* comes on if Palette color image */
\r
790 bExpandGray = 0; /* comes on if Palette is gray */
\r
791 bCompressColor = 0; /* if image is colored and not `colorimage' */
\r
792 if (ColorMapPtr) { /* is it a palette color image ? */
\r
793 (void) ReadColorMap(input, ColorMapPtr, BitsPerSample);
\r
801 sprintf(logline, "Width %ld, Height %ld, BitsPerSample %d, SamplesPerPixel %d\n",
\r
802 ImageWidth, ImageLength, BitsPerSample, SamplesPerPixel);
\r
803 showline(logline, 1);
\r
810 sprintf(logline, "Compression %u PhotometricInterpretation %d\n",
\r
811 compression, PhotometricInterpretation);
\r
812 showline(logline, 1);
\r
817 if (traceflag && Predictor != 1)
\r
819 sprintf(logline, "Predictor %d\n", Predictor);
\r
820 showline(logline, 1);
\r
824 if (ExtraSamples > 0) SamplesPerPixelX = SamplesPerPixel-ExtraSamples;
\r
825 else SamplesPerPixelX = SamplesPerPixel;
\r
827 BitsPerPixel = BitsPerSample * SamplesPerPixel;
\r
828 if (ExtraSamples > 0) BitsPerPixelX = BitsPerSample * SamplesPerPixelX;
\r
829 else BitsPerPixelX = BitsPerPixel;
\r
831 InRowLength = (ImageWidth * BitsPerPixel + 7) / 8; /* row length file */
\r
832 if (ExtraSamples > 0)InRowLengthX = (ImageWidth * BitsPerPixelX + 7) / 8;
\r
833 else InRowLengthX = InRowLength;
\r
835 if (RowsPerStrip > 0)
\r
836 StripsPerImage = (int) ((ImageLength + RowsPerStrip - 1) / RowsPerStrip);
\r
837 else StripsPerImage = 1;
\r
839 if (bExpandColor) BufferLength = ImageWidth * 3;
\r
840 else if (bExpandGray) BufferLength = ImageWidth;
\r
841 else BufferLength = InRowLength;
\r
843 /* do compression of 24 bit color if use of `colorimage' not allowed */
\r
844 /* if (bitsperpixel == 24 && bCompressFlag != 0 && forceice == 0) */
\r
845 /* if (BitsPerPixel == 24 && bCompressFlag != 0) */
\r
846 /* if ((BitsPerPixel == 24 || bExpandColor) && bAllowColor == 0) */
\r
847 if ((BitsPerPixelX == 24 || bExpandColor) && ! bAllowColor)
\r
849 sprintf(logline, " color image (bits %d expand %d): use `*c' flag?",
\r
850 BitsPerPixelX, bExpandColor); /* 96/Aug/15 */
\r
851 // showline(logline, 1);
\r
852 showline(logline, 0); // reduce severity 2000 March 16
\r
853 bCompressColor = 1;
\r
854 OutRowLength = BufferLength / 3;
\r
856 else OutRowLength = BufferLength;
\r
861 sprintf(logline, "InRowLength %ld BufferLength %ld OutRowLength %ld\n",
\r
862 InRowLength, BufferLength, OutRowLength);
\r
863 showline(logline, 1);
\r
867 /* deal with GhostScript TIFF file format with gaps */ /* 94/Dec/16 */
\r
868 /* shouldn't this only kick in if we are not using (LZW) compression ? */
\r
869 if (bGhostHackFlag) { /* made conditional 95/Nov/10 */
\r
870 if (InRowLength + 1 == StripByteCount)
\r
872 InRowLength++; /* a hack */
\r
875 /* should also increase BufferLength allocation ? 95/Nov/10 */
\r
878 bRunLengthFlag = 0;
\r
879 if (bAllowCompression) {
\r
880 /* Use runlength encoding if monochrome *or* if original uses it */
\r
881 /* if (BitsPerSample == 1 && SamplesPerPixel == 1) */
\r
882 if (BitsPerSample == 1 && SamplesPerPixelX == 1)
\r
883 bRunLengthFlag = 1;
\r
884 if (compression == PACK_BITS) bRunLengthFlag = 1;
\r
885 #ifdef LZWCOMPRESSION
\r
887 /* Use LZW if runlength encoding not chosen */
\r
888 if (bRunLengthFlag == 0)
\r
890 // if (compression == LZW_COMPRESSION) bLZWFlag = 1;
\r
891 // else; bLZWFlag = 1 /* otherwise use LZW */
\r
898 if (computeheader() != 0) return -1; /* noticed format not supported? */
\r
900 writepsheader(output, dwidth, dheight);
\r
902 /* following should already be taken care of in `computeheader' */
\r
903 /* if (compression > 1 && compression != PACK_BITS) */
\r
904 if (compression > TIFF_CCITT && compression != LZW_COMPRESSION &&
\r
905 compression != PACK_BITS)
\r
907 sprintf(logline, " ERROR: Unknown compression scheme (%d)", compression);
\r
908 showline(logline, 1);
\r
912 /* ImageSize = (unsigned long) InRowLength * ImageLength; */
\r
913 ImageSize = (unsigned long) InRowLengthX * ImageLength;
\r
914 /* check whether values reasonable */
\r
915 if (ImageSize == 0)
\r
917 sprintf(logline, " ERROR: Zero image size, %d %d (%s)",
\r
918 InRowLengthX, ImageLength, "readTIFFfile");
\r
919 showline(logline, 1);
\r
922 if (ImageWidth > MAXIMAGE || ImageLength > MAXIMAGE || /* bad data ? */
\r
923 ImageSize > 67108864) { /* arbitrary limits (to catch bad files) */
\r
925 " ERROR: image file too large\n(%ld x %ld (%d) => %ld bytes)",
\r
926 ImageWidth, ImageLength, BitsPerPixel, ImageSize);
\r
927 showline(logline, 1);
\r
930 if (ImageWidth < 0 || ImageLength < 0 || /* missing fields */
\r
931 StripOffset < 0) { /* missing fields */
\r
932 showline(" ERROR: TIFF file missing required tags", 1);
\r
936 if (fseek(input, (long) StripOffset + TIFFOffset, SEEK_SET) != 0)
\r
938 sprintf(logline, " Error in seek %s\n", " to StripOffset\n");
\r
939 showline(logline, 1);
\r
943 /* Maybe use far memory ? */ /* lot of changes if we do this ... */
\r
944 /* Maybe don't use if LZW compression ? */
\r
945 /* if (compression != LZW_COMPRESSION) */
\r
946 /* if ((lpBuffer = malloc((int) BufferLength)) == NULL) { */
\r
947 /* Accomodate GhostScript gap bug work around ... just in case 95/Nov/10 */
\r
948 /* nLen = BufferLength + 1; */
\r
949 nLen = (int) ((BufferLength + 3) / 4) * 4;
\r
950 if ((lpBuffer = malloc(nLen)) == NULL)
\r
952 sprintf(logline, " ERROR: Unable to allocate %d bytes\n", nLen);
\r
953 showline(logline, 1);
\r
954 checkexit(1); /* 1995/July/15 ? */
\r
955 // or more serious exit(1) ???
\r
958 /* in case minsamplevalue and maxsamplevalue not given in tags */
\r
959 /* if (MinSampleValue < 0 || MaxSampleValue < 0 ||
\r
960 MinSampleValue == MaxSampleValue) {
\r
961 MinSampleValue = 0; MaxSampleValue = (1 << BitsPerSample) - 1;
\r
962 } */ /* never used */
\r
964 /* Actually go and read the file now ! */
\r
966 /* following should already be taken care of in `computeheader' */
\r
968 if (compression > TIFF_CCITT && compression != LZW_COMPRESSION &&
\r
969 compression != PACK_BITS)
\r
971 sprintf(logline, " ERROR: Unknown compression scheme (%d)", compression);
\r
972 showline(logline, 1);
\r
978 if (compression == PACK_BITS) sprintf(logline, "Using PACK_BITS\n");
\r
979 else if (compression == TIFF_CCITT) sprintf(logline, "Using TIFF_CCITT\n");
\r
980 else if (compression == LZW_COMPRESSION) sprintf(logline, "Using LZW\n");
\r
981 showline(logline, 1);
\r
985 flag = 0; /* flag gets set if EOF hit */
\r
990 ASCIIinitfilter(output); /* 96/Dec/20 */
\r
991 if (bRunLengthFlag) RUNinitfilter(output); /* 96/Dec/24 */
\r
992 #ifdef LZWCOMPRESSION
\r
993 else if (bLZWFlag) LZWinitfilter(output); /* 96/Dec/28 */
\r
998 /* LZW needs to be done by strips, the others can be done by row */
\r
1000 if (compression == LZW_COMPRESSION) DecodeLZW(output, input, lpBuffer);
\r
1002 else { /* else not LZW compression */
\r
1004 for (i = 0; i < (int) ImageLength; i++) { /* read image lines */
\r
1006 if (compression == PACK_BITS) { /* compressed binary file */
\r
1007 if (readpackbits (lpBuffer, input, (int) InRowLength) != 0) {
\r
1012 else if (compression == TIFF_CCITT) { /* CCITT 1D compression */
\r
1013 if (huffmanrow (lpBuffer, input, (int) ImageWidth) != 0) {
\r
1018 else { /* uncompressed file */
\r
1019 nread = fread(lpBuffer, 1, (unsigned int) InRowLength, input);
\r
1020 if (nread != (unsigned int) InRowLength) { /* read a row */
\r
1022 showline("Premature EOF ", 1); /* ??? */
\r
1029 sprintf(logline, "readTIFFFile InRowLength %d\n", InRowLength);
\r
1030 showline(logline, 1);
\r
1033 if (ExtraSamples > 0)
\r
1034 (void) RemoveExtraSamples(lpBuffer, InRowLength); /* 99/May/10 */
\r
1039 sprintf(logline, "readTIFFFile OutRowLength %d BufferLength %d\n",
\r
1040 OutRowLength, BufferLength);
\r
1041 showline(logline, 1);
\r
1045 /* if (ProcessRow (output, lpBuffer, InRowLength, BufferLength, */
\r
1046 if (ProcessRow (output, lpBuffer, InRowLengthX, BufferLength,
\r
1047 OutRowLength) != 0)
\r
1049 showline("\n", 0);
\r
1050 showline("ERROR: Output error ", 1);
\r
1051 perrormod((outputfile != NULL) ? outputfile : "");
\r
1054 /* if (flag != 0) break; *//* hit EOF or other error */
\r
1055 /* check on abort flag here somewhere also ? */
\r
1056 } /* end of this row */
\r
1057 } /* end of not LZW compression */
\r
1059 // Have to flush filters in reverse order
\r
1063 if (bRunLengthFlag) RUNflushfilter(output); /* 96/Dec/24 */
\r
1064 #ifdef LZWCOMPRESSION
\r
1065 else if (bLZWFlag) LZWflushfilter(output); /* 96/Dec/28 */
\r
1067 ASCIIflushfilter(output); /* 96/Dec/20 */
\r
1071 /* now finished reading */ /* maybe use far memory for lpBuffer ? */
\r
1073 if (lpBuffer != NULL) {
\r
1077 if (Palette != NULL) {
\r
1081 writepstrailer(output);
\r
1083 } /* end of readTIFFfile(...) */
\r
1085 /**********************************************************************/
\r
1087 /* following is from windef.h */
\r
1089 typedef unsigned long DWORD;
\r
1091 typedef unsigned char BYTE;
\r
1092 typedef unsigned short WORD;
\r
1093 typedef float FLOAT;
\r
1095 typedef unsigned int UINT;
\r
1097 typedef long LONG;
\r
1099 /* following is from wingdi.h */
\r
1105 #include <pshpack2.h>
\r
1106 typedef struct tagBITMAPFILEHEADER {
\r
1112 } BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
\r
1113 #include <poppack.h>
\r
1115 typedef struct tagBITMAPINFOHEADER {
\r
1121 DWORD biCompression;
\r
1122 DWORD biSizeImage;
\r
1123 LONG biXPelsPerMeter;
\r
1124 LONG biYPelsPerMeter;
\r
1126 DWORD biClrImportant;
\r
1127 } BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
\r
1129 #include <pshpack1.h>
\r
1130 typedef struct tagRGBTRIPLE {
\r
1135 #include <poppack.h>
\r
1137 typedef struct tagRGBQUAD {
\r
1143 typedef RGBQUAD FAR* LPRGBQUAD;
\r
1147 BITMAPFILEHEADER bmfh;
\r
1149 BITMAPINFOHEADER bmih;
\r
1151 /* RGBQUAD colortable[256]; */
\r
1153 int dpifrom(int res)
\r
1155 double dres = (double) res * 25.4 / 1000.0;
\r
1156 dres = (double) ((int) (dres * 10.0 + 0.5)) / 10.0;
\r
1157 return (int) (dres + 0.5);
\r
1160 int colormaplength; /* ??? */
\r
1161 int mingrey, maxgrey; /* ??? */
\r
1162 int nColors; /* ??? */
\r
1163 long OffBits; /* ??? */
\r
1164 long ImageSize; /* ??? */
\r
1166 /* readflag is non-zero in prescan */
\r
1168 int readBMPfields (FILE *input, int readflag)
\r
1173 ImageWidth = ImageLength = -1;
\r
1174 SamplesPerPixel = BitsPerSample = 1;
\r
1176 compression = 0; Orientation = 1;
\r
1177 StripOffset = -1; StripByteCount = -1;
\r
1178 PhotometricInterpretation = 1; /* default */
\r
1179 PlanarConfig = 1; Predictor = 1;
\r
1180 ColorMapPtr = 0; /* pointer to map in case of Palette Color Images */
\r
1181 mingrey = -1; maxgrey = -1;
\r
1182 xresnum = yresnum = nDefaultTIFFDPI; /* 96/Apr/3 */
\r
1183 xresden = yresden = 1; /* 93/Oct/20 */
\r
1184 ResolutionUnit = 2; /* default dpi */ /* 93/Oct/20 */
\r
1186 fseek(input, 0, SEEK_END);
\r
1187 nLen = ftell(input); /* Length of file */
\r
1188 // fseek(input, 0, SEEK_SET); /* rewind */
\r
1190 fread(&bmfh, sizeof(bmfh), 1, input); /* read file header */
\r
1191 if (bmfh.bfType != (77 * 256 + 66)) { /* "BM" */
\r
1192 sprintf(logline, "Not BMP file %X\n", bmfh.bfType);
\r
1193 showline(logline, 1);
\r
1196 /* "Size of header %lu\n", bmih.biSize compare to nLen ? */
\r
1197 OffBits = bmfh.bfOffBits;
\r
1198 /* "Offset to image %lu\n", bmih.bfOffBits */
\r
1200 if (traceflag && sreadflag)
\r
1202 sprintf(logline, "\nnLen %ld bfSize %ld bfOffBits %ld ",
\r
1203 nLen, bmfh.bfSize, bmfh.bfOffBits);
\r
1204 showline(logline, 1);
\r
1207 /* bmfh.bfSize file size in words ? NO */
\r
1208 /* bmfh.bfOffBits offset from end of header ? NO */
\r
1210 fread(&bmih, sizeof(bmih), 1, input); /* read bitmap info header */
\r
1212 /* if (bmih.biClrUsed > 0) nColor = bmih.biClrUsed;
\r
1213 else if (bmih.biBitCount < 24) nColor = 1 << bmih.biBitCount; */
\r
1214 if (bmih.biClrUsed > 0) nColors = bmih.biClrUsed;
\r
1215 else if (bmih.biBitCount < 24) nColors = 1 << bmih.biBitCount;
\r
1217 ImageWidth = bmih.biWidth;
\r
1218 ImageLength = bmih.biHeight;
\r
1219 if (bmih.biBitCount < 24) {
\r
1220 BitsPerSample = bmih.biBitCount;
\r
1221 SamplesPerPixel = 1;
\r
1224 BitsPerSample = 8;
\r
1225 SamplesPerPixel = 3;
\r
1228 if (traceflag && readflag) {
\r
1229 sprintf(logline, "\nBMIH: %d x %d bits %d x %d",
\r
1230 ImageWidth, ImageLength, SamplesPerPixel, BitsPerSample);
\r
1231 showline(logline, 1);
\r
1233 if (traceflag && readflag) {
\r
1234 sprintf(logline, "\nBMIH: Size %ld Planes %d Compression %d SizeImage %ld ColorsUsed %d",
\r
1235 bmih.biSize, bmih.biPlanes,
\r
1236 bmih.biCompression, bmih.biSizeImage, bmih.biClrUsed);
\r
1237 showline(logline, 1);
\r
1242 /* "Number of image planes %u\n", bmih.biPlanes */
\r
1243 /* "Compression %lu\n", bmih.biCompression */
\r
1244 /* "Size of compressed image %lu\n", bmih.biSizeImage */
\r
1245 /* "Number of colors used %lu %d\n", bmih.biClrUsed */
\r
1247 /* "Horizontal pixel per meter %ld\n", bmih.biXPelsPerMeter */
\r
1248 xresnum = dpifrom(bmih.biXPelsPerMeter);
\r
1249 if (xresnum == 0) xresnum = nDefaultTIFFDPI;
\r
1250 dw = (double) ImageWidth / xresnum;
\r
1251 /* "%d dpi (horizontal)\twidth %lg inch\n", xresnum, dw */
\r
1253 /* "Vertical pixel per meter %ld\n", bmih.biYPelsPerMeter */
\r
1254 yresnum = dpifrom(bmih.biYPelsPerMeter);
\r
1255 if (yresnum == 0) yresnum = nDefaultTIFFDPI;
\r
1256 dh = (double) ImageLength / yresnum;
\r
1257 /* "%d dpi (vertical)\theight %lg inch\n", yresnum, dh */
\r
1259 compression = bmih.biCompression; /* save it */
\r
1261 if (nColors > 0) { /* read color table unless 24 bit */
\r
1262 if (nColors > 256) {
\r
1263 sprintf(logline, " ERROR: too many colors: %d\n", nColors);
\r
1264 showline(logline, 1);
\r
1268 ColorMapPtr = ftell(input); /* color map starts here */
\r
1270 colormaplength = sizeof(RGBQUAD) * nColors;
\r
1271 /* fread(&colortable, sizeof(RGBQUAD), nColors, input); */
\r
1273 /* ColorMapPtr should be zero for 24 bit RGB images */
\r
1274 OffBits= sizeof(bmfh) + sizeof(bmih) + sizeof(RGBQUAD) * nColors;
\r
1275 fseek(input, OffBits, SEEK_SET);
\r
1276 if (bmih.biSizeImage > 0) ImageSize = bmih.biSizeImage;
\r
1277 else ImageSize = nLen - OffBits;
\r
1279 if (traceflag && readflag)
\r
1281 sprintf(logline, "\nImage at %ld size %ld bytes ", OffBits, ImageSize);
\r
1282 showline(logline, 1);
\r
1288 int readBMPPalette (FILE *input, long ColorMapPtr, int BitsPerSample)
\r
1293 /* should make all these unsigned short int instead for NT */
\r
1295 #ifdef USESHORTINT
\r
1296 unsigned short int *PaletteRed;
\r
1297 unsigned short int *PaletteGreen;
\r
1298 unsigned short int *PaletteBlue;
\r
1300 unsigned int *PaletteRed;
\r
1301 unsigned int *PaletteGreen;
\r
1302 unsigned int *PaletteBlue;
\r
1305 /* need three tables each of 2 ^ BitsPerSample integers */
\r
1306 n = 1 << BitsPerSample; /* integers per table */
\r
1309 sprintf(logline, "Reading Color Map of size %d\n", n);
\r
1310 showline(logline, 1);
\r
1313 PaletteSize = n; /* remember for later */
\r
1314 nint = n * 3; /* total number of integers */
\r
1315 /* check following allocation in NT ? should we use short int ? */
\r
1316 #ifdef USESHORTINT
\r
1317 Palette = (unsigned short int *)
\r
1318 malloc(nint * sizeof(unsigned short int));
\r
1320 Palette = (unsigned int *) malloc(nint * sizeof(unsigned int));
\r
1322 if (Palette == NULL) {
\r
1323 showline("Unable to allocate memory\n", 1);
\r
1325 // or more serious exit(1) ???
\r
1327 PaletteRed = Palette;
\r
1328 PaletteGreen = PaletteRed + PaletteSize;
\r
1329 PaletteBlue = PaletteGreen + PaletteSize;
\r
1331 present = ftell(input);
\r
1334 sprintf(logline, "Going to ColorMap at %ld\n", ColorMapPtr);
\r
1335 showline(logline, 1);
\r
1338 if (fseek (input, (long) ColorMapPtr, SEEK_SET) != 0)
\r
1340 sprintf(logline, " Error in seek %s\n", " to ColorMap\n");
\r
1341 showline(logline, 1);
\r
1343 for (k = 0; k < n; k++) {
\r
1344 fread (&rgb, sizeof(RGBQUAD), 1, input);
\r
1345 PaletteRed[k] = rgb.rgbRed;
\r
1346 /* PaletteRed[k] = rgb.rgbRed << 8; */
\r
1347 PaletteGreen[k] = rgb.rgbGreen;
\r
1348 /* PaletteGreen[k] = rgb.rgbGreen << 8; */
\r
1349 PaletteBlue[k] = rgb.rgbBlue;
\r
1350 /* PaletteBlue[k] = rgb.rgbBlue << 8; */
\r
1352 bGrayFlag = 1; /* non-zero if palette has only grays */
\r
1353 for (k = 0; k < n; k++) {
\r
1354 if (PaletteRed[k] != PaletteGreen[k] ||
\r
1355 PaletteGreen[k] != PaletteBlue[k]) {
\r
1360 bLinearFlag = 0; /* non-zero if Palette is simply linear */
\r
1363 for (k = 0; k < n; k++) {
\r
1364 if (PaletteRed[k] != (unsigned int) (k * 255 / (n-1))) {
\r
1367 sprintf(logline, "R[%d] = %d not %d\n",
\r
1368 k, PaletteRed[k], (k * 255 / (n-1)));
\r
1369 showline(logline, 1);
\r
1378 /* fseek (input, present, SEEK_SET); */
\r
1380 if (traceflag) { /* show palette */
\r
1381 for (k = 0; k < n; k++) {
\r
1382 sprintf(logline, "INX %d\tR %u\tG %u\tB %u\n",
\r
1383 k, PaletteRed[k], PaletteGreen[k], PaletteBlue[k]);
\r
1384 showline(logline, 1);
\r
1391 /* readflag != 0 when prescanning to get fields */
\r
1393 int readBMPfile (FILE *output, FILE *input,
\r
1394 long dwidth, long dheight, int readflag)
\r
1396 unsigned char *lpBuffer=NULL;
\r
1399 unsigned int nread;
\r
1401 int c, d, e=0; /* keep compiler happy */
\r
1406 (void) readBMPfields(input, readflag); /* read tag fields in BMP file */
\r
1407 BitsPerPixel = BitsPerSample * SamplesPerPixel; /* for bmp only */
\r
1408 BitsPerPixelX = BitsPerPixel;
\r
1409 if (readflag != 0) return 0; /* if only reading for info */
\r
1410 bColorImage = 0; /* if image is RGB or Palette color */
\r
1411 bExpandColor = 0; /* comes on if Palette color image */
\r
1412 bExpandGray = 0; /* comes on if Palette is gray */
\r
1413 bCompressColor = 0; /* if image is colored and not `colorimage' */
\r
1414 if (ColorMapPtr > 0) { /* do not read if 24 bit color */
\r
1415 readBMPPalette (input, ColorMapPtr, BitsPerSample);
\r
1416 /* check on bGrayFlag and bLinearFlag here ... */
\r
1419 sprintf(logline, "bGrayFLag %d bLinearFlag %d\n",
\r
1420 bGrayFlag, bLinearFlag);
\r
1421 showline(logline, 1);
\r
1424 if (bGrayFlag) bColorImage = 0;
\r
1425 else bColorImage = 1;
\r
1426 if (! bLinearFlag) {
\r
1427 if (bGrayFlag) bExpandGray = 1;
\r
1428 else bExpandColor = 1;
\r
1430 if (BitsPerPixel == 1 && bGrayFlag != 0) {
\r
1431 bExpandGray = 0; /* treat as MonoChrome */
\r
1432 if (bLinearFlag) bInvertImage = 0;
\r
1433 else bInvertImage = 1;
\r
1435 /* ??? check this */
\r
1437 else PaletteSize = 0; /* not Palette Color */
\r
1438 if (bLinearFlag) PaletteSize = 0; /* no need to use Palette ??? */
\r
1443 "bColorImage %d bExpandColor %d bCompressColor %d PaletteSize %d\n",
\r
1444 bColorImage, bExpandColor, bCompressColor, PaletteSize);
\r
1445 showline(logline, 1);
\r
1448 sprintf(logline, "Width %ld, Height %ld, BitsPerSample %d, SamplesPerPixel %d\n",
\r
1449 ImageWidth, ImageLength, BitsPerSample, SamplesPerPixel);
\r
1450 showline(logline, 1);
\r
1454 /* copied pretty much from readTIFF ... */
\r
1456 SamplesPerPixelX = SamplesPerPixel;
\r
1458 BitsPerPixel = BitsPerSample * SamplesPerPixel; /* only BMP */
\r
1459 BitsPerPixelX = BitsPerPixel;
\r
1461 InRowLength = (ImageWidth * BitsPerPixel + 7) / 8; /* row length file */
\r
1463 InRowRead = ((InRowLength + 3) / 4) * 4; /* multiple of 4 bytes */
\r
1464 if (bExpandColor) BufferLength = ImageWidth * 3;
\r
1465 else if (bExpandGray) BufferLength = ImageWidth;
\r
1466 else BufferLength = InRowLength;
\r
1468 if ((BitsPerPixel == 24 || bExpandColor) && ! bAllowColor) {
\r
1469 sprintf(logline, " color image (bits %d expand %d): use `*c' flag?",
\r
1470 BitsPerPixel, bExpandColor); /* 96/Aug/15 */
\r
1471 showline(logline, 1);
\r
1472 bCompressColor = 1;
\r
1473 OutRowLength = BufferLength / 3;
\r
1475 else OutRowLength = BufferLength;
\r
1480 sprintf(logline, "InRowLength %ld BufferLength %ld OutRowLength %ld\n",
\r
1481 InRowLength, BufferLength, OutRowLength);
\r
1482 showline(logline, 1);
\r
1487 bRunLengthFlag = 0;
\r
1488 if (bAllowCompression) {
\r
1489 /* Use runlength encoding if monochrome *or* if original uses it */
\r
1490 /* if (BitsPerSample == 1 && SamplesPerPixel == 1) */
\r
1491 if (BitsPerSample == 1 && SamplesPerPixelX == 1)
\r
1492 bRunLengthFlag = 1;
\r
1493 if (compression == PACK_BITS) bRunLengthFlag = 1;
\r
1494 #ifdef LZWCOMPRESSION
\r
1496 /* Use LZW if runlength encoding not chosen */
\r
1497 if (bRunLengthFlag == 0) {
\r
1498 // if (compression == LZW_COMPRESSION) bLZWFlag = 1;
\r
1499 // else bLZWFlag = 1; /* otherwise use LZW */
\r
1506 if (computeheader () != 0) return -1; /* noticed format not supported? */
\r
1508 writepsheader(output, dwidth, dheight);
\r
1510 ImageSize = (unsigned long) InRowLength * ImageLength; /* for bmp only */
\r
1512 /* check whether values reasonable */
\r
1513 if (ImageSize == 0) {
\r
1514 sprintf(logline, " ERROR: Zero image size %d %d (%s)",
\r
1515 InRowLength, ImageLength, "readBMPfile");
\r
1516 showline(logline, 1);
\r
1519 if (ImageWidth > MAXIMAGE || ImageLength > MAXIMAGE || /* bad data ? */
\r
1520 ImageSize > 67108864) { /* arbitrary limits (to catch bad files) */
\r
1522 " ERROR: image file too large\n(%ld x %ld (%d) => %ld bytes)",
\r
1523 ImageWidth, ImageLength, BitsPerPixel, ImageSize);
\r
1524 showline(logline, 1);
\r
1531 sprintf(logline, "Seeking to %ld\n", OffBits);
\r
1532 showline(logline, 1);
\r
1535 if (fseek(input, (long) OffBits, SEEK_SET) != 0)
\r
1537 sprintf(logline, " Error in seek %s\n", " to OffBits\n");
\r
1538 showline(logline, 1);
\r
1541 nLen = (int) ((BufferLength + 3) / 4) * 4;
\r
1542 lpBuffer = malloc(nLen);
\r
1543 if (lpBuffer == NULL)
\r
1545 sprintf(logline, " ERROR: Unable to allocate %d bytes\n", nLen);
\r
1546 showline(logline, 1);
\r
1548 // or more serious exit(1) ???
\r
1551 flag = 0; /* flag gets set if EOF hit */
\r
1556 ASCIIinitfilter(output); /* 96/Dec/20 */
\r
1557 if (bRunLengthFlag) RUNinitfilter(output); /* 96/Dec/24 */
\r
1558 #ifdef LZWCOMPRESSION
\r
1559 else if (bLZWFlag) LZWinitfilter(output); /* 96/Dec/28 */
\r
1564 for (i = 0; i < (int) ImageLength; i++) { /* read image lines */
\r
1566 /* May need to uncompress here if compression != 0 */
\r
1567 /* nread = fread(lpBuffer, 1, (unsigned int) InRowLength, input); */
\r
1568 if (compression == 0)
\r
1569 nread = fread(lpBuffer, 1, (unsigned int) InRowRead, input);
\r
1570 else if (BitsPerPixel == 4) { /* decompress, four bit images */
\r
1571 evenflag = 1; /* even nibble is next (output) */
\r
1573 while (s <= lpBuffer + InRowRead) {
\r
1577 sprintf(logline, " %d", c);
\r
1578 showline(logline, 1);
\r
1581 if (c > 0) { /* repeating group pixel count */
\r
1582 d = getc(input); /* pixel */
\r
1583 e = d & 15; /* decompose right nibble */
\r
1584 d = d >> 4; /* decompose left nibble */
\r
1587 sprintf(logline, " repeat %d %d", d, e);
\r
1588 showline(logline, 1);
\r
1591 for (k = 0; k < c; k++) {
\r
1592 nibble = (k % 2 == 0) ? d : e;
\r
1593 /* now stuff nibble */
\r
1594 if (evenflag) *s = (unsigned char) (nibble << 4);
\r
1595 /* else *s++ = *s | nibble; */
\r
1596 else *s++ = (unsigned char) (*s | nibble);
\r
1597 evenflag = 1 - evenflag;
\r
1601 sprintf(logline, " buffered: %d,", s - lpBuffer);
\r
1602 showline(logline, 1);
\r
1606 else { /* c == 0 */
\r
1607 c = getc(input); /* pixel count */
\r
1610 sprintf(logline, " literal %d", c);
\r
1611 showline(logline, 1);
\r
1614 if (c > 2) { /* literal group */
\r
1615 for (k = 0; k < c; k++) {
\r
1618 e = d & 15; /* decompose right nibble */
\r
1619 d = d >> 4; /* decompose left nibble */
\r
1622 sprintf(logline, " %d %d", d, e);
\r
1623 showline(logline, 1);
\r
1629 /* now stuff nibble */
\r
1630 if (evenflag) *s = (unsigned char) (nibble << 4);
\r
1631 /* else *s++ = *s | nibble; */
\r
1632 else *s++ = (unsigned char) (*s | nibble);
\r
1633 evenflag = 1 - evenflag;
\r
1635 n = 2 + (c+1)/2; /* bytes read */
\r
1636 if ((n % 2) != 0) { /* padded out to even bytes */
\r
1640 sprintf(logline, " discard: %d", d);
\r
1641 showline(logline, 1);
\r
1647 sprintf(logline, " buffered: %d,", s - lpBuffer);
\r
1648 showline(logline, 1);
\r
1652 else if (c == 0) {
\r
1653 if (evenflag++ == 0) s++; /* pad last nibble */
\r
1656 sprintf(logline, " EOL\n");
\r
1657 showline(logline, 1);
\r
1660 if (s < lpBuffer + InRowLength) {
\r
1661 sprintf(logline, " Did not fill row %d %d\n",
\r
1662 s - lpBuffer, InRowLength);
\r
1663 showline(logline, 1);
\r
1664 while (s < lpBuffer + InRowLength) *s++ = '\0';
\r
1666 while (s < lpBuffer + InRowRead) *s++ = '\0';
\r
1667 break; /* end of row */
\r
1669 else if (c == 1) {
\r
1672 showline(" EOI\n", 0);
\r
1675 if (i != (int) ImageLength - 1) {
\r
1678 sprintf(logline, "i+1 %d ImageLength %d\n",
\r
1679 i+1, ImageLength);
\r
1680 showline(logline, 0);
\r
1683 showline(" Premature end of image\n", 1);
\r
1685 break; /* end of picture */
\r
1687 else if (c == 2) { /* rats! */
\r
1688 showline(" Skips not implemented\n", 1);
\r
1692 nread = s - lpBuffer;
\r
1694 else { /* decompress, eight bit images only so far */
\r
1696 while (s <= lpBuffer + InRowRead) {
\r
1700 sprintf(logline, " %d", c);
\r
1701 showline(logline, 0);
\r
1704 if (c > 0) { /* repeating group */
\r
1705 d = getc(input); /* pixel */
\r
1708 sprintf(logline, " repeat: %d", d);
\r
1709 showline(logline, 0);
\r
1712 /* for (k = 0; k < c; k++) *s++ = d; */
\r
1713 for (k = 0; k < c; k++) *s++ = (unsigned char) d;
\r
1716 sprintf(logline, " buffered: %d,", s - lpBuffer);
\r
1717 showline(logline, 0);
\r
1724 sprintf(logline, " buffered: %d,", s - lpBuffer);
\r
1725 showline(logline, 0);
\r
1728 c = getc(input); /* pixel count */
\r
1731 sprintf(logline, " %d", c);
\r
1732 showline(logline, 0);
\r
1735 if (c > 2) { /* literal group */
\r
1736 for (k = 0; k < c; k++) {
\r
1738 *s++ = (unsigned char) d;
\r
1741 sprintf(logline, " %d", d);
\r
1742 showline(logline, 0);
\r
1746 if ((c % 2) != 0) { /* padded out to even bytes */
\r
1750 sprintf(logline, " %d", d);
\r
1751 showline(logline, 0);
\r
1756 else if (c == 0) {
\r
1757 if (evenflag++ == 0) *s++ = '\0'; /* pad last byte */
\r
1760 sprintf(logline, " EOL\n");
\r
1761 showline(logline, 0);
\r
1764 if (s < lpBuffer + InRowLength) {
\r
1765 sprintf(logline, " Did not fill row %d %d\n",
\r
1766 s - lpBuffer, InRowLength);
\r
1767 showline(logline, 1);
\r
1768 while (s < lpBuffer + InRowLength) *s++ = '\0';
\r
1770 while (s < lpBuffer + InRowRead) *s++ = '\0';
\r
1771 break; /* end of row EOL */
\r
1773 else if (c == 1) {
\r
1774 if (evenflag++ == 0) *s++ = '\0';; /* pad last byte */
\r
1776 if (traceflag) showline(" EOI\n", 0);
\r
1778 if (i != (int) ImageLength - 1) {
\r
1779 showline(" Premature end of image\n", 1);
\r
1781 break; /* end of picture EOF */
\r
1783 else if (c == 2) { /* rats! */
\r
1784 showline(" Skips not implemented\n", 1);
\r
1788 nread = s - lpBuffer;
\r
1790 /* if (nread != (unsigned int) InRowLength) */
\r
1791 if (nread != (unsigned int) InRowRead) {
\r
1795 sprintf(logline, "nread %d InRowRead %d\n", nread, InRowRead);
\r
1796 showline(logline, 1);
\r
1799 showline(" ERROR: Premature EOF\n", 1);
\r
1803 if (ProcessRow (output, lpBuffer, InRowLength, BufferLength,
\r
1804 OutRowLength) != 0) {
\r
1805 showline(" Output error\n", 1); /* BMP */
\r
1806 perrormod((outputfile != NULL) ? outputfile : "");
\r
1809 /* if (flag != 0) break; *//* hit EOF or other error */
\r
1810 /* check on abort flag here somewhere also ? */
\r
1811 } /* end of this row */
\r
1813 // Have to flush filters in reverse order
\r
1816 if (bRunLengthFlag) RUNflushfilter(output); /* 96/Dec/24 */
\r
1817 #ifdef LZWCOMPRESSION
\r
1818 else if (bLZWFlag) LZWflushfilter(output); /* 96/Dec/28 */
\r
1820 ASCIIflushfilter(output); /* 96/Dec/20 */
\r
1824 /* now finished reading */ /* maybe use far memory for lpBuffer ? */
\r
1826 if (lpBuffer != NULL) {
\r
1830 if (Palette != NULL) {
\r
1834 writepstrailer(output);
\r
1836 /* UNDER CONSTRUCTION !!! */
\r
1837 } /* end of readBMPfile(...) */
\r
1840 /**********************************************************************/
\r
1842 /* Try and see whether EPSF file and read header info if so: */
\r
1843 /* fills in TIFFOffset and PSOffset and MetaOffset and lengths */
\r
1844 /* returns zero if not an EPSF file */ /* file position is end of EPSF head */
\r
1846 int readepsfhead (FILE *special)
\r
1850 PSOffset = 0; /* redundant */
\r
1851 MetaOffset = 0; /* redundant */
\r
1852 TIFFOffset = 0; /* redundant */
\r
1854 c = getc(special); d = getc(special);
\r
1855 e = getc(special); f = getc(special);
\r
1856 if (c == 'E' + 128 && d == 'P' + 128 &&
\r
1857 e == 'S' + 128 && f == 'F' + 128) {
\r
1859 PSOffset = (long) ureadfour(special); /* read PS start offset */
\r
1860 PSLength = (long) ureadfour(special); /* read PS length */
\r
1861 MetaOffset = (long) ureadfour(special); /* read MF start offset */
\r
1862 MetaLength = (long) ureadfour(special); /* read MF length */
\r
1863 TIFFOffset = (long) ureadfour(special); /* read TIFF start offset */
\r
1864 TIFFLength = (long) ureadfour(special); /* read TIFF length */
\r
1865 (void) ureadtwo(special); /* should be 255, 255 */
\r
1868 else return 0; /* not an EPSF file */
\r
1871 int BMPflag=0; /* non-zero while processing BMP image */
\r
1873 int readimagefilesub (FILE *output, FILE *special,
\r
1874 long dwidth, long dheight, int nifd, int readflag)
\r
1876 /* long present; */
\r
1879 TIFFOffset = 0; /* normally beginning of file */
\r
1884 c = getc(special);
\r
1885 (void) ungetc(c, special);
\r
1886 if (c > 128) { /* see whether perhaps EPSF file */
\r
1887 if (readepsfhead(special) != 0) { /* is it EPSF file ? */
\r
1888 /* If valid EPSF header with pointer to TIFF we get here */
\r
1889 if (TIFFOffset == 0 || TIFFLength == 0) {
\r
1890 showline(" ERROR: Zero TIFF offset or length\n", 1);
\r
1893 if (fseek(special, TIFFOffset, SEEK_SET) != 0)
\r
1895 sprintf(logline, " Error in seek %s\n", "to TIFFOffset\n");
\r
1896 showline(logline, 1);
\r
1901 showline(" ERROR: Not a valid EPSF or TIFF file\n", 1);
\r
1904 } /* end of c > 128 (EPSF file) */
\r
1906 /* Try and deal with PostScript ASCII stuff */
\r
1907 /* Or may meet TIFF / BMP preamble */
\r
1908 c = getc(special); d = getc(special);
\r
1909 if (c == '%' && d == '!') { /* ordinary PS file ? */
\r
1910 showline(" ERROR: Ordinary PS file, not TIFF\n", 1);
\r
1913 else if (c == 'I' && d == 'I') bLeastFirst = 1; /* PC style TIFF file */
\r
1914 else if (c == 'M' && d == 'M') bLeastFirst = 0; /* Mac style TIFF file */
\r
1915 else if (c == 'B' && d == 'M') BMPflag = 1; /* BMP 98/Jun/28 */
\r
1917 showline(" ERROR: Not a valid EPSF, TIFF or BMP file\n", 1);
\r
1918 return -1; /* not a TIFF subfile !!! */
\r
1921 /* now have decided that this is a TIFF file (or TIFF preview) or BMP */
\r
1923 (void) readBMPfile(output, special, dwidth, dheight, readflag);
\r
1925 (void) readTIFFfile(output, special, dwidth, dheight, nifd, readflag);
\r
1929 /* In prescan to read TIFF tags, readflag = 1 */
\r
1930 /* Later, when actually using the file, readflag = 0 */
\r
1931 /* Prescan only happens if dheight and dwidth are not already given */
\r
1932 /* Returns -1 if file not found */
\r
1934 int readimagefile (FILE *output, char *filename,
\r
1935 long dwidth, long dheight, int nifd, int readflag)
\r
1937 /* char infilename[FILENAME_MAX]; */ /* make global */
\r
1939 /* long present; */
\r
1942 strcpy(infilename, filename);
\r
1943 /* if ((special = findepsfile(infilename, -1, "tif")) == NULL) { */
\r
1944 /* if ((special = findepsfile(infilename, "tif", 1, readflag)) == NULL) */
\r
1945 /* 1996/Mar/2 don't warn during prescan when readflag = 1 ??? */
\r
1946 if ((special = findepsfile(infilename, "tif", !readflag, readflag)) == NULL)
\r
1952 sprintf(logline, "\nManaged to open file %s\n", infilename);
\r
1953 showline(logline, 0);
\r
1956 flag = readimagefilesub (output, special, dwidth, dheight, nifd, readflag);
\r
1961 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
1965 /* Bitspersample can be 1, 2, 4, 8 for ease of conversion to PS */
\r
1966 /* Each row takes an integral number of bytes */
\r
1968 /* Expand palette color image into full RGB color image */
\r
1969 /* Presently only set up for 8 bit palettes ... !!! */
\r
1971 void expandcolor (unsigned char *lpBuffer, long width)
\r
1974 #ifdef USESHORTINT
\r
1975 unsigned short int *PaletteRed;
\r
1976 unsigned short int *PaletteGreen;
\r
1977 unsigned short int *PaletteBlue;
\r
1979 unsigned int *PaletteRed;
\r
1980 unsigned int *PaletteGreen;
\r
1981 unsigned int *PaletteBlue;
\r
1985 unsigned int red=0, green=0, blue=0;
\r
1986 int PaletteIndex, Mask;
\r
1987 int Byte = 0, BitsLeft = 0;
\r
1990 /* if (traceflag) printf("Palette Color => Color "); */
\r
1993 if (Palette == NULL)
\r
1995 showline(" ERROR: missing palette information\n", 1);
\r
1998 PaletteRed = Palette;
\r
1999 PaletteGreen = PaletteRed + PaletteSize;
\r
2000 PaletteBlue = PaletteGreen + PaletteSize;
\r
2001 Mask = (1 << BitsPerSample) - 1;
\r
2003 /* First slide input data upwards to top of buffer area */
\r
2005 n = (int) width; /* InRowLengthX */
\r
2006 ns = (int) ImageWidth; /* samples per row */
\r
2008 /* if (BufferLength <= InRowLength) */
\r
2009 if (BufferLength <= InRowLengthX) {
\r
2010 showline(" ERROR: buffer overflow\n", 1);
\r
2014 /* possibly use InRowLengthX ? in next two places */
\r
2016 for (k = n-1; k >= 0; k--) /* move it up to end of lpBuffer space */
\r
2017 /* lpBuffer[k + BufferLength - InRowLength] = lpBuffer[k]; */
\r
2018 lpBuffer[k + BufferLength - InRowLengthX] = lpBuffer[k];
\r
2020 /* s = lpBuffer + BufferLength - InRowLength; */ /* start of input data */
\r
2021 s = lpBuffer + BufferLength - InRowLengthX; /* start of input data */
\r
2022 if (BitsPerSample != 8) { /* nibble code init */
\r
2023 Byte = 0; BitsLeft = 0;
\r
2025 t = lpBuffer; /* start of output data */
\r
2026 for (k = 0; k < ns; k++) {
\r
2027 if (BitsPerSample != 8) { /* slow, but inefficient ! */
\r
2028 if (BitsLeft <= 0) {
\r
2029 Byte = *s++; BitsLeft = 8;
\r
2031 BitsLeft -= BitsPerSample;
\r
2032 /* PaletteIndex = Byte >> (BitsPerSample - BitsLeft); */
\r
2033 PaletteIndex = Byte >> BitsLeft;
\r
2034 PaletteIndex = PaletteIndex & Mask;
\r
2035 /* BitsLeft -= BitsPerSample; */
\r
2037 else PaletteIndex = *s++;
\r
2038 if (PaletteIndex < PaletteSize) {
\r
2039 red = PaletteRed[PaletteIndex];
\r
2040 green = PaletteGreen[PaletteIndex];
\r
2041 blue = PaletteBlue[PaletteIndex];
\r
2044 sprintf(logline, " ERROR: Bad Palette Index %d >= %d\n",
\r
2045 PaletteIndex, PaletteSize);
\r
2046 showline(logline, 1);
\r
2050 sprintf(logline, "INX %d\tR %u\tG %u\tB %u\n",
\r
2051 PaletteIndex, red, green, blue);
\r
2052 showline(logline, 0);
\r
2055 if (BMPflag) { /* BMP */
\r
2056 *t++ = (unsigned char) red;
\r
2057 *t++ = (unsigned char) green;
\r
2058 *t++ = (unsigned char) blue;
\r
2061 *t++ = (unsigned char) (red >> 8);
\r
2062 *t++ = (unsigned char) (green >> 8);
\r
2063 *t++ = (unsigned char) (blue >> 8);
\r
2068 /* This is called for BMP image when palette is used, but it is gray */
\r
2069 /* (i.e. R=G=B) and it is *not* linear (i.e. Palette[k] == k) */
\r
2071 void expandgray (unsigned char *lpBuffer, long width)
\r
2074 #ifdef USESHORTINT
\r
2075 unsigned short int *PaletteRed;
\r
2076 unsigned short int *PaletteGreen;
\r
2077 unsigned short int *PaletteBlue;
\r
2079 unsigned int *PaletteRed;
\r
2080 unsigned int *PaletteGreen;
\r
2081 unsigned int *PaletteBlue;
\r
2085 unsigned int red, green, blue;
\r
2086 int PaletteIndex, Mask;
\r
2087 int Byte = 0, BitsLeft = 0;
\r
2090 /* if (traceflag) printf("Palette Gray => Gray "); */
\r
2093 if (Palette == NULL)
\r
2095 showline(" ERROR: missing palette information\n", 1);
\r
2098 PaletteRed = Palette;
\r
2099 PaletteGreen = PaletteRed + PaletteSize;
\r
2100 PaletteBlue = PaletteGreen + PaletteSize;
\r
2101 Mask = (1 << BitsPerSample) - 1;
\r
2103 /* First slide input data upwards to top of buffer area */
\r
2105 n = (int) width; /* InRowLength */
\r
2106 ns = (int) ImageWidth; /* samples per row */
\r
2108 /* if (BufferLength <= InRowLength) */
\r
2109 if (BufferLength <= InRowLengthX)
\r
2111 showline(" ERROR: buffer overflow\n", 1);
\r
2115 for (k = n-1; k >= 0; k--)
\r
2116 /* lpBuffer[k + BufferLength - InRowLength] = lpBuffer[k]; */
\r
2117 lpBuffer[k + BufferLength - InRowLengthX] = lpBuffer[k];
\r
2119 /* s = lpBuffer + BufferLength - InRowLength; */ /* start of input data */
\r
2120 s = lpBuffer + BufferLength - InRowLengthX; /* start of input data */
\r
2121 if (BitsPerSample != 8) { /* nibble code init */
\r
2122 Byte = 0; BitsLeft = 0;
\r
2124 t = lpBuffer; /* start of output data */
\r
2125 for (k = 0; k < ns; k++) {
\r
2126 if (BitsPerSample != 8) { /* slow, but inefficient ! */
\r
2127 if (BitsLeft <= 0) {
\r
2128 Byte = *s++; BitsLeft = 8;
\r
2130 BitsLeft -= BitsPerSample;
\r
2131 /* PaletteIndex = Byte >> (BitsPerSample - BitsLeft); */
\r
2132 PaletteIndex = Byte >> BitsLeft;
\r
2133 PaletteIndex = PaletteIndex & Mask;
\r
2134 /* BitsLeft -= BitsPerSample; */
\r
2136 else PaletteIndex = *s++;
\r
2137 if (PaletteIndex < PaletteSize) {
\r
2138 red = PaletteRed[PaletteIndex];
\r
2139 green = PaletteGreen[PaletteIndex]; /* not used */
\r
2140 blue = PaletteBlue[PaletteIndex]; /* not used */
\r
2143 sprintf(logline, " ERROR: Bad Palette Index %d >= %d\n",
\r
2144 PaletteIndex, PaletteSize);
\r
2145 showline(logline, 1);
\r
2146 red = green = blue = 0; /* keep compiler happy */
\r
2149 /* if (traceflag) printf("Index %d red %u green %u blue %u\n", */
\r
2151 sprintf(logline, "INX %d\tR %u\tG %u\tB %u\n",
\r
2152 PaletteIndex, red, green, blue);
\r
2153 showline(logline, 0);
\r
2156 if (BMPflag) *t++ = (unsigned char) red; /* BMP */
\r
2157 else *t++ = (unsigned char) (red >> 8); /* TIFF */
\r
2161 /* gray = 0.3 * red + 0.59 * green + 0.11 * blue */
\r
2163 void compresscolor (unsigned char *lpBuffer, long width)
\r
2168 unsigned int red, green, blue, gray;
\r
2171 if (traceflag) showline("Color => Gray ", 0);
\r
2173 s = lpBuffer; t = lpBuffer;
\r
2174 n = (int) (width / 3);
\r
2175 for (k = 0; k < n; k++) {
\r
2176 red = *s++; green = *s++; blue = *s++;
\r
2177 gray = (int) (((long) blue * 28 + (long) red * 77 + (long) green * 151)
\r
2179 *t++ = (unsigned char) gray;
\r
2183 /*****************************************************************************/
\r
2187 //#pragma optimize ("lge", on) /* 2000 June 17 */
\r
2189 /* use ASCII85Encode if bLevel2 enabled */
\r
2191 /* ASCII85 encoding (b1 b2 b3 b4) => (c1 c2 c3 c4 c5) */
\r
2193 /* b1 * 256^3 + b2 * 256^2 + b3 * 256 + b4 =
\r
2194 c1 * 85^4 + c2 * 85^3 + c3 * 85^2 + c4 * 85 + c5 */
\r
2196 /* Add `!' = 33 to make ASCII code. ! represents 0, u represent 84. */
\r
2198 /* If all five digits are zero, use z instead of !!!!! - special case. */
\r
2200 /* At end, given n = 1, 2, 3 bytes of binary data, append 4 - n zeros.
\r
2201 Encode this in usual way (but *without* z special case).
\r
2202 Write first (n+1) bytes. Follow by -> (EOD) */
\r
2204 unsigned long asciinum = 0; /* accumulated so far up to four bytes */
\r
2205 int asciicount = 0; /* how many bytes accumulated so far */
\r
2207 /* Output 4 bytes --- 32 bit unsigned int --- as 5 ASCII 85 bytes */
\r
2208 /* nbytes is number of bytes accumulated, which is 4 until the last time */
\r
2209 /* Move this inline for speed ? */
\r
2211 void ASCIIlong (FILE *output, unsigned long n, int nbytes)
\r
2213 unsigned int c[5];
\r
2216 // sprintf(logline, "ASCIIlong %08X %d ", n, nbytes);
\r
2217 // showline(logline, 0); // debugging only
\r
2218 if (nbytes == 0) nbytes--; /* nothing to do at end - avoid ! */
\r
2219 if (n == 0 && nbytes == 4) { /* special case !!!!! => z */
\r
2220 PSputc('z', output); /* shorthand for !!!!! */
\r
2222 if (column >= MAXCOLUMNASCII) {
\r
2223 PSputc('\n', output);
\r
2228 for (k = 4; k >= 0; k--) { /* get base 85 digits reverse order */
\r
2229 c[k] = (unsigned int) (n % 85);
\r
2232 for (k = 0; k < 5; k++) { /* spit them out in correct order */
\r
2233 if (nbytes-- < 0) { /* last one, finish with EOD */
\r
2234 if (column+1 >= MAXCOLUMNASCII) { /* see if space for ~> */
\r
2235 PSputc('\n', output);
\r
2238 PSputs("~>\n", output); /* EOD */
\r
2242 PSputc((char) (c[k] + '!'), output);
\r
2244 if (column >= MAXCOLUMNASCII) {
\r
2245 PSputc('\n', output);
\r
2248 } /* end of for k = 0; k < 5; k++ */
\r
2251 /* Output single byte (accumulate until four seen, then call ASCIIlong) */
\r
2252 /* Move this inline for speed ? */
\r
2254 void ASCIIout (FILE *output, unsigned int x)
\r
2256 // sprintf(logline, "ASCII %d ", x);
\r
2257 // showline(logline, 0); // debugging only
\r
2258 if (x > 255) x = x & 255; // sanity check ???
\r
2259 asciinum = (asciinum << 8) | x;
\r
2261 if (asciicount >= 4) {
\r
2262 ASCIIlong(output, asciinum, asciicount);
\r
2268 /* initialize ASCII85 filter */
\r
2270 void ASCIIinitfilter (FILE *output) /* 96/Dec/20 */
\r
2272 // showline("ASCIIinitfilter ", 0); // debugging only
\r
2275 column = 0; /* ??? */
\r
2278 void RUNinitfilter (FILE *output) /* 95/Dec/24 */
\r
2280 /* apparently nothing special to do */
\r
2283 /* flush out anything left in ASCII85 filter */
\r
2285 void ASCIIflushfilter (FILE *output) /* 96/Dec/20 */
\r
2288 // showline("ASCIIflushfilter ", 0); // debugging only
\r
2289 for (k = asciicount; k < 4; k++) {
\r
2290 asciinum = (asciinum << 8); /* append n-4 zeros */
\r
2292 ASCIIlong(output, asciinum, asciicount);
\r
2297 void RUNflushfilter (FILE *output)
\r
2299 ASCIIout(output, 128); /* EOD */
\r
2302 /*****************************************************************************/
\r
2304 /* write a row in ASCII85 format */
\r
2306 void writearowASCII (FILE *output, unsigned char *s, unsigned long width)
\r
2310 unsigned long num;
\r
2314 if (asciicount > 0) { /* finish off group of four bytes first */
\r
2315 for (i = asciicount; i < 4; i++) {
\r
2316 ASCIIout(output, *s++);
\r
2318 if (k >= n) break; /* in case of miniscule width! */
\r
2321 while (k < n-3) { /* then do groups of four bytes */
\r
2323 for (i = 0; i < 4; i++) {
\r
2325 num = (num << 8) | c;
\r
2327 ASCIIlong(output, num, 4);
\r
2330 while (k < n) { /* then do remaining bytes at tail of row */
\r
2331 ASCIIout(output, *s++);
\r
2336 /**************************************************************************/
\r
2338 #if (defined(DEBUGLZWENCODE) || defined(DEBUGRUNLENGTH))
\r
2339 int debugflag=1; /* debugging output */
\r
2342 /* Do run encoding per row (rather than image) --- easier, if not optimal */
\r
2344 void dumprun(FILE *output, int nlen, int previous)
\r
2346 #ifdef DEBUGRUNLENGTH
\r
2349 sprintf(logline, "Zero length run %d ", nlen);
\r
2350 showline(logline, 0);
\r
2353 else if (nlen < 3) {
\r
2354 sprintf(logline, " ERROR: run %d < 3\n", nlen);
\r
2355 showline(logline, 1);
\r
2357 else if (nlen > 128) {
\r
2358 sprintf(logline, " ERROR: run %d > 128", nlen);
\r
2359 showline(logline, 1);
\r
2361 for (i = 0; i < nlen; i++) {
\r
2362 sprintf(logline, "%02X", previous);
\r
2363 showline(logline, 1);
\r
2366 ASCIIout(output, 257 - nlen);
\r
2367 ASCIIout(output, previous);
\r
2370 void dumpnonrun(FILE *output, int nlen, unsigned char *buffer)
\r
2375 #ifdef DEBUGRUNLENGTH
\r
2377 sprintf(logline, "Zero length nonrun %d ", nlen);
\r
2378 showline(logline, 0);
\r
2382 sprintf(logline, " ERROR: nonrun %d > 128", nlen);
\r
2383 showline(logline, 1);
\r
2387 for (i = 0; i < nlen; i++) {
\r
2390 sprintf(logline, "%02X", c);
\r
2391 showline(logline, 1);
\r
2395 ASCIIout(output, nlen - 1);
\r
2397 for (i = 0; i < nlen; i++) ASCIIout(output, *s++);
\r
2400 /* RunLengthEncode filter */
\r
2402 /* This basically has two states: */
\r
2403 /* (1) accumulating non-run (runflag == 0) */
\r
2404 /* (2) accumulating run (runflag != 0) */
\r
2405 /* Here (1) is the starting state */
\r
2406 /* Dumps out when (i) state changes (ii) 128 bytes seen (iii) end input */
\r
2408 void writearowrun (FILE *output, unsigned char *s, unsigned long width)
\r
2410 int runflag; /* non-zero if in accumulating run state */
\r
2411 int previous; /* character that appears to be repeating */
\r
2412 int repeat; /* how many times we have seen previous */
\r
2413 int bcount; /* count of bytes buffered up (s-new) */
\r
2414 unsigned char *new; /* points to part of string not yet dumped */
\r
2419 bcount = 0; /* non run length accumulated */
\r
2420 new = s; /* points to first byte not yet output */
\r
2421 previous = -1; /* previous character in a run */
\r
2422 repeat = 0; /* how many repetetions of previous */
\r
2423 runflag = 0; /* start in non run state */
\r
2426 c = *s; /* grab next byte */
\r
2427 if (runflag) { /* accumulating a run ? */
\r
2428 if (repeat >= 128) { /* run too long ? */
\r
2429 dumprun(output, repeat, previous);
\r
2434 runflag = 0; /* switch back to non run state */
\r
2436 else if (c == previous) { /* continue the run ? */
\r
2439 else { /* c != previous --- end of a run */
\r
2440 dumprun(output, repeat, previous);
\r
2445 runflag = 0; /* switch back to non run state */
\r
2448 else { /* runflag == 0 accumulating a non run */
\r
2449 if (bcount >= 128) { /* accumulated too much ? */
\r
2450 dumpnonrun(output, bcount, new);
\r
2455 /* and stay in non run mode */
\r
2457 else if (c == previous) {
\r
2459 if (repeat >= 4) { /* end of non-run */
\r
2460 if (bcount+1 > repeat)
\r
2461 dumpnonrun(output, bcount-repeat+1, new);
\r
2462 bcount = 0; /* needed ? */
\r
2463 runflag = 1; /* switch to accumulating run state */
\r
2464 /* don't change previous, repeat */
\r
2466 if (runflag == 0) bcount++;
\r
2471 /* don't change new, bcount */
\r
2477 } /* end of while loop */
\r
2478 #ifdef DEBUGRUNLENGTH
\r
2479 /* if (debugflag) showline("EOL ", 0); */
\r
2481 if (runflag) dumprun(output, repeat, previous);
\r
2482 else if (repeat >= bcount && repeat > 1)
\r
2483 dumprun(output, repeat, previous);
\r
2484 else dumpnonrun(output, bcount, new);
\r
2485 #ifdef DEBUGRUNLENGTH
\r
2486 if (debugflag) showline("\n", 0);
\r
2490 /**************************************************************************/
\r
2492 /* code for LZW compression on OUTPUT side LZWcompress rewrite 2000 June 17 */
\r
2494 #ifdef LZWCOMPRESSION
\r
2497 int chr; // byte to get to this node --- or -1
\r
2498 // NODE nextinlist; // next in list at this level ptr
\r
2499 int nextinlist; // next in list at this level
\r
2500 // NODE nextlevel; // first at next level ptr
\r
2501 int nextlevel; // first at next level
\r
2504 // May get some added performance by making the last two components be
\r
2505 // pointers rather than indeces...
\r
2507 struct NODE *node=NULL; // array of nodes --- allocated
\r
2509 int currentnode; // code of node currently at
\r
2510 int nextnode; // code of next node to be used
\r
2511 int codelength; // how many bits needed for code at this stage 9, 10, 11, 12
\r
2513 void DeAllocStringsOut (void) // called from dvibody() in dvipsone.c
\r
2515 if (node != NULL) {
\r
2521 void CleanOut (FILE *output, int n)
\r
2525 // sprintf(logline, "CLEANOUT %d\n", n);
\r
2526 // showline(logline, 0);
\r
2528 // 0 to MAXCHR, and CLEAR and EOD
\r
2529 for (k = 0; k < FIRSTCODE; k++) {
\r
2531 node[k].nextinlist = -1;
\r
2532 node[k].nextlevel = -1;
\r
2534 LZWput(CLEAR, output); // using current code length
\r
2535 nextnode = FIRSTCODE; // next node available
\r
2536 currentnode = n; // string in progress
\r
2537 codelength = 9; // reset code length now
\r
2540 int SetupNodes (FILE *output)
\r
2544 if (node == NULL) {
\r
2545 nlen = MAXCODES * sizeof(struct NODE); // 49,152 bytes
\r
2547 sprintf(logline, "Allocating %d bytes\n", nlen); // debugging only
\r
2548 showline(logline, 0);
\r
2550 node = (struct NODE *) malloc(nlen);
\r
2551 if (node == NULL) {
\r
2552 sprintf(logline, "Unable to allocate %d bytes for NODE table\n", nlen);
\r
2553 showline(logline, 1);
\r
2557 // LZWput(CLEAR, output); // do separately
\r
2558 // nextnode = FIRSTCODE;
\r
2559 // currentnode = -1;
\r
2560 codelength = 9; // need to initialize
\r
2561 // CleanOut(output, -1); // do separately
\r
2566 // We are at node n and adding a new branch for byte chr -- NOT USED
\r
2567 void AddaNode (FILE *output, int n, int chr, int previous)
\r
2570 // if (nextnode < 0 || nextnode >= MAXCODES) showline("TABLE OVERFLOW", 1);
\r
2571 // Is there already a node at the next level ?
\r
2572 k = node[n].nextlevel;
\r
2573 if (k < 0) { // no, start next level list
\r
2574 node[n].nextlevel = nextnode; // link to new node
\r
2576 else { // yes, link to end of that list
\r
2577 // k = node[n].nextlevel;
\r
2578 // find end of linked list
\r
2581 k = node[klast].nextinlist;
\r
2583 node[klast].nextinlist = nextnode; // link new node to end of list
\r
2585 // set up new node being added
\r
2586 // node[nextnode].code = nextnode;
\r
2587 node[nextnode].chr = chr;
\r
2588 node[nextnode].nextinlist = -1;
\r
2589 node[nextnode].nextlevel = -1;
\r
2591 if (nextnode == 512 || nextnode == 1024 || nextnode == 2048) {
\r
2592 // sprintf(logline, "CODELENGTH %d ", codelength);
\r
2593 // showline(logline, 0);
\r
2596 else if (nextnode == 4096) CleanOut(output, chr);
\r
2600 // We are adding a new node for byte chr
\r
2602 void NewNode (FILE *output, int chr, int previous) {
\r
2603 if (nextnode < 0 || nextnode >= MAXCODES) showline("TABLE OVERFLOW", 1);
\r
2604 // set up new node being added
\r
2605 // node[nextnode].code = nextnode;
\r
2606 // sprintf(logline, "NEW NODE %d %d\n", chr, previous);
\r
2607 // showline(logline, 1);
\r
2608 // sprintf(logline, "NEW NODE %d for %d from %d ", nextnode, chr, previous);
\r
2609 // showline(logline, 1); // debugging only
\r
2610 node[nextnode].chr = chr;
\r
2611 node[nextnode].nextinlist = -1;
\r
2612 node[nextnode].nextlevel = -1;
\r
2614 if (nextnode == 512 || nextnode == 1024 || nextnode == 2048) {
\r
2615 // sprintf(logline, "CODELENGTH %d ", codelength);
\r
2616 // showline(logline, 0);
\r
2619 else if (nextnode == 4096) CleanOut(output, chr);
\r
2622 // Process next incoming byte
\r
2624 void DoNextByte (FILE *output, int chr) { // called from writearowLZW
\r
2626 // sprintf(logline, "(%d) ", chr); // debugging only
\r
2627 // showline(logline, 0);
\r
2628 if (currentnode < 0) { // starting from scratch ? (empty string)
\r
2629 currentnode = chr;
\r
2632 k = node[currentnode].nextlevel;
\r
2633 if (k < 0) { // does next level exist ?
\r
2634 // AddaNode(currentnode, n);
\r
2635 LZWput(currentnode, output); // new string NOT in table
\r
2636 node[currentnode].nextlevel = nextnode; // NEXT LEVEL
\r
2637 // sprintf(logline, "NEW LEVEL %d %d %d ", currentnode, nextnode, chr);
\r
2638 // showline(logline, 0); // debugging only
\r
2639 NewNode(output, chr, currentnode); // new node at nextnode
\r
2640 currentnode = chr; // string of one byte
\r
2643 // there is a list at the next level --- search it
\r
2644 // k = node[currentnode].nextlevel;
\r
2645 while (k >= 0 && node[k].chr != chr) {
\r
2647 k = node[klast].nextinlist;
\r
2649 if (k < 0) { // hit end of list ?
\r
2650 // AddaNode(currentnode, n);
\r
2651 LZWput(currentnode, output); // new string NOT in table
\r
2652 node[klast].nextinlist = nextnode; // NEXT IN LIST
\r
2653 // sprintf(logline, "NEW ELEM %d (%d) %d %d ", currentnode, klast, nextnode, chr);
\r
2654 // showline(logline, 0); // debugging only
\r
2655 NewNode(output, chr, currentnode); // new node at nextnode
\r
2656 currentnode = chr; // string of one byte
\r
2659 // we did find this string in the table
\r
2660 // if (k < 0 || k >= MAXCODES) showline("ERROR ", 0); // debugging only
\r
2661 currentnode = k; // it IS in table, no output
\r
2665 void DoCleanup (FILE *output) // not used - see LZWflushfilter
\r
2667 if (currentnode >= 0) LZWput(currentnode, output);
\r
2668 // LZWput(CLEAR, output);
\r
2669 // nextnode = FIRSTCODE;
\r
2670 // currentnode = -1;
\r
2671 // codelength = 9;
\r
2672 CleanOut(output, -1);
\r
2676 /***************************************************************************/
\r
2680 long leftover; /* byte accumulated so far - need up to 12 + 12 bits */
\r
2681 int bitsused; /* bits used so far */
\r
2683 /* stuff codelength bits of c into output stream */
\r
2684 /* may produce one or two bytes ready to spit out */
\r
2685 /* bitsused is always < 8 before and always < 8 after this */
\r
2687 void LZWput (int code, FILE *output)
\r
2691 // if (bitsused < 0 || bitsused >= 8) showline("ERROR ", 1);
\r
2692 #ifdef DEBUGLZWENCODE
\r
2695 if (code >= (1 << codelength))
\r
2696 sprintf(logline, "code %d too long for code length %d\n",
\r
2697 code, codelength);
\r
2698 showline(logline, 1);
\r
2701 // sprintf(logline, "LEFT %08X USED %d ", leftover, bitsused);
\r
2702 // showline(logline, 0); // debugging only
\r
2703 leftover = (leftover << codelength) | code;
\r
2704 bitsused += codelength;
\r
2705 if (bitsused >= 16) {
\r
2706 c = (int) (leftover >> (bitsused - 8)); /* get left most 8 bits */
\r
2707 ASCIIout(output, c & 255); // expand ?
\r
2710 c = (int) (leftover >> (bitsused - 8)); /* get left most 8 bits */
\r
2711 ASCIIout(output, c & 255); // expand ?
\r
2713 // if (bitsused < 0 || bitsused >= 8) showline("ERROR ", 1);
\r
2716 void LZWputinit (FILE *output) { /* called from LZWinitfilter */
\r
2717 // showline("LZWputinit ", 0); // debugging only
\r
2722 void LZWputflush (FILE *output)
\r
2725 // showline("LZWputflush ", 0); // debugging only
\r
2726 if (bitsused == 0) return; /* nothing left to push out */
\r
2727 c = (int) (leftover << (8 - bitsused));
\r
2728 /* c = (int) (leftover >> (bitsused - 8)); */ /* same thing ? */
\r
2729 ASCIIout(output, c & 255); /* fill last byte with zeros */
\r
2730 /* leftover = 0; */
\r
2731 /* bitsused = 0; */
\r
2734 void LZWinitfilter (FILE *output) /* initialization */
\r
2736 // showline("LZWinitfilter ", 0); // debugging only
\r
2737 LZWputinit(output);
\r
2738 // LZWput(CLEAR, output); /* write CLEAR */
\r
2739 SetupNodes(output);
\r
2740 CleanOut(output, -1);
\r
2741 /* codelength = 9; */
\r
2744 void LZWflushfilter (FILE *output) /* termination */
\r
2746 // showline("LZWflushfilter ", 0); // debugging only
\r
2747 if (currentnode >= 0) {
\r
2748 LZWput(currentnode, output);
\r
2749 #ifdef DEBUGLZWENCODE
\r
2750 if (debugflag > 1) showcode(currentnode);
\r
2753 LZWput(EOD, output);
\r
2754 #ifdef DEBUGLZWENCODE
\r
2755 if (debugflag) showline("EOD ", 1);
\r
2757 sprintf(logline, "%d entries ", nextnode);
\r
2758 showline(logline, 1);
\r
2761 LZWputflush(output);
\r
2762 /* CleanOut(output, -1); */
\r
2765 /* Basic LZW encoding for output */ /* encode width bytes starting at *s */
\r
2766 /* Initialization and Termination taken care of elsewhere */
\r
2767 /* int code; */ /* code of the string matched so far to input */
\r
2768 /* int last; */ /* last character of input string */
\r
2770 int writearowLZW (FILE *output, unsigned char *s, unsigned long width)
\r
2772 unsigned char *send = s + width;
\r
2774 /* This picks up unfinished business --- currentnode >= 0 */
\r
2775 while (s < send) {
\r
2776 DoNextByte(output, *s++);
\r
2779 /* This may leave unfinished business --- currentnode >= 0 */
\r
2782 #endif /* end of ifdef LZWCOMPRESSION */
\r
2784 /*************************************************************************/
\r
2786 //#pragma optimize ("lge", off)
\r
2788 #endif /* end of ifdef PSLEVEL2 */
\r
2790 /* write row in hex format */
\r
2792 void writearowhex (FILE *output, unsigned char *s, unsigned long width)
\r
2794 unsigned int c, d;
\r
2799 for (k = 0; k < n; k++) {
\r
2800 if (column >= MAXCOLUMNHEX) {
\r
2801 // putc('\n', output);
\r
2802 PSputc('\n', output);
\r
2809 // putc(c + 'A' - 10, output);
\r
2810 PSputc((char) (c + 'A' - 10), output);
\r
2813 // putc(c + '0', output);
\r
2814 PSputc((char) (c + '0'), output);
\r
2818 // putc(d + 'A' - 10, output);
\r
2819 PSputc((char) (d + 'A' - 10), output);
\r
2822 // putc(d + '0', output);
\r
2823 PSputc((char) (d + '0'), output);
\r
2827 // putc('\n', output); /* also start each image row on new line */
\r
2828 PSputc('\n', output); /* also start each image row on new line */
\r
2832 /* returns -1 if output error */ /* write a row of data in hex */
\r
2834 int writearow (FILE *output, unsigned char *s, unsigned long width)
\r
2838 if (bRunLengthFlag) writearowrun(output, s, width);
\r
2839 #ifdef LZWCOMPRESSION
\r
2840 else if (bLZWFlag) writearowLZW(output, s, width);
\r
2842 else writearowASCII(output, s, width);
\r
2844 else writearowhex(output, s, width);
\r
2846 writearowhex(output, s, width);
\r
2849 // if (ferror(output))
\r
2850 if (output != NULL && ferror(output))
\r
2852 showline(" ERROR: Output error\n", 1);
\r
2853 perrormod((outputfile != NULL) ? outputfile : "");
\r
2856 if (bAbort) abortjob(); /* 97/Mar/1 ? */
\r
2857 if (abortflag) return -1;
\r
2861 int computeheader (void) {
\r
2862 /* int changeflag= 0; */
\r
2865 if (traceflag) showline("Now computing header information\n", 0);
\r
2868 /* Now for some sanity checks */
\r
2869 if (PlanarConfig != 1) {
\r
2870 showline(" ERROR: Multiple color planes not supported\n", 1);
\r
2873 if (BitsPerSample > 8) {
\r
2874 sprintf(logline, " ERROR: Maximum of 8 bits per sample (%d)\n",
\r
2876 showline(logline, 1);
\r
2879 if ((BitsPerSample & (BitsPerSample-1)) != 0) {
\r
2880 sprintf(logline, " ERROR: Bits per sample must be power of two (%d)\n",
\r
2882 showline(logline, 1);
\r
2885 if (compression > TIFF_CCITT && compression != LZW_COMPRESSION &&
\r
2886 compression != PACK_BITS ) {
\r
2887 sprintf(logline, " ERROR: Unknown compression scheme (%d)", compression);
\r
2888 showline(logline, 1);
\r
2892 if (PhotometricInterpretation == 3) { /* that is palette color */
\r
2893 /* if (SamplesPerPixel != 1) */
\r
2894 if (SamplesPerPixelX != 1) {
\r
2895 showline(" ERROR: Palette color must have one sample per pixel", 1);
\r
2899 /* check whether need to use `colorimage' operator instead of `image' */
\r
2900 /* if (SamplesPerPixel != 1) */
\r
2901 if (SamplesPerPixelX != 1) {
\r
2902 // if (PhotometricInterpretation != 2)
\r
2903 if (PhotometricInterpretation != 2 && PhotometricInterpretation != 5)
\r
2904 // showline(" More than one sample per pixel, but not RGB?", 1);
\r
2905 showline(" More than one sample per pixel, but not RGB or CMYK?", 1);
\r
2907 if (! bAllowColor) {
\r
2908 sprintf(logline, " WARNING: More than one sample per pixel (%d) use `*c' flag?",
\r
2910 showline(logline, 0);
\r
2912 bCompressColor = 1; /* then need to compress colors */
\r
2915 /* if (verboseflag && PhotometricInterpretation > 3) {
\r
2916 printf("Photometricinterpretation %d\n", PhotometricInterpretation);
\r
2918 /* 0 => 0 will be white and 2^n-1 black */
\r
2919 /* 1 => 0 will be black and 2^n-1 white (default) */
\r
2920 /* 2 => RGB model */
\r
2921 /* 3 => palette color */
\r
2922 /* 4 => transparency mask */
\r
2923 /* Fix this one later */
\r
2924 /* if (PhotometricInterpretation == 3) bColorImage = 1; */
\r
2925 /* if (ColorMapPtr != 0) bColorImage = 1; */
\r
2926 if (PhotometricInterpretation == 3 && ColorMapPtr == 0) {
\r
2927 showline(" ERROR: Palette Color Image must have Palette!\n", 1);
\r
2930 if (PhotometricInterpretation == 2)
\r
2932 /* if (SamplesPerPixel == 1) */
\r
2933 if (SamplesPerPixelX == 1)
\r
2935 sprintf(logline, " %s, but not more than one sample per pixel?\n", "RGB");
\r
2936 showline(logline, 1);
\r
2938 if (! bAllowColor)
\r
2940 sprintf(logline, " WARNING: %s color image (%d) use `*c' flag?", "RGB", SamplesPerPixel);
\r
2941 // showline(logline, 1);
\r
2942 showline(logline, 0);
\r
2943 bCompressColor = 1;
\r
2947 if (PhotometricInterpretation == 5) { // 2000 May 27
\r
2948 /* if (SamplesPerPixel == 1) */
\r
2949 if (SamplesPerPixelX == 1)
\r
2951 sprintf(logline, " %s, but not more than one sample per pixel?\n", "CMYK");
\r
2952 showline(logline, 1);
\r
2954 if (! bAllowColor)
\r
2956 sprintf(logline, " WARNING: %s color image (%d) use `*c' flag?", "CMYK", SamplesPerPixel);
\r
2957 // showline(logline, 1);
\r
2958 showline(logline, 0);
\r
2959 bCompressColor = 1;
\r
2963 /* 0 => 0 will be white and 2^n-1 black */
\r
2964 /* 1 => 0 will be black and 2^n-1 white (default) */
\r
2966 if (PhotometricInterpretation == 0)
\r
2969 if (traceflag) showline("Image grey levels will be inverted\n", 0);
\r
2973 else bInvertImage = 0;
\r
2978 sprintf(logline, "ExpandColor %d CompressColor %d InvertImage %d\n",
\r
2979 bExpandColor, bCompressColor, bInvertImage);
\r
2980 showline(logline, 0);
\r
2984 /* compute bytes per row (both input and output?) */
\r
2985 /* if (bColorImage)bytes = (int) (((long) ImageWidth * BitsPerPixel + 7) / 8);
\r
2986 else bytes = (int) (((long) ImageWidth * BitsPerSample + 7) / 8); */
\r
2987 /* Following only correct if no expansion or contraction of color images */
\r
2988 /* bytes = (int) (((long) ImageWidth * BitsPerPixel + 7) / 8); */
\r
2989 bytes = (int) OutRowLength; /* ever used ? */
\r
2992 sprintf(logline, "%d bytes per row\n", bytes);
\r
2993 showline(logline, 0);
\r
2999 /* long xll=0, yll=0, xur=0, yur=0; */
\r
3001 /* {1 exch sub} settransfer */
\r
3002 /* currenttranser {1 exch sub 0 exec} exch 4 put bind */
\r
3003 /* char *invertgray=
\r
3004 "[{1 exch sub} /exec load currentransfer /exec load] cvx settransfer\n"; */
\r
3006 /* compress some of this code into DVIPREAM.PS ? */
\r
3008 void writepsheader (FILE *output, long dwidth, long dheight)
\r
3010 int bits=1; /* bits per pixel in image */
\r
3011 int samples=3; /* samples per pixel 96/July/7 */
\r
3012 int bMonoChrome=0; /* if need to use image mask */
\r
3013 /* int paintback=0; */ /* if need to paint background */
\r
3014 /* long XOffset, YOffset; */
\r
3018 if (traceflag) showline("Now writing out header information\n", 0);
\r
3020 /* if (BitsPerSample == 1) bMonoChrome = 1; */ /* use image mask */
\r
3022 if (bExpandColor) bits = 8;
\r
3023 else if (bExpandGray) bits = 8;
\r
3024 else bits = BitsPerSample;
\r
3026 if (bits == 1) bMonoChrome = 1; /* use image mask */
\r
3028 if (bExpandColor) samples = 3;
\r
3029 else if (bExpandGray) samples = 1;
\r
3030 /* else samples = SamplesPerPixel; */ /* 96/July/7 */
\r
3031 else samples = SamplesPerPixelX;
\r
3033 // fprintf(output, "\nsave\n");
\r
3034 // putc('\n', output);
\r
3035 PSputc('\n', output);
\r
3036 // fputs("save ", output);
\r
3037 PSputs("save ", output);
\r
3038 if (stripcomment == 0) {
\r
3039 sprintf(logline, "%% %s\n", infilename); /* 98/Jul/12 */
\r
3040 PSputs(logline, output);
\r
3043 // putc('\n', output);
\r
3044 PSputc('\n', output);
\r
3046 if (! bColorImage) { /* only use screen for B/W */
\r
3047 /* if (bInvertImage) fputs("invert\n", output); */
\r
3048 if (bInvertImage && !bMonoChrome) {
\r
3049 // fputs("invert\n", output);
\r
3050 PSputs("invert\n", output);
\r
3052 /* if (wantmagic) fputs(eps_magic, output); */
\r
3053 /* fprintf(output, "currentscreen pop dviscreen\n"); */
\r
3054 if (wantmagictiff) {
\r
3055 if (frequency > 0) { /* did user specified frequency & angle ? */
\r
3056 sprintf(logline, "%d %d dviscreen\n", frequency, angle);
\r
3057 PSputs(logline, output);
\r
3060 // fputs("currentscreen pop dviscreen\n", output);
\r
3061 PSputs("currentscreen pop dviscreen\n", output);
\r
3065 /* for monochrome, paint background first, then use imagemask */
\r
3066 /* if (BitsPerSample == 1) {
\r
3067 if (bFigureColor)
\r
3068 fprintf(output, "%lg %lg %lg rgb\n",
\r
3069 figurered, figuregreen, figureblue);
\r
3070 else if (bTextColor) fputs("black\n", output);
\r
3073 /* create the string before or after the `save' ? */
\r
3074 /* fprintf(output, "/picstr %d string def\n", bytes); */
\r
3075 /* string not needed if using ASCII85Decode filter 96/Dec/20 */
\r
3077 sprintf(logline, "/picstr %d string def\n", bytes);
\r
3078 PSputs(logline, output);
\r
3080 // fprintf(output, "%d %d translate ", xll, yll);
\r
3081 // fputs("currentpoint translate ", output);
\r
3082 PSputs("currentpoint translate ", output);
\r
3083 if (dwidth == 0 || dheight == 0) {
\r
3084 showline(" Zero width or height ", 1);
\r
3087 if (outscaleflag) {
\r
3088 sprintf(logline, "%.9lg %.9lg scale\n",
\r
3089 (double) dwidth / outscale, (double) dheight / outscale);
\r
3092 sprintf(logline, "%ld %ld scale\n", dwidth, dheight);
\r
3095 sprintf(logline, "%ld %ld scale\n", dwidth, dheight);
\r
3097 PSputs(logline, output);
\r
3099 /* if (bFigureColor && paintback) { */ /* need to paint background */
\r
3100 /* proper support for \special{figurecolor: . . . . . .} 94/Mar/14 */
\r
3101 if (BitsPerSample == 1) { /* need to paint background ? */
\r
3102 /* fputs("gsave\n", output); */ /* not needed */
\r
3103 /* paint background here in background color */
\r
3104 /* if (backred != 1.0 || backgreen != 1.0 || backblue != 1.0) */
\r
3105 if (bFigureColor) {
\r
3106 sprintf(logline, "%lg %lg %lg rgb\n",
\r
3107 backred, backgreen, backblue); /* color for background */
\r
3108 PSputs(logline, output);
\r
3111 // fputs("white\n", output);
\r
3112 PSputs("white\n", output);
\r
3114 /* now paint background in this color *//* use `box' in preamble ? */
\r
3115 if (bSuppressBack == 0) {
\r
3116 // fputs("0 0 moveto 1 0 lineto ", output);
\r
3117 PSputs("0 0 moveto 1 0 lineto ", output);
\r
3118 /* fputs("0 0 moveto 1 0 lineto 1 -1 lineto 0 -1 lineto closepath fill\n", output); */
\r
3119 /* background seems to be painted above not on image 95/Dec/31 */
\r
3120 /* fputs("0 0 moveto 1 0 lineto 1 1 lineto 0 1 lineto closepath fill\n", output); */
\r
3121 if (hptagflag != 0) {
\r
3122 // fputs("1 1 lineto 0 1 lineto ", output);
\r
3123 PSputs("1 1 lineto 0 1 lineto ", output);
\r
3125 /* background seems to be painted below not on image 96/May/6 */
\r
3127 // fputs("1 -1 lineto 0 -1 lineto ", output);
\r
3128 PSputs("1 -1 lineto 0 -1 lineto ", output);
\r
3130 // fputs("closepath fill\n", output);
\r
3131 PSputs("closepath fill\n", output);
\r
3133 if (bFigureColor) {
\r
3134 sprintf(logline, "%lg %lg %lg rgb\n",
\r
3135 figurered, figuregreen, figureblue); /* color for foreground */
\r
3136 PSputs(logline, output);
\r
3139 // fputs("black\n", output);
\r
3140 PSputs("black\n", output);
\r
3142 /* fputs("grestore\n", output); */ /* not needed */
\r
3144 // fprintf(output, "%ld %ld %d\n", ImageWidth, ImageLength, bits);
\r
3145 sprintf(logline, "%ld %ld ", ImageWidth, ImageLength);
\r
3146 PSputs(logline, output);
\r
3147 if (bMonoChrome) {
\r
3148 if (bInvertImage) {
\r
3149 // fputs("true\n", output);
\r
3150 PSputs("true\n", output);
\r
3153 // fputs("false\n", output);
\r
3154 PSputs("false\n", output);
\r
3158 sprintf(logline, "%d\n", bits); /* not monochrome */
\r
3159 PSputs(logline, output);
\r
3161 if (BMPflag) { /* new mode 98/Jul/9 */
\r
3162 sprintf(logline, "[%ld 0 0 %ld 0 %ld]\n",
\r
3163 ImageWidth, -ImageLength, 0);
\r
3164 PSputs(logline, output);
\r
3167 if (hptagflag != 0) YOffset = 0;
\r
3168 else YOffset = ImageLength;
\r
3169 sprintf(logline, "[%ld 0 0 %ld 0 %ld]\n",
\r
3170 ImageWidth, ImageLength, YOffset);
\r
3171 PSputs(logline, output);
\r
3173 /* fputs("{currentfile picstr readhexstring pop} bind\n", output); */
\r
3175 // fputs("currentfile", output);
\r
3176 PSputs("currentfile", output);
\r
3177 // fputs(" /ASCII85Decode filter", output);
\r
3178 PSputs(" /ASCII85Decode filter", output);
\r
3179 if (bRunLengthFlag) {
\r
3180 // fputs(" /RunLengthDecode filter", output);
\r
3181 PSputs(" /RunLengthDecode filter", output);
\r
3183 #ifdef LZWCOMPRESSION
\r
3184 else if (bLZWFlag) {
\r
3185 // fputs(" /LZWDecode filter", output);
\r
3186 PSputs(" /LZWDecode filter", output);
\r
3189 // putc('\n', output);
\r
3190 PSputc('\n', output);
\r
3193 // fputs("{currentfile picstr readhexstring pop} bind\n", output);
\r
3194 PSputs("{currentfile picstr readhexstring pop} bind\n", output);
\r
3196 /* samples per pixel better be 1 (grey), 3 (RGB) or 4 (CMYK) */
\r
3197 if (bColorImage && bAllowColor) {
\r
3198 // fprintf(output, "false %d colorimage\n", SamplesPerPixel);
\r
3199 sprintf(logline, "false %d colorimage", samples); /* 96/July/7 */
\r
3200 PSputs(logline, output);
\r
3202 /* else if (bCompressColor) fputs("image\n", output); */
\r
3203 else if (bMonoChrome) {
\r
3204 // fputs("imagemask", output); /* monochrome */
\r
3205 PSputs("imagemask", output); /* monochrome */
\r
3208 // fputs("image", output); /* either not color, or color compressed */
\r
3209 PSputs("image", output); /* either not color, or color compressed */
\r
3211 // putc('\n', output);
\r
3212 PSputc('\n', output);
\r
3213 /* image data must follow right away */
\r
3216 void writepstrailer (FILE *output)
\r
3219 if (traceflag) showline("Now writing trailer\n", 0);
\r
3221 /* if (BitsPerSample == 1) {
\r
3222 if (bTextColor) fprintf(output, "%lg %lg %lg rgb\n",
\r
3223 Textred, Textgreen, Textblue);
\r
3224 else if(bFigureColor) fputs("black\n");
\r
3225 } */ /* monochrome - not needed */
\r
3226 // fputs("restore\n", output);
\r
3227 PSputs("restore\n", output);
\r
3230 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
3232 /* Read a row using PACK_BITS compression scheme */
\r
3233 /* returns non-zero if problems encountered */
\r
3235 int readpackbits (unsigned char *lpBuffer, FILE *input, int RowLength)
\r
3237 unsigned char *u=lpBuffer;
\r
3238 int c, k, n, total=0, flag=0;
\r
3241 if ((n = getc(input)) < 0) { /* premature EOF */
\r
3242 showline(" Premature EOF", 1);
\r
3246 else if (n < 128) { /* use next (n+1) bytes as is */
\r
3247 for (k=0; k < n+1; k++) *u++ = (char) getc(input);
\r
3250 else if (n > 128) { /* repeat next byte (257 - n) times */
\r
3252 for (k=0; k < (257 - n); k++) *u++ = (char) c;
\r
3253 total += (257 - n);
\r
3255 /* and n == 128 is a NOP */
\r
3256 if (total == RowLength) break; /* enough bytes yet ? */
\r
3257 if (total > RowLength) { /* too many bytes ? */
\r
3258 showline(" Too many bytes in compressed row\n", 1);
\r
3266 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
3268 /* Implement 1d CCITT Huffman code decompression (minus EOL) */
\r
3269 /* ==> implies BitsPerSample == 1 */
\r
3270 /* white runs = 0, black runs = 1 */
\r
3271 /* normal PhotometricInterpretation == 0 */
\r
3272 /* invert black/white if PhotometricInterpretation == 1 */
\r
3274 int bytex, bitsleft; /* input buffering in splitting bits */
\r
3276 int getbit (FILE *input)
\r
3278 if (bitsleft-- <= 0) {
\r
3279 if ((bytex = getc(input)) == EOF) {
\r
3280 sprintf(logline, " Unexpected EOF (%s)\n", "getbit TIFF");
\r
3281 showline(logline, 0);
\r
3282 /* checkexit(1); */ /* Wait for it to create bad code */
\r
3286 bytex = bytex << 1;
\r
3289 sprintf(logline, "%d", (bytex & 256) ? 1 : 0);
\r
3290 showline(logline, 0);
\r
3293 if (bytex & 256) return 1;
\r
3297 //#pragma optimize ("lge", on)
\r
3299 /* It's the Huffman code stuff that wants to be not optimized */
\r
3301 //#pragma optimize ("lge", off)
\r
3303 /* Actually commonmake may be OK with compiler optimizations ON */
\r
3305 int commonmake (FILE *input) /* common black/white make up codes (7 zeros) */
\r
3309 showline("commonmake entry ", 0);
\r
3312 if (getbit(input)) { /* 00000001 */
\r
3313 if (getbit(input)) { /* 000000011 */
\r
3314 if (getbit(input)) { /* 0000000111 */
\r
3315 if (getbit(input)) { /* 00000001111 */
\r
3316 if (getbit(input)) { /* 000000011111 */
\r
3319 else { /* 000000011110 */
\r
3323 else { /* 00000001110 */
\r
3324 if (getbit(input)) { /* 000000011101 */
\r
3327 else { /* 000000011100 */
\r
3332 else { /* 0000000110 */
\r
3333 if (getbit(input)) { /* 00000001101 */
\r
3336 else { /* 00000001100 */
\r
3341 else { /* 000000010 */
\r
3342 if (getbit(input)) { /* 0000000101 */
\r
3343 if (getbit(input)) { /* 00000001011 */
\r
3344 if (getbit(input)) { /* 000000010111 */
\r
3347 else { /* 000000010110 */
\r
3351 else { /* 00000001010 */
\r
3352 if (getbit(input)) { /* 000000010101 */
\r
3355 else { /* 000000010100 */
\r
3360 else { /* 0000000100 */
\r
3361 if (getbit(input)) { /* 00000001001 */
\r
3362 if (getbit(input)) { /* 000000010011 */
\r
3365 else { /* 000000010010 */
\r
3369 else { /* 00000001000 */
\r
3375 else { /* 00000000 */
\r
3376 /* Actually, EOL code is not supposed to be used in TIFF compression 2 */
\r
3377 if (!getbit(input)) { /* 000000000 */
\r
3378 if (!getbit(input)) { /* 0000000000 */
\r
3379 if (!getbit(input)) { /* 00000000000 */
\r
3380 if (getbit(input)) { /* 000000000001 */
\r
3381 showline("EOL ", 1);
\r
3382 return 0; /* ??? */
\r
3388 showline(" Impossible make-up run\n", 1);
\r
3389 return -1; /* error */
\r
3392 /* Compiler screws up the following code if optimizations turned on */
\r
3394 int whiterun (FILE *input)
\r
3399 showline("whiterun entry ", 0);
\r
3402 if (getbit(input)) { /* 1 */
\r
3403 if (getbit(input)) { /* 11 */
\r
3404 if (getbit(input)) { /* 111 */
\r
3405 if (getbit(input)) { /* 1111 */
\r
3413 if (getbit(input)) { /* 1101 */
\r
3414 if (getbit(input)) { /* 11011 */
\r
3415 return 64; /* make up */
\r
3417 else { /* 11010 */
\r
3418 if (getbit(input)) { /* 110101 */
\r
3421 else { /* 110100 */
\r
3432 if (getbit(input)) { /* 101 */
\r
3433 if (getbit(input)) { /* 1011 */
\r
3437 if (getbit(input)) { /* 10101 */
\r
3438 if (getbit(input)) { /* 101011 */
\r
3441 else { /* 101010 */
\r
3445 else { /* 10100 */
\r
3451 if (getbit(input)) { /* 1001 */
\r
3452 if (getbit(input)) { /* 10011 */
\r
3455 else { /* 10010 */
\r
3456 return 128; /* make up */
\r
3466 if (getbit(input)) { /* 01 */
\r
3467 if (getbit(input)) { /* 011 */
\r
3468 if (getbit(input)) { /* 0111 */
\r
3472 if (getbit(input)) { /* 01101 */
\r
3473 if (getbit(input)) { /* 011011 */
\r
3474 if (getbit(input)) { /* 0110111 */
\r
3475 return 256; /* make up */
\r
3477 else { /* 0110110 */
\r
3478 if (getbit(input)) { /* 01101101 */
\r
3479 if (getbit(input)) { /* 011011011 */
\r
3480 return 1408; /* make up */
\r
3482 else { /* 011011010 */
\r
3483 return 1344; /* make up */
\r
3486 else { /* 01101100 */
\r
3487 if (getbit(input)) { /* 011011001 */
\r
3488 return 1280; /* make up */
\r
3490 else { /* 011011000 */
\r
3491 return 1216; /* make up */
\r
3496 else { /* 011010 */
\r
3497 if (getbit(input)) { /* 0110101 */
\r
3498 if (getbit(input)) { /* 01101011 */
\r
3499 if (getbit(input)) { /* 011010111 */
\r
3500 return 1152; /* make up */
\r
3502 else { /* 011010110 */
\r
3503 return 1088; /* make up */
\r
3506 else { /* 01101010 */
\r
3507 if (getbit(input)) { /* 011010101 */
\r
3508 return 1024; /* make up */
\r
3510 else { /* 011010100 */
\r
3511 return 960; /* make up */
\r
3515 else { /* 0110100 */
\r
3516 if (getbit(input)) { /* 01101001 */
\r
3517 if (getbit(input)) { /* 011010011 */
\r
3518 return 896; /* make up */
\r
3520 else { /* 011010010 */
\r
3521 return 832; /* make up */
\r
3524 else { /* 01101000 */
\r
3525 return 576; /* make up */
\r
3530 else { /* 01100 */
\r
3531 if (getbit(input)) { /* 011001 */
\r
3532 if (getbit(input)) { /* 0110011 */
\r
3533 if (getbit(input)) { /* 01100111 */
\r
3534 return 640; /* make up */
\r
3536 else { /* 01100110 */
\r
3537 if (getbit(input)) { /* 011001101 */
\r
3538 return 768; /* make up */
\r
3540 else { /* 011001100 */
\r
3541 return 704; /* make up */
\r
3545 else { /* 0110010 */
\r
3546 if (getbit(input)) { /* 01100101 */
\r
3547 return 512; /* make up */
\r
3549 else { /* 01100100 */
\r
3550 return 448; /* make up */
\r
3554 else { /* 011000 */
\r
3555 return 1664; /* make up */
\r
3561 if (getbit(input)) { /* 0101 */
\r
3562 if (getbit(input)) { /* 01011 */
\r
3563 if (getbit(input)) { /* 010111 */
\r
3564 return 192; /* make up */
\r
3566 else { /* 010110 */
\r
3567 if (getbit(input)) { /* 0101101 */
\r
3568 if (getbit(input)) { /* 01011011 */
\r
3571 else { /* 01011010 */
\r
3575 else { /* 0101100 */
\r
3576 if (getbit(input)) { /* 01011001 */
\r
3579 else { /* 01011000 */
\r
3585 else { /* 01010 */
\r
3586 if (getbit(input)) { /* 010101 */
\r
3587 if (getbit(input)) { /* 0101011 */
\r
3590 else { /* 0101010 */
\r
3591 if (getbit(input)) { /* 01010101 */
\r
3594 else { /* 01010100 */
\r
3599 else { /* 010100 */
\r
3600 if (getbit(input)) { /* 0101001 */
\r
3601 if (getbit(input)) { /* 01010011 */
\r
3604 else { /* 01010010 */
\r
3608 else { /* 0101000 */
\r
3615 if (getbit(input)) { /* 01001 */
\r
3616 if (getbit(input)) { /* 010011 */
\r
3617 if (getbit(input)) { /* 0100111 */
\r
3620 else { /* 0100110 */
\r
3621 if (getbit(input)) { /* 01001101 */
\r
3622 if (getbit(input)) { /* 010011011 */
\r
3623 return 1728; /* make up */
\r
3625 else { /* 010011010 */
\r
3626 return 1600; /* make up */
\r
3629 else { /* 01001100 */
\r
3630 if (getbit(input)) { /* 010011001 */
\r
3631 return 1536; /* make up */
\r
3633 else { /* 010011000 */
\r
3634 return 1472; /* make up */
\r
3639 else { /* 010010 */
\r
3640 if (getbit(input)) { /* 0100101 */
\r
3641 if (getbit(input)) { /* 01001011 */
\r
3644 else { /* 01001010 */
\r
3648 else { /* 0100100 */
\r
3653 else { /* 01000 */
\r
3660 if (getbit(input)) { /* 001 */
\r
3661 if (getbit(input)) { /* 0011 */
\r
3662 if (getbit(input)) { /* 00111 */
\r
3665 else { /* 00110 */
\r
3666 if (getbit(input)) { /* 001101 */
\r
3667 if (getbit(input)) { /* 0011011 */
\r
3668 if (getbit(input)) { /* 0110111 */
\r
3669 return 384; /* make up */
\r
3671 else { /* 0110110 */
\r
3672 return 320; /* make up */
\r
3675 else { /* 0011010 */
\r
3676 if (getbit(input)) { /* 00110101 */
\r
3679 else { /* 00110100 */
\r
3684 else { /* 001100 */
\r
3685 if (getbit(input)) { /* 0011001 */
\r
3686 if (getbit(input)) { /* 00110011 */
\r
3689 else { /* 00110010 */
\r
3693 else { /* 0011000 */
\r
3700 if (getbit(input)) { /* 00101 */
\r
3701 if (getbit(input)) { /* 001011 */
\r
3702 if (getbit(input)) { /* 0010111 */
\r
3705 else { /* 0010110 */
\r
3706 if (getbit(input)) { /* 00101101 */
\r
3709 else { /* 00101100 */
\r
3714 else { /* 001010 */
\r
3715 if (getbit(input)) { /* 0010101 */
\r
3716 if (getbit(input)) { /* 00101011 */
\r
3719 else { /* 00101010 */
\r
3723 else { /* 0010100 */
\r
3724 if (getbit(input)) { /* 00101001 */
\r
3727 else { /* 00101000 */
\r
3733 else { /* 00100 */
\r
3734 if (getbit(input)) { /* 001001 */
\r
3735 if (getbit(input)) { /* 0010011 */
\r
3738 else { /* 0010010 */
\r
3739 if (getbit(input)) { /* 00100101 */
\r
3742 else { /* 00100100 */
\r
3747 else { /* 001000 */
\r
3754 if (getbit(input)) { /* 0001 */
\r
3755 if (getbit(input)) { /* 00011 */
\r
3756 if (getbit(input)) { /* 000111 */
\r
3759 else { /* 000110 */
\r
3760 if (getbit(input)) { /* 0001101 */
\r
3761 if (getbit(input)) { /* 00011011 */
\r
3764 else { /* 00011010 */
\r
3768 else { /* 0001100 */
\r
3773 else { /* 00010 */
\r
3774 if (getbit(input)) { /* 000101 */
\r
3775 if (getbit(input)) { /* 0001011 */
\r
3776 if (getbit(input)) { /* 00010111 */
\r
3779 else { /* 00010110 */
\r
3783 else { /* 0001010 */
\r
3784 if (getbit(input)) { /* 00010101 */
\r
3787 else { /* 00010100 */
\r
3792 else { /* 000100 */
\r
3793 if (getbit(input)) { /* 0001001 */
\r
3794 if (getbit(input)) { /* 00010011 */
\r
3797 else { /* 00010010 */
\r
3801 else { /* 0001000 */
\r
3808 if (getbit(input)) { /* 00001 */
\r
3809 if (getbit(input)) { /* 000011 */
\r
3812 else { /* 000010 */
\r
3813 if (getbit(input)) { /* 0000101 */
\r
3814 if (getbit(input)) { /* 00001011 */
\r
3817 else { /* 00001010 */
\r
3821 else { /* 0000100 */
\r
3826 else { /* 00000 */
\r
3827 if (getbit(input)) { /* 000001 */
\r
3828 if (getbit(input)) { /* 0000011 */
\r
3831 else { /* 0000010 */
\r
3832 if (getbit(input)) { /* 00000101 */
\r
3835 else { /* 00000100 */
\r
3840 else { /* 000000 */
\r
3841 if (getbit(input)) { /* 0000001 */
\r
3842 if (getbit(input)) { /* 00000011 */
\r
3845 else { /* 00000010 */
\r
3849 else { /* 0000000 */
\r
3850 return commonmake(input); /* seven zeros */
\r
3858 showline(" Impossible white run\n", 1);
\r
3859 return -1; /* error */
\r
3862 /* Compiler screws up the following code if optimizations turned on */
\r
3864 int blackzero (FILE *input) /* black run code starts with four zeros */
\r
3867 if (traceflag) showline (" blackzero entry ", 0);
\r
3869 if (getbit(input)) { /* 00001 */
\r
3870 if (getbit(input)) { /* 000011 */
\r
3871 if (getbit(input)) { /* 0000111 */
\r
3874 else { /* 0000110 */
\r
3875 if (getbit(input)) { /* 00001101 */
\r
3876 if (getbit(input)) { /* 000011011 */
\r
3877 if (getbit(input)) { /* 0000110111 */
\r
3880 else { /* 0000110110 */
\r
3881 if (getbit(input)) { /* 00001101101 */
\r
3882 if (getbit(input)) { /* 000011011011 */
\r
3885 else { /* 000011011010 */
\r
3889 else { /* 00001101100 */
\r
3894 else { /* 000011010 */
\r
3895 if (getbit(input)) { /* 0000110101 */
\r
3896 if (getbit(input)) { /* 00001101011 */
\r
3897 if (getbit(input)) { /* 000011010111 */
\r
3900 else { /* 000011010110 */
\r
3904 else { /* 00001101010 */
\r
3905 if (getbit(input)) { /* 000011010101 */
\r
3908 else { /* 000011010100 */
\r
3913 else { /* 0000110100 */
\r
3914 if (getbit(input)) { /* 00001101001 */
\r
3915 if (getbit(input)) { /* 000011010011 */
\r
3918 else { /* 000011010010 */
\r
3922 else { /* 00001101000 */
\r
3928 else { /* 00001100 */
\r
3929 if (getbit(input)) { /* 000011001 */
\r
3930 if (getbit(input)) { /* 0000110011 */
\r
3931 if (getbit(input)) { /* 00001100111 */
\r
3934 else { /* 00001100110 */
\r
3935 if (getbit(input)) { /* 000011001101 */
\r
3938 else { /* 000011001100 */
\r
3943 else { /* 0000110010 */
\r
3944 if (getbit(input)) { /* 00001100101 */
\r
3945 if (getbit(input)) { /* 000011001011 */
\r
3948 else { /* 000011001010 */
\r
3952 else { /* 00001100100 */
\r
3953 if (getbit(input)) { /* 000011001001 */
\r
3954 return 192; /* make up */
\r
3956 else { /* 000011001000 */
\r
3957 return 128; /* make up */
\r
3962 else { /* 000011000 */
\r
3968 else { /* 000010 */
\r
3969 if (getbit(input)) { /* 0000101 */
\r
3972 else { /* 0000100 */
\r
3977 else { /* 00000 */
\r
3978 if (getbit(input)) { /* 000001 */
\r
3979 if (getbit(input)) { /* 0000011 */
\r
3980 if (getbit(input)) { /* 00000111 */
\r
3983 else { /* 00000110 */
\r
3984 if (getbit(input)) { /* 000001101 */
\r
3985 if (getbit(input)) { /* 0000011011 */
\r
3986 if (getbit(input)) { /* 00000110111 */
\r
3989 else { /* 00000110110 */
\r
3990 if (getbit(input)) { /* 000001101101 */
\r
3993 else { /* 000001101100 */
\r
3998 else { /* 0000011010 */
\r
3999 if (getbit(input)) { /* 00000110101 */
\r
4000 if (getbit(input)) { /* 000001101011 */
\r
4003 else { /* 000001101010 */
\r
4007 else { /* 00000110100 */
\r
4008 if (getbit(input)) { /* 000001101001 */
\r
4011 else { /* 000001101000 */
\r
4017 else { /* 000001100 */
\r
4018 if (getbit(input)) { /* 0000011001 */
\r
4019 if (getbit(input)) { /* 00000110011 */
\r
4020 if (getbit(input)) { /* 000001100111 */
\r
4023 else { /* 000001100110 */
\r
4027 else { /* 00000110010 */
\r
4028 if (getbit(input)) { /* 000001100101 */
\r
4031 else { /* 000001100100 */
\r
4036 else { /* 0000011000 */
\r
4042 else { /* 0000010 */
\r
4043 if (getbit(input)) { /* 00000101 */
\r
4044 if (getbit(input)) { /* 000001011 */
\r
4045 if (getbit(input)) { /* 0000010111 */
\r
4048 else { /* 0000010110 */
\r
4049 if (getbit(input)) { /* 00000101101 */
\r
4050 if (getbit(input)) { /* 000001011011 */
\r
4051 return 256; /* make up */
\r
4053 else { /* 000001011010 */
\r
4057 else { /* 00000101100 */
\r
4058 if (getbit(input)) { /* 000001011001 */
\r
4061 else { /* 000001011000 */
\r
4067 else { /* 000001010 */
\r
4068 if (getbit(input)) { /* 0000010101 */
\r
4069 if (getbit(input)) { /* 00000101011 */
\r
4070 if (getbit(input)) { /* 000001010111 */
\r
4073 else { /* 000001010110 */
\r
4077 else { /* 00000101010 */
\r
4078 if (getbit(input)) { /* 000001010101 */
\r
4081 else { /* 000001010100 */
\r
4086 else { /* 0000010100 */
\r
4087 if (getbit(input)) { /* 00000101001 */
\r
4088 if (getbit(input)) { /* 000001010011 */
\r
4091 else { /* 000001010010 */
\r
4095 else { /* 00000101000 */
\r
4101 else { /* 00000100 */
\r
4106 else { /* 000000 */
\r
4107 if (getbit(input)) { /* 0000001 */
\r
4108 if (getbit(input)) { /* 00000011 */
\r
4109 if (getbit(input)) { /* 000000111 */
\r
4110 if (getbit(input)) { /* 0000001111 */
\r
4111 return 64; /* make up */
\r
4113 else { /* 0000001110 */
\r
4114 if (getbit(input)) { /* 00000011101 */
\r
4115 if (getbit(input)) { /* 000000111011 */
\r
4116 if (getbit(input)) { /* 0000001110111 */
\r
4119 else { /* 0000001110110 */
\r
4123 else { /* 000000111010 */
\r
4124 if (getbit(input)) { /* 0000001110101 */
\r
4127 else { /* 0000001110100 */
\r
4133 else { /* 00000011100 */
\r
4134 if (getbit(input)) { /* 000000111001 */
\r
4135 if (getbit(input)) { /* 0000001110011 */
\r
4138 else { /* 0000001110010 */
\r
4142 else { /* 000000111000 */
\r
4148 else { /* 000000110 */
\r
4149 if (getbit(input)) { /* 0000001101 */
\r
4150 if (getbit(input)) { /* 00000011011 */
\r
4151 if (getbit(input)) { /* 000000110111 */
\r
4154 else { /* 000000110110 */
\r
4155 if (getbit(input)) { /* 0000001101101 */
\r
4156 return 576; /*make up */
\r
4158 else { /* 0000001101100 */
\r
4159 return 512; /* make up */
\r
4163 else { /* 00000011010 */
\r
4164 if (getbit(input)) { /* 000000110101 */
\r
4165 return 448; /* make up */
\r
4167 else { /* 000000110100 */
\r
4168 return 384; /* make up */
\r
4172 else { /* 0000001100 */
\r
4173 if (getbit(input)) { /* 00000011001 */
\r
4174 if (getbit(input)) { /* 000000110011 */
\r
4175 return 320; /* make up */
\r
4177 else { /* 000000110010 */
\r
4178 if (getbit(input)) { /* 0000001100101 */
\r
4181 else { /* 0000001100100 */
\r
4186 else { /* 00000011000 */
\r
4192 else { /* 00000010 */
\r
4193 if (getbit(input)) { /* 000000101 */
\r
4194 if (getbit(input)) { /* 0000001011 */
\r
4195 if (getbit(input)) { /* 00000010111 */
\r
4198 else { /* 00000010110 */
\r
4199 if (getbit(input)) { /* 000000101101 */
\r
4200 if (getbit(input)) { /* 0000001011011 */
\r
4203 else { /* 0000001011010 */
\r
4207 else { /* 000000101100 */
\r
4212 else { /* 0000001010 */
\r
4213 if (getbit(input)) { /* 00000010101 */
\r
4214 if (getbit(input)) { /* 000000101011 */
\r
4217 else { /* 000000101010 */
\r
4218 if (getbit(input)) { /* 0000001010101 */
\r
4221 else { /* 0000001010100 */
\r
4226 else { /* 00000010100 */
\r
4227 if (getbit(input)) { /* 000000101001 */
\r
4228 if (getbit(input)) { /* 0000001010011 */
\r
4231 else { /* 0000001010010 */
\r
4235 else { /* 000000101000 */
\r
4241 else { /* 000000100 */
\r
4242 if (getbit(input)) { /* 0000001001 */
\r
4243 if (getbit(input)) { /* 00000010011 */
\r
4244 if (getbit(input)) { /* 000000100111 */
\r
4247 else { /* 000000100110 */
\r
4248 if (getbit(input)) { /* 0000001001101 */
\r
4251 else { /* 0000001001100 */
\r
4256 else { /* 00000010010 */
\r
4257 if (getbit(input)) { /* 000000100101 */
\r
4258 if (getbit(input)) { /* 0000001001011 */
\r
4261 else { /* 0000001001010 */
\r
4265 else { /* 000000100100 */
\r
4270 else { /* 0000001000 */
\r
4276 else { /* 0000000 */
\r
4277 return commonmake(input); /* seven zeros */
\r
4281 showline(" Impossible black run", 1);
\r
4282 showline(" (starting with four zeros)\n", 1);
\r
4283 return -1; /* error */
\r
4286 /* blackrun may actually be OK with compiler optimizations turned on */
\r
4288 int blackrun (FILE *input)
\r
4293 showline ("blackrun entry ", 0);
\r
4296 if (getbit(input)) { /* 1 */
\r
4297 if (getbit(input)) { /* 11 */
\r
4305 if (getbit(input)) { /* 01 */
\r
4306 if (getbit(input)) { /* 011 */
\r
4314 if (getbit(input)) { /* 001 */
\r
4315 if (getbit(input)) { /* 0011 */
\r
4323 if (getbit(input)) { /* 0001 */
\r
4324 if (getbit(input)) { /* 00011 */
\r
4327 else { /* 00010 */
\r
4328 if (getbit(input)) { /* 000101 */
\r
4331 else { /* 000100 */
\r
4337 return blackzero(input); /* four zeros */
\r
4342 showline(" ERROR: Impossible black run", 1);
\r
4343 showline("\n", 0);
\r
4344 return -1; /* error */
\r
4347 //#pragma optimize ("lge", on)
\r
4349 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
4351 /* FOLLOWING IS EXPERIMENT 97/OCT/21 */
\r
4353 //#pragma optimize ("lge", off)
\r
4355 int index, bitinx; /* index into row of bytes and bits within them */
\r
4357 int total; /* maybe long ? */
\r
4359 /* Following could be speeded up some ... */
\r
4361 int writewhite (unsigned char *lpBuffer, int run, int width)
\r
4363 if (run == 0) return 0; /* nothing to do */
\r
4364 if (run < 0) return -1; /* hit invalid run */
\r
4368 sprintf(logline, "run %d total %d\n", run, total);
\r
4369 showline(logline, 0);
\r
4372 if (total > width) return -1; /* error */
\r
4373 /* just advance pointers */
\r
4375 if (bitinx == 0) {
\r
4376 while (run >= 8) {
\r
4380 sprintf(logline, "index %d run %d ", index, run);
\r
4381 showline(logline, 0);
\r
4384 /* *(lpBuffer+index) = 0; */ /* already zeroed out */
\r
4389 if (bitinx-- <= 0) {
\r
4390 index++; bitinx = 7;
\r
4394 sprintf(logline, "index %d bitinx %d ", index, bitinx);
\r
4395 showline(logline, 0);
\r
4398 /* *(lpBuffer + index) &= ~(1 << bitinx); */
\r
4402 if (total == width) return 1; /* EOL */
\r
4406 int writeblack (unsigned char *lpBuffer, int run, int width)
\r
4408 if (run == 0) return 0; /* nothing to do */
\r
4409 if (run < 0) return -1; /* hit invalid run */
\r
4413 sprintf(logline, "run %d total %d\n", run, total);
\r
4414 showline(logline, 0);
\r
4417 if (total > width) return -1; /* error */
\r
4419 if (bitinx == 0) {
\r
4420 while (run >= 8) {
\r
4424 sprintf(logline, "index %d run %d ", index, run);
\r
4425 showline(logline, 0);
\r
4428 *(lpBuffer+index) = 255; /* write a byte at a time */
\r
4433 if (bitinx-- <= 0) {
\r
4434 index++; bitinx = 7;
\r
4438 sprintf(logline, "index %d bitinx %d ", index, bitinx);
\r
4439 showline(logline, 0);
\r
4442 *(lpBuffer + index) |= (1 << bitinx); /* write a bit at a time */
\r
4446 if (total == width) return 1; /* EOL */
\r
4450 /* make width long ? */
\r
4452 int huffmanrow (unsigned char *lpBuffer, FILE *input, int width)
\r
4456 /* int total = 0; */ /* long total ? */
\r
4458 /* if (lpBuffer == NULL) {
\r
4459 showline(" Bad buffer pointer\n", 1);
\r
4463 index = -1; bitinx = 0; /* output buffering */
\r
4464 bytex = 0; bitsleft = 0; /* input buffering */
\r
4466 bytes = (width + 7) / 8; /* preset with zeros */
\r
4469 sprintf(logline, "Cleaning out %d bytes\n", bytes);
\r
4470 showline(logline, 0);
\r
4473 for (k = 0; k < bytes; k++) lpBuffer[k] = 0;
\r
4478 sprintf(logline, "Looking for white run\n");
\r
4479 showline(logline, 0);
\r
4482 while ((run = whiterun (input)) >= 64) {
\r
4485 sprintf(logline, " W %d ", run);
\r
4486 showline(logline, 0);
\r
4489 if (writewhite(lpBuffer, run, width) < 0) break;
\r
4491 if (total >= width) break;
\r
4494 sprintf(logline, " W %d\n", run);
\r
4495 showline(logline, 0);
\r
4498 if (writewhite(lpBuffer, run, width) != 0) break; /* terminal run */
\r
4502 sprintf(logline, "Looking for black run\n");
\r
4503 showline(logline, 0);
\r
4506 while ((run = blackrun (input)) >= 64) {
\r
4509 sprintf(logline, " B %d ", run);
\r
4510 showline(logline, 0);
\r
4513 if (writeblack(lpBuffer, run, width) < 0) break;
\r
4515 if (total >= width) break;
\r
4518 sprintf(logline, " B %d\n", run);
\r
4519 showline(logline, 0);
\r
4522 if (writeblack(lpBuffer, run, width) != 0) break; /* terminal run */
\r
4524 if (total != width) {
\r
4525 sprintf(logline, " Sum of runs %d not equal width %d\n", total, width);
\r
4526 showline(logline, 1);
\r
4530 else if (traceflag ) {
\r
4531 sprintf(logline, "Sum of runs equal to width %d\n", width);
\r
4532 showline(logline, 0);
\r
4538 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
4540 //#pragma optimize ("lge", on) /* experiment 2000 June 17 */
\r
4542 /* Here is the code for LZW (compression scheme number 5) input side */
\r
4544 char *StringByte=NULL; /* contains last byte of string */
\r
4546 char *StringFirst=NULL; /* contains first byte of string */
\r
4547 /* to speed up processing ... */
\r
4549 #ifdef USESHORTINT
\r
4550 short int *StringPrevious=NULL; /* points to previous char of string */
\r
4551 short int *StringLength=NULL; /* length of string */
\r
4552 /* to speed up processing ... */
\r
4554 int *StringPrevious=NULL; /* points to previous char of string */
\r
4555 int *StringLength=NULL; /* length of string */
\r
4556 /* to speed up processing ... */
\r
4559 int TableIndex=FIRSTCODE; /* index into above String Tables */
\r
4560 /* next available string entry */
\r
4562 int CodeLength=9; /* current code length INPUT */
\r
4564 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
4566 /* following is never called ? now called from dvipsone.c when exiting */
\r
4568 void DeAllocStringsIn (void) /* remember to do this at end */
\r
4570 /* if (Memory != NULL) {
\r
4571 free(Memory); Memory = NULL;
\r
4573 if (StringByte != NULL) {
\r
4574 free(StringByte); StringByte = NULL;
\r
4576 if (StringFirst != NULL) {
\r
4577 free(StringFirst); StringFirst = NULL;
\r
4579 if (StringPrevious != NULL) {
\r
4580 free(StringPrevious); StringPrevious = NULL;
\r
4582 if (StringLength != NULL) {
\r
4583 free(StringLength); StringLength = NULL;
\r
4587 /* worry here about allocation in NT ? sizeof(int) */
\r
4589 int AllocStringsIn (void)
\r
4591 /* if (Memory == NULL) {
\r
4592 Memory = (char *) malloc(INIMEMORY);
\r
4593 MemorySize = INIMEMORY;
\r
4594 } */ /* memory for strings in string table */
\r
4595 if (StringByte == NULL) { /* allocate string table indeces */
\r
4596 StringByte = (char *) malloc(MAXCODES * sizeof(char));
\r
4598 if (StringFirst == NULL) { /* allocate string table indeces */
\r
4599 StringFirst = (char *) malloc(MAXCODES * sizeof(char));
\r
4601 /* should this be short int in NT ? */
\r
4602 #ifdef USESHORTINT
\r
4603 if (StringPrevious == NULL) { /* allocate string table lengths */
\r
4604 StringPrevious = (short int *)
\r
4605 malloc(MAXCODES * sizeof(short int));
\r
4607 if (StringLength == NULL) { /* allocate string table lengths */
\r
4608 StringLength = (short int *)
\r
4609 malloc(MAXCODES * sizeof(short int));
\r
4612 if (StringPrevious == NULL) { /* allocate string table lengths */
\r
4613 StringPrevious = (int *) malloc(MAXCODES * sizeof(int));
\r
4615 if (StringLength == NULL) { /* allocate string table lengths */
\r
4616 StringLength = (int *) malloc(MAXCODES * sizeof(int));
\r
4619 /* if (Memory == NULL || StringTable == NULL || StringLength == NULL) { */
\r
4620 if (StringByte == NULL || StringFirst == NULL ||
\r
4621 StringPrevious == NULL || StringLength == NULL) {
\r
4622 showline("Unable to allocate memory\n", 1);
\r
4624 // or more serious exit(1) ???
\r
4629 void InitializeStringTable (void) /* set up string table initially */
\r
4633 AllocStringsIn(); /* grab memory for tables if needed */
\r
4634 // What if it failed ???
\r
4635 for (k = 0; k < MAXCHR; k++) { /* 256 single byte strings */
\r
4636 StringByte[k] = (char) k;
\r
4637 StringFirst[k] = (char) k;
\r
4638 StringPrevious[k] = -1; /* indicate beginning of string */
\r
4639 StringLength[k] = 1;
\r
4641 /* FreeIndex = MAXCHR; */
\r
4642 TableIndex = FIRSTCODE;
\r
4643 CodeLength = 9; /* initial code length */
\r
4646 void ResetStringTable (int quietflag) /* clear string table */
\r
4653 if (traceflag) showline("CLEAR ", 0);
\r
4654 if (traceflag) showline("\n", 0);
\r
4655 if (traceflag && TableIndex > FIRSTCODE)
\r
4657 /* printf("TableIndex %d FreeIndex %u CodeLength %d\n",
\r
4658 TableIndex, FreeIndex, CodeLength); */
\r
4659 sprintf(logline, "TableIndex %d CodeLength %d\n", TableIndex, CodeLength);
\r
4660 showline(logline, 0);
\r
4664 /* following not really needed */
\r
4665 /* for (k = FIRSTCODE; k < TableIndex; k++) {
\r
4666 StringTable[k] = 0;
\r
4667 StringLength[k] = 0;
\r
4669 /* FreeIndex = MAXCHR; */
\r
4670 TableIndex = FIRSTCODE;
\r
4674 #ifdef USESHORTINT
\r
4675 void AddNewEntry (short int OldCode, short int Code)
\r
4678 void AddNewEntry (int OldCode, int Code)
\r
4688 sprintf(logline, "Add string TableIndex %4d (%d)\n",
\r
4689 TableIndex, StringLength[OldCode] + 1);
\r
4690 showline(logline, 0);
\r
4694 /* This is where we enter new one in table */
\r
4695 /* StringTable[TableIndex] = FreeIndex; */
\r
4696 /* StringLength[TableIndex] = len; */
\r
4697 StringByte[TableIndex] = StringFirst[Code];
\r
4698 StringFirst[TableIndex] = StringFirst[OldCode];
\r
4699 StringPrevious[TableIndex] = OldCode;
\r
4700 #ifdef USESHORTINT
\r
4701 StringLength[TableIndex] =
\r
4702 (unsigned short int) (StringLength[OldCode] + 1);
\r
4704 StringLength[TableIndex] = StringLength[OldCode] + 1;
\r
4707 /* s = Memory + FreeIndex; */
\r
4708 /* t = Memory + StringTable[OldCode]; */
\r
4709 /* for (k = 0; k < len-1; k++) *s++ = *t++; */
\r
4710 /* t = Memory + StringTable[Code]; */
\r
4711 /* *s = *t; */ /* last byte comes from next code string */
\r
4712 /* FreeIndex += len; */
\r
4714 if (TableIndex == 511 || TableIndex == 1023 || TableIndex == 2047)
\r
4720 sprintf(logline, "LENGTH %d (%d)\n", TableIndex, CodeLength);
\r
4721 showline(logline, 0);
\r
4726 if (TableIndex > MAXCODES)
\r
4728 showline(" ERROR: Table overflow\n", 1);
\r
4733 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
4735 int IsInTable (int Code) /* is code already in table ? */
\r
4737 return (Code >= 0 && Code < TableIndex);
\r
4740 /* copy string from table by code number */
\r
4742 unsigned char *WriteString (unsigned char *buffer, int Code)
\r
4750 /* t = Memory + StringTable[Code]; */
\r
4751 // if (Code < TableIndex)
\r
4752 len = StringLength[Code];
\r
4753 t = buffer + len; /* byte after last one to copy */
\r
4754 if (t > StripData + StripDataLen) {
\r
4755 /* special case kludge if terminates right after code length switch */
\r
4756 if (((unsigned int) (buffer - StripData) == StripDataLen) &&
\r
4757 // kludge to try and deal with lack of code length increase just before EOI
\r
4758 ((Code == (EOD*2)) || (Code == (EOD*4)))) // 2000/Feb/4
\r
4762 /* showline(" ERROR: ran off end of Strip Buffer\n", 1); */
\r
4764 "ERROR: Strip Buffer len %d code %d EOD %d CodeLength %d TableIndex %d",
\r
4765 len, Code, EOD, CodeLength, TableIndex);
\r
4766 showline(logline, 0);
\r
4769 "code %d len %d buffer %ld buffer + len %ld stripdatalen %ld\n",
\r
4770 Code, len, buffer-StripData, t-StripData, StripDataLen);
\r
4771 showline(logline, 0);
\r
4775 s = t - 1; /* last byte to copy */
\r
4776 /* for (k = 0; k < len; k++) *s++ = *t++; */
\r
4778 /* for (k = 0; k < len; k++) */
\r
4779 /* for (k = len; k > 0; k--) */
\r
4781 /* if (k != StringLength[n])
\r
4782 printf("k %d <> len %d ", k, StringLength[n]); */ /* check */
\r
4783 *s-- = StringByte[n]; /* copy the byte */
\r
4784 /* if (StringPrevious[n] < 0 && k != 1)
\r
4785 printf("k %d n %d Code %d ", k, n, Code); */
\r
4786 n = StringPrevious[n];
\r
4787 /* if (n < 0) break; */ /* termination */
\r
4789 if ((s + 1) != buffer) { /* sanity check */
\r
4791 if ((s+1) > buffer) err = (s+1) - buffer;
\r
4792 else err = buffer - (s+1);
\r
4793 sprintf(logline, "Off by %d (len %d Code %d)\n", err, len, Code);
\r
4794 showline(logline, 1);
\r
4798 if (*s++ != 0) putc('1', stdout);
\r
4799 else putc('0', stdout);
\r
4800 if (counter++ % 1024 == 0) putc('\n', stdout);
\r
4802 return buffer; */ /* TESTING HACK! */
\r
4806 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
4808 unsigned long OldByte=0; /* cadaver being eaten */
\r
4809 int OldBitsLeft=0; /* how many bits left in OldByte */
\r
4811 #ifdef USESHORTINT
\r
4812 short int GetNextCode (FILE *input) /* get next LZW code number from input */
\r
4815 int GetNextCode (FILE *input) /* get next LZW code number from input */
\r
4822 bits = OldBitsLeft; /* how many bits do we have */
\r
4823 k = OldByte; /* start with old bits */
\r
4825 while (bits < CodeLength) { /* need more bits ? */
\r
4826 if (InStripLen-- <= 0) { /* treat as EOD 96/Nov/17 */
\r
4828 sprintf(logline, " No EOD at end of strip %d ", CurrentStrip);
\r
4829 showline(logline, 1);
\r
4833 if ((c = getc(input)) == EOF)
\r
4835 sprintf(logline, " Unexpected EOF (%s)\n", "getnextcode");
\r
4836 showline(logline, 1);
\r
4839 // return -1; /* EOF serious error ... */
\r
4845 OldBitsLeft = bits - CodeLength; /* extra bits not used */
\r
4846 /* OldByte = OldByte & ((1 << OldBitsLeft) - 1); *//* redundant */
\r
4847 k = k >> OldBitsLeft; /* shift out extra bits */
\r
4848 k = k & ((1 << CodeLength) - 1); /* mask out high order */
\r
4851 sprintf(logline, "CODE %4d ", k);
\r
4852 showline(logline, 0);
\r
4855 #ifdef USESHORTINT
\r
4856 return (short int) k;
\r
4862 void LZWdecompress (unsigned char *StripData, FILE *input)
\r
4864 #ifdef USESHORTINT
\r
4865 short int Code, OldCode;
\r
4867 int Code, OldCode;
\r
4869 unsigned int nlen;
\r
4870 unsigned char *s = StripData;
\r
4872 OldCode = 0; /* to keep compiler happy */
\r
4873 /* InitializeStringTable(); */ /* assume already done once */
\r
4874 /* ResetStringTable(1); */ /* not needed - first code CLEAR */
\r
4875 while ((Code = GetNextCode(input)) != EOD) {
\r
4876 if (Code == -1) { // error check only
\r
4877 showline(" ERROR: Premature end of LZW", 1);
\r
4878 showline("\n", 0);
\r
4881 // #ifdef DEBUGLZW
\r
4882 // if (traceflag) {
\r
4883 // sprintf(logline, "%4d ", Code); /* debugging */
\r
4884 // showline(logline, 0);
\r
4887 if (Code == CLEAR) {
\r
4888 ResetStringTable(0);
\r
4889 Code = GetNextCode(input);
\r
4890 if (traceflag) showline("\n", 0);
\r
4891 if (Code == -1) { // error check only
\r
4892 showline(" ERROR: Premature end of LZW", 1);
\r
4893 showline(" (after CLEAR)", 0);
\r
4894 showline("\n", 0);
\r
4897 if (Code == EOD) break;
\r
4898 s = WriteString(s, Code);
\r
4900 } /* end of CLEAR case */
\r
4902 // if (IsInTable(Code)) {
\r
4903 if (Code >= 0 && Code < TableIndex) {
\r
4904 /* AddTableEntry(StringTable(OldCode)
\r
4905 + FirstChar(StringFromCode(Code);)); */
\r
4906 AddNewEntry(OldCode, Code);
\r
4907 s = WriteString(s, Code);
\r
4909 } /* end of Code in Table case */
\r
4910 else { /* Code is *not* in table */
\r
4911 /* OutString = StringFromCode (OldCode) +
\r
4912 + FirstChar(StringFromCode(Code);)); */
\r
4913 if (Code > TableIndex) {
\r
4914 // kludge to try and deal with lack of code length increase just before EOI
\r
4920 " Code (%d) > TableIndex (%d) CodeLength %d ",
\r
4921 Code, TableIndex, CodeLength);
\r
4922 showline(logline, 1);
\r
4924 // break; /* ugh! */
\r
4925 } // error check only
\r
4926 /* strcpy(Omega, StringFromCode(OldCode));
\r
4927 ConcatOneChar(Omega, StringFromCode(OldCode));
\r
4928 WriteString(Omega, output);
\r
4929 AddTableEntry(Omega); */
\r
4930 AddNewEntry(OldCode, OldCode);
\r
4931 s = WriteString(s, Code);
\r
4933 } /* end of Code *not* in Table case */
\r
4934 } /* end of *not* CLEAR case */
\r
4935 } /* end of not EOD loop */
\r
4937 /* if (bExpandColor) nlen = StripDataLen / 3;
\r
4938 else nlen = StripDataLen; */ /* ??? */
\r
4939 if (traceflag) { /* NOTE: mismatch on last strip is OK */
\r
4940 if (CurrentStrip < StripsPerImage-1) { /* 96/Nov/17 */
\r
4941 if (bExpandColor) nlen = StripDataLen / 3;
\r
4942 else nlen = StripDataLen;
\r
4943 if ((unsigned int) (s - StripData) != nlen) {
\r
4945 " Strip data mismatch %u < %u bytes (Strip %d of %ld)\n",
\r
4946 (s - StripData), nlen, CurrentStrip, StripsPerImage);
\r
4947 showline(logline, 1);
\r
4952 /* if (verboseflag) printf("EOD "); */
\r
4953 /* reset table for next one */
\r
4954 ResetStringTable(0);
\r
4958 sprintf(logline, "Now at byte %ld in file\n", ftell(input));
\r
4959 showline(logline, 0);
\r
4964 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
4966 /* Set up StripOffset & StripByteCount for strip number k */
\r
4967 /* and go to start of data for strip number k */
\r
4968 /* First one was already set up - don't disturb in case not indirect */
\r
4969 /* In practice, strips are usually contiguous, but no guarantee... */
\r
4971 long SetupStrip (FILE *input, int k) /* 96/Nov/17 */
\r
4974 StripOffset = indirectvalue(StripOffsetsType, 1,
\r
4975 StripOffsetsPtr + k * typesize[StripOffsetsType], input);
\r
4976 StripByteCount = indirectvalue(StripByteCountsType, 1,
\r
4977 StripByteCountsPtr + k * typesize[StripByteCountsType], input);
\r
4981 sprintf(logline, "Strip %d Offset %ld ByteCount %ld\n",
\r
4982 k, StripOffset, StripByteCount);
\r
4983 showline(logline, 0);
\r
4986 if (fseek (input, StripOffset, SEEK_SET))
\r
4988 showline("Error in seek to StripOffset", 1); /* ??? */
\r
4992 if (k == 0 && StripByteCount < 0)
\r
4993 StripByteCount = 0XFFFFFF; // kludge if missing 2000/Apr/13
\r
4994 return StripByteCount; /* 96/Nov/17 */
\r
4997 /* Copy a row from far space used by LZW to near space used for output */
\r
4999 void CopyRow (unsigned char *lpBuffer, unsigned char *StripData,
\r
5003 unsigned char *s=lpBuffer;
\r
5004 unsigned char *t=StripData;
\r
5005 n = (int) InRowLength; /* assuming row not longer than 32k */
\r
5006 /* if (InRowLength > BufferLength) { */ /* DEBUGGING 95/Nov/10 */
\r
5007 if (InRowLength > BufferLength+1) { /* DEBUGGING 95/Nov/10 */
\r
5008 sprintf(logline, " ERROR: InRowLength %ld > BufferLength %ld\n",
\r
5009 InRowLength, BufferLength);
\r
5010 showline(logline, 1);
\r
5012 n = (int) BufferLength; /* prevent heap corruption */
\r
5014 for (k = 0; k < n; k++) *s++ = *t++;
\r
5017 /* A whole strip is treated as one unit for LZW encoding ... */
\r
5018 /* So need to do once per strip and need memory for strip output */
\r
5020 int DecodeLZW (FILE *output, FILE *input, unsigned char *lpBuffer)
\r
5022 int k, row = 0, i, j, n, m, flag = 0;
\r
5023 /* unsigned char *StripData; */
\r
5026 nlen = (long) BufferLength * RowsPerStrip;
\r
5028 /* is this 65535U limit still valid in NT ? malloc limitation ? */
\r
5029 if (nlen > 65535U) {
\r
5030 sprintf(logline, " Cannot handle Strip Buffer of %lu bytes\n", nlen);
\r
5031 showline(logline, 1);
\r
5032 /* nlen = 30000U; */ /* TESTING HACK! */
\r
5036 StripDataLen = (unsigned int) nlen;
\r
5038 if (traceflag) { /* debugging */
\r
5039 sprintf(logline, " Allocating %u bytes for Strip Buffer\n", StripDataLen);
\r
5040 showline(logline, 0);
\r
5043 StripData = (unsigned char *) malloc(StripDataLen);
\r
5044 /* malloc((unsigned int) (InRowLength * RowsPerStrip)); */
\r
5045 /* malloc((unsigned int) (BufferLength * RowsPerStrip)); */
\r
5046 if (StripData == NULL) {
\r
5047 // showline(" ", 0);
\r
5048 showline(" Unable to allocate memory\n", 1); /* 1995/July/15 */
\r
5050 // or more serious exit(1) ???
\r
5052 InitializeStringTable();
\r
5053 /* checkheap("AFTER INITIALIZE", 0); */ /* debugging only 1995/Nov/10 */
\r
5055 for (k = 0; k < StripsPerImage; k++) {
\r
5056 CurrentStrip = k; /* global for debug output */
\r
5057 /* SetupStrip(input, k); */
\r
5058 InStripLen = SetupStrip(input, k); /* save GetNextCode 96/Nov/17 */
\r
5059 OldByte = 0; OldBitsLeft = 0;
\r
5060 ResetStringTable(1); /* redundant ? */
\r
5061 LZWdecompress(StripData, input);
\r
5063 if (row + n > ImageLength) n = (int) (ImageLength - row);
\r
5064 for (i = 0; i < n; i++) {
\r
5065 CopyRow(lpBuffer, StripData + i * InRowLength, InRowLength);
\r
5066 /* Following new 1996/Sep/9 */
\r
5067 if (Predictor == 2) { /* only applies to LZW images */
\r
5068 /* We will assume here that BitsPerSample == 8 ... */
\r
5069 /* if (SamplesPerPixel == 1) */ /* gray level */
\r
5070 if (SamplesPerPixelX == 1) { /* gray level */
\r
5071 for (j = 1; j < InRowLength; j++)
\r
5072 /* lpBuffer[j] += lpBuffer[j-1]; */
\r
5073 lpBuffer[j] = (unsigned char) (lpBuffer[j] + lpBuffer[j-1]);
\r
5075 else { /* RGB (3) or CMYK (4) */
\r
5076 /* for (j = SamplesPerPixel; j < InRowLength; j++) */
\r
5077 for (j = SamplesPerPixelX; j < InRowLength; j++)
\r
5078 /* lpBuffer[j] += lpBuffer[j-SamplesPerPixel]; */
\r
5080 /* (unsigned char) (lpBuffer[j] + lpBuffer[j-SamplesPerPixel]); */
\r
5081 (unsigned char) (lpBuffer[j] + lpBuffer[j-SamplesPerPixelX]);
\r
5084 if (ExtraSamples > 0)
\r
5085 (void) RemoveExtraSamples(lpBuffer, InRowLength); /* 99/May/10 */
\r
5086 /* if (ProcessRow (output, lpBuffer, InRowLength, BufferLength, */
\r
5087 if (ProcessRow (output, lpBuffer, InRowLengthX, BufferLength,
\r
5088 OutRowLength) != 0) break; /* break if output error */
\r
5089 /* if (bCompressColor)
\r
5090 compresscolorfar(StripData + i * BufferLength, InRowLength);
\r
5091 if (writearowfar (output, StripData + i * BufferLength,
\r
5092 OutRowLength) != 0) {
\r
5096 if (flag) break; */
\r
5100 ResetStringTable(1); /* redundant ? */
\r
5102 if (traceflag) { /* debugging */
\r
5103 sprintf(logline, " Freeing %u bytes Strip Buffer\n", StripDataLen);
\r
5104 showline(logline, 0);
\r
5108 StripData = NULL; /* debugging 95/Nov/10 */
\r
5109 if (traceflag) { /* debugging code added */ /* should work also in NT */
\r
5110 if ((m = _heapchk ()) != _HEAPOK) { /* 1995/Nov/10 */
\r
5111 sprintf(logline, " ERROR: heap corrupted (%d)\n", m);
\r
5112 /* sprintf(logline, " ERROR: __near heap corrupted (%d)\n", m); */
\r
5113 showline(logline, 1);
\r
5114 /* checkexit(9); */
\r
5115 exit(9); /* terminate with extreme prejudice */
\r
5121 /* InitializeStringTable AllocString - may need to DeAllocString eventually */
\r
5123 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
5125 /* change long => int where sensible */
\r
5127 /* complain if samplesperpixel other than one */ /* no color support */
\r
5128 /* quit early (before writing header) if 24 bit image */
\r
5130 /* implement CCIT Huffman decompression also OK */
\r
5131 /* implement LZW decompression also */ /* need Predictor also ? */
\r
5133 /* implement gray scale response curve ? */ /* although ignored by some apps */
\r
5135 /* II* or MM* followed by four byte offset to first IFD (often == 8) */
\r
5137 /* IFD: 2 byte count of fields, followed by 12 byte tag fields */
\r
5138 /* after that, four byte offset to next IFD (or zero) (or junk!) */
\r
5140 /* Field entries sorted in ascending order on tag: */
\r
5142 /* Byte 0 & 1: tag */
\r
5143 /* Byte 2 & 3: type */
\r
5144 /* Byte 4 - 7: `length' (better called `count') */
\r
5145 /* Byte 8 -11: value offset -- always even (or value itself if it fits) */
\r
5147 /* if bAllowColor is false, maybe just use green component and `image' */
\r
5149 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
\r
5151 BOOL bTIFFAllow=1;
\r
5153 /* x * (numer / denom) 1995/Oct/12 */
\r
5154 /* or use MulDiv ??? */
\r
5156 long MulRatio (long x, unsigned long numer, unsigned long denom)
\r
5159 if (denom == 0 || numer == 0) return 0;
\r
5160 if ((numer % denom) == 0) {
\r
5161 numer = numer / denom;
\r
5164 if ((denom % numer) == 0) {
\r
5165 denom = denom / numer;
\r
5168 while (denom > 65536 || numer > 65536) {
\r
5169 denom = denom >> 1;
\r
5170 numer = numer >> 1;
\r
5172 result = x / denom * numer;
\r
5176 // long MulRatio (long x, unsigned long numer, unsigned long denom) {
\r
5177 // if (denom == 0 || numer == 0) return 0;
\r
5178 // else return(MulDiv(x, numer, denom));
\r
5181 /* actually insert the TIFF figure here */
\r
5182 /* negative nifd indicates figure missing - draw box and filename only */
\r
5183 /* if dheight == 0 => calculate dheight from dwidth based on aspect ratio */
\r
5184 /* if dwidth == 0 => calculate dwidth & dheight from xres and yres */
\r
5186 /* actually insert the TIFF figure here */
\r
5187 /* negative nifd indicates figure missing - draw box and filename only */
\r
5188 /* if dheight == 0 => calculate dheight from dwidth based on aspect ratio */
\r
5190 int showtiffhere (FILE *output, char *filename, long dwidth, long dheight,
\r
5191 double xscale, double yscale, int nifd)
\r
5194 if (bTIFFAllow != 0) {
\r
5195 /* if (dheight == 0) { */ /* need aspect ratio from TIFF file */
\r
5196 if (dheight == 0 || dwidth == 0) {
\r
5198 sprintf(logline, " Prescanning %s\n", filename);
\r
5199 showline(logline, 0);
\r
5201 flag = readimagefile(output, filename, dwidth, dheight, nifd, 1);
\r
5202 /* if (flag < 0) return; */ /* was unable to find file 96/Dec/27 */
\r
5203 /* if (traceflag) printf("FLAG %d\n", flag); */
\r
5204 if (flag == 0) { /* 96/Dec/27 */
\r
5205 if (dwidth == 0 && dheight == 0) { /* fix 95/Oct/12 */
\r
5206 /* convert information in image to scaled points */
\r
5207 /* dwidth = (ImageWidth * xresden / xresnum) << 16; */
\r
5208 /* dheight = (ImageLength * yresden / yresnum) << 16; */
\r
5210 printf(" ImageWidth %ld (%lu / %lu) ImageLength %ld (%lu / %lu)\n",
\r
5211 ImageWidth, xresnum, xresden, ImageLength, yresnum, yresden); */
\r
5212 if (xresnum == 0 || yresnum == 0) { /* 96/Apr/4 */
\r
5214 " xres %lu / %lu yres %lu / %lu unit %d\n",
\r
5215 xresnum, xresden, yresnum, yresden, ResolutionUnit);
\r
5216 showline(logline, 1);
\r
5217 /* xresnum = yresnum = 72; */ /* 96/Apr/3 */
\r
5218 xresnum = yresnum = nDefaultTIFFDPI;
\r
5219 /* return; */ /* 96/Apr/4 */
\r
5222 /* dwidth = (ImageWidth << 16) / xresnum * xresden; */
\r
5223 dwidth = MulRatio(ImageWidth << 16, xresden, xresnum);
\r
5224 /* dheight = (ImageLength << 16) / yresnum * yresden; */
\r
5225 dheight = MulRatio(ImageLength << 16, yresden, yresnum);
\r
5227 printf(" dwidth %ld dheight %ld\n", dwidth, dheight); */
\r
5228 if (ResolutionUnit == 1) { /* what to do ? */
\r
5229 showline(" resolution == 1", 1);
\r
5231 else if (ResolutionUnit == 2) { /* 72.27 pt per in */
\r
5232 dwidth = dwidth / 100 * 7227;
\r
5233 dheight = dheight / 100 * 7227;
\r
5235 else if (ResolutionUnit == 3) { /* 28.45 pt per cm */
\r
5236 dwidth = dwidth / 100 * 2845;
\r
5237 dheight = dheight / 100 * 2845;
\r
5240 /* adjusted order of mul and div to avoid potential overflow 94/Dec/16 */
\r
5241 /* or use MulDiv ??? */ /* switched to MulRatio 98/Jul/9 */
\r
5242 else if (dheight == 0) {
\r
5243 if (ImageWidth != 0)
\r
5244 /* dheight = (ImageLength * dwidth) / ImageWidth; */
\r
5245 /* dheight = (dwidth / ImageWidth) * ImageLength; */
\r
5246 dheight = MulRatio(dwidth, ImageLength, ImageWidth);
\r
5248 else if (dwidth == 0) {
\r
5249 if (ImageLength != 0)
\r
5250 /* dwidth = (ImageWidth * dheight) / ImageLength; */
\r
5251 /* dwidth = (dheight / ImageLength) * ImageWidth; */
\r
5252 dwidth = MulRatio(dheight, ImageWidth, ImageLength);
\r
5254 /* added 99/July/2 */
\r
5255 if (xscale != 0.0) dwidth = (long) ((double) dwidth * xscale);
\r
5256 if (yscale != 0.0) dheight = (long) ((double) dheight * yscale);
\r
5259 sprintf(logline, " dwidth %ld dheight %ld", dwidth, dheight);
\r
5260 showline(logline, 0);
\r
5264 /* xll = mapx(dvi_h); yll = mapy(dvi_v); */
\r
5265 /* xll = dvi_h; yll = dvi_v; */
\r
5266 /* xur = mapx(dvi_h + dwidth); yur = mapy(dvi_v - dheight); */
\r
5267 /* xur = dvi_h + dwidth; yur = dvi_v - dheight; */
\r
5269 /* if (nifd >= 0) readimagefile(output, filename, dwidth, dheight, nifd, 1); */
\r
5271 flag = readimagefile(output, filename, dwidth, dheight, nifd, 0);
\r
5277 /* have the \special in line at this point - entry point from dvispeci.c */
\r
5279 /* else if (strcmp(line, "textcolor") == 0 ||
\r
5280 strcmp(line, "rulecolor") == 0 ||
\r
5281 strcmp(line, "figurecolor") == 0 ||
\r
5282 strcmp(line, "reversevideo") == 0 ||
\r
5283 strcmp(line, "button") == 0 ||
\r
5284 strcmp(line, "mark") == 0 ||
\r
5285 strcmp(line, "viewrule") == 0 ||
\r
5286 strcmp(line, "viewtext") == 0 ||
\r
5287 strcmp(line, "insertimage") == 0) { */
\r
5289 /* made common to save string space */
\r
5291 void dontunderline (void)
\r
5293 // showline(" ERROR: don't understand ", 1);
\r
5294 // showline(line, 1);
\r
5295 sprintf(logline, " ERROR: don't understand: %s", line);
\r
5296 showline(logline, 1);
\r
5299 /* name => buffer convert \ to / and change : to / and so on */
\r
5301 void platformindependent (char *buffer, char *name) { /* 96/Mar/3 */
\r
5303 strcpy(buffer, name);
\r
5304 /* avoid trouble with file names that contain spaces - truncate 'em! */
\r
5305 if ((s = strchr(buffer, ' ')) != NULL) *s = '\0';
\r
5306 /* if ((s = strchr(buffer, ':')) != NULL) { */
\r
5307 if ((s = strchr(buffer, ':')) != NULL &&
\r
5308 *(s+1) != '\\' && *(s+1) != '/') { /* 98/Jun/30 */
\r
5310 memmove(buffer+1, buffer, strlen(buffer)+1);
\r
5313 /* which is not really much use unless it is a relative file name ... */
\r
5314 /* while ((s = strchr(buffer, '\\')) != NULL) *s = '/'; */
\r
5315 s = buffer; /* now convert \ to / */
\r
5316 while ((s = strchr(s, '\\')) != NULL) *s = '/';
\r
5319 /* clean up hyper-text mark name for PostScript Distiller 95/Feb/25 */
\r
5321 /* Remove characters from name to make it valid PS name */
\r
5322 /* Valid name may not contain white space or delimiters (pgs 30, 27 PS bible) */
\r
5323 /* White space is null (0), tab (9), linefeed (10), formfeed (12), */
\r
5324 /* return (13), and space (32) */
\r
5325 /* Delimiters are () <> [] {} / % */
\r
5326 /* Note: some question about allowing \ here, since in a *string* */
\r
5327 /* backslash is used as an escape - so if name converted to string ... */
\r
5329 /* Implementation limit on name length is 127 (Appendix B.1 in PS reference) */
\r
5330 /* Implementation limit on file name length is 100 */
\r
5332 /* #define MAXPSNAME 32 */ /* old limit */
\r
5333 #define MAXPSNAME 63 /* 98/Jul/16 */
\r
5335 /* This removes punctuation also . , : ; ! ? etc NOT ANYMORE! 97/Feb/23 */
\r
5336 /* Removes white space and delimiters - limits to MAXPSNAME char */
\r
5337 /* NOTE: must use cleanupname *both* in mark: and button: */
\r
5338 /* and URL calls with named destinations 97/Feb/23 ! */
\r
5340 /* what if the string is quoted ? */ /* \b is not strictly forbidden */
\r
5342 /* what about #? not allowed in PDF name. but we want to pass it here? */
\r
5344 /* char *badcharinname=" \t\n\r\f()<>[]{}/%"; */
\r
5345 char *badcharinname=" \b\t\n\f\r()<>[]{}/%";
\r
5347 void cleanupname (char *name)
\r
5350 #ifdef DEBUGCLEANUP
\r
5353 sprintf(logline, " CLEANUPNAME: %s", name); /* debugging */
\r
5354 showline(logline, 0);
\r
5357 if (*name == '\0')
\r
5359 showline(" ERROR: empty mark or button", 1);
\r
5362 while ((s = strpbrk(s, badcharinname)) != NULL)
\r
5364 if (strlen(name) > MAXPSNAME) *(name+MAXPSNAME) = '\0'; /* 96/Aug/12 */
\r
5365 #ifdef DEBUGCLEANUP
\r
5368 sprintf(logline, " CLEANEXIT: %s", name); /* debugging */
\r
5369 showline(logline, 0);
\r
5372 if (*name == '\0') showline(" ERROR: empty mark or button", 1);
\r
5375 /* support for old textcolor / rulecolor specials */
\r
5377 int oldcolor (FILE *output, FILE *input)
\r
5381 /* old text color support */
\r
5382 if (strcmp(line, "textcolor") == 0) {
\r
5383 (void) scanspecial (input, line, MAXLINE);
\r
5385 sprintf(logline, " %s ", line);
\r
5386 showline(logline, 0);
\r
5388 if (!bKeepBlack) {
\r
5389 if (strstr(line, "revert") != NULL) {
\r
5390 textred = 0.0; textgreen = 0.0; textblue = 0.0;
\r
5391 // fputs("\nblack\n", output);
\r
5392 PSputs("\nblack\n", output);
\r
5395 else if (sscanf(line, "%lg %lg %lg",
\r
5396 &textred, &textgreen, &textblue) == 3) {
\r
5397 /* see whether floating point or not */
\r
5398 if ((s = strchr(line, '.')) == NULL || *(s+1) < '0') {
\r
5399 textred = textred / 255.0;
\r
5400 textgreen = textgreen / 255.0;
\r
5401 textblue = textblue / 255.0;
\r
5403 if (textred == 0.0 && textgreen == 0.0 && textblue == 0.0) {
\r
5404 // fputs("\nblack\n", output);
\r
5405 PSputs("\nblack\n", output);
\r
5407 } /* treat 0 0 0 same as revert ? */
\r
5409 sprintf(logline, "\n%lg %lg %lg rgb\n",
\r
5410 textred, textgreen, textblue);
\r
5411 PSputs(logline, output);
\r
5419 // fprintf(output, "\n%lg %lg %lg setrgbcolor\n",
\r
5423 /* old rule color support */
\r
5424 else if (strcmp(line, "rulecolor") == 0) {
\r
5425 (void) scanspecial (input, line, MAXLINE);
\r
5428 sprintf(logline, " %s ", line);
\r
5429 showline(logline, 0);
\r
5432 if (!bKeepBlack) {
\r
5433 if (strstr(line, "revert") != NULL) {
\r
5434 rulered = 0.0; rulegreen = 0.0; ruleblue = 0.0;
\r
5437 else if (sscanf(line, "%lg %lg %lg", &rulered, &rulegreen, &ruleblue) == 3) {
\r
5438 /* see whether floating point or not */
\r
5439 if ((s = strchr(line, '.')) == NULL || *(s+1) < '0') {
\r
5440 rulered = rulered / 255.0;
\r
5441 rulegreen = rulegreen / 255.0;
\r
5442 ruleblue = ruleblue / 255.0;
\r
5444 if (rulered == 0.0 && rulegreen == 0.0 && ruleblue == 0.0)
\r
5446 else bRuleColor = 1;
\r
5455 /* old figurecolor support */
\r
5456 else if (strcmp(line, "figurecolor") == 0) {
\r
5457 (void) scanspecial (input, line, MAXLINE);
\r
5460 sprintf(logline, " %s ", line);
\r
5461 showline(logline, 0);
\r
5464 if (!bKeepBlack) {
\r
5465 if (strstr(line, "revert") != NULL) {
\r
5466 figurered = 0.0; figuregreen = 0.0; figureblue = 0.0;
\r
5467 backred = 1.0; backgreen = 1.0; backblue = 1.0;
\r
5470 else if ((n = sscanf(line, "%lg %lg %lg %lg %lg %lg",
\r
5471 &figurered, &figuregreen, &figureblue,
\r
5472 &backred, &backgreen, &backblue)) >= 3) {
\r
5474 /* see whether floating point or not */
\r
5475 if ((s = strchr(line, '.')) == NULL || *(s+1) < '0') {
\r
5476 figurered = figurered / 255.0;
\r
5477 figuregreen = figuregreen / 255.0;
\r
5478 figureblue = figureblue / 255.0;
\r
5480 backred = backred / 255.0;
\r
5481 backgreen = backgreen / 255.0;
\r
5482 backblue = backblue / 255.0;
\r
5485 if (n < 6) { /* default background color */
\r
5486 backred = 1.0; backgreen = 1.0; backblue = 1.0;
\r
5489 if (figurered == 0.0 && figuregreen == 0.0 && figureblue == 0.0
\r
5490 && backred == 1.0 && backgreen == 1.0 && backblue == 1.0)
\r
5491 bFigureColor = 0;
\r
5492 else bFigureColor = 1;
\r
5493 } /* end of three or more numbers found case */
\r
5501 /* old reverse video support */
\r
5502 else if (strcmp(line, "reversevideo") == 0) {
\r
5503 (void) scanspecial (input, line, MAXLINE);
\r
5506 sprintf(logline, " %s ", line);
\r
5507 showline(logline, 0);
\r
5510 if (!bKeepBlack) {
\r
5511 if (strstr(line, "on") != NULL) bReverseVideo = 1;
\r
5512 else if (strstr(line, "off") != NULL) bReverseVideo = 0;
\r
5513 else if (strstr(line, "toggle") != NULL)
\r
5514 bReverseVideo = ~bReverseVideo;
\r
5515 /* ignore reversevideo for the moment ??? */
\r
5516 if (bReverseVideo) {
\r
5517 // fputs("{1 exch sub} settransfer\n", output);
\r
5518 PSputs("{1 exch sub} settransfer\n", output);
\r
5521 // fputs("{} settransfer\n", output);
\r
5522 PSputs("{} settransfer\n", output);
\r
5527 else dontunderline();
\r
5531 /* new to allow quoted file names with spaces 98/Jul/9 */
\r
5533 char *scaninsert(char *line, char *filename)
\r
5536 char *t = filename;
\r
5540 while (*s <= ' ' && *s != '\0') s++; /* step over white space */
\r
5542 if (*s == '\0') return 0;
\r
5544 if (*s == '\"') { /* is it quoted file name ? */
\r
5545 s++; /* step over initial " */
\r
5546 while (*s != '\"' && *s != '\0') *t++ = *s++;
\r
5547 if (*s != '\0') s++; /* step over final " */
\r
5549 else { /* normal file name */
\r
5550 while (*s > ' ' && *s != '\0') *t++ = *s++;
\r
5553 if (*s <= ' ' && *s != '\0') s++; /* step over white space after name */
\r
5554 /* special hack to convert ## to # */
\r
5555 if ((t = strstr(filename, "##")) != NULL) strcpy(t, t+1);
\r
5557 sprintf(logline, "line: %s filename: %s\n",
\r
5559 showline(logline, 0);
\r
5564 /* returns zero if *not* one of our DVIWindo \specials */
\r
5566 int newspecials (FILE *output, FILE *input)
\r
5569 long dheight, dwidth;
\r
5570 char filename[FILENAME_MAX];
\r
5573 char *slaunch=NULL;
\r
5574 char *sparams=NULL;
\r
5575 char *spage=NULL; /* 96/May/4 */
\r
5577 int npage=0, noffset=0; /* 96/May/4 */
\r
5579 int URLflag=0; /* 97/Jan/7 */
\r
5580 double xscale, yscale;
\r
5585 sprintf(logline, " %s:", line);
\r
5586 showline(logline, 0);
\r
5590 /* insert TIFF or BMP image */
\r
5591 if (strcmp(line, "insertimage") == 0)
\r
5593 /* (void) scanspecial (input, line, MAXLINE); */
\r
5594 (void) scanspecialraw (input, line, MAXLINE);
\r
5598 sprintf(logline, " %s ", line);
\r
5599 showline(logline, 0);
\r
5602 nifd = 1; /* n-th (sub-)image in TIFF file */
\r
5603 dwidth = dheight = 0; /* NEW - use all info from file */
\r
5604 xscale = yscale = 0.0; /* 99/July/2 */
\r
5605 /* if (sscanf(line, "%s %ld %ld %d", filename, &dwidth, &dheight, &nifd) */
\r
5606 s = scaninsert(line, filename);
\r
5607 if ((t = strstr(s, "scaled")) == NULL)
\r
5609 sscanf(s, "%ld %ld %d", &dwidth, &dheight, &nifd); /* normal */
\r
5611 else { /* new case 99/July/2 */
\r
5612 sscanf(t+7, "%lg %lg", &xscale, &yscale);
\r
5613 if (xscale > 33.33) xscale = xscale / 1000.0;
\r
5614 if (yscale > 33.33) yscale = yscale / 1000.0;
\r
5615 if (xscale != 0.0 && yscale == 0.0) yscale = xscale;
\r
5616 if (xscale == 0.0) xscale = 1.0;
\r
5617 if (yscale == 0.0) yscale = 1.0;
\r
5619 if (*filename != '\0') { /* need at least file name */
\r
5620 // clock_t sclock, eclock;
\r
5621 // sclock = clock();
\r
5623 showtiffhere(output, filename, dwidth, dheight, xscale, yscale, nifd);
\r
5624 // eclock = clock();
\r
5625 // sprintf(logline, " TIFF %lg sec\n", (double) (eclock - sclock) / CLOCKS_PER_SEC);
\r
5626 // showline(logline, 0); // debugging only
\r
5628 else dontunderline();
\r
5632 /* old textcolor, rulecolor \specials{...}s */
\r
5633 else if (strstr(line, "color") != NULL ||
\r
5634 strstr(line, "video") != NULL)
\r
5635 return oldcolor(output, input);
\r
5637 /* mark: name --- mark: "<File Open>" */ /* turn into named destination */
\r
5638 else if (strcmp(line, "mark") == 0) {
\r
5639 if (bPDFmarks == 0) {
\r
5640 flushspecial(input);
\r
5641 return 1; /* we recognize it, but ignore it */
\r
5643 /* (void) scanspecial (input, line, MAXLINE); */
\r
5644 (void) scanspecialraw (input, line, MAXLINE); /* fix 97/Nov/11 */
\r
5646 sprintf(logline, " %s ", line);
\r
5647 showline(logline, 0);
\r
5649 /* deal with <FOO BAR> style --- flush all < and > and ' ' in string */
\r
5650 if (usealtGoToR == 0)
\r
5651 cleanupname(line); /* should only contain mark name */
\r
5652 /* and nothing after the mark */
\r
5653 // putc('\n', output); /* ??? */
\r
5654 PSputc('\n', output); /* ??? */
\r
5655 if (*line < ' ') {
\r
5656 showline(" ERROR: empty destination %s ", 1);
\r
5657 showline(line, 1);
\r
5659 /* need alternate form of /Dest ? */
\r
5660 /* fprintf(stdout, "[ /Dest /%s\n", line); */
\r
5661 sprintf(logline, "[ /Dest /%s\n", line);
\r
5662 PSputs(logline, output);
\r
5663 /* need to find current position in *default* user space */
\r
5664 /* move up 20 point, ignore x component --- i.e. keep the old x (null) */
\r
5665 /* keep original zoom (null) */ /* 20 point is arbitrary */
\r
5668 " /View [ /XYZ gsave revscl currentpoint grestore 20 add exch pop null exch null]\n",
\r
5669 output); /* revscl ? */
\r
5670 // fputs("/DEST pdfmark\n", output);
\r
5671 PSputs("/DEST pdfmark\n", output);
\r
5675 /* button: <width> <height> name --- button: 1138360 433848 "<DVIfile>" */
\r
5676 /* we are ignoring for the moment file: ... and launch: ... */
\r
5677 else if (strcmp(line, "button") == 0) {
\r
5678 if (bPDFmarks == 0) {
\r
5679 flushspecial(input);
\r
5680 return 1; /* we recognize it, but ignore it */
\r
5682 /* (void) scanspecial (input, line, MAXLINE); */
\r
5683 (void) scanspecialraw (input, line, MAXLINE);
\r
5685 sprintf(logline, " %s ", line);
\r
5686 showline(logline, 0);
\r
5688 if (sscanf(line, "%ld %ld%n", &dwidth, &dheight, &n) < 2) {
\r
5689 showline(" ERROR: button ", 1); /* error output */
\r
5690 showline(line, 1);
\r
5691 flushspecial(input);
\r
5692 return 1; /* it does not have required width and height ! */
\r
5694 /* if (strstr(line, "launch:") != NULL) {
\r
5695 flushspecial(input);
\r
5698 sname = line + n; /* now after width and height */
\r
5699 while (*sname == ' ') sname++; /* step over white space */
\r
5700 /* catch case where no mark given, only file: , launch: or page: ... */
\r
5701 /* if ((strncmp(sname, "file:", 5) == 0)) sname = NULL; */
\r
5702 /* if ((strncmp(sname, "launch:", 7) == 0)) sname = NULL; */
\r
5703 /* if (strncmp(sname, "file:", 5) == 0 || */ /* avoid file://... */
\r
5704 if ((strncmp(sname, "file:", 5) == 0 && *(sname+5) != '/') ||
\r
5705 strncmp(sname, "launch:", 7) == 0 ||
\r
5706 strncmp(sname, "execute:", 8) == 0 ||
\r
5707 strncmp(sname, "page:", 5) == 0) sname = NULL;
\r
5708 /* check whether page number is given 96/May/12 */
\r
5709 if ((spage = strstr(line, "page:")) != NULL) {
\r
5712 if (sscanf(spage+5, "%d+%d", &npage, &noffset) < 2) {
\r
5713 if (sscanf(spage+5, "%d", &npage) < 1) {
\r
5714 sprintf(logline, " ERROR: %s ", spage); /* error output */
\r
5715 showline(logline, 1);
\r
5718 /* if (traceflag) printf("npage %d noffset %d spage-line %d\n",
\r
5719 npage, noffset, spage-line); */
\r
5721 /* check whether file: given */
\r
5722 /* if ((sfile = strstr(line, "file:")) != NULL) { */ /* avoid file:// */
\r
5723 if ((sfile = strstr(line, "file:")) != NULL && *(sfile+5) != '/') {
\r
5725 while (*sfile == ' ') sfile++;
\r
5726 /* if (traceflag) printf("sfile-line %d\n", sfile-line); */
\r
5727 if (sscanf(sfile, "-p=%d%n", &np, &n) == 1) { /* 98/Dec/8 */
\r
5729 /* what if npage has already been set ? */
\r
5732 while (*sfile == ' ') sfile++;
\r
5734 printf("npage %d sfile-line %d\n", npage, sfile-line); */
\r
5737 /* check whether launch: given */
\r
5738 if ((slaunch = strstr(line, "launch:")) != NULL) {
\r
5739 slaunch = slaunch+7;
\r
5740 while (*slaunch == ' ') slaunch++;
\r
5742 if (sfile != NULL) slaunch = NULL; /* can do only one ??? */
\r
5743 // putc('\n', output); /* ??? */
\r
5744 PSputc('\n', output); /* ??? */
\r
5745 // fprintf(output,
\r
5747 "[ /Rect [currentpoint 2 copy exch %ld add exch %ld sub]\n",
\r
5749 PSputs(logline, output);
\r
5750 /* Note: default is /Action /GoTo */
\r
5751 if (sname != NULL) { /* was a named destination given ? */
\r
5752 if ((s = strchr(sname, ',')) != NULL) *s = '\0';
\r
5753 /* should we make a new case for this http: action: PDF: ? */
\r
5754 /* special case `named destination' http:// ... */
\r
5755 /* This form of URL link supported under Acrobat 2.1 and later */
\r
5756 /* use http://www.adobe.com/test.pdf#name for named destination */
\r
5757 if (strncmp(sname, "http:", 5) == 0 ||
\r
5758 strncmp(sname, "ftp:", 4) == 0 ||
\r
5759 strncmp(sname, "news:", 5) == 0 ||
\r
5760 strncmp(sname, "mailto:", 7) == 0 ||
\r
5761 /* strncmp(sname, "file://localhost", 16) == 0 || */
\r
5762 /* strncmp(sname, "file:///|c/...", 16) == 0 || */
\r
5763 strncmp(sname, "file://", 7) == 0 ||
\r
5764 strncmp(sname, "gopher:", 7) == 0
\r
5765 ) { /* 1996/July/4 */
\r
5766 /* Now deal with *relative* URL given as http: pdf_from.pdf e.g. 97/May/3 */
\r
5767 /* Assumes base URL set via \special{PDF: base http://www.YandY.com}% */
\r
5768 if ((s = strchr(sname, ':')) != NULL && *(s+1) == ' ') {
\r
5770 while (*sname == ' ') sname++;
\r
5772 /* TeX changes # => ## so change back ## => # 97/Jan/8 */
\r
5773 if ((s = strstr(sname, "##")) != NULL) strcpy(s, s+1);
\r
5774 if ((s = strchr(sname, '#')) != NULL) { /* 97/Feb/23 */
\r
5775 if (usealtGoToR == 0)
\r
5776 cleanupname(s+1); /* clean up named destination */
\r
5778 sprintf(logline, " /Action << /Subtype /URI /URI (%s) >>\n",
\r
5780 PSputs(logline, output);
\r
5782 else { /* not a URL type of thing */
\r
5783 /* terminate the mark name - in case file: after - 97/Apr/23 */
\r
5784 /* but avoid truncating a destination that happens to include a : */
\r
5785 if ((s = strchr(sname, ':')) != NULL) {
\r
5786 while (s > sname && *s > ' ') s--;
\r
5787 if (s > sname) /* fix 97/Nov/11 */
\r
5788 *s = '\0'; /* terminate the mark name */
\r
5790 if (usealtGoToR == 0)
\r
5791 cleanupname(sname); /* clean up the destination */
\r
5792 if (*sname < ' ') {
\r
5793 sprintf(logline, " ERROR: empty destination %s ", sname);
\r
5794 showline(logline, 1);
\r
5796 /* fprintf(stdout, " /Dest /%s\n", sname); */
\r
5797 if (! usealtGoToR) {
\r
5798 sprintf(logline, " /Dest /%s\n", sname);
\r
5799 PSputs(logline, output);
\r
5802 } /* end of named destination given */
\r
5803 /* 97/Jan/7 Acrobat 3.0 wants page number in GoToR ? 97/Jan/7 */
\r
5804 if (sfile != NULL && spage == NULL) {
\r
5805 npage = 1; noffset = 0; /* go to page 1 as default */
\r
5806 spage = sfile; /* pretend there was a number */
\r
5808 if (spage != NULL) { /* was a page number given ? 96/May/12 */
\r
5809 if (noffset != 0) npage += noffset;
\r
5810 /* fprintf(output, " /Page %d\n", npage + nPDFoffset); */
\r
5811 sprintf(logline, " /Page %d\n", npage);
\r
5812 PSputs(logline, output);
\r
5813 // fputs(" /View [ /XYZ -4 PageHeight 4 add null]\n", output);
\r
5814 PSputs(" /View [ /XYZ -4 PageHeight 4 add null]\n", output);
\r
5816 /* case where a file or URL is specified */
\r
5817 if (sfile != NULL) {
\r
5819 /* check whether the `file' specified is a URL */
\r
5820 if (strncmp(sfile, "http:", 5) == 0 ||
\r
5821 strncmp(sfile, "ftp:", 4) == 0 ||
\r
5822 strncmp(sfile, "news:", 5) == 0 ||
\r
5823 strncmp(sfile, "mailto:", 7) == 0 ||
\r
5824 /* strncmp(sfile, "file://localhost", 16) == 0 || */
\r
5825 /* strncmp(sfile, "file:///|c/...", 16) == 0 || */
\r
5826 strncmp(sfile, "file://", 7) == 0 ||
\r
5827 strncmp(sfile, "gopher:", 7) == 0
\r
5828 ) URLflag=1; /* treat URL style things different 97/Jan/7 */
\r
5829 if (usealtGoToR == 0) { /* for now */
\r
5830 // fputs(" /Action /GoToR\n", output);
\r
5831 PSputs(" /Action /GoToR\n", output);
\r
5832 if ((s = strchr(sfile, ',')) != NULL) *s = '\0'; /* 96/May/4 */
\r
5833 if (URLflag == 0) { /* don't mess with extension if URL ? */
\r
5834 /* remove extension if any (typically .dvi) use .pdf instead */
\r
5835 /* be careful about ../foo if there is no extension 97/Jan/7 */
\r
5836 if ((s = strrchr(sfile, '.')) != NULL &&
\r
5837 ((t = strrchr(sfile, '/')) == NULL || s > t) &&
\r
5838 ((t = strrchr(sfile, '\\')) == NULL || s > t))
\r
5840 strcat(sfile, ".pdf"); /* default extension in PS output */
\r
5841 } /* end of if URLflag == 0 */
\r
5842 /* massage into Acrobat `platform independent' format */
\r
5843 platformindependent (filename, sfile); /* reuse filename */
\r
5844 sprintf(logline, " /File (%s)\n", filename);
\r
5845 PSputs(logline, output);
\r
5846 // fprintf(output, " /DosFile (%s)\n", sfile);
\r
5847 sprintf(logline, " /DOSFile (%s)\n", sfile); /* 98/Jun/20 */
\r
5848 PSputs(logline, output);
\r
5850 else { /* use alternative format */
\r
5851 sprintf(logline, " /Action << /S /GoToR /D (%s) /F (%s) >>/n",
\r
5852 sname, sfile); /* ??? 98/Jun/30 */
\r
5853 PSputs(logline, output);
\r
5856 if (slaunch != NULL) {
\r
5857 if ((s = strchr(slaunch, ',')) != NULL) *s = '\0';
\r
5858 // fputs(" /Action /Launch\n", output);
\r
5859 PSputs(" /Action /Launch\n", output);
\r
5860 /* massage into Acrobat `platform independent' format */
\r
5861 platformindependent (filename, slaunch);
\r
5862 /* do special things for Windows call ... */
\r
5863 sprintf(logline, " /File (%s)\n", filename);
\r
5864 PSputs(logline, output);
\r
5865 if ((s = strchr(slaunch, ' ')) != NULL) {
\r
5869 /* Acrobat Reader uses Windows ShellExecute(...) */
\r
5870 sprintf(logline, " /WinFile (%s)\n", slaunch);
\r
5871 PSputs(logline, output);
\r
5872 if (sparams != NULL) {
\r
5873 sprintf(logline, " /Params (%s)\n", sparams);
\r
5874 PSputs(logline, output);
\r
5876 /* optional key /Dir (current directory) */
\r
5877 /* optional key /Op (open or print) */
\r
5880 /* Default border is [0 0 1] - we want it to be invisible instead */
\r
5881 // fputs(" /Border [ 0 0 0]\n", output);
\r
5882 PSputs(" /Border [ 0 0 0]\n", output);
\r
5883 // fputs(" /Subtype /Link\n", output);
\r
5884 PSputs(" /Subtype /Link\n", output);
\r
5885 // fputs("/ANN pdfmark\n", output);
\r
5886 PSputs("/ANN pdfmark\n", output);
\r
5889 else if (strcmp(line, "viewrule") == 0 || /* 95/Mar/27 */
\r
5890 strcmp(line, "viewtext") == 0) { /* 95/Mar/27 */
\r
5891 flushspecial(input);
\r
5892 return 1; /* we recognize it, but ignore it */
\r
5895 else if (traceflag) showline(line, 1);
\r
5897 return 0; /* not a DVIWindo special */
\r
5902 /* proper support for figurecolor \special / bilevel images 1994/March/14 */
\r
5904 /* \special{tiff:/mount/mktpub_d1/users/temp_jobs/59625100nl/procroms.tif
\r
5905 lib=control.glb xmag=1 ymag=1 hleft vhigh bclip=0.000000 lclip=0.000000
\r
5906 rclip=0.000000 tclip=0.000000 nostrip */
\r
5907 /* New stuff for HPTAG */ /* 95/Oct/12 */
\r
5909 int dohptag (FILE *output, FILE *input)
\r
5911 /* double bclip=0, lclip=0, rclip=0, tclip=0; */
\r
5912 /* int hleft=1, hright=0, vhigh=1, vlow=0; */
\r
5913 /* double xmag=1, ymag=1; */
\r
5914 /* int nostrip=1; */
\r
5916 char filename[FILENAME_MAX];
\r
5918 (void) scanspecial (input, line, MAXLINE);
\r
5919 if ((s = strchr(line, ' ')) != NULL) *s = '\0';
\r
5920 if ((t = strrchr(line, '/')) != NULL) strcpy(filename, t+1);
\r
5921 else if (strlen(line) < sizeof(filename)) strcpy(filename, line);
\r
5922 else return 0; /* failure */
\r
5923 /* now analyze the rest of the line starting at s+1 */
\r
5924 /* showtiffhere(output, filename, dwidth, dheight, 0, 0, nifd); */
\r
5927 showtiffhere(output, filename, 0, 0, 0, 0, 1);
\r
5928 return 1; /* success */
\r
5931 /* for setting hyper-text buttons we want the *real* underlying PS */
\r
5932 /* (not what we would have seen had mag = 1000 */
\r
5933 /* hence use revscl, *not* revsclx */
\r
5935 /* #pragma optimize ("lge", on) */
\r
5937 /* END OF EXPERIMENT */
\r
5939 /* int WINAPI MulDiv(int nNumber, int nNumerator, int nDenominator); */
\r