]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | //======================================================================== |
2 | // | |
3 | // Stream.h | |
4 | // | |
5 | // Copyright 1996-2003 Glyph & Cog, LLC | |
6 | // | |
7 | //======================================================================== | |
8 | ||
9 | #ifndef STREAM_H | |
10 | #define STREAM_H | |
11 | ||
12 | #include <config.h> | |
13 | ||
14 | #ifdef USE_GCC_PRAGMAS | |
15 | #pragma interface | |
16 | #endif | |
17 | ||
18 | #include <stdio.h> | |
19 | #include "gtypes.h" | |
20 | #include "Object.h" | |
21 | ||
22 | class Decrypt; | |
23 | class BaseStream; | |
24 | ||
25 | //------------------------------------------------------------------------ | |
26 | ||
27 | enum StreamKind { | |
28 | strFile, | |
29 | strASCIIHex, | |
30 | strASCII85, | |
31 | strLZW, | |
32 | strRunLength, | |
33 | strCCITTFax, | |
34 | strDCT, | |
35 | strFlate, | |
36 | strJBIG2, | |
37 | strJPX, | |
38 | strWeird // internal-use stream types | |
39 | }; | |
40 | ||
41 | enum StreamColorSpaceMode { | |
42 | streamCSNone, | |
43 | streamCSDeviceGray, | |
44 | streamCSDeviceRGB, | |
45 | streamCSDeviceCMYK | |
46 | }; | |
47 | ||
48 | //------------------------------------------------------------------------ | |
49 | // Stream (base class) | |
50 | //------------------------------------------------------------------------ | |
51 | ||
52 | class Stream { | |
53 | public: | |
54 | ||
55 | // Constructor. | |
56 | Stream(); | |
57 | ||
58 | // Destructor. | |
59 | virtual ~Stream(); | |
60 | ||
61 | // Reference counting. | |
62 | int incRef() { return ++ref; } | |
63 | int decRef() { return --ref; } | |
64 | ||
65 | // Get kind of stream. | |
66 | virtual StreamKind getKind() = 0; | |
67 | ||
68 | // Reset stream to beginning. | |
69 | virtual void reset() = 0; | |
70 | ||
71 | // Close down the stream. | |
72 | virtual void close(); | |
73 | ||
74 | // Get next char from stream. | |
75 | virtual int getChar() = 0; | |
76 | ||
77 | // Peek at next char in stream. | |
78 | virtual int lookChar() = 0; | |
79 | ||
80 | // Get next char from stream without using the predictor. | |
81 | // This is only used by StreamPredictor. | |
82 | virtual int getRawChar(); | |
83 | ||
84 | // Get next line from stream. | |
85 | virtual char *getLine(char *buf, int size); | |
86 | ||
87 | // Get current position in file. | |
88 | virtual int getPos() = 0; | |
89 | ||
90 | // Go to a position in the stream. If <dir> is negative, the | |
91 | // position is from the end of the file; otherwise the position is | |
92 | // from the start of the file. | |
93 | virtual void setPos(Guint pos, int dir = 0) = 0; | |
94 | ||
95 | // Get PostScript command for the filter(s). | |
96 | virtual GString *getPSFilter(int psLevel, char *indent); | |
97 | ||
98 | // Does this stream type potentially contain non-printable chars? | |
99 | virtual GBool isBinary(GBool last = gTrue) = 0; | |
100 | ||
101 | // Get the BaseStream of this stream. | |
102 | virtual BaseStream *getBaseStream() = 0; | |
103 | ||
104 | // Get the dictionary associated with this stream. | |
105 | virtual Dict *getDict() = 0; | |
106 | ||
107 | // Is this an encoding filter? | |
108 | virtual GBool isEncoder() { return gFalse; } | |
109 | ||
110 | // Get image parameters which are defined by the stream contents. | |
111 | virtual void getImageParams(int *bitsPerComponent, | |
112 | StreamColorSpaceMode *csMode) {} | |
113 | ||
114 | // Add filters to this stream according to the parameters in <dict>. | |
115 | // Returns the new stream. | |
116 | Stream *addFilters(Object *dict); | |
117 | ||
118 | private: | |
119 | ||
120 | Stream *makeFilter(char *name, Stream *str, Object *params); | |
121 | ||
122 | int ref; // reference count | |
123 | }; | |
124 | ||
125 | //------------------------------------------------------------------------ | |
126 | // BaseStream | |
127 | // | |
128 | // This is the base class for all streams that read directly from a file. | |
129 | //------------------------------------------------------------------------ | |
130 | ||
131 | class BaseStream: public Stream { | |
132 | public: | |
133 | ||
134 | BaseStream(Object *dictA); | |
135 | virtual ~BaseStream(); | |
136 | virtual Stream *makeSubStream(Guint start, GBool limited, | |
137 | Guint length, Object *dict) = 0; | |
138 | virtual void setPos(Guint pos, int dir = 0) = 0; | |
139 | virtual GBool isBinary(GBool last = gTrue) { return last; } | |
140 | virtual BaseStream *getBaseStream() { return this; } | |
141 | virtual Dict *getDict() { return dict.getDict(); } | |
142 | ||
143 | // Get/set position of first byte of stream within the file. | |
144 | virtual Guint getStart() = 0; | |
145 | virtual void moveStart(int delta) = 0; | |
146 | ||
147 | // Set decryption for this stream. | |
148 | virtual void doDecryption(Guchar *fileKey, int keyLength, | |
149 | int objNum, int objGen); | |
150 | ||
151 | protected: | |
152 | ||
153 | Decrypt *decrypt; | |
154 | ||
155 | private: | |
156 | ||
157 | Object dict; | |
158 | }; | |
159 | ||
160 | //------------------------------------------------------------------------ | |
161 | // FilterStream | |
162 | // | |
163 | // This is the base class for all streams that filter another stream. | |
164 | //------------------------------------------------------------------------ | |
165 | ||
166 | class FilterStream: public Stream { | |
167 | public: | |
168 | ||
169 | FilterStream(Stream *strA); | |
170 | virtual ~FilterStream(); | |
171 | virtual void close(); | |
172 | virtual int getPos() { return str->getPos(); } | |
173 | virtual void setPos(Guint pos, int dir = 0); | |
174 | virtual BaseStream *getBaseStream() { return str->getBaseStream(); } | |
175 | virtual Dict *getDict() { return str->getDict(); } | |
176 | ||
177 | protected: | |
178 | ||
179 | Stream *str; | |
180 | }; | |
181 | ||
182 | //------------------------------------------------------------------------ | |
183 | // ImageStream | |
184 | //------------------------------------------------------------------------ | |
185 | ||
186 | class ImageStream { | |
187 | public: | |
188 | ||
189 | // Create an image stream object for an image with the specified | |
190 | // parameters. Note that these are the actual image parameters, | |
191 | // which may be different from the predictor parameters. | |
192 | ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA); | |
193 | ||
194 | ~ImageStream(); | |
195 | ||
196 | // Reset the stream. | |
197 | void reset(); | |
198 | ||
199 | // Gets the next pixel from the stream. <pix> should be able to hold | |
200 | // at least nComps elements. Returns false at end of file. | |
201 | GBool getPixel(Guchar *pix); | |
202 | ||
203 | // Returns a pointer to the next line of pixels. Returns NULL at | |
204 | // end of file. | |
205 | Guchar *getLine(); | |
206 | ||
207 | // Skip an entire line from the image. | |
208 | void skipLine(); | |
209 | ||
210 | private: | |
211 | ||
212 | Stream *str; // base stream | |
213 | int width; // pixels per line | |
214 | int nComps; // components per pixel | |
215 | int nBits; // bits per component | |
216 | int nVals; // components per line | |
217 | Guchar *imgLine; // line buffer | |
218 | int imgIdx; // current index in imgLine | |
219 | }; | |
220 | ||
221 | //------------------------------------------------------------------------ | |
222 | // StreamPredictor | |
223 | //------------------------------------------------------------------------ | |
224 | ||
225 | class StreamPredictor { | |
226 | public: | |
227 | ||
228 | // Create a predictor object. Note that the parameters are for the | |
229 | // predictor, and may not match the actual image parameters. | |
230 | StreamPredictor(Stream *strA, int predictorA, | |
231 | int widthA, int nCompsA, int nBitsA); | |
232 | ||
233 | ~StreamPredictor(); | |
234 | ||
235 | GBool isOk() { return ok; } | |
236 | ||
237 | int lookChar(); | |
238 | int getChar(); | |
239 | ||
240 | private: | |
241 | ||
242 | GBool getNextLine(); | |
243 | ||
244 | Stream *str; // base stream | |
245 | int predictor; // predictor | |
246 | int width; // pixels per line | |
247 | int nComps; // components per pixel | |
248 | int nBits; // bits per component | |
249 | int nVals; // components per line | |
250 | int pixBytes; // bytes per pixel | |
251 | int rowBytes; // bytes per line | |
252 | Guchar *predLine; // line buffer | |
253 | int predIdx; // current index in predLine | |
254 | GBool ok; | |
255 | }; | |
256 | ||
257 | //------------------------------------------------------------------------ | |
258 | // FileStream | |
259 | //------------------------------------------------------------------------ | |
260 | ||
261 | #define fileStreamBufSize 256 | |
262 | ||
263 | class FileStream: public BaseStream { | |
264 | public: | |
265 | ||
266 | FileStream(FILE *fA, Guint startA, GBool limitedA, | |
267 | Guint lengthA, Object *dictA); | |
268 | virtual ~FileStream(); | |
269 | virtual Stream *makeSubStream(Guint startA, GBool limitedA, | |
270 | Guint lengthA, Object *dictA); | |
271 | virtual StreamKind getKind() { return strFile; } | |
272 | virtual void reset(); | |
273 | virtual void close(); | |
274 | virtual int getChar() | |
275 | { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } | |
276 | virtual int lookChar() | |
277 | { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } | |
278 | virtual int getPos() { return bufPos + (bufPtr - buf); } | |
279 | virtual void setPos(Guint pos, int dir = 0); | |
280 | virtual Guint getStart() { return start; } | |
281 | virtual void moveStart(int delta); | |
282 | ||
283 | private: | |
284 | ||
285 | GBool fillBuf(); | |
286 | ||
287 | FILE *f; | |
288 | Guint start; | |
289 | GBool limited; | |
290 | Guint length; | |
291 | char buf[fileStreamBufSize]; | |
292 | char *bufPtr; | |
293 | char *bufEnd; | |
294 | Guint bufPos; | |
295 | int savePos; | |
296 | GBool saved; | |
297 | }; | |
298 | ||
299 | //------------------------------------------------------------------------ | |
300 | // MemStream | |
301 | //------------------------------------------------------------------------ | |
302 | ||
303 | class MemStream: public BaseStream { | |
304 | public: | |
305 | ||
306 | MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA); | |
307 | virtual ~MemStream(); | |
308 | virtual Stream *makeSubStream(Guint start, GBool limited, | |
309 | Guint lengthA, Object *dictA); | |
310 | virtual StreamKind getKind() { return strWeird; } | |
311 | virtual void reset(); | |
312 | virtual void close(); | |
313 | virtual int getChar() | |
314 | { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; } | |
315 | virtual int lookChar() | |
316 | { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; } | |
317 | virtual int getPos() { return (int)(bufPtr - buf); } | |
318 | virtual void setPos(Guint pos, int dir = 0); | |
319 | virtual Guint getStart() { return start; } | |
320 | virtual void moveStart(int delta); | |
321 | virtual void doDecryption(Guchar *fileKey, int keyLength, | |
322 | int objNum, int objGen); | |
323 | ||
324 | private: | |
325 | ||
326 | char *buf; | |
327 | Guint start; | |
328 | Guint length; | |
329 | char *bufEnd; | |
330 | char *bufPtr; | |
331 | GBool needFree; | |
332 | }; | |
333 | ||
334 | //------------------------------------------------------------------------ | |
335 | // EmbedStream | |
336 | // | |
337 | // This is a special stream type used for embedded streams (inline | |
338 | // images). It reads directly from the base stream -- after the | |
339 | // EmbedStream is deleted, reads from the base stream will proceed where | |
340 | // the BaseStream left off. Note that this is very different behavior | |
341 | // that creating a new FileStream (using makeSubStream). | |
342 | //------------------------------------------------------------------------ | |
343 | ||
344 | class EmbedStream: public BaseStream { | |
345 | public: | |
346 | ||
347 | EmbedStream(Stream *strA, Object *dictA, GBool limitedA, Guint lengthA); | |
348 | virtual ~EmbedStream(); | |
349 | virtual Stream *makeSubStream(Guint start, GBool limitedA, | |
350 | Guint lengthA, Object *dictA); | |
351 | virtual StreamKind getKind() { return str->getKind(); } | |
352 | virtual void reset() {} | |
353 | virtual int getChar(); | |
354 | virtual int lookChar(); | |
355 | virtual int getPos() { return str->getPos(); } | |
356 | virtual void setPos(Guint pos, int dir = 0); | |
357 | virtual Guint getStart(); | |
358 | virtual void moveStart(int delta); | |
359 | ||
360 | private: | |
361 | ||
362 | Stream *str; | |
363 | GBool limited; | |
364 | Guint length; | |
365 | }; | |
366 | ||
367 | //------------------------------------------------------------------------ | |
368 | // ASCIIHexStream | |
369 | //------------------------------------------------------------------------ | |
370 | ||
371 | class ASCIIHexStream: public FilterStream { | |
372 | public: | |
373 | ||
374 | ASCIIHexStream(Stream *strA); | |
375 | virtual ~ASCIIHexStream(); | |
376 | virtual StreamKind getKind() { return strASCIIHex; } | |
377 | virtual void reset(); | |
378 | virtual int getChar() | |
379 | { int c = lookChar(); buf = EOF; return c; } | |
380 | virtual int lookChar(); | |
381 | virtual GString *getPSFilter(int psLevel, char *indent); | |
382 | virtual GBool isBinary(GBool last = gTrue); | |
383 | ||
384 | private: | |
385 | ||
386 | int buf; | |
387 | GBool eof; | |
388 | }; | |
389 | ||
390 | //------------------------------------------------------------------------ | |
391 | // ASCII85Stream | |
392 | //------------------------------------------------------------------------ | |
393 | ||
394 | class ASCII85Stream: public FilterStream { | |
395 | public: | |
396 | ||
397 | ASCII85Stream(Stream *strA); | |
398 | virtual ~ASCII85Stream(); | |
399 | virtual StreamKind getKind() { return strASCII85; } | |
400 | virtual void reset(); | |
401 | virtual int getChar() | |
402 | { int ch = lookChar(); ++index; return ch; } | |
403 | virtual int lookChar(); | |
404 | virtual GString *getPSFilter(int psLevel, char *indent); | |
405 | virtual GBool isBinary(GBool last = gTrue); | |
406 | ||
407 | private: | |
408 | ||
409 | int c[5]; | |
410 | int b[4]; | |
411 | int index, n; | |
412 | GBool eof; | |
413 | }; | |
414 | ||
415 | //------------------------------------------------------------------------ | |
416 | // LZWStream | |
417 | //------------------------------------------------------------------------ | |
418 | ||
419 | class LZWStream: public FilterStream { | |
420 | public: | |
421 | ||
422 | LZWStream(Stream *strA, int predictor, int columns, int colors, | |
423 | int bits, int earlyA); | |
424 | virtual ~LZWStream(); | |
425 | virtual StreamKind getKind() { return strLZW; } | |
426 | virtual void reset(); | |
427 | virtual int getChar(); | |
428 | virtual int lookChar(); | |
429 | virtual int getRawChar(); | |
430 | virtual GString *getPSFilter(int psLevel, char *indent); | |
431 | virtual GBool isBinary(GBool last = gTrue); | |
432 | ||
433 | private: | |
434 | ||
435 | StreamPredictor *pred; // predictor | |
436 | int early; // early parameter | |
437 | GBool eof; // true if at eof | |
438 | int inputBuf; // input buffer | |
439 | int inputBits; // number of bits in input buffer | |
440 | struct { // decoding table | |
441 | int length; | |
442 | int head; | |
443 | Guchar tail; | |
444 | } table[4097]; | |
445 | int nextCode; // next code to be used | |
446 | int nextBits; // number of bits in next code word | |
447 | int prevCode; // previous code used in stream | |
448 | int newChar; // next char to be added to table | |
449 | Guchar seqBuf[4097]; // buffer for current sequence | |
450 | int seqLength; // length of current sequence | |
451 | int seqIndex; // index into current sequence | |
452 | GBool first; // first code after a table clear | |
453 | ||
454 | GBool processNextCode(); | |
455 | void clearTable(); | |
456 | int getCode(); | |
457 | }; | |
458 | ||
459 | //------------------------------------------------------------------------ | |
460 | // RunLengthStream | |
461 | //------------------------------------------------------------------------ | |
462 | ||
463 | class RunLengthStream: public FilterStream { | |
464 | public: | |
465 | ||
466 | RunLengthStream(Stream *strA); | |
467 | virtual ~RunLengthStream(); | |
468 | virtual StreamKind getKind() { return strRunLength; } | |
469 | virtual void reset(); | |
470 | virtual int getChar() | |
471 | { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } | |
472 | virtual int lookChar() | |
473 | { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } | |
474 | virtual GString *getPSFilter(int psLevel, char *indent); | |
475 | virtual GBool isBinary(GBool last = gTrue); | |
476 | ||
477 | private: | |
478 | ||
479 | char buf[128]; // buffer | |
480 | char *bufPtr; // next char to read | |
481 | char *bufEnd; // end of buffer | |
482 | GBool eof; | |
483 | ||
484 | GBool fillBuf(); | |
485 | }; | |
486 | ||
487 | //------------------------------------------------------------------------ | |
488 | // CCITTFaxStream | |
489 | //------------------------------------------------------------------------ | |
490 | ||
491 | struct CCITTCodeTable; | |
492 | ||
493 | class CCITTFaxStream: public FilterStream { | |
494 | public: | |
495 | ||
496 | CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA, | |
497 | GBool byteAlignA, int columnsA, int rowsA, | |
498 | GBool endOfBlockA, GBool blackA); | |
499 | virtual ~CCITTFaxStream(); | |
500 | virtual StreamKind getKind() { return strCCITTFax; } | |
501 | virtual void reset(); | |
502 | virtual int getChar() | |
503 | { int c = lookChar(); buf = EOF; return c; } | |
504 | virtual int lookChar(); | |
505 | virtual GString *getPSFilter(int psLevel, char *indent); | |
506 | virtual GBool isBinary(GBool last = gTrue); | |
507 | ||
508 | private: | |
509 | ||
510 | int encoding; // 'K' parameter | |
511 | GBool endOfLine; // 'EndOfLine' parameter | |
512 | GBool byteAlign; // 'EncodedByteAlign' parameter | |
513 | int columns; // 'Columns' parameter | |
514 | int rows; // 'Rows' parameter | |
515 | GBool endOfBlock; // 'EndOfBlock' parameter | |
516 | GBool black; // 'BlackIs1' parameter | |
517 | GBool eof; // true if at eof | |
518 | GBool nextLine2D; // true if next line uses 2D encoding | |
519 | int row; // current row | |
520 | int inputBuf; // input buffer | |
521 | int inputBits; // number of bits in input buffer | |
522 | short *refLine; // reference line changing elements | |
523 | int b1; // index into refLine | |
524 | short *codingLine; // coding line changing elements | |
525 | int a0; // index into codingLine | |
526 | int outputBits; // remaining ouput bits | |
527 | int buf; // character buffer | |
528 | ||
529 | short getTwoDimCode(); | |
530 | short getWhiteCode(); | |
531 | short getBlackCode(); | |
532 | short lookBits(int n); | |
bd7854cb | 533 | void eatBits(int n) { if ((inputBits -= n) < 0) inputBits = 0; } |
ef416fc2 | 534 | }; |
535 | ||
536 | //------------------------------------------------------------------------ | |
537 | // DCTStream | |
538 | //------------------------------------------------------------------------ | |
539 | ||
540 | // DCT component info | |
541 | struct DCTCompInfo { | |
542 | int id; // component ID | |
543 | int hSample, vSample; // horiz/vert sampling resolutions | |
544 | int quantTable; // quantization table number | |
545 | int prevDC; // DC coefficient accumulator | |
546 | }; | |
547 | ||
548 | struct DCTScanInfo { | |
549 | GBool comp[4]; // comp[i] is set if component i is | |
550 | // included in this scan | |
551 | int numComps; // number of components in the scan | |
552 | int dcHuffTable[4]; // DC Huffman table numbers | |
553 | int acHuffTable[4]; // AC Huffman table numbers | |
554 | int firstCoeff, lastCoeff; // first and last DCT coefficient | |
555 | int ah, al; // successive approximation parameters | |
556 | }; | |
557 | ||
558 | // DCT Huffman decoding table | |
559 | struct DCTHuffTable { | |
560 | Guchar firstSym[17]; // first symbol for this bit length | |
561 | Gushort firstCode[17]; // first code for this bit length | |
562 | Gushort numCodes[17]; // number of codes of this bit length | |
563 | Guchar sym[256]; // symbols | |
564 | }; | |
565 | ||
566 | class DCTStream: public FilterStream { | |
567 | public: | |
568 | ||
569 | DCTStream(Stream *strA); | |
570 | virtual ~DCTStream(); | |
571 | virtual StreamKind getKind() { return strDCT; } | |
572 | virtual void reset(); | |
573 | virtual int getChar(); | |
574 | virtual int lookChar(); | |
575 | virtual GString *getPSFilter(int psLevel, char *indent); | |
576 | virtual GBool isBinary(GBool last = gTrue); | |
577 | Stream *getRawStream() { return str; } | |
578 | ||
579 | private: | |
580 | ||
581 | GBool progressive; // set if in progressive mode | |
582 | GBool interleaved; // set if in interleaved mode | |
583 | int width, height; // image size | |
584 | int mcuWidth, mcuHeight; // size of min coding unit, in data units | |
585 | int bufWidth, bufHeight; // frameBuf size | |
586 | DCTCompInfo compInfo[4]; // info for each component | |
587 | DCTScanInfo scanInfo; // info for the current scan | |
588 | int numComps; // number of components in image | |
589 | int colorXform; // need YCbCr-to-RGB transform? | |
590 | GBool gotJFIFMarker; // set if APP0 JFIF marker was present | |
591 | GBool gotAdobeMarker; // set if APP14 Adobe marker was present | |
592 | int restartInterval; // restart interval, in MCUs | |
593 | Gushort quantTables[4][64]; // quantization tables | |
594 | int numQuantTables; // number of quantization tables | |
595 | DCTHuffTable dcHuffTables[4]; // DC Huffman tables | |
596 | DCTHuffTable acHuffTables[4]; // AC Huffman tables | |
597 | int numDCHuffTables; // number of DC Huffman tables | |
598 | int numACHuffTables; // number of AC Huffman tables | |
599 | Guchar *rowBuf[4][32]; // buffer for one MCU (non-progressive mode) | |
600 | int *frameBuf[4]; // buffer for frame (progressive mode) | |
601 | int comp, x, y, dy; // current position within image/MCU | |
602 | int restartCtr; // MCUs left until restart | |
603 | int restartMarker; // next restart marker | |
604 | int eobRun; // number of EOBs left in the current run | |
605 | int inputBuf; // input buffer for variable length codes | |
606 | int inputBits; // number of valid bits in input buffer | |
607 | ||
608 | void restart(); | |
609 | GBool readMCURow(); | |
610 | void readScan(); | |
611 | GBool readDataUnit(DCTHuffTable *dcHuffTable, | |
612 | DCTHuffTable *acHuffTable, | |
613 | int *prevDC, int data[64]); | |
614 | GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable, | |
615 | DCTHuffTable *acHuffTable, | |
616 | int *prevDC, int data[64]); | |
617 | void decodeImage(); | |
618 | void transformDataUnit(Gushort *quantTable, | |
619 | int dataIn[64], Guchar dataOut[64]); | |
620 | int readHuffSym(DCTHuffTable *table); | |
621 | int readAmp(int size); | |
622 | int readBit(); | |
623 | GBool readHeader(); | |
624 | GBool readBaselineSOF(); | |
625 | GBool readProgressiveSOF(); | |
626 | GBool readScanInfo(); | |
627 | GBool readQuantTables(); | |
628 | GBool readHuffmanTables(); | |
629 | GBool readRestartInterval(); | |
630 | GBool readJFIFMarker(); | |
631 | GBool readAdobeMarker(); | |
632 | GBool readTrailer(); | |
633 | int readMarker(); | |
634 | int read16(); | |
635 | }; | |
636 | ||
637 | //------------------------------------------------------------------------ | |
638 | // FlateStream | |
639 | //------------------------------------------------------------------------ | |
640 | ||
641 | #define flateWindow 32768 // buffer size | |
642 | #define flateMask (flateWindow-1) | |
643 | #define flateMaxHuffman 15 // max Huffman code length | |
644 | #define flateMaxCodeLenCodes 19 // max # code length codes | |
645 | #define flateMaxLitCodes 288 // max # literal codes | |
646 | #define flateMaxDistCodes 30 // max # distance codes | |
647 | ||
648 | // Huffman code table entry | |
649 | struct FlateCode { | |
650 | Gushort len; // code length, in bits | |
651 | Gushort val; // value represented by this code | |
652 | }; | |
653 | ||
654 | struct FlateHuffmanTab { | |
655 | FlateCode *codes; | |
656 | int maxLen; | |
657 | }; | |
658 | ||
659 | // Decoding info for length and distance code words | |
660 | struct FlateDecode { | |
661 | int bits; // # extra bits | |
662 | int first; // first length/distance | |
663 | }; | |
664 | ||
665 | class FlateStream: public FilterStream { | |
666 | public: | |
667 | ||
668 | FlateStream(Stream *strA, int predictor, int columns, | |
669 | int colors, int bits); | |
670 | virtual ~FlateStream(); | |
671 | virtual StreamKind getKind() { return strFlate; } | |
672 | virtual void reset(); | |
673 | virtual int getChar(); | |
674 | virtual int lookChar(); | |
675 | virtual int getRawChar(); | |
676 | virtual GString *getPSFilter(int psLevel, char *indent); | |
677 | virtual GBool isBinary(GBool last = gTrue); | |
678 | ||
679 | private: | |
680 | ||
681 | StreamPredictor *pred; // predictor | |
682 | Guchar buf[flateWindow]; // output data buffer | |
683 | int index; // current index into output buffer | |
684 | int remain; // number valid bytes in output buffer | |
685 | int codeBuf; // input buffer | |
686 | int codeSize; // number of bits in input buffer | |
687 | int // literal and distance code lengths | |
688 | codeLengths[flateMaxLitCodes + flateMaxDistCodes]; | |
689 | FlateHuffmanTab litCodeTab; // literal code table | |
690 | FlateHuffmanTab distCodeTab; // distance code table | |
691 | GBool compressedBlock; // set if reading a compressed block | |
692 | int blockLen; // remaining length of uncompressed block | |
693 | GBool endOfBlock; // set when end of block is reached | |
694 | GBool eof; // set when end of stream is reached | |
695 | ||
696 | static int // code length code reordering | |
697 | codeLenCodeMap[flateMaxCodeLenCodes]; | |
698 | static FlateDecode // length decoding info | |
699 | lengthDecode[flateMaxLitCodes-257]; | |
700 | static FlateDecode // distance decoding info | |
701 | distDecode[flateMaxDistCodes]; | |
702 | static FlateHuffmanTab // fixed literal code table | |
703 | fixedLitCodeTab; | |
704 | static FlateHuffmanTab // fixed distance code table | |
705 | fixedDistCodeTab; | |
706 | ||
707 | void readSome(); | |
708 | GBool startBlock(); | |
709 | void loadFixedCodes(); | |
710 | GBool readDynamicCodes(); | |
711 | void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab); | |
712 | int getHuffmanCodeWord(FlateHuffmanTab *tab); | |
713 | int getCodeWord(int bits); | |
714 | }; | |
715 | ||
716 | //------------------------------------------------------------------------ | |
717 | // EOFStream | |
718 | //------------------------------------------------------------------------ | |
719 | ||
720 | class EOFStream: public FilterStream { | |
721 | public: | |
722 | ||
723 | EOFStream(Stream *strA); | |
724 | virtual ~EOFStream(); | |
725 | virtual StreamKind getKind() { return strWeird; } | |
726 | virtual void reset() {} | |
727 | virtual int getChar() { return EOF; } | |
728 | virtual int lookChar() { return EOF; } | |
729 | virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; } | |
730 | virtual GBool isBinary(GBool last = gTrue) { return gFalse; } | |
731 | }; | |
732 | ||
733 | //------------------------------------------------------------------------ | |
734 | // FixedLengthEncoder | |
735 | //------------------------------------------------------------------------ | |
736 | ||
737 | class FixedLengthEncoder: public FilterStream { | |
738 | public: | |
739 | ||
740 | FixedLengthEncoder(Stream *strA, int lengthA); | |
741 | ~FixedLengthEncoder(); | |
742 | virtual StreamKind getKind() { return strWeird; } | |
743 | virtual void reset(); | |
744 | virtual int getChar(); | |
745 | virtual int lookChar(); | |
746 | virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; } | |
747 | virtual GBool isBinary(GBool last = gTrue); | |
748 | virtual GBool isEncoder() { return gTrue; } | |
749 | ||
750 | private: | |
751 | ||
752 | int length; | |
753 | int count; | |
754 | }; | |
755 | ||
756 | //------------------------------------------------------------------------ | |
757 | // ASCIIHexEncoder | |
758 | //------------------------------------------------------------------------ | |
759 | ||
760 | class ASCIIHexEncoder: public FilterStream { | |
761 | public: | |
762 | ||
763 | ASCIIHexEncoder(Stream *strA); | |
764 | virtual ~ASCIIHexEncoder(); | |
765 | virtual StreamKind getKind() { return strWeird; } | |
766 | virtual void reset(); | |
767 | virtual int getChar() | |
768 | { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } | |
769 | virtual int lookChar() | |
770 | { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } | |
771 | virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; } | |
772 | virtual GBool isBinary(GBool last = gTrue) { return gFalse; } | |
773 | virtual GBool isEncoder() { return gTrue; } | |
774 | ||
775 | private: | |
776 | ||
777 | char buf[4]; | |
778 | char *bufPtr; | |
779 | char *bufEnd; | |
780 | int lineLen; | |
781 | GBool eof; | |
782 | ||
783 | GBool fillBuf(); | |
784 | }; | |
785 | ||
786 | //------------------------------------------------------------------------ | |
787 | // ASCII85Encoder | |
788 | //------------------------------------------------------------------------ | |
789 | ||
790 | class ASCII85Encoder: public FilterStream { | |
791 | public: | |
792 | ||
793 | ASCII85Encoder(Stream *strA); | |
794 | virtual ~ASCII85Encoder(); | |
795 | virtual StreamKind getKind() { return strWeird; } | |
796 | virtual void reset(); | |
797 | virtual int getChar() | |
798 | { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } | |
799 | virtual int lookChar() | |
800 | { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } | |
801 | virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; } | |
802 | virtual GBool isBinary(GBool last = gTrue) { return gFalse; } | |
803 | virtual GBool isEncoder() { return gTrue; } | |
804 | ||
805 | private: | |
806 | ||
807 | char buf[8]; | |
808 | char *bufPtr; | |
809 | char *bufEnd; | |
810 | int lineLen; | |
811 | GBool eof; | |
812 | ||
813 | GBool fillBuf(); | |
814 | }; | |
815 | ||
816 | //------------------------------------------------------------------------ | |
817 | // RunLengthEncoder | |
818 | //------------------------------------------------------------------------ | |
819 | ||
820 | class RunLengthEncoder: public FilterStream { | |
821 | public: | |
822 | ||
823 | RunLengthEncoder(Stream *strA); | |
824 | virtual ~RunLengthEncoder(); | |
825 | virtual StreamKind getKind() { return strWeird; } | |
826 | virtual void reset(); | |
827 | virtual int getChar() | |
828 | { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } | |
829 | virtual int lookChar() | |
830 | { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } | |
831 | virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; } | |
832 | virtual GBool isBinary(GBool last = gTrue) { return gTrue; } | |
833 | virtual GBool isEncoder() { return gTrue; } | |
834 | ||
835 | private: | |
836 | ||
837 | char buf[131]; | |
838 | char *bufPtr; | |
839 | char *bufEnd; | |
840 | char *nextEnd; | |
841 | GBool eof; | |
842 | ||
843 | GBool fillBuf(); | |
844 | }; | |
845 | ||
846 | #endif |