//======================================================================== // // Stream.h // // Copyright 1996-2003 Glyph & Cog, LLC // //======================================================================== #ifndef STREAM_H #define STREAM_H #include #ifdef USE_GCC_PRAGMAS #pragma interface #endif #include #if HAVE_JPEGLIB #include #include #endif #include "gtypes.h" #include "gfile.h" #include "Object.h" class BaseStream; class SharedFile; //------------------------------------------------------------------------ enum StreamKind { strFile, strASCIIHex, strASCII85, strLZW, strRunLength, strCCITTFax, strDCT, strFlate, strJBIG2, strJPX, strWeird // internal-use stream types }; enum StreamColorSpaceMode { streamCSNone, streamCSDeviceGray, streamCSDeviceRGB, streamCSDeviceCMYK }; //------------------------------------------------------------------------ // This is in Stream.h instead of Decrypt.h to avoid really annoying // include file dependency loops. enum CryptAlgorithm { cryptRC4, cryptAES, cryptAES256 }; //------------------------------------------------------------------------ // Stream (base class) //------------------------------------------------------------------------ class Stream { public: // Constructor. Stream(); // Destructor. virtual ~Stream(); virtual Stream *copy() = 0; // Get kind of stream. virtual StreamKind getKind() = 0; virtual GBool isEmbedStream() { return gFalse; } // Reset stream to beginning. virtual void reset() = 0; // Close down the stream. virtual void close(); // Get next char from stream. virtual int getChar() = 0; // Peek at next char in stream. virtual int lookChar() = 0; // Get next char from stream without using the predictor. // This is only used by StreamPredictor. virtual int getRawChar(); // Get exactly bytes from stream. Returns the number of // bytes read -- the returned count will be less than at EOF. virtual int getBlock(char *blk, int size); // Get next line from stream. virtual char *getLine(char *buf, int size); // Discard the next bytes from stream. Returns the number of // bytes discarded, which will be less than only if EOF is // reached. virtual Guint discardChars(Guint n); // Get current position in file. virtual GFileOffset getPos() = 0; // Go to a position in the stream. If is negative, the // position is from the end of the file; otherwise the position is // from the start of the file. virtual void setPos(GFileOffset pos, int dir = 0) = 0; // Get PostScript command for the filter(s). virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream); // Does this stream type potentially contain non-printable chars? virtual GBool isBinary(GBool last = gTrue) = 0; // Get the BaseStream of this stream. virtual BaseStream *getBaseStream() = 0; // Get the stream after the last decoder (this may be a BaseStream // or a DecryptStream). virtual Stream *getUndecodedStream() = 0; // Get the dictionary associated with this stream. virtual Dict *getDict() = 0; // Is this an encoding filter? virtual GBool isEncoder() { return gFalse; } // Get image parameters which are defined by the stream contents. virtual void getImageParams(int *bitsPerComponent, StreamColorSpaceMode *csMode) {} // Return the next stream in the "stack". virtual Stream *getNextStream() { return NULL; } // Add filters to this stream according to the parameters in . // Returns the new stream. Stream *addFilters(Object *dict, int recursion = 0); private: Stream *makeFilter(char *name, Stream *str, Object *params, int recursion); }; //------------------------------------------------------------------------ // BaseStream // // This is the base class for all streams that read directly from a file. //------------------------------------------------------------------------ class BaseStream: public Stream { public: BaseStream(Object *dictA); virtual ~BaseStream(); virtual Stream *makeSubStream(GFileOffset start, GBool limited, GFileOffset length, Object *dict) = 0; virtual void setPos(GFileOffset pos, int dir = 0) = 0; virtual GBool isBinary(GBool last = gTrue) { return last; } virtual BaseStream *getBaseStream() { return this; } virtual Stream *getUndecodedStream() { return this; } virtual Dict *getDict() { return dict.getDict(); } virtual GString *getFileName() { return NULL; } // Get/set position of first byte of stream within the file. virtual GFileOffset getStart() = 0; virtual void moveStart(int delta) = 0; protected: Object dict; }; //------------------------------------------------------------------------ // FilterStream // // This is the base class for all streams that filter another stream. //------------------------------------------------------------------------ class FilterStream: public Stream { public: FilterStream(Stream *strA); virtual ~FilterStream(); virtual void close(); virtual GFileOffset getPos() { return str->getPos(); } virtual void setPos(GFileOffset pos, int dir = 0); virtual BaseStream *getBaseStream() { return str->getBaseStream(); } virtual Stream *getUndecodedStream() { return str->getUndecodedStream(); } virtual Dict *getDict() { return str->getDict(); } virtual Stream *getNextStream() { return str; } protected: Stream *str; }; //------------------------------------------------------------------------ // ImageStream //------------------------------------------------------------------------ class ImageStream { public: // Create an image stream object for an image with the specified // parameters. Note that these are the actual image parameters, // which may be different from the predictor parameters. ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA); ~ImageStream(); // Reset the stream. void reset(); // Close down the stream. void close(); // Gets the next pixel from the stream. should be able to hold // at least nComps elements. Returns false at end of file. GBool getPixel(Guchar *pix); // Returns a pointer to the next line of pixels. Returns NULL at // end of file. Guchar *getLine(); // Skip an entire line from the image. void skipLine(); private: Stream *str; // base stream int width; // pixels per line int nComps; // components per pixel int nBits; // bits per component int nVals; // components per line int inputLineSize; // input line buffer size char *inputLine; // input line buffer Guchar *imgLine; // line buffer int imgIdx; // current index in imgLine }; //------------------------------------------------------------------------ // StreamPredictor //------------------------------------------------------------------------ class StreamPredictor { public: // Create a predictor object. Note that the parameters are for the // predictor, and may not match the actual image parameters. StreamPredictor(Stream *strA, int predictorA, int widthA, int nCompsA, int nBitsA); ~StreamPredictor(); GBool isOk() { return ok; } void reset(); int lookChar(); int getChar(); int getBlock(char *blk, int size); int getPredictor() { return predictor; } int getWidth() { return width; } int getNComps() { return nComps; } int getNBits() { return nBits; } private: GBool getNextLine(); Stream *str; // base stream int predictor; // predictor int width; // pixels per line int nComps; // components per pixel int nBits; // bits per component int nVals; // components per line int pixBytes; // bytes per pixel int rowBytes; // bytes per line Guchar *predLine; // line buffer int predIdx; // current index in predLine GBool ok; }; //------------------------------------------------------------------------ // FileStream //------------------------------------------------------------------------ #define fileStreamBufSize 256 class FileStream: public BaseStream { public: FileStream(FILE *fA, GFileOffset startA, GBool limitedA, GFileOffset lengthA, Object *dictA); virtual ~FileStream(); virtual Stream *copy(); virtual Stream *makeSubStream(GFileOffset startA, GBool limitedA, GFileOffset lengthA, Object *dictA); virtual StreamKind getKind() { return strFile; } virtual void reset(); virtual int getChar() { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } virtual int lookChar() { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } virtual int getBlock(char *blk, int size); virtual GFileOffset getPos() { return bufPos + (int)(bufPtr - buf); } virtual void setPos(GFileOffset pos, int dir = 0); virtual GFileOffset getStart() { return start; } virtual void moveStart(int delta); private: FileStream(SharedFile *fA, GFileOffset startA, GBool limitedA, GFileOffset lengthA, Object *dictA); GBool fillBuf(); SharedFile *f; GFileOffset start; GBool limited; GFileOffset length; char buf[fileStreamBufSize]; char *bufPtr; char *bufEnd; GFileOffset bufPos; }; //------------------------------------------------------------------------ // MemStream //------------------------------------------------------------------------ class MemStream: public BaseStream { public: MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA); virtual ~MemStream(); virtual Stream *copy(); virtual Stream *makeSubStream(GFileOffset start, GBool limited, GFileOffset lengthA, Object *dictA); virtual StreamKind getKind() { return strWeird; } virtual void reset(); virtual void close(); virtual int getChar() { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; } virtual int lookChar() { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; } virtual int getBlock(char *blk, int size); virtual GFileOffset getPos() { return (GFileOffset)(bufPtr - buf); } virtual void setPos(GFileOffset pos, int dir = 0); virtual GFileOffset getStart() { return start; } virtual void moveStart(int delta); private: char *buf; Guint start; Guint length; char *bufEnd; char *bufPtr; GBool needFree; }; //------------------------------------------------------------------------ // EmbedStream // // This is a special stream type used for embedded streams (inline // images). It reads directly from the base stream -- after the // EmbedStream is deleted, reads from the base stream will proceed where // the BaseStream left off. Note that this is very different behavior // that creating a new FileStream (using makeSubStream). //------------------------------------------------------------------------ class EmbedStream: public BaseStream { public: EmbedStream(Stream *strA, Object *dictA, GBool limitedA, GFileOffset lengthA); virtual ~EmbedStream(); virtual Stream *copy(); virtual Stream *makeSubStream(GFileOffset start, GBool limitedA, GFileOffset lengthA, Object *dictA); virtual StreamKind getKind() { return str->getKind(); } virtual GBool isEmbedStream() { return gTrue; } virtual void reset() {} virtual int getChar(); virtual int lookChar(); virtual int getBlock(char *blk, int size); virtual GFileOffset getPos() { return str->getPos(); } virtual void setPos(GFileOffset pos, int dir = 0); virtual GFileOffset getStart(); virtual void moveStart(int delta); private: Stream *str; GBool limited; GFileOffset length; }; //------------------------------------------------------------------------ // ASCIIHexStream //------------------------------------------------------------------------ class ASCIIHexStream: public FilterStream { public: ASCIIHexStream(Stream *strA); virtual ~ASCIIHexStream(); virtual Stream *copy(); virtual StreamKind getKind() { return strASCIIHex; } virtual void reset(); virtual int getChar() { int c = lookChar(); buf = EOF; return c; } virtual int lookChar(); virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream); virtual GBool isBinary(GBool last = gTrue); private: int buf; GBool eof; }; //------------------------------------------------------------------------ // ASCII85Stream //------------------------------------------------------------------------ class ASCII85Stream: public FilterStream { public: ASCII85Stream(Stream *strA); virtual ~ASCII85Stream(); virtual Stream *copy(); virtual StreamKind getKind() { return strASCII85; } virtual void reset(); virtual int getChar() { int ch = lookChar(); ++index; return ch; } virtual int lookChar(); virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream); virtual GBool isBinary(GBool last = gTrue); private: int c[5]; int b[4]; int index, n; GBool eof; }; //------------------------------------------------------------------------ // LZWStream //------------------------------------------------------------------------ class LZWStream: public FilterStream { public: LZWStream(Stream *strA, int predictor, int columns, int colors, int bits, int earlyA); virtual ~LZWStream(); virtual Stream *copy(); virtual StreamKind getKind() { return strLZW; } virtual void reset(); virtual int getChar(); virtual int lookChar(); virtual int getRawChar(); virtual int getBlock(char *blk, int size); virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream); virtual GBool isBinary(GBool last = gTrue); private: StreamPredictor *pred; // predictor int early; // early parameter GBool eof; // true if at eof int inputBuf; // input buffer int inputBits; // number of bits in input buffer struct { // decoding table int length; int head; Guchar tail; } table[4097]; int nextCode; // next code to be used int nextBits; // number of bits in next code word int prevCode; // previous code used in stream int newChar; // next char to be added to table Guchar seqBuf[4097]; // buffer for current sequence int seqLength; // length of current sequence int seqIndex; // index into current sequence GBool first; // first code after a table clear unsigned long long totalIn; // total number of encoded bytes read so far unsigned long long totalOut; // total number of bytes decoded so far GBool processNextCode(); void clearTable(); int getCode(); }; //------------------------------------------------------------------------ // RunLengthStream //------------------------------------------------------------------------ class RunLengthStream: public FilterStream { public: RunLengthStream(Stream *strA); virtual ~RunLengthStream(); virtual Stream *copy(); virtual StreamKind getKind() { return strRunLength; } virtual void reset(); virtual int getChar() { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } virtual int lookChar() { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } virtual int getBlock(char *blk, int size); virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream); virtual GBool isBinary(GBool last = gTrue); private: char buf[128]; // buffer char *bufPtr; // next char to read char *bufEnd; // end of buffer GBool eof; GBool fillBuf(); }; //------------------------------------------------------------------------ // CCITTFaxStream //------------------------------------------------------------------------ struct CCITTCodeTable; class CCITTFaxStream: public FilterStream { public: CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA, GBool byteAlignA, int columnsA, int rowsA, GBool endOfBlockA, GBool blackA); virtual ~CCITTFaxStream(); virtual Stream *copy(); virtual StreamKind getKind() { return strCCITTFax; } virtual void reset(); virtual int getChar(); virtual int lookChar(); virtual int getBlock(char *blk, int size); virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream); virtual GBool isBinary(GBool last = gTrue); private: int encoding; // 'K' parameter GBool endOfLine; // 'EndOfLine' parameter GBool byteAlign; // 'EncodedByteAlign' parameter int columns; // 'Columns' parameter int rows; // 'Rows' parameter GBool endOfBlock; // 'EndOfBlock' parameter GBool black; // 'BlackIs1' parameter int blackXOR; GBool eof; // true if at eof GBool nextLine2D; // true if next line uses 2D encoding int row; // current row Guint inputBuf; // input buffer int inputBits; // number of bits in input buffer int *codingLine; // coding line changing elements int *refLine; // reference line changing elements int nextCol; // next column to read int a0i; // index into codingLine GBool err; // error on current line int nErrors; // number of errors so far in this stream void addPixels(int a1, int blackPixels); void addPixelsNeg(int a1, int blackPixels); GBool readRow(); short getTwoDimCode(); short getWhiteCode(); short getBlackCode(); short lookBits(int n); void eatBits(int n) { if ((inputBits -= n) < 0) inputBits = 0; } }; //------------------------------------------------------------------------ // DCTStream //------------------------------------------------------------------------ #if HAVE_JPEGLIB class DCTStream; #define dctStreamBufSize 4096 struct DCTSourceMgr { jpeg_source_mgr src; DCTStream *str; char buf[dctStreamBufSize]; }; struct DCTErrorMgr { struct jpeg_error_mgr err; jmp_buf setjmpBuf; }; #else // HAVE_JPEGLIB // DCT component info struct DCTCompInfo { int id; // component ID int hSample, vSample; // horiz/vert sampling resolutions int quantTable; // quantization table number int prevDC; // DC coefficient accumulator }; struct DCTScanInfo { GBool comp[4]; // comp[i] is set if component i is // included in this scan int numComps; // number of components in the scan int dcHuffTable[4]; // DC Huffman table numbers int acHuffTable[4]; // AC Huffman table numbers int firstCoeff, lastCoeff; // first and last DCT coefficient int ah, al; // successive approximation parameters }; // DCT Huffman decoding table struct DCTHuffTable { Guchar firstSym[17]; // first symbol for this bit length Gushort firstCode[17]; // first code for this bit length Gushort numCodes[17]; // number of codes of this bit length Guchar sym[256]; // symbols }; #endif // HAVE_JPEGLIB class DCTStream: public FilterStream { public: DCTStream(Stream *strA, int colorXformA); virtual ~DCTStream(); virtual Stream *copy(); virtual StreamKind getKind() { return strDCT; } virtual void reset(); virtual void close(); virtual int getChar(); virtual int lookChar(); virtual int getBlock(char *blk, int size); virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream); virtual GBool isBinary(GBool last = gTrue); Stream *getRawStream() { return str; } private: GBool checkSequentialInterleaved(); #if HAVE_JPEGLIB int colorXform; // color transform: -1 = unspecified // 0 = none // 1 = YUV/YUVK -> RGB/CMYK jpeg_decompress_struct decomp; DCTErrorMgr errorMgr; DCTSourceMgr sourceMgr; GBool error; char *lineBuf; int lineBufHeight; char *lineBufRows[4]; char *bufPtr; char *bufEnd; GBool inlineImage; GBool fillBuf(); static void errorExit(j_common_ptr d); static void errorMessage(j_common_ptr d); static void initSourceCbk(j_decompress_ptr d); static boolean fillInputBufferCbk(j_decompress_ptr d); static void skipInputDataCbk(j_decompress_ptr d, long numBytes); static void termSourceCbk(j_decompress_ptr d); #else // HAVE_JPEGLIB GBool progressive; // set if in progressive mode GBool interleaved; // set if in interleaved mode int width, height; // image size int mcuWidth, mcuHeight; // size of min coding unit, in data units int bufWidth, bufHeight; // frameBuf size DCTCompInfo compInfo[4]; // info for each component DCTScanInfo scanInfo; // info for the current scan int numComps; // number of components in image int colorXform; // color transform: -1 = unspecified // 0 = none // 1 = YUV/YUVK -> RGB/CMYK GBool gotJFIFMarker; // set if APP0 JFIF marker was present GBool gotAdobeMarker; // set if APP14 Adobe marker was present int restartInterval; // restart interval, in MCUs Gushort quantTables[4][64]; // quantization tables int numQuantTables; // number of quantization tables DCTHuffTable dcHuffTables[4]; // DC Huffman tables DCTHuffTable acHuffTables[4]; // AC Huffman tables int numDCHuffTables; // number of DC Huffman tables int numACHuffTables; // number of AC Huffman tables Guchar *rowBuf; Guchar *rowBufPtr; // current position within rowBuf Guchar *rowBufEnd; // end of valid data in rowBuf int *frameBuf[4]; // buffer for frame (progressive mode) int comp, x, y; // current position within image/MCU int restartCtr; // MCUs left until restart int restartMarker; // next restart marker int eobRun; // number of EOBs left in the current run int inputBuf; // input buffer for variable length codes int inputBits; // number of valid bits in input buffer void restart(); GBool readMCURow(); void readScan(); GBool readDataUnit(DCTHuffTable *dcHuffTable, DCTHuffTable *acHuffTable, int *prevDC, int data[64]); GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable, DCTHuffTable *acHuffTable, int *prevDC, int data[64]); void decodeImage(); void transformDataUnit(Gushort *quantTable, int dataIn[64], Guchar dataOut[64]); int readHuffSym(DCTHuffTable *table); int readAmp(int size); int readBit(); GBool readHeader(GBool frame); GBool readBaselineSOF(); GBool readProgressiveSOF(); GBool readScanInfo(); GBool readQuantTables(); GBool readHuffmanTables(); GBool readRestartInterval(); GBool readJFIFMarker(); GBool readAdobeMarker(); GBool readTrailer(); int readMarker(); int read16(); #endif // HAVE_JPEGLIB }; //------------------------------------------------------------------------ // FlateStream //------------------------------------------------------------------------ #define flateWindow 32768 // buffer size #define flateMask (flateWindow-1) #define flateMaxHuffman 15 // max Huffman code length #define flateMaxCodeLenCodes 19 // max # code length codes #define flateMaxLitCodes 288 // max # literal codes #define flateMaxDistCodes 30 // max # distance codes // Huffman code table entry struct FlateCode { Gushort len; // code length, in bits Gushort val; // value represented by this code }; struct FlateHuffmanTab { FlateCode *codes; int maxLen; }; // Decoding info for length and distance code words struct FlateDecode { int bits; // # extra bits int first; // first length/distance }; class FlateStream: public FilterStream { public: FlateStream(Stream *strA, int predictor, int columns, int colors, int bits); virtual ~FlateStream(); virtual Stream *copy(); virtual StreamKind getKind() { return strFlate; } virtual void reset(); virtual int getChar(); virtual int lookChar(); virtual int getRawChar(); virtual int getBlock(char *blk, int size); virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream); virtual GBool isBinary(GBool last = gTrue); private: StreamPredictor *pred; // predictor Guchar buf[flateWindow]; // output data buffer int index; // current index into output buffer int remain; // number valid bytes in output buffer int codeBuf; // input buffer int codeSize; // number of bits in input buffer int // literal and distance code lengths codeLengths[flateMaxLitCodes + flateMaxDistCodes]; FlateHuffmanTab litCodeTab; // literal code table FlateHuffmanTab distCodeTab; // distance code table GBool compressedBlock; // set if reading a compressed block int blockLen; // remaining length of uncompressed block GBool endOfBlock; // set when end of block is reached GBool eof; // set when end of stream is reached unsigned long long totalIn; // total number of encoded bytes read so far unsigned long long totalOut; // total number of bytes decoded so far static int // code length code reordering codeLenCodeMap[flateMaxCodeLenCodes]; static FlateDecode // length decoding info lengthDecode[flateMaxLitCodes-257]; static FlateDecode // distance decoding info distDecode[flateMaxDistCodes]; static FlateHuffmanTab // fixed literal code table fixedLitCodeTab; static FlateHuffmanTab // fixed distance code table fixedDistCodeTab; void readSome(); GBool startBlock(); void loadFixedCodes(); GBool readDynamicCodes(); void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab); int getHuffmanCodeWord(FlateHuffmanTab *tab); int getCodeWord(int bits); }; //------------------------------------------------------------------------ // EOFStream //------------------------------------------------------------------------ class EOFStream: public FilterStream { public: EOFStream(Stream *strA); virtual ~EOFStream(); virtual Stream *copy(); virtual StreamKind getKind() { return strWeird; } virtual void reset() {} virtual int getChar() { return EOF; } virtual int lookChar() { return EOF; } virtual int getBlock(char *blk, int size) { return 0; } virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream) { return NULL; } virtual GBool isBinary(GBool last = gTrue) { return gFalse; } }; //------------------------------------------------------------------------ // BufStream //------------------------------------------------------------------------ class BufStream: public FilterStream { public: BufStream(Stream *strA, int bufSizeA); virtual ~BufStream(); virtual Stream *copy(); virtual StreamKind getKind() { return strWeird; } virtual void reset(); virtual int getChar(); virtual int lookChar(); virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream) { return NULL; } virtual GBool isBinary(GBool last = gTrue); int lookChar(int idx); private: int *buf; int bufSize; }; //------------------------------------------------------------------------ // FixedLengthEncoder //------------------------------------------------------------------------ class FixedLengthEncoder: public FilterStream { public: FixedLengthEncoder(Stream *strA, int lengthA); ~FixedLengthEncoder(); virtual Stream *copy(); virtual StreamKind getKind() { return strWeird; } virtual void reset(); virtual int getChar(); virtual int lookChar(); virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream) { return NULL; } virtual GBool isBinary(GBool last = gTrue); virtual GBool isEncoder() { return gTrue; } private: int length; int count; }; //------------------------------------------------------------------------ // ASCIIHexEncoder //------------------------------------------------------------------------ class ASCIIHexEncoder: public FilterStream { public: ASCIIHexEncoder(Stream *strA); virtual ~ASCIIHexEncoder(); virtual Stream *copy(); virtual StreamKind getKind() { return strWeird; } virtual void reset(); virtual int getChar() { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } virtual int lookChar() { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream) { return NULL; } virtual GBool isBinary(GBool last = gTrue) { return gFalse; } virtual GBool isEncoder() { return gTrue; } private: char buf[4]; char *bufPtr; char *bufEnd; int lineLen; GBool eof; GBool fillBuf(); }; //------------------------------------------------------------------------ // ASCII85Encoder //------------------------------------------------------------------------ class ASCII85Encoder: public FilterStream { public: ASCII85Encoder(Stream *strA); virtual ~ASCII85Encoder(); virtual Stream *copy(); virtual StreamKind getKind() { return strWeird; } virtual void reset(); virtual int getChar() { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } virtual int lookChar() { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream) { return NULL; } virtual GBool isBinary(GBool last = gTrue) { return gFalse; } virtual GBool isEncoder() { return gTrue; } private: char buf[8]; char *bufPtr; char *bufEnd; int lineLen; GBool eof; GBool fillBuf(); }; //------------------------------------------------------------------------ // RunLengthEncoder //------------------------------------------------------------------------ class RunLengthEncoder: public FilterStream { public: RunLengthEncoder(Stream *strA); virtual ~RunLengthEncoder(); virtual Stream *copy(); virtual StreamKind getKind() { return strWeird; } virtual void reset(); virtual int getChar() { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } virtual int lookChar() { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream) { return NULL; } virtual GBool isBinary(GBool last = gTrue) { return gTrue; } virtual GBool isEncoder() { return gTrue; } private: char buf[131]; char *bufPtr; char *bufEnd; char *nextEnd; GBool eof; GBool fillBuf(); }; //------------------------------------------------------------------------ // LZWEncoder //------------------------------------------------------------------------ struct LZWEncoderNode { int byte; LZWEncoderNode *next; // next sibling LZWEncoderNode *children; // first child }; class LZWEncoder: public FilterStream { public: LZWEncoder(Stream *strA); virtual ~LZWEncoder(); virtual Stream *copy(); virtual StreamKind getKind() { return strWeird; } virtual void reset(); virtual int getChar(); virtual int lookChar(); virtual GString *getPSFilter(int psLevel, const char *indent, GBool okToReadStream) { return NULL; } virtual GBool isBinary(GBool last = gTrue) { return gTrue; } virtual GBool isEncoder() { return gTrue; } private: LZWEncoderNode table[4096]; int nextSeq; int codeLen; Guchar inBuf[8192]; int inBufStart; int inBufLen; int outBuf; int outBufLen; GBool needEOD; void fillBuf(); }; #endif