#ifndef STREAM_H
#define STREAM_H
#include <config.h>
#ifdef USE_GCC_PRAGMAS
#pragma interface
#endif
#include <stdio.h>
#include "gtypes.h"
#include "Object.h"
class Decrypt;
class BaseStream;
enum StreamKind {
strFile,
strASCIIHex,
strASCII85,
strLZW,
strRunLength,
strCCITTFax,
strDCT,
strFlate,
strJBIG2,
strJPX,
strWeird };
enum StreamColorSpaceMode {
streamCSNone,
streamCSDeviceGray,
streamCSDeviceRGB,
streamCSDeviceCMYK
};
class Stream {
public:
Stream();
virtual ~Stream();
int incRef() { return ++ref; }
int decRef() { return --ref; }
virtual StreamKind getKind() = 0;
virtual void reset() = 0;
virtual void close();
virtual int getChar() = 0;
virtual int lookChar() = 0;
virtual int getRawChar();
virtual char *getLine(char *buf, int size);
virtual int getPos() = 0;
virtual void setPos(Guint pos, int dir = 0) = 0;
virtual GString *getPSFilter(int psLevel, char *indent);
virtual GBool isBinary(GBool last = gTrue) = 0;
virtual BaseStream *getBaseStream() = 0;
virtual Dict *getDict() = 0;
virtual GBool isEncoder() { return gFalse; }
virtual void getImageParams(int *bitsPerComponent,
StreamColorSpaceMode *csMode) {}
Stream *addFilters(Object *dict);
private:
Stream *makeFilter(char *name, Stream *str, Object *params);
int ref; };
class BaseStream: public Stream {
public:
BaseStream(Object *dictA);
virtual ~BaseStream();
virtual Stream *makeSubStream(Guint start, GBool limited,
Guint length, Object *dict) = 0;
virtual void setPos(Guint pos, int dir = 0) = 0;
virtual GBool isBinary(GBool last = gTrue) { return last; }
virtual BaseStream *getBaseStream() { return this; }
virtual Dict *getDict() { return dict.getDict(); }
virtual Guint getStart() = 0;
virtual void moveStart(int delta) = 0;
virtual void doDecryption(Guchar *fileKey, int keyLength,
int objNum, int objGen);
protected:
Decrypt *decrypt;
private:
Object dict;
};
class FilterStream: public Stream {
public:
FilterStream(Stream *strA);
virtual ~FilterStream();
virtual void close();
virtual int getPos() { return str->getPos(); }
virtual void setPos(Guint pos, int dir = 0);
virtual BaseStream *getBaseStream() { return str->getBaseStream(); }
virtual Dict *getDict() { return str->getDict(); }
protected:
Stream *str;
};
class ImageStream {
public:
ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA);
~ImageStream();
void reset();
GBool getPixel(Guchar *pix);
Guchar *getLine();
void skipLine();
private:
Stream *str; int width; int nComps; int nBits; int nVals; Guchar *imgLine; int imgIdx; };
class StreamPredictor {
public:
StreamPredictor(Stream *strA, int predictorA,
int widthA, int nCompsA, int nBitsA);
~StreamPredictor();
GBool isOk() { return ok; }
int lookChar();
int getChar();
private:
GBool getNextLine();
Stream *str; int predictor; int width; int nComps; int nBits; int nVals; int pixBytes; int rowBytes; Guchar *predLine; int predIdx; GBool ok;
};
#define fileStreamBufSize 256
class FileStream: public BaseStream {
public:
FileStream(FILE *fA, Guint startA, GBool limitedA,
Guint lengthA, Object *dictA);
virtual ~FileStream();
virtual Stream *makeSubStream(Guint startA, GBool limitedA,
Guint lengthA, Object *dictA);
virtual StreamKind getKind() { return strFile; }
virtual void reset();
virtual void close();
virtual int getChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
virtual int getPos() { return bufPos + (bufPtr - buf); }
virtual void setPos(Guint pos, int dir = 0);
virtual Guint getStart() { return start; }
virtual void moveStart(int delta);
private:
GBool fillBuf();
FILE *f;
Guint start;
GBool limited;
Guint length;
char buf[fileStreamBufSize];
char *bufPtr;
char *bufEnd;
Guint bufPos;
int savePos;
GBool saved;
};
class MemStream: public BaseStream {
public:
MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA);
virtual ~MemStream();
virtual Stream *makeSubStream(Guint start, GBool limited,
Guint 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 getPos() { return (int)(bufPtr - buf); }
virtual void setPos(Guint pos, int dir = 0);
virtual Guint getStart() { return start; }
virtual void moveStart(int delta);
virtual void doDecryption(Guchar *fileKey, int keyLength,
int objNum, int objGen);
private:
char *buf;
Guint start;
Guint length;
char *bufEnd;
char *bufPtr;
GBool needFree;
};
class EmbedStream: public BaseStream {
public:
EmbedStream(Stream *strA, Object *dictA, GBool limitedA, Guint lengthA);
virtual ~EmbedStream();
virtual Stream *makeSubStream(Guint start, GBool limitedA,
Guint lengthA, Object *dictA);
virtual StreamKind getKind() { return str->getKind(); }
virtual void reset() {}
virtual int getChar();
virtual int lookChar();
virtual int getPos() { return str->getPos(); }
virtual void setPos(Guint pos, int dir = 0);
virtual Guint getStart();
virtual void moveStart(int delta);
private:
Stream *str;
GBool limited;
Guint length;
};
class ASCIIHexStream: public FilterStream {
public:
ASCIIHexStream(Stream *strA);
virtual ~ASCIIHexStream();
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, char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
int buf;
GBool eof;
};
class ASCII85Stream: public FilterStream {
public:
ASCII85Stream(Stream *strA);
virtual ~ASCII85Stream();
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, char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
int c[5];
int b[4];
int index, n;
GBool eof;
};
class LZWStream: public FilterStream {
public:
LZWStream(Stream *strA, int predictor, int columns, int colors,
int bits, int earlyA);
virtual ~LZWStream();
virtual StreamKind getKind() { return strLZW; }
virtual void reset();
virtual int getChar();
virtual int lookChar();
virtual int getRawChar();
virtual GString *getPSFilter(int psLevel, char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
StreamPredictor *pred; int early; GBool eof; int inputBuf; int inputBits; struct { int length;
int head;
Guchar tail;
} table[4097];
int nextCode; int nextBits; int prevCode; int newChar; Guchar seqBuf[4097]; int seqLength; int seqIndex; GBool first;
GBool processNextCode();
void clearTable();
int getCode();
};
class RunLengthStream: public FilterStream {
public:
RunLengthStream(Stream *strA);
virtual ~RunLengthStream();
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 GString *getPSFilter(int psLevel, char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
char buf[128]; char *bufPtr; char *bufEnd; GBool eof;
GBool fillBuf();
};
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 StreamKind getKind() { return strCCITTFax; }
virtual void reset();
virtual int getChar()
{ int c = lookChar(); buf = EOF; return c; }
virtual int lookChar();
virtual GString *getPSFilter(int psLevel, char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
int encoding; GBool endOfLine; GBool byteAlign; int columns; int rows; GBool endOfBlock; GBool black; GBool eof; GBool nextLine2D; int row; int inputBuf; int inputBits; int *codingLine; int *refLine; int a0i; GBool err; int outputBits; int buf;
void addPixels(int a1, int black);
void addPixelsNeg(int a1, int black);
short getTwoDimCode();
short getWhiteCode();
short getBlackCode();
short lookBits(int n);
void eatBits(int n) { if ((inputBits -= n) < 0) inputBits = 0; }
};
struct DCTCompInfo {
int id; int hSample, vSample; int quantTable; int prevDC; };
struct DCTScanInfo {
GBool comp[4]; int numComps; int dcHuffTable[4]; int acHuffTable[4]; int firstCoeff, lastCoeff; int ah, al; };
struct DCTHuffTable {
Guchar firstSym[17]; Gushort firstCode[17]; Gushort numCodes[17]; Guchar sym[256]; };
class DCTStream: public FilterStream {
public:
DCTStream(Stream *strA);
virtual ~DCTStream();
virtual StreamKind getKind() { return strDCT; }
virtual void reset();
virtual int getChar();
virtual int lookChar();
virtual GString *getPSFilter(int psLevel, char *indent);
virtual GBool isBinary(GBool last = gTrue);
Stream *getRawStream() { return str; }
private:
GBool progressive; GBool interleaved; int width, height; int mcuWidth, mcuHeight; int bufWidth, bufHeight; DCTCompInfo compInfo[4]; DCTScanInfo scanInfo; int numComps; int colorXform; GBool gotJFIFMarker; GBool gotAdobeMarker; int restartInterval; Gushort quantTables[4][64]; int numQuantTables; DCTHuffTable dcHuffTables[4]; DCTHuffTable acHuffTables[4]; int numDCHuffTables; int numACHuffTables; Guchar *rowBuf[4][32]; int *frameBuf[4]; int comp, x, y, dy; int restartCtr; int restartMarker; int eobRun; int inputBuf; int inputBits;
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 readBaselineSOF();
GBool readProgressiveSOF();
GBool readScanInfo();
GBool readQuantTables();
GBool readHuffmanTables();
GBool readRestartInterval();
GBool readJFIFMarker();
GBool readAdobeMarker();
GBool readTrailer();
int readMarker();
int read16();
};
#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
struct FlateCode {
Gushort len; Gushort val; };
struct FlateHuffmanTab {
FlateCode *codes;
int maxLen;
};
struct FlateDecode {
int bits; int first; };
class FlateStream: public FilterStream {
public:
FlateStream(Stream *strA, int predictor, int columns,
int colors, int bits);
virtual ~FlateStream();
virtual StreamKind getKind() { return strFlate; }
virtual void reset();
virtual int getChar();
virtual int lookChar();
virtual int getRawChar();
virtual GString *getPSFilter(int psLevel, char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
StreamPredictor *pred; Guchar buf[flateWindow]; int index; int remain; int codeBuf; int codeSize; int codeLengths[flateMaxLitCodes + flateMaxDistCodes];
FlateHuffmanTab litCodeTab; FlateHuffmanTab distCodeTab; GBool compressedBlock; int blockLen; GBool endOfBlock; GBool eof;
static int codeLenCodeMap[flateMaxCodeLenCodes];
static FlateDecode lengthDecode[flateMaxLitCodes-257];
static FlateDecode distDecode[flateMaxDistCodes];
static FlateHuffmanTab fixedLitCodeTab;
static FlateHuffmanTab 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);
};
class EOFStream: public FilterStream {
public:
EOFStream(Stream *strA);
virtual ~EOFStream();
virtual StreamKind getKind() { return strWeird; }
virtual void reset() {}
virtual int getChar() { return EOF; }
virtual int lookChar() { return EOF; }
virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
};
class FixedLengthEncoder: public FilterStream {
public:
FixedLengthEncoder(Stream *strA, int lengthA);
~FixedLengthEncoder();
virtual StreamKind getKind() { return strWeird; }
virtual void reset();
virtual int getChar();
virtual int lookChar();
virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
virtual GBool isBinary(GBool last = gTrue);
virtual GBool isEncoder() { return gTrue; }
private:
int length;
int count;
};
class ASCIIHexEncoder: public FilterStream {
public:
ASCIIHexEncoder(Stream *strA);
virtual ~ASCIIHexEncoder();
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, char *indent) { 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();
};
class ASCII85Encoder: public FilterStream {
public:
ASCII85Encoder(Stream *strA);
virtual ~ASCII85Encoder();
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, char *indent) { 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();
};
class RunLengthEncoder: public FilterStream {
public:
RunLengthEncoder(Stream *strA);
virtual ~RunLengthEncoder();
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, char *indent) { 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();
};
#endif