1 //========================================================================
5 // Copyright 1996 Derek B. Noonburg
7 //========================================================================
20 //------------------------------------------------------------------------
31 strWeird // internal-use stream types
34 //------------------------------------------------------------------------
35 // Stream (base class)
36 //------------------------------------------------------------------------
47 // Reference counting.
48 int incRef() { return ++ref; }
49 int decRef() { return --ref; }
51 // Get kind of stream.
52 virtual StreamKind getKind() = 0;
54 // Reset stream to beginning.
55 virtual void reset() = 0;
57 // Get next char from stream.
58 virtual int getChar() = 0;
60 // Peek at next char in stream.
61 virtual int lookChar() = 0;
63 // Get next char from stream without using the predictor.
64 // This is only used by StreamPredictor.
65 virtual int getRawChar();
67 // Get next line from stream.
68 virtual char *getLine(char *buf, int size);
70 // Get current position in file.
71 virtual int getPos() = 0;
73 // Go to a position in the stream.
74 virtual void setPos(int pos1);
76 // Get PostScript command for the filter(s).
77 virtual GString *getPSFilter(char *indent);
79 // Does this stream type potentially contain non-printable chars?
80 virtual GBool isBinary(GBool last = gTrue) = 0;
82 // Get the base FileStream or SubStream of this stream.
83 virtual Stream *getBaseStream() = 0;
85 // Get a substream of this stream.
86 virtual Stream *subStream(int start1, int length1, Object *dict1) = 0;
88 // Get start offset of a stream's data.
89 virtual int getStart() = 0;
91 // Whether we failed to load ?
92 virtual GBool isOk() = 0;
94 // Get the dictionary associated with this stream.
95 virtual Dict *getDict() = 0;
97 // Is this an encoding filter?
98 virtual GBool isEncoder() { return gFalse; }
100 // Add filters to this stream according to the parameters in <dict>.
101 // Returns the new stream.
102 Stream *addFilters(Object *dict);
106 Stream *makeFilter(char *name, Stream *str, Object *params);
108 int ref; // reference count
111 //------------------------------------------------------------------------
113 //------------------------------------------------------------------------
118 // Create an image stream object for an image with the specified
119 // parameters. Note that these are the actual image parameters,
120 // which may be different from the predictor parameters.
121 ImageStream(Stream *str, int width, int nComps, int nBits);
128 // Gets the next pixel from the stream. <pix> should be able to hold
129 // at least nComps elements. Returns false at end of file.
130 GBool getPixel(Guchar *pix);
132 // Skip an entire line from the image.
137 Stream *str; // base stream
138 int width; // pixels per line
139 int nComps; // components per pixel
140 int nBits; // bits per component
141 int nVals; // components per line
142 Guchar *imgLine; // line buffer
143 int imgIdx; // current index in imgLine
146 //------------------------------------------------------------------------
148 //------------------------------------------------------------------------
150 class StreamPredictor {
153 // Create a predictor object. Note that the parameters are for the
154 // predictor, and may not match the actual image parameters.
155 StreamPredictor(Stream *str, int predictor,
156 int width, int nComps, int nBits);
167 Stream *str; // base stream
168 int predictor; // predictor
169 int width; // pixels per line
170 int nComps; // components per pixel
171 int nBits; // bits per component
172 int nVals; // components per line
173 int pixBytes; // bytes per pixel
174 int rowBytes; // bytes per line
175 Guchar *predLine; // line buffer
176 int predIdx; // current index in predLine
179 //------------------------------------------------------------------------
181 //------------------------------------------------------------------------
183 // Portable pdf open helper function.
184 extern FILE *fileOpen (GString *fileName1);
186 class FileStream: public Stream {
190 FileStream(FILE *f1);
191 virtual ~FileStream();
192 virtual StreamKind getKind() { return strFile; }
193 virtual void reset();
194 virtual int getChar()
195 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
196 virtual int lookChar()
197 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
198 virtual int getPos() { return bufPos + (bufPtr - buf); }
199 virtual void setPos(int pos1);
200 virtual GBool isBinary(GBool last = gTrue) { return last; }
201 virtual Stream *getBaseStream() { return this; }
202 virtual Stream *subStream (int start1, int length1, Object *dict1);
203 virtual int getStart() { return start; }
204 virtual GBool isOk() { return f != NULL; }
205 virtual Dict *getDict() { return dict.getDict(); }
223 //------------------------------------------------------------------------
225 //------------------------------------------------------------------------
227 class SubStream: public Stream {
230 SubStream(Stream *str1, Object *dict1);
231 virtual ~SubStream();
232 virtual StreamKind getKind() { return str->getKind(); }
233 virtual void reset() {}
234 virtual int getChar() { return str->getChar(); }
235 virtual int lookChar() { return str->lookChar(); }
236 virtual int getPos() { return str->getPos(); }
237 virtual GBool isBinary(GBool last = gTrue) { return last; }
238 virtual Stream *getBaseStream() { return this; }
239 virtual Stream *subStream (int start1, int length1, Object *dict1)
240 { return str->subStream (start1, length1, dict1); }
241 virtual int getStart() { return str->getStart(); }
242 virtual GBool isOk() { return str->isOk(); }
243 virtual Dict *getDict() { return dict.getDict(); }
251 //------------------------------------------------------------------------
253 //------------------------------------------------------------------------
255 class ASCIIHexStream: public Stream {
258 ASCIIHexStream(Stream *str1);
259 virtual ~ASCIIHexStream();
260 virtual StreamKind getKind() { return strASCIIHex; }
261 virtual void reset();
262 virtual int getChar()
263 { int c = lookChar(); buf = EOF; return c; }
264 virtual int lookChar();
265 virtual int getPos() { return str->getPos(); }
266 virtual GString *getPSFilter(char *indent);
267 virtual GBool isBinary(GBool last = gTrue);
268 virtual Stream *getBaseStream() { return str->getBaseStream(); }
269 virtual Stream *subStream (int start1, int length1, Object *dict1)
270 { return str->subStream (start1, length1, dict1); }
271 virtual int getStart() { return str->getStart(); }
272 virtual GBool isOk() { return str->isOk(); }
273 virtual Dict *getDict() { return str->getDict(); }
282 //------------------------------------------------------------------------
284 //------------------------------------------------------------------------
286 class ASCII85Stream: public Stream {
289 ASCII85Stream(Stream *str1);
290 virtual ~ASCII85Stream();
291 virtual StreamKind getKind() { return strASCII85; }
292 virtual void reset();
293 virtual int getChar()
294 { int ch = lookChar(); ++index; return ch; }
295 virtual int lookChar();
296 virtual int getPos() { return str->getPos(); }
297 virtual GString *getPSFilter(char *indent);
298 virtual GBool isBinary(GBool last = gTrue);
299 virtual Stream *getBaseStream() { return str->getBaseStream(); }
300 virtual Stream *subStream (int start1, int length1, Object *dict1)
301 { return str->subStream (start1, length1, dict1); }
302 virtual int getStart() { return str->getStart(); }
303 virtual GBool isOk() { return str->isOk(); }
304 virtual Dict *getDict() { return str->getDict(); }
315 //------------------------------------------------------------------------
317 //------------------------------------------------------------------------
319 class LZWStream: public Stream {
322 LZWStream(Stream *str1, int predictor1, int columns1, int colors1,
323 int bits1, int early1);
324 virtual ~LZWStream();
325 virtual StreamKind getKind() { return strLZW; }
326 virtual void reset();
327 virtual int getChar();
328 virtual int lookChar();
329 virtual int getRawChar();
330 virtual int getPos() { return str->getPos(); }
331 virtual GString *getPSFilter(char *indent);
332 virtual GBool isBinary(GBool last = gTrue);
333 virtual Stream *getBaseStream() { return str->getBaseStream(); }
334 virtual Stream *subStream (int start1, int length1, Object *dict1)
335 { return str->subStream (start1, length1, dict1); }
336 virtual int getStart() { return str->getStart(); }
337 virtual GBool isOk() { return str->isOk(); }
338 virtual Dict *getDict() { return str->getDict(); }
342 Stream *str; // stream
343 StreamPredictor *pred; // predictor
344 int early; // early parameter
345 char zCmd[256]; // uncompress command
346 FILE *zPipe; // uncompress pipe
347 char *zName; // .Z file name (in zCmd)
348 int inputBuf; // input buffer
349 int inputBits; // number of bits in input buffer
350 int inCodeBits; // size of input code
351 char buf[256]; // buffer
352 char *bufPtr; // next char to read
353 char *bufEnd; // end of buffer
355 void dumpFile(FILE *f);
360 //------------------------------------------------------------------------
362 //------------------------------------------------------------------------
364 class RunLengthStream: public Stream {
367 RunLengthStream(Stream *str1);
368 virtual ~RunLengthStream();
369 virtual StreamKind getKind() { return strRunLength; }
370 virtual void reset();
371 virtual int getChar()
372 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
373 virtual int lookChar()
374 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
375 virtual int getPos() { return str->getPos(); }
376 virtual GString *getPSFilter(char *indent);
377 virtual GBool isBinary(GBool last = gTrue);
378 virtual Stream *getBaseStream() { return str->getBaseStream(); }
379 virtual Stream *subStream (int start1, int length1, Object *dict1)
380 { return str->subStream (start1, length1, dict1); }
381 virtual int getStart() { return str->getStart(); }
382 virtual GBool isOk() { return str->isOk(); }
383 virtual Dict *getDict() { return str->getDict(); }
388 char buf[128]; // buffer
389 char *bufPtr; // next char to read
390 char *bufEnd; // end of buffer
396 //------------------------------------------------------------------------
398 //------------------------------------------------------------------------
400 struct CCITTCodeTable;
402 class CCITTFaxStream: public Stream {
405 CCITTFaxStream(Stream *str, int encoding, GBool endOfLine,
406 GBool byteAlign, int columns, int rows,
407 GBool endOfBlock, GBool black);
408 virtual ~CCITTFaxStream();
409 virtual StreamKind getKind() { return strCCITTFax; }
410 virtual void reset();
411 virtual int getChar()
412 { int c = lookChar(); buf = EOF; return c; }
413 virtual int lookChar();
414 virtual int getPos() { return str->getPos(); }
415 virtual GString *getPSFilter(char *indent);
416 virtual GBool isBinary(GBool last = gTrue);
417 virtual Stream *getBaseStream() { return str->getBaseStream(); }
418 virtual Stream *subStream (int start1, int length1, Object *dict1)
419 { return str->subStream (start1, length1, dict1); }
420 virtual int getStart() { return str->getStart(); }
421 virtual GBool isOk() { return str->isOk(); }
422 virtual Dict *getDict() { return str->getDict(); }
426 Stream *str; // stream
427 int encoding; // 'K' parameter
428 GBool endOfLine; // 'EndOfLine' parameter
429 GBool byteAlign; // 'EncodedByteAlign' parameter
430 int columns; // 'Columns' parameter
431 int rows; // 'Rows' parameter
432 GBool endOfBlock; // 'EndOfBlock' parameter
433 GBool black; // 'BlackIs1' parameter
434 GBool eof; // true if at eof
435 GBool nextLine2D; // true if next line uses 2D encoding
436 int row; // current row
437 int inputBuf; // input buffer
438 int inputBits; // number of bits in input buffer
439 short *refLine; // reference line changing elements
440 int b1; // index into refLine
441 short *codingLine; // coding line changing elements
442 int a0; // index into codingLine
443 int outputBits; // remaining ouput bits
444 int buf; // character buffer
446 short getTwoDimCode();
447 short getWhiteCode();
448 short getBlackCode();
449 short lookBits(int n);
450 void eatBits(int n) { inputBits -= n; }
453 //------------------------------------------------------------------------
455 //------------------------------------------------------------------------
457 // DCT component info
459 int id; // component ID
460 GBool inScan; // is this component in the current scan?
461 int hSample, vSample; // horiz/vert sampling resolutions
462 int quantTable; // quantization table number
463 int dcHuffTable, acHuffTable; // Huffman table numbers
464 int prevDC; // DC coefficient accumulator
467 // DCT Huffman decoding table
468 struct DCTHuffTable {
469 Guchar firstSym[17]; // first symbol for this bit length
470 Gushort firstCode[17]; // first code for this bit length
471 Gushort numCodes[17]; // number of codes of this bit length
472 Guchar sym[256]; // symbols
475 class DCTStream: public Stream {
478 DCTStream(Stream *str1);
479 virtual ~DCTStream();
480 virtual StreamKind getKind() { return strDCT; }
481 virtual void reset();
482 virtual int getChar();
483 virtual int lookChar();
484 virtual int getPos() { return str->getPos(); }
485 virtual GString *getPSFilter(char *indent);
486 virtual GBool isBinary(GBool last = gTrue);
487 virtual Stream *getBaseStream() { return str->getBaseStream(); }
488 virtual Stream *subStream (int start1, int length1, Object *dict1)
489 { return str->subStream (start1, length1, dict1); }
490 virtual int getStart() { return str->getStart(); }
491 virtual GBool isOk() { return str->isOk(); }
492 virtual Dict *getDict() { return str->getDict(); }
493 Stream *getRawStream() { return str; }
497 Stream *str; // stream
498 int width, height; // image size
499 int mcuWidth, mcuHeight; // size of min coding unit, in data units
500 DCTCompInfo compInfo[4]; // info for each component
501 int numComps; // number of components in image
502 int colorXform; // need YCbCr-to-RGB transform?
503 GBool gotAdobeMarker; // set if APP14 Adobe marker was present
504 int restartInterval; // restart interval, in MCUs
505 Guchar quantTables[4][64]; // quantization tables
506 int numQuantTables; // number of quantization tables
507 DCTHuffTable dcHuffTables[4]; // DC Huffman tables
508 DCTHuffTable acHuffTables[4]; // AC Huffman tables
509 int numDCHuffTables; // number of DC Huffman tables
510 int numACHuffTables; // number of AC Huffman tables
511 Guchar *rowBuf[4][32]; // buffer for one MCU
512 int comp, x, y, dy; // current position within image/MCU
513 int restartCtr; // MCUs left until restart
514 int restartMarker; // next restart marker
515 int inputBuf; // input buffer for variable length codes
516 int inputBits; // number of valid bits in input buffer
520 GBool readDataUnit(DCTHuffTable *dcHuffTable, DCTHuffTable *acHuffTable,
521 Guchar quantTable[64], int *prevDC, Guchar data[64]);
522 int readHuffSym(DCTHuffTable *table);
523 int readAmp(int size);
526 GBool readFrameInfo();
527 GBool readScanInfo();
528 GBool readQuantTables();
529 GBool readHuffmanTables();
530 GBool readRestartInterval();
531 GBool readAdobeMarker();
537 //------------------------------------------------------------------------
539 //------------------------------------------------------------------------
541 #define flateWindow 32768 // buffer size
542 #define flateMask (flateWindow-1)
543 #define flateMaxHuffman 15 // max Huffman code length
544 #define flateMaxCodeLenCodes 19 // max # code length codes
545 #define flateMaxLitCodes 288 // max # literal codes
546 #define flateMaxDistCodes 30 // max # distance codes
548 // Huffman code table entry
550 int len; // code length in bits
551 int code; // code word
552 int val; // value represented by this code
555 // Huffman code table
556 struct FlateHuffmanTab {
557 int start[flateMaxHuffman+2]; // indexes of first code of each length
558 FlateCode *codes; // codes, sorted by length and code word
561 // Decoding info for length and distance code words
563 int bits; // # extra bits
564 int first; // first length/distance
567 class FlateStream: public Stream {
570 FlateStream(Stream *str1, int predictor1, int columns1,
571 int colors1, int bits1);
572 virtual ~FlateStream();
573 virtual StreamKind getKind() { return strFlate; }
574 virtual void reset();
575 virtual int getChar();
576 virtual int lookChar();
577 virtual int getRawChar();
578 virtual int getPos() { return str->getPos(); }
579 virtual GString *getPSFilter(char *indent);
580 virtual GBool isBinary(GBool last = gTrue);
581 virtual Stream *getBaseStream() { return str->getBaseStream(); }
582 virtual Stream *subStream (int start1, int length1, Object *dict1)
583 { return str->subStream (start1, length1, dict1); }
584 virtual int getStart() { return str->getStart(); }
585 virtual GBool isOk() { return str->isOk(); }
586 virtual Dict *getDict() { return str->getDict(); }
590 Stream *str; // stream
591 StreamPredictor *pred; // predictor
592 Guchar buf[flateWindow]; // output data buffer
593 int index; // current index into output buffer
594 int remain; // number valid bytes in output buffer
595 int codeBuf; // input buffer
596 int codeSize; // number of bits in input buffer
597 FlateCode // literal and distance codes
598 allCodes[flateMaxLitCodes + flateMaxDistCodes];
599 FlateHuffmanTab litCodeTab; // literal code table
600 FlateHuffmanTab distCodeTab; // distance code table
601 GBool compressedBlock; // set if reading a compressed block
602 int blockLen; // remaining length of uncompressed block
603 GBool endOfBlock; // set when end of block is reached
604 GBool eof; // set when end of stream is reached
606 static int // code length code reordering
607 codeLenCodeMap[flateMaxCodeLenCodes];
608 static FlateDecode // length decoding info
609 lengthDecode[flateMaxLitCodes-257];
610 static FlateDecode // distance decoding info
611 distDecode[flateMaxDistCodes];
615 void loadFixedCodes();
616 GBool readDynamicCodes();
617 void compHuffmanCodes(FlateHuffmanTab *tab, int n);
618 int getHuffmanCodeWord(FlateHuffmanTab *tab);
619 int getCodeWord(int bits);
622 //------------------------------------------------------------------------
624 //------------------------------------------------------------------------
626 class EOFStream: public Stream {
629 EOFStream(Stream *str1);
630 virtual ~EOFStream();
631 virtual StreamKind getKind() { return strWeird; }
632 virtual void reset() {}
633 virtual int getChar() { return EOF; }
634 virtual int lookChar() { return EOF; }
635 virtual int getPos() { return str->getPos(); }
636 virtual GString *getPSFilter(char *indent) { return NULL; }
637 virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
638 virtual Stream *getBaseStream() { return str->getBaseStream(); }
639 virtual Stream *subStream (int start1, int length1, Object *dict1)
640 { return str->subStream (start1, length1, dict1); }
641 virtual int getStart() { return str->getStart(); }
642 virtual GBool isOk() { return str->isOk(); }
643 virtual Dict *getDict() { return str->getDict(); }
650 //------------------------------------------------------------------------
651 // FixedLengthEncoder
652 //------------------------------------------------------------------------
654 class FixedLengthEncoder: public Stream {
657 FixedLengthEncoder(Stream *str1, int length1);
658 ~FixedLengthEncoder();
659 virtual StreamKind getKind() { return strWeird; }
660 virtual void reset();
661 virtual int getChar();
662 virtual int lookChar();
663 virtual int getPos() { return str->getPos(); }
664 virtual GString *getPSFilter(char *indent) { return NULL; }
665 virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
666 virtual Stream *getBaseStream() { return str->getBaseStream(); }
667 virtual Stream *subStream (int start1, int length1, Object *dict1)
668 { return str->subStream (start1, length1, dict1); }
669 virtual int getStart() { return str->getStart(); }
670 virtual GBool isOk() { return str->isOk(); }
671 virtual Dict *getDict() { return str->getDict(); }
672 virtual GBool isEncoder() { return gTrue; }
681 //------------------------------------------------------------------------
683 //------------------------------------------------------------------------
685 class ASCII85Encoder: public Stream {
688 ASCII85Encoder(Stream *str1);
689 virtual ~ASCII85Encoder();
690 virtual StreamKind getKind() { return strWeird; }
691 virtual void reset();
692 virtual int getChar()
693 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
694 virtual int lookChar()
695 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
696 virtual int getPos() { return str->getPos(); }
697 virtual GString *getPSFilter(char *indent) { return NULL; }
698 virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
699 virtual Stream *getBaseStream() { return str->getBaseStream(); }
700 virtual Stream *subStream (int start1, int length1, Object *dict1)
701 { return str->subStream (start1, length1, dict1); }
702 virtual int getStart() { return str->getStart(); }
703 virtual GBool isOk() { return str->isOk(); }
704 virtual Dict *getDict() { return str->getDict(); }
705 virtual GBool isEncoder() { return gTrue; }
719 //------------------------------------------------------------------------
721 //------------------------------------------------------------------------
723 class RunLengthEncoder: public Stream {
726 RunLengthEncoder(Stream *str1);
727 virtual ~RunLengthEncoder();
728 virtual StreamKind getKind() { return strWeird; }
729 virtual void reset();
730 virtual int getChar()
731 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
732 virtual int lookChar()
733 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
734 virtual int getPos() { return str->getPos(); }
735 virtual GString *getPSFilter(char *indent) { return NULL; }
736 virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
737 virtual Stream *getBaseStream() { return str->getBaseStream(); }
738 virtual Stream *subStream (int start1, int length1, Object *dict1)
739 { return str->subStream (start1, length1, dict1); }
740 virtual int getStart() { return str->getStart(); }
741 virtual GBool isOk() { return str->isOk(); }
742 virtual Dict *getDict() { return str->getDict(); }
743 virtual GBool isEncoder() { return gTrue; }