1 //========================================================================
5 // Copyright 1996-2002 Glyph & Cog, LLC
7 //========================================================================
14 #ifdef USE_GCC_PRAGMAS
27 //------------------------------------------------------------------------
39 strWeird // internal-use stream types
42 //------------------------------------------------------------------------
43 // Stream (base class)
44 //------------------------------------------------------------------------
55 // Reference counting.
56 int incRef() { return ++ref; }
57 int decRef() { return --ref; }
59 // Get kind of stream.
60 virtual StreamKind getKind() = 0;
62 // Reset stream to beginning.
63 virtual void reset() = 0;
65 // Close down the stream.
68 // Get next char from stream.
69 virtual int getChar() = 0;
71 // Peek at next char in stream.
72 virtual int lookChar() = 0;
74 // Get next char from stream without using the predictor.
75 // This is only used by StreamPredictor.
76 virtual int getRawChar();
78 // Get next line from stream.
79 virtual char *getLine(char *buf, int size);
81 // Get current position in file.
82 virtual int getPos() = 0;
84 // Go to a position in the stream. If <dir> is negative, the
85 // position is from the end of the file; otherwise the position is
86 // from the start of the file.
87 virtual void setPos(Guint pos, int dir = 0) = 0;
89 // Get PostScript command for the filter(s).
90 virtual GString *getPSFilter(char *indent);
92 // Does this stream type potentially contain non-printable chars?
93 virtual GBool isBinary(GBool last = gTrue) = 0;
95 // Get the BaseStream or EmbedStream of this stream.
96 virtual BaseStream *getBaseStream() = 0;
98 // Get the dictionary associated with this stream.
99 virtual Dict *getDict() = 0;
101 // Is this an encoding filter?
102 virtual GBool isEncoder() { return gFalse; }
104 // Add filters to this stream according to the parameters in <dict>.
105 // Returns the new stream.
106 Stream *addFilters(Object *dict);
110 Stream *makeFilter(char *name, Stream *str, Object *params);
112 int ref; // reference count
115 //------------------------------------------------------------------------
118 // This is the base class for all streams that read directly from a file.
119 //------------------------------------------------------------------------
121 class BaseStream: public Stream {
124 BaseStream(Object *dictA);
125 virtual ~BaseStream();
126 virtual Stream *makeSubStream(Guint start, GBool limited,
127 Guint length, Object *dict) = 0;
128 virtual void setPos(Guint pos, int dir = 0) = 0;
129 virtual BaseStream *getBaseStream() { return this; }
130 virtual Dict *getDict() { return dict.getDict(); }
132 // Get/set position of first byte of stream within the file.
133 virtual Guint getStart() = 0;
134 virtual void moveStart(int delta) = 0;
136 #ifndef NO_DECRYPTION
137 // Set decryption for this stream.
138 virtual void doDecryption(Guchar *fileKey, int keyLength,
139 int objNum, int objGen);
142 #ifndef NO_DECRYPTION
153 //------------------------------------------------------------------------
156 // This is the base class for all streams that filter another stream.
157 //------------------------------------------------------------------------
159 class FilterStream: public Stream {
162 FilterStream(Stream *strA);
163 virtual ~FilterStream();
164 virtual void close();
165 virtual int getPos() { return str->getPos(); }
166 virtual void setPos(Guint pos, int dir = 0);
167 virtual BaseStream *getBaseStream() { return str->getBaseStream(); }
168 virtual Dict *getDict() { return str->getDict(); }
175 //------------------------------------------------------------------------
177 //------------------------------------------------------------------------
182 // Create an image stream object for an image with the specified
183 // parameters. Note that these are the actual image parameters,
184 // which may be different from the predictor parameters.
185 ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA);
192 // Gets the next pixel from the stream. <pix> should be able to hold
193 // at least nComps elements. Returns false at end of file.
194 GBool getPixel(Guchar *pix);
196 // Returns a pointer to the next line of pixels. Returns NULL at
200 // Skip an entire line from the image.
205 Stream *str; // base stream
206 int width; // pixels per line
207 int nComps; // components per pixel
208 int nBits; // bits per component
209 int nVals; // components per line
210 Guchar *imgLine; // line buffer
211 int imgIdx; // current index in imgLine
214 //------------------------------------------------------------------------
216 //------------------------------------------------------------------------
218 class StreamPredictor {
221 // Create a predictor object. Note that the parameters are for the
222 // predictor, and may not match the actual image parameters.
223 StreamPredictor(Stream *strA, int predictorA,
224 int widthA, int nCompsA, int nBitsA);
235 Stream *str; // base stream
236 int predictor; // predictor
237 int width; // pixels per line
238 int nComps; // components per pixel
239 int nBits; // bits per component
240 int nVals; // components per line
241 int pixBytes; // bytes per pixel
242 int rowBytes; // bytes per line
243 Guchar *predLine; // line buffer
244 int predIdx; // current index in predLine
247 //------------------------------------------------------------------------
249 //------------------------------------------------------------------------
251 #define fileStreamBufSize 256
253 class FileStream: public BaseStream {
256 FileStream(FILE *fA, Guint startA, GBool limitedA,
257 Guint lengthA, Object *dictA);
258 virtual ~FileStream();
259 virtual Stream *makeSubStream(Guint startA, GBool limitedA,
260 Guint lengthA, Object *dictA);
261 virtual StreamKind getKind() { return strFile; }
262 virtual void reset();
263 virtual void close();
264 virtual int getChar()
265 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
266 virtual int lookChar()
267 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
268 virtual int getPos() { return bufPos + (bufPtr - buf); }
269 virtual void setPos(Guint pos, int dir = 0);
270 virtual GBool isBinary(GBool last = gTrue) { return last; }
271 virtual Guint getStart() { return start; }
272 virtual void moveStart(int delta);
282 char buf[fileStreamBufSize];
290 //------------------------------------------------------------------------
292 //------------------------------------------------------------------------
294 class MemStream: public BaseStream {
297 MemStream(char *bufA, Guint lengthA, Object *dictA);
298 virtual ~MemStream();
299 virtual Stream *makeSubStream(Guint start, GBool limited,
300 Guint lengthA, Object *dictA);
301 virtual StreamKind getKind() { return strWeird; }
302 virtual void reset();
303 virtual void close();
304 virtual int getChar()
305 { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; }
306 virtual int lookChar()
307 { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; }
308 virtual int getPos() { return bufPtr - buf; }
309 virtual void setPos(Guint pos, int dir = 0);
310 virtual GBool isBinary(GBool last = gTrue) { return last; }
311 virtual Guint getStart() { return 0; }
312 virtual void moveStart(int delta);
313 #ifndef NO_DECRYPTION
314 virtual void doDecryption(Guchar *fileKey, int keyLength,
315 int objNum, int objGen);
327 //------------------------------------------------------------------------
330 // This is a special stream type used for embedded streams (inline
331 // images). It reads directly from the base stream -- after the
332 // EmbedStream is deleted, reads from the base stream will proceed where
333 // the BaseStream left off. Note that this is very different behavior
334 // that creating a new FileStream (using makeSubStream).
335 //------------------------------------------------------------------------
337 class EmbedStream: public BaseStream {
340 EmbedStream(Stream *strA, Object *dictA);
341 virtual ~EmbedStream();
342 virtual Stream *makeSubStream(Guint start, GBool limited,
343 Guint length, Object *dictA);
344 virtual StreamKind getKind() { return str->getKind(); }
345 virtual void reset() {}
346 virtual int getChar() { return str->getChar(); }
347 virtual int lookChar() { return str->lookChar(); }
348 virtual int getPos() { return str->getPos(); }
349 virtual void setPos(Guint pos, int dir = 0);
350 virtual GBool isBinary(GBool last = gTrue) { return last; }
351 virtual Guint getStart();
352 virtual void moveStart(int delta);
359 //------------------------------------------------------------------------
361 //------------------------------------------------------------------------
363 class ASCIIHexStream: public FilterStream {
366 ASCIIHexStream(Stream *strA);
367 virtual ~ASCIIHexStream();
368 virtual StreamKind getKind() { return strASCIIHex; }
369 virtual void reset();
370 virtual int getChar()
371 { int c = lookChar(); buf = EOF; return c; }
372 virtual int lookChar();
373 virtual GString *getPSFilter(char *indent);
374 virtual GBool isBinary(GBool last = gTrue);
382 //------------------------------------------------------------------------
384 //------------------------------------------------------------------------
386 class ASCII85Stream: public FilterStream {
389 ASCII85Stream(Stream *strA);
390 virtual ~ASCII85Stream();
391 virtual StreamKind getKind() { return strASCII85; }
392 virtual void reset();
393 virtual int getChar()
394 { int ch = lookChar(); ++index; return ch; }
395 virtual int lookChar();
396 virtual GString *getPSFilter(char *indent);
397 virtual GBool isBinary(GBool last = gTrue);
407 //------------------------------------------------------------------------
409 //------------------------------------------------------------------------
411 class LZWStream: public FilterStream {
414 LZWStream(Stream *strA, int predictor, int columns, int colors,
415 int bits, int earlyA);
416 virtual ~LZWStream();
417 virtual StreamKind getKind() { return strLZW; }
418 virtual void reset();
419 virtual int getChar();
420 virtual int lookChar();
421 virtual int getRawChar();
422 virtual GString *getPSFilter(char *indent);
423 virtual GBool isBinary(GBool last = gTrue);
427 StreamPredictor *pred; // predictor
428 int early; // early parameter
429 GBool eof; // true if at eof
430 int inputBuf; // input buffer
431 int inputBits; // number of bits in input buffer
432 struct { // decoding table
437 int nextCode; // next code to be used
438 int nextBits; // number of bits in next code word
439 int prevCode; // previous code used in stream
440 int newChar; // next char to be added to table
441 Guchar seqBuf[4097]; // buffer for current sequence
442 int seqLength; // length of current sequence
443 int seqIndex; // index into current sequence
444 GBool first; // first code after a table clear
446 GBool processNextCode();
451 //------------------------------------------------------------------------
453 //------------------------------------------------------------------------
455 class RunLengthStream: public FilterStream {
458 RunLengthStream(Stream *strA);
459 virtual ~RunLengthStream();
460 virtual StreamKind getKind() { return strRunLength; }
461 virtual void reset();
462 virtual int getChar()
463 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
464 virtual int lookChar()
465 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
466 virtual GString *getPSFilter(char *indent);
467 virtual GBool isBinary(GBool last = gTrue);
471 char buf[128]; // buffer
472 char *bufPtr; // next char to read
473 char *bufEnd; // end of buffer
479 //------------------------------------------------------------------------
481 //------------------------------------------------------------------------
483 struct CCITTCodeTable;
485 class CCITTFaxStream: public FilterStream {
488 CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
489 GBool byteAlignA, int columnsA, int rowsA,
490 GBool endOfBlockA, GBool blackA);
491 virtual ~CCITTFaxStream();
492 virtual StreamKind getKind() { return strCCITTFax; }
493 virtual void reset();
494 virtual int getChar()
495 { int c = lookChar(); buf = EOF; return c; }
496 virtual int lookChar();
497 virtual GString *getPSFilter(char *indent);
498 virtual GBool isBinary(GBool last = gTrue);
502 int encoding; // 'K' parameter
503 GBool endOfLine; // 'EndOfLine' parameter
504 GBool byteAlign; // 'EncodedByteAlign' parameter
505 int columns; // 'Columns' parameter
506 int rows; // 'Rows' parameter
507 GBool endOfBlock; // 'EndOfBlock' parameter
508 GBool black; // 'BlackIs1' parameter
509 GBool eof; // true if at eof
510 GBool nextLine2D; // true if next line uses 2D encoding
511 int row; // current row
512 int inputBuf; // input buffer
513 int inputBits; // number of bits in input buffer
514 short *refLine; // reference line changing elements
515 int b1; // index into refLine
516 short *codingLine; // coding line changing elements
517 int a0; // index into codingLine
518 int outputBits; // remaining ouput bits
519 int buf; // character buffer
521 short getTwoDimCode();
522 short getWhiteCode();
523 short getBlackCode();
524 short lookBits(int n);
525 void eatBits(int n) { inputBits -= n; }
528 //------------------------------------------------------------------------
530 //------------------------------------------------------------------------
532 // DCT component info
534 int id; // component ID
535 int hSample, vSample; // horiz/vert sampling resolutions
536 int quantTable; // quantization table number
537 int prevDC; // DC coefficient accumulator
541 GBool comp[4]; // comp[i] is set if component i is
542 // included in this scan
543 int numComps; // number of components in the scan
544 int dcHuffTable[4]; // DC Huffman table numbers
545 int acHuffTable[4]; // AC Huffman table numbers
546 int firstCoeff, lastCoeff; // first and last DCT coefficient
547 int ah, al; // successive approximation parameters
550 // DCT Huffman decoding table
551 struct DCTHuffTable {
552 Guchar firstSym[17]; // first symbol for this bit length
553 Gushort firstCode[17]; // first code for this bit length
554 Gushort numCodes[17]; // number of codes of this bit length
555 Guchar sym[256]; // symbols
558 class DCTStream: public FilterStream {
561 DCTStream(Stream *strA);
562 virtual ~DCTStream();
563 virtual StreamKind getKind() { return strDCT; }
564 virtual void reset();
565 virtual int getChar();
566 virtual int lookChar();
567 virtual GString *getPSFilter(char *indent);
568 virtual GBool isBinary(GBool last = gTrue);
569 Stream *getRawStream() { return str; }
573 GBool progressive; // set if in progressive mode
574 GBool interleaved; // set if in interleaved mode
575 int width, height; // image size
576 int mcuWidth, mcuHeight; // size of min coding unit, in data units
577 int bufWidth, bufHeight; // frameBuf size
578 DCTCompInfo compInfo[4]; // info for each component
579 DCTScanInfo scanInfo; // info for the current scan
580 int numComps; // number of components in image
581 int colorXform; // need YCbCr-to-RGB transform?
582 GBool gotAdobeMarker; // set if APP14 Adobe marker was present
583 int restartInterval; // restart interval, in MCUs
584 Guchar quantTables[4][64]; // quantization tables
585 int numQuantTables; // number of quantization tables
586 DCTHuffTable dcHuffTables[4]; // DC Huffman tables
587 DCTHuffTable acHuffTables[4]; // AC Huffman tables
588 int numDCHuffTables; // number of DC Huffman tables
589 int numACHuffTables; // number of AC Huffman tables
590 Guchar *rowBuf[4][32]; // buffer for one MCU (non-progressive mode)
591 int *frameBuf[4]; // buffer for frame (progressive mode)
592 int comp, x, y, dy; // current position within image/MCU
593 int restartCtr; // MCUs left until restart
594 int restartMarker; // next restart marker
595 int eobRun; // number of EOBs left in the current run
596 int inputBuf; // input buffer for variable length codes
597 int inputBits; // number of valid bits in input buffer
602 GBool readDataUnit(DCTHuffTable *dcHuffTable,
603 DCTHuffTable *acHuffTable,
604 int *prevDC, int data[64]);
605 GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
606 DCTHuffTable *acHuffTable,
607 int *prevDC, int data[64]);
609 void transformDataUnit(Guchar *quantTable,
610 int dataIn[64], Guchar dataOut[64]);
611 int readHuffSym(DCTHuffTable *table);
612 int readAmp(int size);
615 GBool readBaselineSOF();
616 GBool readProgressiveSOF();
617 GBool readScanInfo();
618 GBool readQuantTables();
619 GBool readHuffmanTables();
620 GBool readRestartInterval();
621 GBool readAdobeMarker();
627 //------------------------------------------------------------------------
629 //------------------------------------------------------------------------
631 #define flateWindow 32768 // buffer size
632 #define flateMask (flateWindow-1)
633 #define flateMaxHuffman 15 // max Huffman code length
634 #define flateMaxCodeLenCodes 19 // max # code length codes
635 #define flateMaxLitCodes 288 // max # literal codes
636 #define flateMaxDistCodes 30 // max # distance codes
638 // Huffman code table entry
640 Gushort len; // code length, in bits
641 Gushort val; // value represented by this code
644 struct FlateHuffmanTab {
649 // Decoding info for length and distance code words
651 int bits; // # extra bits
652 int first; // first length/distance
655 class FlateStream: public FilterStream {
658 FlateStream(Stream *strA, int predictor, int columns,
659 int colors, int bits);
660 virtual ~FlateStream();
661 virtual StreamKind getKind() { return strFlate; }
662 virtual void reset();
663 virtual int getChar();
664 virtual int lookChar();
665 virtual int getRawChar();
666 virtual GString *getPSFilter(char *indent);
667 virtual GBool isBinary(GBool last = gTrue);
671 StreamPredictor *pred; // predictor
672 Guchar buf[flateWindow]; // output data buffer
673 int index; // current index into output buffer
674 int remain; // number valid bytes in output buffer
675 int codeBuf; // input buffer
676 int codeSize; // number of bits in input buffer
677 int // literal and distance code lengths
678 codeLengths[flateMaxLitCodes + flateMaxDistCodes];
679 FlateHuffmanTab litCodeTab; // literal code table
680 FlateHuffmanTab distCodeTab; // distance code table
681 GBool compressedBlock; // set if reading a compressed block
682 int blockLen; // remaining length of uncompressed block
683 GBool endOfBlock; // set when end of block is reached
684 GBool eof; // set when end of stream is reached
686 static int // code length code reordering
687 codeLenCodeMap[flateMaxCodeLenCodes];
688 static FlateDecode // length decoding info
689 lengthDecode[flateMaxLitCodes-257];
690 static FlateDecode // distance decoding info
691 distDecode[flateMaxDistCodes];
695 void loadFixedCodes();
696 GBool readDynamicCodes();
697 void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab);
698 int getHuffmanCodeWord(FlateHuffmanTab *tab);
699 int getCodeWord(int bits);
702 //------------------------------------------------------------------------
704 //------------------------------------------------------------------------
706 class EOFStream: public FilterStream {
709 EOFStream(Stream *strA);
710 virtual ~EOFStream();
711 virtual StreamKind getKind() { return strWeird; }
712 virtual void reset() {}
713 virtual int getChar() { return EOF; }
714 virtual int lookChar() { return EOF; }
715 virtual GString *getPSFilter(char *indent) { return NULL; }
716 virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
719 //------------------------------------------------------------------------
720 // FixedLengthEncoder
721 //------------------------------------------------------------------------
723 class FixedLengthEncoder: public FilterStream {
726 FixedLengthEncoder(Stream *strA, int lengthA);
727 ~FixedLengthEncoder();
728 virtual StreamKind getKind() { return strWeird; }
729 virtual void reset();
730 virtual void close();
731 virtual int getChar();
732 virtual int lookChar();
733 virtual GString *getPSFilter(char *indent) { return NULL; }
734 virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
735 virtual GBool isEncoder() { return gTrue; }
743 //------------------------------------------------------------------------
745 //------------------------------------------------------------------------
747 class ASCIIHexEncoder: public FilterStream {
750 ASCIIHexEncoder(Stream *strA);
751 virtual ~ASCIIHexEncoder();
752 virtual StreamKind getKind() { return strWeird; }
753 virtual void reset();
754 virtual void close();
755 virtual int getChar()
756 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
757 virtual int lookChar()
758 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
759 virtual GString *getPSFilter(char *indent) { return NULL; }
760 virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
761 virtual GBool isEncoder() { return gTrue; }
774 //------------------------------------------------------------------------
776 //------------------------------------------------------------------------
778 class ASCII85Encoder: public FilterStream {
781 ASCII85Encoder(Stream *strA);
782 virtual ~ASCII85Encoder();
783 virtual StreamKind getKind() { return strWeird; }
784 virtual void reset();
785 virtual void close();
786 virtual int getChar()
787 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
788 virtual int lookChar()
789 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
790 virtual GString *getPSFilter(char *indent) { return NULL; }
791 virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
792 virtual GBool isEncoder() { return gTrue; }
805 //------------------------------------------------------------------------
807 //------------------------------------------------------------------------
809 class RunLengthEncoder: public FilterStream {
812 RunLengthEncoder(Stream *strA);
813 virtual ~RunLengthEncoder();
814 virtual StreamKind getKind() { return strWeird; }
815 virtual void reset();
816 virtual void close();
817 virtual int getChar()
818 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
819 virtual int lookChar()
820 { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
821 virtual GString *getPSFilter(char *indent) { return NULL; }
822 virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
823 virtual GBool isEncoder() { return gTrue; }