1 : //========================================================================
2 : //
3 : // Stream.h
4 : //
5 : // Copyright 1996-2003 Glyph & Cog, LLC
6 : //
7 : //========================================================================
8 :
9 : //========================================================================
10 : //
11 : // Modified under the Poppler project - http://poppler.freedesktop.org
12 : //
13 : // All changes made under the Poppler project to this file are licensed
14 : // under GPL version 2 or later
15 : //
16 : // Copyright (C) 2005 Jeff Muizelaar <jeff@infidigm.net>
17 : // Copyright (C) 2008 Julien Rebetez <julien@fhtagn.net>
18 : // Copyright (C) 2008, 2010, 2011 Albert Astals Cid <aacid@kde.org>
19 : // Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
20 : // Copyright (C) 2009 Stefan Thomas <thomas@eload24.com>
21 : // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
22 : // Copyright (C) 2011, 2012 William Bader <williambader@hotmail.com>
23 : // Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
24 : // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
25 : // Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
26 : //
27 : // To see a description of the changes please see the Changelog file that
28 : // came with your tarball or type make ChangeLog if you are building from git
29 : //
30 : //========================================================================
31 :
32 : #ifndef STREAM_H
33 : #define STREAM_H
34 :
35 : #ifdef USE_GCC_PRAGMAS
36 : #pragma interface
37 : #endif
38 :
39 : #include "poppler-config.h"
40 : #include <stdio.h>
41 : #include "goo/gtypes.h"
42 : #include "Object.h"
43 : #include "goo/GooMutex.h"
44 :
45 : class BaseStream;
46 : class CachedFile;
47 :
48 : //------------------------------------------------------------------------
49 :
50 : enum StreamKind {
51 : strFile,
52 : strCachedFile,
53 : strASCIIHex,
54 : strASCII85,
55 : strLZW,
56 : strRunLength,
57 : strCCITTFax,
58 : strDCT,
59 : strFlate,
60 : strJBIG2,
61 : strJPX,
62 : strWeird // internal-use stream types
63 : };
64 :
65 : enum StreamColorSpaceMode {
66 : streamCSNone,
67 : streamCSDeviceGray,
68 : streamCSDeviceRGB,
69 : streamCSDeviceCMYK
70 : };
71 :
72 : //------------------------------------------------------------------------
73 :
74 : // This is in Stream.h instead of Decrypt.h to avoid really annoying
75 : // include file dependency loops.
76 : enum CryptAlgorithm {
77 : cryptRC4,
78 : cryptAES,
79 : cryptAES256
80 : };
81 :
82 : //------------------------------------------------------------------------
83 :
84 : typedef struct _ByteRange {
85 : Guint offset;
86 : Guint length;
87 : } ByteRange;
88 :
89 : //------------------------------------------------------------------------
90 : // Stream (base class)
91 : //------------------------------------------------------------------------
92 :
93 : class Stream {
94 : public:
95 :
96 : // Constructor.
97 : Stream();
98 :
99 : // Destructor.
100 : virtual ~Stream();
101 :
102 : // Reference counting.
103 : int incRef();
104 : int decRef();
105 :
106 : // Get kind of stream.
107 : virtual StreamKind getKind() = 0;
108 :
109 : // Reset stream to beginning.
110 : virtual void reset() = 0;
111 :
112 : // Close down the stream.
113 : virtual void close();
114 :
115 1660 : inline int doGetChars(int nChars, Guchar *buffer)
116 : {
117 1660 : if (hasGetChars()) {
118 1644 : return getChars(nChars, buffer);
119 : } else {
120 1184 : for (int i = 0; i < nChars; ++i) {
121 592 : const int c = getChar();
122 592 : if (likely(c != EOF)) buffer[i] = c;
123 16 : else return i;
124 : }
125 0 : return nChars;
126 : }
127 : }
128 :
129 352 : inline void fillGooString(GooString *s)
130 : {
131 : Guchar readBuf[4096];
132 : int readChars;
133 352 : reset();
134 2012 : while ((readChars = doGetChars(4096, readBuf)) != 0) {
135 1308 : s->append((const char *)readBuf, readChars);
136 : }
137 352 : }
138 :
139 : inline Guchar *toUnsignedChars(int *length, int initialSize = 4096, int sizeIncrement = 4096)
140 : {
141 : int readChars;
142 : Guchar *buf = (Guchar *)gmalloc(initialSize);
143 : int size = initialSize;
144 : *length = 0;
145 : int charsToRead = initialSize;
146 : bool continueReading = true;
147 : reset();
148 : while (continueReading && (readChars = doGetChars(charsToRead, &buf[*length])) != 0) {
149 : *length += readChars;
150 : if (readChars == charsToRead) {
151 : if (lookChar() != EOF) {
152 : size += sizeIncrement;
153 : charsToRead = sizeIncrement;
154 : buf = (Guchar *)grealloc(buf, size);
155 : } else {
156 : continueReading = false;
157 : }
158 : } else {
159 : continueReading = false;
160 : }
161 : }
162 : return buf;
163 : }
164 :
165 : // Get next char from stream.
166 : virtual int getChar() = 0;
167 :
168 : // Peek at next char in stream.
169 : virtual int lookChar() = 0;
170 :
171 : // Get next char from stream without using the predictor.
172 : // This is only used by StreamPredictor.
173 : virtual int getRawChar();
174 : virtual void getRawChars(int nChars, int *buffer);
175 :
176 : // Get next char directly from stream source, without filtering it
177 : virtual int getUnfilteredChar () = 0;
178 :
179 : // Resets the stream without reading anything (even not the headers)
180 : // WARNING: Reading the stream with something else than getUnfilteredChar
181 : // may lead to unexcepted behaviour until you call reset ()
182 : virtual void unfilteredReset () = 0;
183 :
184 : // Get next line from stream.
185 : virtual char *getLine(char *buf, int size);
186 :
187 : // Get current position in file.
188 : virtual Goffset getPos() = 0;
189 :
190 : // Go to a position in the stream. If <dir> is negative, the
191 : // position is from the end of the file; otherwise the position is
192 : // from the start of the file.
193 : virtual void setPos(Goffset pos, int dir = 0) = 0;
194 :
195 : // Get PostScript command for the filter(s).
196 : virtual GooString *getPSFilter(int psLevel, const char *indent);
197 :
198 : // Does this stream type potentially contain non-printable chars?
199 : virtual GBool isBinary(GBool last = gTrue) = 0;
200 :
201 : // Get the BaseStream of this stream.
202 : virtual BaseStream *getBaseStream() = 0;
203 :
204 : // Get the stream after the last decoder (this may be a BaseStream
205 : // or a DecryptStream).
206 : virtual Stream *getUndecodedStream() = 0;
207 :
208 : // Get the dictionary associated with this stream.
209 : virtual Dict *getDict() = 0;
210 :
211 : // Is this an encoding filter?
212 0 : virtual GBool isEncoder() { return gFalse; }
213 :
214 : // Get image parameters which are defined by the stream contents.
215 2 : virtual void getImageParams(int * /*bitsPerComponent*/,
216 2 : StreamColorSpaceMode * /*csMode*/) {}
217 :
218 : // Return the next stream in the "stack".
219 0 : virtual Stream *getNextStream() { return NULL; }
220 :
221 : // Add filters to this stream according to the parameters in <dict>.
222 : // Returns the new stream.
223 : Stream *addFilters(Object *dict, int recursion = 0);
224 :
225 : private:
226 108 : virtual GBool hasGetChars() { return false; }
227 : virtual int getChars(int nChars, Guchar *buffer);
228 :
229 : Stream *makeFilter(char *name, Stream *str, Object *params, int recursion = 0);
230 :
231 : int ref; // reference count
232 : #if MULTITHREADED
233 : GooMutex mutex;
234 : #endif
235 : };
236 :
237 :
238 : //------------------------------------------------------------------------
239 : // OutStream
240 : //
241 : // This is the base class for all streams that output to a file
242 : //------------------------------------------------------------------------
243 : class OutStream {
244 : public:
245 : // Constructor.
246 : OutStream ();
247 :
248 : // Desctructor.
249 : virtual ~OutStream ();
250 :
251 : // Reference counting.
252 : int incRef() { return ++ref; }
253 : int decRef() { return --ref; }
254 :
255 : // Close the stream
256 : virtual void close() = 0;
257 :
258 : // Return position in stream
259 : virtual Goffset getPos() = 0;
260 :
261 : // Put a char in the stream
262 : virtual void put (char c) = 0;
263 :
264 : //FIXME
265 : // Printf-like function 2,3 because the first arg is class instance ?
266 : virtual void printf (const char *format, ...) = 0 ; //__attribute__((format(printf, 2,3))) = 0;
267 :
268 : private:
269 : int ref; // reference count
270 :
271 : };
272 :
273 : //------------------------------------------------------------------------
274 : // FileOutStream
275 : //------------------------------------------------------------------------
276 : class FileOutStream : public OutStream {
277 : public:
278 : FileOutStream (FILE* fa, Goffset startA);
279 :
280 : virtual ~FileOutStream ();
281 :
282 : virtual void close();
283 :
284 : virtual Goffset getPos();
285 :
286 : virtual void put (char c);
287 :
288 : virtual void printf (const char *format, ...);
289 : private:
290 : FILE *f;
291 : Goffset start;
292 :
293 : };
294 :
295 :
296 : //------------------------------------------------------------------------
297 : // BaseStream
298 : //
299 : // This is the base class for all streams that read directly from a file.
300 : //------------------------------------------------------------------------
301 :
302 : class BaseStream: public Stream {
303 : public:
304 :
305 : BaseStream(Object *dictA, Goffset lengthA);
306 : virtual ~BaseStream();
307 : virtual BaseStream *copy() = 0;
308 : virtual Stream *makeSubStream(Goffset start, GBool limited,
309 : Goffset length, Object *dict) = 0;
310 : virtual void setPos(Goffset pos, int dir = 0) = 0;
311 0 : virtual GBool isBinary(GBool last = gTrue) { return last; }
312 669 : virtual BaseStream *getBaseStream() { return this; }
313 0 : virtual Stream *getUndecodedStream() { return this; }
314 519 : virtual Dict *getDict() { return dict.getDict(); }
315 : virtual GooString *getFileName() { return NULL; }
316 1386 : virtual Goffset getLength() { return length; }
317 :
318 : // Get/set position of first byte of stream within the file.
319 : virtual Goffset getStart() = 0;
320 : virtual void moveStart(Goffset delta) = 0;
321 :
322 : protected:
323 :
324 : Goffset length;
325 : Object dict;
326 : };
327 :
328 : //------------------------------------------------------------------------
329 : // FilterStream
330 : //
331 : // This is the base class for all streams that filter another stream.
332 : //------------------------------------------------------------------------
333 :
334 : class FilterStream: public Stream {
335 : public:
336 :
337 : FilterStream(Stream *strA);
338 : virtual ~FilterStream();
339 : virtual void close();
340 : virtual Goffset getPos() { return str->getPos(); }
341 : virtual void setPos(Goffset pos, int dir = 0);
342 : virtual BaseStream *getBaseStream() { return str->getBaseStream(); }
343 : virtual Stream *getUndecodedStream() { return str->getUndecodedStream(); }
344 : virtual Dict *getDict() { return str->getDict(); }
345 : virtual Stream *getNextStream() { return str; }
346 :
347 : virtual int getUnfilteredChar () { return str->getUnfilteredChar(); }
348 : virtual void unfilteredReset () { str->unfilteredReset(); }
349 :
350 : protected:
351 :
352 : Stream *str;
353 : };
354 :
355 : //------------------------------------------------------------------------
356 : // ImageStream
357 : //------------------------------------------------------------------------
358 :
359 : class ImageStream {
360 : public:
361 :
362 : // Create an image stream object for an image with the specified
363 : // parameters. Note that these are the actual image parameters,
364 : // which may be different from the predictor parameters.
365 : ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA);
366 :
367 : ~ImageStream();
368 :
369 : // Reset the stream.
370 : void reset();
371 :
372 : // Close the stream previously reset
373 : void close();
374 :
375 : // Gets the next pixel from the stream. <pix> should be able to hold
376 : // at least nComps elements. Returns false at end of file.
377 : GBool getPixel(Guchar *pix);
378 :
379 : // Returns a pointer to the next line of pixels. Returns NULL at
380 : // end of file.
381 : Guchar *getLine();
382 :
383 : // Skip an entire line from the image.
384 : void skipLine();
385 :
386 : private:
387 :
388 : Stream *str; // base stream
389 : int width; // pixels per line
390 : int nComps; // components per pixel
391 : int nBits; // bits per component
392 : int nVals; // components per line
393 : int inputLineSize; // input line buffer size
394 : Guchar *inputLine; // input line buffer
395 : Guchar *imgLine; // line buffer
396 : int imgIdx; // current index in imgLine
397 : };
398 :
399 : //------------------------------------------------------------------------
400 : // StreamPredictor
401 : //------------------------------------------------------------------------
402 :
403 : class StreamPredictor {
404 : public:
405 :
406 : // Create a predictor object. Note that the parameters are for the
407 : // predictor, and may not match the actual image parameters.
408 : StreamPredictor(Stream *strA, int predictorA,
409 : int widthA, int nCompsA, int nBitsA);
410 :
411 : ~StreamPredictor();
412 :
413 : GBool isOk() { return ok; }
414 :
415 : int lookChar();
416 : int getChar();
417 : int getChars(int nChars, Guchar *buffer);
418 :
419 : private:
420 :
421 : GBool getNextLine();
422 :
423 : Stream *str; // base stream
424 : int predictor; // predictor
425 : int width; // pixels per line
426 : int nComps; // components per pixel
427 : int nBits; // bits per component
428 : int nVals; // components per line
429 : int pixBytes; // bytes per pixel
430 : int rowBytes; // bytes per line
431 : Guchar *predLine; // line buffer
432 : int predIdx; // current index in predLine
433 : GBool ok;
434 : };
435 :
436 : //------------------------------------------------------------------------
437 : // FileStream
438 : //------------------------------------------------------------------------
439 :
440 : #define fileStreamBufSize 256
441 :
442 : class FileStream: public BaseStream {
443 : public:
444 :
445 : FileStream(FILE *fA, char *fileName, Goffset startA, GBool limitedA,
446 : Goffset lengthA, Object *dictA);
447 : virtual ~FileStream();
448 : virtual BaseStream *copy();
449 : virtual Stream *makeSubStream(Goffset startA, GBool limitedA,
450 : Goffset lengthA, Object *dictA);
451 : virtual StreamKind getKind() { return strFile; }
452 : virtual void reset();
453 : virtual void close();
454 : virtual int getChar()
455 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
456 : virtual int lookChar()
457 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
458 : virtual Goffset getPos() { return bufPos + (bufPtr - buf); }
459 : virtual void setPos(Goffset pos, int dir = 0);
460 : virtual Goffset getStart() { return start; }
461 : virtual void moveStart(Goffset delta);
462 :
463 : virtual int getUnfilteredChar () { return getChar(); }
464 : virtual void unfilteredReset () { reset(); }
465 :
466 : private:
467 :
468 : GBool fillBuf();
469 :
470 : virtual GBool hasGetChars() { return true; }
471 : virtual int getChars(int nChars, Guchar *buffer)
472 : {
473 : int n, m;
474 :
475 : n = 0;
476 : while (n < nChars) {
477 : if (bufPtr >= bufEnd) {
478 : if (!fillBuf()) {
479 : break;
480 : }
481 : }
482 : m = (int)(bufEnd - bufPtr);
483 : if (m > nChars - n) {
484 : m = nChars - n;
485 : }
486 : memcpy(buffer + n, bufPtr, m);
487 : bufPtr += m;
488 : n += m;
489 : }
490 : return n;
491 : }
492 :
493 : protected:
494 : FILE *f;
495 : char *fileName;
496 : private:
497 : Goffset start;
498 : GBool limited;
499 : char buf[fileStreamBufSize];
500 : char *bufPtr;
501 : char *bufEnd;
502 : Goffset bufPos;
503 : Goffset savePos;
504 : GBool saved;
505 : };
506 :
507 : class UniqueFileStream: public FileStream {
508 : public:
509 :
510 : UniqueFileStream(FILE *fA, char *fileNameA, Goffset startA, GBool limitedA,
511 : Goffset lengthA, Object *dictA);
512 : virtual ~UniqueFileStream();
513 : };
514 :
515 : //------------------------------------------------------------------------
516 : // CachedFileStream
517 : //------------------------------------------------------------------------
518 :
519 : #define cachedStreamBufSize 1024
520 :
521 : class CachedFileStream: public BaseStream {
522 : public:
523 :
524 : CachedFileStream(CachedFile *ccA, Goffset startA, GBool limitedA,
525 : Goffset lengthA, Object *dictA);
526 : virtual ~CachedFileStream();
527 : virtual BaseStream *copy();
528 : virtual Stream *makeSubStream(Goffset startA, GBool limitedA,
529 : Goffset lengthA, Object *dictA);
530 : virtual StreamKind getKind() { return strCachedFile; }
531 : virtual void reset();
532 : virtual void close();
533 : virtual int getChar()
534 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
535 : virtual int lookChar()
536 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
537 : virtual Goffset getPos() { return bufPos + (bufPtr - buf); }
538 : virtual void setPos(Goffset pos, int dir = 0);
539 : virtual Goffset getStart() { return start; }
540 : virtual void moveStart(Goffset delta);
541 :
542 : virtual int getUnfilteredChar () { return getChar(); }
543 : virtual void unfilteredReset () { reset(); }
544 :
545 : private:
546 :
547 : GBool fillBuf();
548 :
549 : CachedFile *cc;
550 : Goffset start;
551 : GBool limited;
552 : char buf[cachedStreamBufSize];
553 : char *bufPtr;
554 : char *bufEnd;
555 : Guint bufPos;
556 : int savePos;
557 : GBool saved;
558 : };
559 :
560 :
561 : //------------------------------------------------------------------------
562 : // MemStream
563 : //------------------------------------------------------------------------
564 :
565 : class MemStream: public BaseStream {
566 : public:
567 :
568 : MemStream(char *bufA, Goffset startA, Goffset lengthA, Object *dictA);
569 : virtual ~MemStream();
570 : virtual BaseStream *copy();
571 : virtual Stream *makeSubStream(Goffset start, GBool limited,
572 : Goffset lengthA, Object *dictA);
573 : virtual StreamKind getKind() { return strWeird; }
574 : virtual void reset();
575 : virtual void close();
576 : virtual int getChar()
577 : { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; }
578 : virtual int lookChar()
579 : { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; }
580 : virtual Goffset getPos() { return (int)(bufPtr - buf); }
581 : virtual void setPos(Goffset pos, int dir = 0);
582 : virtual Goffset getStart() { return start; }
583 : virtual void moveStart(Goffset delta);
584 :
585 : //if needFree = true, the stream will delete buf when it is destroyed
586 : //otherwise it will not touch it. Default value is false
587 : virtual void setNeedFree (GBool val) { needFree = val; }
588 :
589 : virtual int getUnfilteredChar () { return getChar(); }
590 : virtual void unfilteredReset () { reset (); }
591 :
592 : private:
593 :
594 : virtual GBool hasGetChars() { return true; }
595 : virtual int getChars(int nChars, Guchar *buffer);
596 :
597 : char *buf;
598 : Goffset start;
599 : char *bufEnd;
600 : char *bufPtr;
601 : GBool needFree;
602 : };
603 :
604 : //------------------------------------------------------------------------
605 : // EmbedStream
606 : //
607 : // This is a special stream type used for embedded streams (inline
608 : // images). It reads directly from the base stream -- after the
609 : // EmbedStream is deleted, reads from the base stream will proceed where
610 : // the BaseStream left off. Note that this is very different behavior
611 : // that creating a new FileStream (using makeSubStream).
612 : //------------------------------------------------------------------------
613 :
614 : class EmbedStream: public BaseStream {
615 : public:
616 :
617 : EmbedStream(Stream *strA, Object *dictA, GBool limitedA, Goffset lengthA);
618 : virtual ~EmbedStream();
619 : virtual BaseStream *copy();
620 : virtual Stream *makeSubStream(Goffset start, GBool limitedA,
621 : Goffset lengthA, Object *dictA);
622 : virtual StreamKind getKind() { return str->getKind(); }
623 : virtual void reset() {}
624 : virtual int getChar();
625 : virtual int lookChar();
626 : virtual Goffset getPos() { return str->getPos(); }
627 : virtual void setPos(Goffset pos, int dir = 0);
628 : virtual Goffset getStart();
629 : virtual void moveStart(Goffset delta);
630 :
631 : virtual int getUnfilteredChar () { return str->getUnfilteredChar(); }
632 : virtual void unfilteredReset () { str->unfilteredReset(); }
633 :
634 :
635 : private:
636 :
637 : virtual GBool hasGetChars() { return true; }
638 : virtual int getChars(int nChars, Guchar *buffer);
639 :
640 : Stream *str;
641 : GBool limited;
642 : };
643 :
644 : //------------------------------------------------------------------------
645 : // ASCIIHexStream
646 : //------------------------------------------------------------------------
647 :
648 : class ASCIIHexStream: public FilterStream {
649 : public:
650 :
651 : ASCIIHexStream(Stream *strA);
652 : virtual ~ASCIIHexStream();
653 : virtual StreamKind getKind() { return strASCIIHex; }
654 : virtual void reset();
655 : virtual int getChar()
656 : { int c = lookChar(); buf = EOF; return c; }
657 : virtual int lookChar();
658 : virtual GooString *getPSFilter(int psLevel, const char *indent);
659 : virtual GBool isBinary(GBool last = gTrue);
660 :
661 : private:
662 :
663 : int buf;
664 : GBool eof;
665 : };
666 :
667 : //------------------------------------------------------------------------
668 : // ASCII85Stream
669 : //------------------------------------------------------------------------
670 :
671 : class ASCII85Stream: public FilterStream {
672 : public:
673 :
674 : ASCII85Stream(Stream *strA);
675 : virtual ~ASCII85Stream();
676 : virtual StreamKind getKind() { return strASCII85; }
677 : virtual void reset();
678 : virtual int getChar()
679 : { int ch = lookChar(); ++index; return ch; }
680 : virtual int lookChar();
681 : virtual GooString *getPSFilter(int psLevel, const char *indent);
682 : virtual GBool isBinary(GBool last = gTrue);
683 :
684 : private:
685 :
686 : int c[5];
687 : int b[4];
688 : int index, n;
689 : GBool eof;
690 : };
691 :
692 : //------------------------------------------------------------------------
693 : // LZWStream
694 : //------------------------------------------------------------------------
695 :
696 : class LZWStream: public FilterStream {
697 : public:
698 :
699 : LZWStream(Stream *strA, int predictor, int columns, int colors,
700 : int bits, int earlyA);
701 : virtual ~LZWStream();
702 : virtual StreamKind getKind() { return strLZW; }
703 : virtual void reset();
704 : virtual int getChar();
705 : virtual int lookChar();
706 : virtual int getRawChar();
707 : virtual void getRawChars(int nChars, int *buffer);
708 : virtual GooString *getPSFilter(int psLevel, const char *indent);
709 : virtual GBool isBinary(GBool last = gTrue);
710 :
711 : private:
712 :
713 : virtual GBool hasGetChars() { return true; }
714 : virtual int getChars(int nChars, Guchar *buffer);
715 :
716 : inline int doGetRawChar() {
717 : if (eof) {
718 : return EOF;
719 : }
720 : if (seqIndex >= seqLength) {
721 : if (!processNextCode()) {
722 : return EOF;
723 : }
724 : }
725 : return seqBuf[seqIndex++];
726 : }
727 :
728 : StreamPredictor *pred; // predictor
729 : int early; // early parameter
730 : GBool eof; // true if at eof
731 : int inputBuf; // input buffer
732 : int inputBits; // number of bits in input buffer
733 : struct { // decoding table
734 : int length;
735 : int head;
736 : Guchar tail;
737 : } table[4097];
738 : int nextCode; // next code to be used
739 : int nextBits; // number of bits in next code word
740 : int prevCode; // previous code used in stream
741 : int newChar; // next char to be added to table
742 : Guchar seqBuf[4097]; // buffer for current sequence
743 : int seqLength; // length of current sequence
744 : int seqIndex; // index into current sequence
745 : GBool first; // first code after a table clear
746 :
747 : GBool processNextCode();
748 : void clearTable();
749 : int getCode();
750 : };
751 :
752 : //------------------------------------------------------------------------
753 : // RunLengthStream
754 : //------------------------------------------------------------------------
755 :
756 : class RunLengthStream: public FilterStream {
757 : public:
758 :
759 : RunLengthStream(Stream *strA);
760 : virtual ~RunLengthStream();
761 : virtual StreamKind getKind() { return strRunLength; }
762 : virtual void reset();
763 : virtual int getChar()
764 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
765 : virtual int lookChar()
766 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
767 : virtual GooString *getPSFilter(int psLevel, const char *indent);
768 : virtual GBool isBinary(GBool last = gTrue);
769 :
770 : private:
771 :
772 : virtual GBool hasGetChars() { return true; }
773 : virtual int getChars(int nChars, Guchar *buffer);
774 :
775 : char buf[128]; // buffer
776 : char *bufPtr; // next char to read
777 : char *bufEnd; // end of buffer
778 : GBool eof;
779 :
780 : GBool fillBuf();
781 : };
782 :
783 : //------------------------------------------------------------------------
784 : // CCITTFaxStream
785 : //------------------------------------------------------------------------
786 :
787 : struct CCITTCodeTable;
788 :
789 : class CCITTFaxStream: public FilterStream {
790 : public:
791 :
792 : CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
793 : GBool byteAlignA, int columnsA, int rowsA,
794 : GBool endOfBlockA, GBool blackA);
795 : virtual ~CCITTFaxStream();
796 : virtual StreamKind getKind() { return strCCITTFax; }
797 : virtual void reset();
798 : virtual int getChar()
799 : { int c = lookChar(); buf = EOF; return c; }
800 : virtual int lookChar();
801 : virtual GooString *getPSFilter(int psLevel, const char *indent);
802 : virtual GBool isBinary(GBool last = gTrue);
803 :
804 : virtual void unfilteredReset ();
805 :
806 : private:
807 :
808 : void ccittReset(GBool unfiltered);
809 : int encoding; // 'K' parameter
810 : GBool endOfLine; // 'EndOfLine' parameter
811 : GBool byteAlign; // 'EncodedByteAlign' parameter
812 : int columns; // 'Columns' parameter
813 : int rows; // 'Rows' parameter
814 : GBool endOfBlock; // 'EndOfBlock' parameter
815 : GBool black; // 'BlackIs1' parameter
816 : GBool eof; // true if at eof
817 : GBool nextLine2D; // true if next line uses 2D encoding
818 : int row; // current row
819 : Guint inputBuf; // input buffer
820 : int inputBits; // number of bits in input buffer
821 : int *codingLine; // coding line changing elements
822 : int *refLine; // reference line changing elements
823 : int a0i; // index into codingLine
824 : GBool err; // error on current line
825 : int outputBits; // remaining ouput bits
826 : int buf; // character buffer
827 :
828 : void addPixels(int a1, int blackPixels);
829 : void addPixelsNeg(int a1, int blackPixels);
830 : short getTwoDimCode();
831 : short getWhiteCode();
832 : short getBlackCode();
833 : short lookBits(int n);
834 : void eatBits(int n) { if ((inputBits -= n) < 0) inputBits = 0; }
835 : };
836 :
837 : #ifndef ENABLE_LIBJPEG
838 : //------------------------------------------------------------------------
839 : // DCTStream
840 : //------------------------------------------------------------------------
841 :
842 : // DCT component info
843 : struct DCTCompInfo {
844 : int id; // component ID
845 : int hSample, vSample; // horiz/vert sampling resolutions
846 : int quantTable; // quantization table number
847 : int prevDC; // DC coefficient accumulator
848 : };
849 :
850 : struct DCTScanInfo {
851 : GBool comp[4]; // comp[i] is set if component i is
852 : // included in this scan
853 : int numComps; // number of components in the scan
854 : int dcHuffTable[4]; // DC Huffman table numbers
855 : int acHuffTable[4]; // AC Huffman table numbers
856 : int firstCoeff, lastCoeff; // first and last DCT coefficient
857 : int ah, al; // successive approximation parameters
858 : };
859 :
860 : // DCT Huffman decoding table
861 : struct DCTHuffTable {
862 : Guchar firstSym[17]; // first symbol for this bit length
863 : Gushort firstCode[17]; // first code for this bit length
864 : Gushort numCodes[17]; // number of codes of this bit length
865 : Guchar sym[256]; // symbols
866 : };
867 :
868 : class DCTStream: public FilterStream {
869 : public:
870 :
871 : DCTStream(Stream *strA, int colorXformA);
872 : virtual ~DCTStream();
873 : virtual StreamKind getKind() { return strDCT; }
874 : virtual void reset();
875 : virtual void close();
876 : virtual int getChar();
877 : virtual int lookChar();
878 : virtual GooString *getPSFilter(int psLevel, const char *indent);
879 : virtual GBool isBinary(GBool last = gTrue);
880 :
881 : virtual void unfilteredReset();
882 :
883 : private:
884 :
885 : void dctReset(GBool unfiltered);
886 : GBool progressive; // set if in progressive mode
887 : GBool interleaved; // set if in interleaved mode
888 : int width, height; // image size
889 : int mcuWidth, mcuHeight; // size of min coding unit, in data units
890 : int bufWidth, bufHeight; // frameBuf size
891 : DCTCompInfo compInfo[4]; // info for each component
892 : DCTScanInfo scanInfo; // info for the current scan
893 : int numComps; // number of components in image
894 : int colorXform; // color transform: -1 = unspecified
895 : // 0 = none
896 : // 1 = YUV/YUVK -> RGB/CMYK
897 : GBool gotJFIFMarker; // set if APP0 JFIF marker was present
898 : GBool gotAdobeMarker; // set if APP14 Adobe marker was present
899 : int restartInterval; // restart interval, in MCUs
900 : Gushort quantTables[4][64]; // quantization tables
901 : int numQuantTables; // number of quantization tables
902 : DCTHuffTable dcHuffTables[4]; // DC Huffman tables
903 : DCTHuffTable acHuffTables[4]; // AC Huffman tables
904 : int numDCHuffTables; // number of DC Huffman tables
905 : int numACHuffTables; // number of AC Huffman tables
906 : Guchar *rowBuf[4][32]; // buffer for one MCU (non-progressive mode)
907 : int *frameBuf[4]; // buffer for frame (progressive mode)
908 : int comp, x, y, dy; // current position within image/MCU
909 : int restartCtr; // MCUs left until restart
910 : int restartMarker; // next restart marker
911 : int eobRun; // number of EOBs left in the current run
912 : int inputBuf; // input buffer for variable length codes
913 : int inputBits; // number of valid bits in input buffer
914 :
915 : void restart();
916 : GBool readMCURow();
917 : void readScan();
918 : GBool readDataUnit(DCTHuffTable *dcHuffTable,
919 : DCTHuffTable *acHuffTable,
920 : int *prevDC, int data[64]);
921 : GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
922 : DCTHuffTable *acHuffTable,
923 : int *prevDC, int data[64]);
924 : void decodeImage();
925 : void transformDataUnit(Gushort *quantTable,
926 : int dataIn[64], Guchar dataOut[64]);
927 : int readHuffSym(DCTHuffTable *table);
928 : int readAmp(int size);
929 : int readBit();
930 : GBool readHeader();
931 : GBool readBaselineSOF();
932 : GBool readProgressiveSOF();
933 : GBool readScanInfo();
934 : GBool readQuantTables();
935 : GBool readHuffmanTables();
936 : GBool readRestartInterval();
937 : GBool readJFIFMarker();
938 : GBool readAdobeMarker();
939 : GBool readTrailer();
940 : int readMarker();
941 : int read16();
942 : };
943 :
944 : #endif
945 :
946 : #ifndef ENABLE_ZLIB
947 : //------------------------------------------------------------------------
948 : // FlateStream
949 : //------------------------------------------------------------------------
950 :
951 : #define flateWindow 32768 // buffer size
952 : #define flateMask (flateWindow-1)
953 : #define flateMaxHuffman 15 // max Huffman code length
954 : #define flateMaxCodeLenCodes 19 // max # code length codes
955 : #define flateMaxLitCodes 288 // max # literal codes
956 : #define flateMaxDistCodes 30 // max # distance codes
957 :
958 : // Huffman code table entry
959 : struct FlateCode {
960 : Gushort len; // code length, in bits
961 : Gushort val; // value represented by this code
962 : };
963 :
964 : struct FlateHuffmanTab {
965 : FlateCode *codes;
966 : int maxLen;
967 : };
968 :
969 : // Decoding info for length and distance code words
970 : struct FlateDecode {
971 : int bits; // # extra bits
972 : int first; // first length/distance
973 : };
974 :
975 : class FlateStream: public FilterStream {
976 : public:
977 :
978 : FlateStream(Stream *strA, int predictor, int columns,
979 : int colors, int bits);
980 : virtual ~FlateStream();
981 : virtual StreamKind getKind() { return strFlate; }
982 : virtual void reset();
983 : virtual int getChar();
984 : virtual int lookChar();
985 : virtual int getRawChar();
986 : virtual void getRawChars(int nChars, int *buffer);
987 : virtual GooString *getPSFilter(int psLevel, const char *indent);
988 : virtual GBool isBinary(GBool last = gTrue);
989 : virtual void unfilteredReset ();
990 :
991 : private:
992 : void flateReset(GBool unfiltered);
993 : inline int doGetRawChar() {
994 : int c;
995 :
996 : while (remain == 0) {
997 : if (endOfBlock && eof)
998 : return EOF;
999 : readSome();
1000 : }
1001 : c = buf[index];
1002 : index = (index + 1) & flateMask;
1003 : --remain;
1004 : return c;
1005 : }
1006 :
1007 : virtual GBool hasGetChars() { return true; }
1008 : virtual int getChars(int nChars, Guchar *buffer);
1009 :
1010 : StreamPredictor *pred; // predictor
1011 : Guchar buf[flateWindow]; // output data buffer
1012 : int index; // current index into output buffer
1013 : int remain; // number valid bytes in output buffer
1014 : int codeBuf; // input buffer
1015 : int codeSize; // number of bits in input buffer
1016 : int // literal and distance code lengths
1017 : codeLengths[flateMaxLitCodes + flateMaxDistCodes];
1018 : FlateHuffmanTab litCodeTab; // literal code table
1019 : FlateHuffmanTab distCodeTab; // distance code table
1020 : GBool compressedBlock; // set if reading a compressed block
1021 : int blockLen; // remaining length of uncompressed block
1022 : GBool endOfBlock; // set when end of block is reached
1023 : GBool eof; // set when end of stream is reached
1024 :
1025 : static int // code length code reordering
1026 : codeLenCodeMap[flateMaxCodeLenCodes];
1027 : static FlateDecode // length decoding info
1028 : lengthDecode[flateMaxLitCodes-257];
1029 : static FlateDecode // distance decoding info
1030 : distDecode[flateMaxDistCodes];
1031 : static FlateHuffmanTab // fixed literal code table
1032 : fixedLitCodeTab;
1033 : static FlateHuffmanTab // fixed distance code table
1034 : fixedDistCodeTab;
1035 :
1036 : void readSome();
1037 : GBool startBlock();
1038 : void loadFixedCodes();
1039 : GBool readDynamicCodes();
1040 : void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab);
1041 : int getHuffmanCodeWord(FlateHuffmanTab *tab);
1042 : int getCodeWord(int bits);
1043 : };
1044 : #endif
1045 :
1046 : //------------------------------------------------------------------------
1047 : // EOFStream
1048 : //------------------------------------------------------------------------
1049 :
1050 : class EOFStream: public FilterStream {
1051 : public:
1052 :
1053 : EOFStream(Stream *strA);
1054 : virtual ~EOFStream();
1055 : virtual StreamKind getKind() { return strWeird; }
1056 : virtual void reset() {}
1057 : virtual int getChar() { return EOF; }
1058 : virtual int lookChar() { return EOF; }
1059 : virtual GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) { return NULL; }
1060 : virtual GBool isBinary(GBool /*last = gTrue*/) { return gFalse; }
1061 : };
1062 :
1063 : //------------------------------------------------------------------------
1064 : // BufStream
1065 : //------------------------------------------------------------------------
1066 :
1067 : class BufStream: public FilterStream {
1068 : public:
1069 :
1070 : BufStream(Stream *strA, int bufSizeA);
1071 : virtual ~BufStream();
1072 : virtual StreamKind getKind() { return strWeird; }
1073 : virtual void reset();
1074 : virtual int getChar();
1075 : virtual int lookChar();
1076 : virtual GooString *getPSFilter(int psLevel, const char *indent)
1077 : { return NULL; }
1078 : virtual GBool isBinary(GBool last = gTrue);
1079 :
1080 : int lookChar(int idx);
1081 :
1082 : private:
1083 :
1084 : int *buf;
1085 : int bufSize;
1086 : };
1087 :
1088 : //------------------------------------------------------------------------
1089 : // FixedLengthEncoder
1090 : //------------------------------------------------------------------------
1091 :
1092 : class FixedLengthEncoder: public FilterStream {
1093 : public:
1094 :
1095 : FixedLengthEncoder(Stream *strA, int lengthA);
1096 : ~FixedLengthEncoder();
1097 : virtual StreamKind getKind() { return strWeird; }
1098 : virtual void reset();
1099 : virtual int getChar();
1100 : virtual int lookChar();
1101 : virtual GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) { return NULL; }
1102 : virtual GBool isBinary(GBool /*last = gTrue*/);
1103 : virtual GBool isEncoder() { return gTrue; }
1104 :
1105 : private:
1106 :
1107 : int length;
1108 : int count;
1109 : };
1110 :
1111 : //------------------------------------------------------------------------
1112 : // ASCIIHexEncoder
1113 : //------------------------------------------------------------------------
1114 :
1115 : class ASCIIHexEncoder: public FilterStream {
1116 : public:
1117 :
1118 : ASCIIHexEncoder(Stream *strA);
1119 : virtual ~ASCIIHexEncoder();
1120 : virtual StreamKind getKind() { return strWeird; }
1121 : virtual void reset();
1122 : virtual int getChar()
1123 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
1124 : virtual int lookChar()
1125 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
1126 : virtual GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) { return NULL; }
1127 : virtual GBool isBinary(GBool /*last = gTrue*/) { return gFalse; }
1128 : virtual GBool isEncoder() { return gTrue; }
1129 :
1130 : private:
1131 :
1132 : char buf[4];
1133 : char *bufPtr;
1134 : char *bufEnd;
1135 : int lineLen;
1136 : GBool eof;
1137 :
1138 : GBool fillBuf();
1139 : };
1140 :
1141 : //------------------------------------------------------------------------
1142 : // ASCII85Encoder
1143 : //------------------------------------------------------------------------
1144 :
1145 : class ASCII85Encoder: public FilterStream {
1146 : public:
1147 :
1148 : ASCII85Encoder(Stream *strA);
1149 : virtual ~ASCII85Encoder();
1150 : virtual StreamKind getKind() { return strWeird; }
1151 : virtual void reset();
1152 : virtual int getChar()
1153 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
1154 : virtual int lookChar()
1155 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
1156 : virtual GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) { return NULL; }
1157 : virtual GBool isBinary(GBool /*last = gTrue*/) { return gFalse; }
1158 : virtual GBool isEncoder() { return gTrue; }
1159 :
1160 : private:
1161 :
1162 : char buf[8];
1163 : char *bufPtr;
1164 : char *bufEnd;
1165 : int lineLen;
1166 : GBool eof;
1167 :
1168 : GBool fillBuf();
1169 : };
1170 :
1171 : //------------------------------------------------------------------------
1172 : // RunLengthEncoder
1173 : //------------------------------------------------------------------------
1174 :
1175 : class RunLengthEncoder: public FilterStream {
1176 : public:
1177 :
1178 : RunLengthEncoder(Stream *strA);
1179 : virtual ~RunLengthEncoder();
1180 : virtual StreamKind getKind() { return strWeird; }
1181 : virtual void reset();
1182 : virtual int getChar()
1183 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
1184 : virtual int lookChar()
1185 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
1186 : virtual GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) { return NULL; }
1187 : virtual GBool isBinary(GBool /*last = gTrue*/) { return gTrue; }
1188 : virtual GBool isEncoder() { return gTrue; }
1189 :
1190 : private:
1191 :
1192 : char buf[131];
1193 : char *bufPtr;
1194 : char *bufEnd;
1195 : char *nextEnd;
1196 : GBool eof;
1197 :
1198 : GBool fillBuf();
1199 : };
1200 :
1201 : //------------------------------------------------------------------------
1202 : // CMYKGrayEncoder
1203 : //------------------------------------------------------------------------
1204 :
1205 : class CMYKGrayEncoder: public FilterStream {
1206 : public:
1207 :
1208 : CMYKGrayEncoder(Stream *strA);
1209 : virtual ~CMYKGrayEncoder();
1210 : virtual StreamKind getKind() { return strWeird; }
1211 : virtual void reset();
1212 : virtual int getChar()
1213 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
1214 : virtual int lookChar()
1215 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
1216 : virtual GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) { return NULL; }
1217 : virtual GBool isBinary(GBool /*last = gTrue*/) { return gFalse; }
1218 : virtual GBool isEncoder() { return gTrue; }
1219 :
1220 : private:
1221 :
1222 : char buf[2];
1223 : char *bufPtr;
1224 : char *bufEnd;
1225 : GBool eof;
1226 :
1227 : GBool fillBuf();
1228 : };
1229 :
1230 : //------------------------------------------------------------------------
1231 : // RGBGrayEncoder
1232 : //------------------------------------------------------------------------
1233 :
1234 : class RGBGrayEncoder: public FilterStream {
1235 : public:
1236 :
1237 : RGBGrayEncoder(Stream *strA);
1238 : virtual ~RGBGrayEncoder();
1239 : virtual StreamKind getKind() { return strWeird; }
1240 : virtual void reset();
1241 : virtual int getChar()
1242 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
1243 : virtual int lookChar()
1244 : { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
1245 : virtual GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) { return NULL; }
1246 : virtual GBool isBinary(GBool /*last = gTrue*/) { return gFalse; }
1247 : virtual GBool isEncoder() { return gTrue; }
1248 :
1249 : private:
1250 :
1251 : char buf[2];
1252 : char *bufPtr;
1253 : char *bufEnd;
1254 : GBool eof;
1255 :
1256 : GBool fillBuf();
1257 : };
1258 :
1259 : #endif
|