1 //========================================================================
5 // Copyright 1996-2003 Glyph & Cog, LLC
7 //========================================================================
9 //========================================================================
11 // Modified under the Poppler project - http://poppler.freedesktop.org
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
16 // Copyright (C) 2005 Jeff Muizelaar <jeff@infidigm.net>
17 // Copyright (C) 2006-2010, 2012-2014 Albert Astals Cid <aacid@kde.org>
18 // Copyright (C) 2007 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
19 // Copyright (C) 2008 Julien Rebetez <julien@fhtagn.net>
20 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
21 // Copyright (C) 2009 Glenn Ganz <glenn.ganz@uptime.ch>
22 // Copyright (C) 2009 Stefan Thomas <thomas@eload24.com>
23 // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
24 // Copyright (C) 2010 Tomas Hoger <thoger@redhat.com>
25 // Copyright (C) 2011, 2012 William Bader <williambader@hotmail.com>
26 // Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
27 // Copyright (C) 2012 Oliver Sander <sander@mi.fu-berlin.de>
28 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
29 // Copyright (C) 2012 Even Rouault <even.rouault@mines-paris.org>
30 // Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
31 // Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
32 // Copyright (C) 2013 Pino Toscano <pino@kde.org>
33 // Copyright (C) 2015 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
34 // Copyright (C) 2015 Jason Crain <jason@aquaticape.us>
36 // To see a description of the changes please see the Changelog file that
37 // came with your tarball or type make ChangeLog if you are building from git
39 //========================================================================
43 #ifdef USE_GCC_PRAGMAS
44 #pragma implementation
57 #include "goo/gfile.h"
58 #include "poppler-config.h"
65 #include "JBIG2Stream.h"
66 #include "Stream-CCITT.h"
67 #include "CachedFile.h"
70 #include "DCTStream.h"
74 #include "FlateStream.h"
77 #ifdef ENABLE_LIBOPENJPEG
78 #include "JPEG2000Stream.h"
80 #include "JPXStream.h"
84 static GBool setDJSYSFLAGS
= gFalse
;
96 # define streamLocker() MutexLocker locker(&mutex)
98 # define streamLocker()
100 //------------------------------------------------------------------------
101 // Stream (base class)
102 //------------------------------------------------------------------------
113 gDestroyMutex(&mutex
);
117 int Stream::incRef() {
123 int Stream::decRef() {
129 void Stream::close() {
132 int Stream::getRawChar() {
133 error(errInternal
, -1, "Internal: called getRawChar() on non-predictor stream");
137 int Stream::getChars(int nChars
, Guchar
*buffer
) {
138 error(errInternal
, -1, "Internal: called getChars() on non-predictor stream");
142 void Stream::getRawChars(int nChars
, int *buffer
) {
143 error(errInternal
, -1, "Internal: called getRawChars() on non-predictor stream");
146 char *Stream::getLine(char *buf
, int size
) {
150 if (lookChar() == EOF
|| size
< 0)
152 for (i
= 0; i
< size
- 1; ++i
) {
154 if (c
== EOF
|| c
== '\n')
157 if ((c
= lookChar()) == '\n')
167 GooString
*Stream::getPSFilter(int psLevel
, const char *indent
) {
168 return new GooString();
171 Stream
*Stream::addFilters(Object
*dict
, int recursion
) {
173 Object params
, params2
;
178 dict
->dictLookup("Filter", &obj
, recursion
);
181 dict
->dictLookup("F", &obj
);
183 dict
->dictLookup("DecodeParms", ¶ms
, recursion
);
184 if (params
.isNull()) {
186 dict
->dictLookup("DP", ¶ms
);
189 str
= makeFilter(obj
.getName(), str
, ¶ms
, recursion
, dict
);
190 } else if (obj
.isArray()) {
191 for (i
= 0; i
< obj
.arrayGetLength(); ++i
) {
192 obj
.arrayGet(i
, &obj2
, recursion
);
193 if (params
.isArray())
194 params
.arrayGet(i
, ¶ms2
, recursion
);
198 str
= makeFilter(obj2
.getName(), str
, ¶ms2
, recursion
);
200 error(errSyntaxError
, getPos(), "Bad filter name");
201 str
= new EOFStream(str
);
206 } else if (!obj
.isNull()) {
207 error(errSyntaxError
, getPos(), "Bad 'Filter' attribute in stream");
215 Stream
*Stream::makeFilter(char *name
, Stream
*str
, Object
*params
, int recursion
, Object
*dict
) {
216 int pred
; // parameters
221 GBool endOfLine
, byteAlign
, endOfBlock
, black
;
226 if (!strcmp(name
, "ASCIIHexDecode") || !strcmp(name
, "AHx")) {
227 str
= new ASCIIHexStream(str
);
228 } else if (!strcmp(name
, "ASCII85Decode") || !strcmp(name
, "A85")) {
229 str
= new ASCII85Stream(str
);
230 } else if (!strcmp(name
, "LZWDecode") || !strcmp(name
, "LZW")) {
236 if (params
->isDict()) {
237 params
->dictLookup("Predictor", &obj
, recursion
);
241 params
->dictLookup("Columns", &obj
, recursion
);
243 columns
= obj
.getInt();
245 params
->dictLookup("Colors", &obj
, recursion
);
247 colors
= obj
.getInt();
249 params
->dictLookup("BitsPerComponent", &obj
, recursion
);
253 params
->dictLookup("EarlyChange", &obj
, recursion
);
255 early
= obj
.getInt();
258 str
= new LZWStream(str
, pred
, columns
, colors
, bits
, early
);
259 } else if (!strcmp(name
, "RunLengthDecode") || !strcmp(name
, "RL")) {
260 str
= new RunLengthStream(str
);
261 } else if (!strcmp(name
, "CCITTFaxDecode") || !strcmp(name
, "CCF")) {
269 if (params
->isDict()) {
270 params
->dictLookup("K", &obj
, recursion
);
272 encoding
= obj
.getInt();
275 params
->dictLookup("EndOfLine", &obj
, recursion
);
277 endOfLine
= obj
.getBool();
280 params
->dictLookup("EncodedByteAlign", &obj
, recursion
);
282 byteAlign
= obj
.getBool();
285 params
->dictLookup("Columns", &obj
, recursion
);
287 columns
= obj
.getInt();
290 params
->dictLookup("Rows", &obj
, recursion
);
295 params
->dictLookup("EndOfBlock", &obj
, recursion
);
297 endOfBlock
= obj
.getBool();
300 params
->dictLookup("BlackIs1", &obj
, recursion
);
302 black
= obj
.getBool();
306 str
= new CCITTFaxStream(str
, encoding
, endOfLine
, byteAlign
,
307 columns
, rows
, endOfBlock
, black
);
308 } else if (!strcmp(name
, "DCTDecode") || !strcmp(name
, "DCT")) {
310 if (params
->isDict()) {
311 if (params
->dictLookup("ColorTransform", &obj
, recursion
)->isInt()) {
312 colorXform
= obj
.getInt();
316 str
= new DCTStream(str
, colorXform
, dict
, recursion
);
317 } else if (!strcmp(name
, "FlateDecode") || !strcmp(name
, "Fl")) {
322 if (params
->isDict()) {
323 params
->dictLookup("Predictor", &obj
, recursion
);
327 params
->dictLookup("Columns", &obj
, recursion
);
329 columns
= obj
.getInt();
331 params
->dictLookup("Colors", &obj
, recursion
);
333 colors
= obj
.getInt();
335 params
->dictLookup("BitsPerComponent", &obj
, recursion
);
340 str
= new FlateStream(str
, pred
, columns
, colors
, bits
);
341 } else if (!strcmp(name
, "JBIG2Decode")) {
342 if (params
->isDict()) {
343 XRef
*xref
= params
->getDict()->getXRef();
344 params
->dictLookupNF("JBIG2Globals", &obj
);
345 obj
.fetch(xref
, &globals
, recursion
);
347 str
= new JBIG2Stream(str
, &globals
, &obj
);
350 } else if (!strcmp(name
, "JPXDecode")) {
351 str
= new JPXStream(str
);
352 } else if (!strcmp(name
, "Crypt")) {
353 if (str
->getKind() == strCrypt
) {
354 str
= str
->getBaseStream();
356 error(errSyntaxError
, getPos(), "Can't revert non decrypt streams");
359 error(errSyntaxError
, getPos(), "Unknown filter '{0:s}'", name
);
360 str
= new EOFStream(str
);
365 //------------------------------------------------------------------------
367 //------------------------------------------------------------------------
368 OutStream::OutStream ()
373 OutStream::~OutStream ()
377 //------------------------------------------------------------------------
379 //------------------------------------------------------------------------
380 FileOutStream::FileOutStream (FILE* fa
, Goffset startA
)
386 FileOutStream::~FileOutStream ()
391 void FileOutStream::close ()
396 Goffset
FileOutStream::getPos ()
401 void FileOutStream::put (char c
)
406 void FileOutStream::printf(const char *format
, ...)
409 va_start (argptr
, format
);
410 vfprintf(f
, format
, argptr
);
415 //------------------------------------------------------------------------
417 //------------------------------------------------------------------------
419 BaseStream::BaseStream(Object
*dictA
, Goffset lengthA
) {
424 BaseStream::~BaseStream() {
428 //------------------------------------------------------------------------
430 //------------------------------------------------------------------------
432 FilterStream::FilterStream(Stream
*strA
) {
436 FilterStream::~FilterStream() {
439 void FilterStream::close() {
443 void FilterStream::setPos(Goffset pos
, int dir
) {
444 error(errInternal
, -1, "Internal: called setPos() on FilterStream");
447 //------------------------------------------------------------------------
449 //------------------------------------------------------------------------
451 ImageStream::ImageStream(Stream
*strA
, int widthA
, int nCompsA
, int nBitsA
) {
459 nVals
= width
* nComps
;
460 inputLineSize
= (nVals
* nBits
+ 7) >> 3;
461 if (nBits
<= 0 || nVals
> INT_MAX
/ nBits
- 7 || width
> INT_MAX
/ nComps
) {
464 inputLine
= (Guchar
*)gmallocn_checkoverflow(inputLineSize
, sizeof(char));
466 imgLine
= (Guchar
*)inputLine
;
469 imgLineSize
= (nVals
+ 7) & ~7;
473 if (width
> INT_MAX
/ nComps
) {
474 // force a call to gmallocn(-1,...), which will throw an exception
477 imgLine
= (Guchar
*)gmallocn(imgLineSize
, sizeof(Guchar
));
482 ImageStream::~ImageStream() {
483 if (imgLine
!= (Guchar
*)inputLine
) {
489 void ImageStream::reset() {
493 void ImageStream::close() {
497 GBool
ImageStream::getPixel(Guchar
*pix
) {
500 if (imgIdx
>= nVals
) {
506 for (i
= 0; i
< nComps
; ++i
) {
507 pix
[i
] = imgLine
[imgIdx
++];
512 Guchar
*ImageStream::getLine() {
519 if (unlikely(inputLine
== NULL
)) {
523 int readChars
= str
->doGetChars(inputLineSize
, inputLine
);
524 for ( ; readChars
< inputLineSize
; readChars
++) inputLine
[readChars
] = EOF
;
527 for (i
= 0; i
< nVals
; i
+= 8) {
529 imgLine
[i
+0] = (Guchar
)((c
>> 7) & 1);
530 imgLine
[i
+1] = (Guchar
)((c
>> 6) & 1);
531 imgLine
[i
+2] = (Guchar
)((c
>> 5) & 1);
532 imgLine
[i
+3] = (Guchar
)((c
>> 4) & 1);
533 imgLine
[i
+4] = (Guchar
)((c
>> 3) & 1);
534 imgLine
[i
+5] = (Guchar
)((c
>> 2) & 1);
535 imgLine
[i
+6] = (Guchar
)((c
>> 1) & 1);
536 imgLine
[i
+7] = (Guchar
)(c
& 1);
538 } else if (nBits
== 8) {
539 // special case: imgLine == inputLine
540 } else if (nBits
== 16) {
541 // this is a hack to support 16 bits images, everywhere
542 // we assume a component fits in 8 bits, with this hack
543 // we treat 16 bit images as 8 bit ones until it's fixed correctly.
544 // The hack has another part on GfxImageColorMap::GfxImageColorMap
546 for (i
= 0; i
< nVals
; ++i
) {
551 bitMask
= (1 << nBits
) - 1;
555 for (i
= 0; i
< nVals
; ++i
) {
557 buf
= (buf
<< 8) | (*p
++ & 0xff);
560 imgLine
[i
] = (Guchar
)((buf
>> (bits
- nBits
)) & bitMask
);
567 void ImageStream::skipLine() {
568 str
->doGetChars(inputLineSize
, inputLine
);
571 //------------------------------------------------------------------------
573 //------------------------------------------------------------------------
575 StreamPredictor::StreamPredictor(Stream
*strA
, int predictorA
,
576 int widthA
, int nCompsA
, int nBitsA
) {
578 predictor
= predictorA
;
585 nVals
= width
* nComps
;
586 pixBytes
= (nComps
* nBits
+ 7) >> 3;
587 rowBytes
= ((nVals
* nBits
+ 7) >> 3) + pixBytes
;
588 if (width
<= 0 || nComps
<= 0 || nBits
<= 0 ||
589 nComps
> gfxColorMaxComps
||
591 width
>= INT_MAX
/ nComps
|| // check for overflow in nVals
592 nVals
>= (INT_MAX
- 7) / nBits
) { // check for overflow in rowBytes
595 predLine
= (Guchar
*)gmalloc(rowBytes
);
596 memset(predLine
, 0, rowBytes
);
602 StreamPredictor::~StreamPredictor() {
606 int StreamPredictor::lookChar() {
607 if (predIdx
>= rowBytes
) {
608 if (!getNextLine()) {
612 return predLine
[predIdx
];
615 int StreamPredictor::getChar() {
616 if (predIdx
>= rowBytes
) {
617 if (!getNextLine()) {
621 return predLine
[predIdx
++];
624 int StreamPredictor::getChars(int nChars
, Guchar
*buffer
) {
629 if (predIdx
>= rowBytes
) {
630 if (!getNextLine()) {
634 m
= rowBytes
- predIdx
;
635 if (m
> nChars
- n
) {
638 memcpy(buffer
+ n
, predLine
+ predIdx
, m
);
645 GBool
StreamPredictor::getNextLine() {
647 Guchar upLeftBuf
[gfxColorMaxComps
* 2 + 1];
648 int left
, up
, upLeft
, p
, pa
, pb
, pc
;
650 Gulong inBuf
, outBuf
, bitMask
;
654 // get PNG optimum predictor number
655 if (predictor
>= 10) {
656 if ((curPred
= str
->getRawChar()) == EOF
) {
664 // read the raw line, apply PNG (byte) predictor
665 int *rawCharLine
= new int[rowBytes
- pixBytes
];
666 str
->getRawChars(rowBytes
- pixBytes
, rawCharLine
);
667 memset(upLeftBuf
, 0, pixBytes
+ 1);
668 for (i
= pixBytes
; i
< rowBytes
; ++i
) {
669 for (j
= pixBytes
; j
> 0; --j
) {
670 upLeftBuf
[j
] = upLeftBuf
[j
-1];
672 upLeftBuf
[0] = predLine
[i
];
673 if ((c
= rawCharLine
[i
- pixBytes
]) == EOF
) {
675 // this ought to return false, but some (broken) PDF files
676 // contain truncated image data, and Adobe apparently reads the
680 delete[] rawCharLine
;
685 predLine
[i
] = predLine
[i
- pixBytes
] + (Guchar
)c
;
688 predLine
[i
] = predLine
[i
] + (Guchar
)c
;
690 case 13: // PNG average
691 predLine
[i
] = ((predLine
[i
- pixBytes
] + predLine
[i
]) >> 1) +
694 case 14: // PNG Paeth
695 left
= predLine
[i
- pixBytes
];
697 upLeft
= upLeftBuf
[pixBytes
];
698 p
= left
+ up
- upLeft
;
699 if ((pa
= p
- left
) < 0)
701 if ((pb
= p
- up
) < 0)
703 if ((pc
= p
- upLeft
) < 0)
705 if (pa
<= pb
&& pa
<= pc
)
706 predLine
[i
] = left
+ (Guchar
)c
;
708 predLine
[i
] = up
+ (Guchar
)c
;
710 predLine
[i
] = upLeft
+ (Guchar
)c
;
713 default: // no predictor or TIFF predictor
714 predLine
[i
] = (Guchar
)c
;
718 delete[] rawCharLine
;
720 // apply TIFF (component) predictor
721 if (predictor
== 2) {
723 inBuf
= predLine
[pixBytes
- 1];
724 for (i
= pixBytes
; i
< rowBytes
; i
+= 8) {
725 // 1-bit add is just xor
726 inBuf
= (inBuf
<< 8) | predLine
[i
];
727 predLine
[i
] ^= inBuf
>> nComps
;
729 } else if (nBits
== 8) {
730 for (i
= pixBytes
; i
< rowBytes
; ++i
) {
731 predLine
[i
] += predLine
[i
- nComps
];
734 memset(upLeftBuf
, 0, nComps
+ 1);
735 bitMask
= (1 << nBits
) - 1;
737 inBits
= outBits
= 0;
739 for (i
= 0; i
< width
; ++i
) {
740 for (kk
= 0; kk
< nComps
; ++kk
) {
741 if (inBits
< nBits
) {
742 inBuf
= (inBuf
<< 8) | (predLine
[j
++] & 0xff);
745 upLeftBuf
[kk
] = (Guchar
)((upLeftBuf
[kk
] +
746 (inBuf
>> (inBits
- nBits
))) & bitMask
);
748 outBuf
= (outBuf
<< nBits
) | upLeftBuf
[kk
];
751 predLine
[k
++] = (Guchar
)(outBuf
>> (outBits
- 8));
757 predLine
[k
++] = (Guchar
)((outBuf
<< (8 - outBits
)) +
758 (inBuf
& ((1 << (8 - outBits
)) - 1)));
763 // reset to start of line
769 //------------------------------------------------------------------------
771 //------------------------------------------------------------------------
773 FileStream::FileStream(GooFile
* fileA
, Goffset startA
, GBool limitedA
,
774 Goffset lengthA
, Object
*dictA
):
775 BaseStream(dictA
, lengthA
) {
777 offset
= start
= startA
;
780 bufPtr
= bufEnd
= buf
;
786 FileStream::~FileStream() {
790 BaseStream
*FileStream::copy() {
791 return new FileStream(file
, start
, limited
, length
, &dict
);
794 Stream
*FileStream::makeSubStream(Goffset startA
, GBool limitedA
,
795 Goffset lengthA
, Object
*dictA
) {
796 return new FileStream(file
, startA
, limitedA
, lengthA
, dictA
);
799 void FileStream::reset() {
803 bufPtr
= bufEnd
= buf
;
807 void FileStream::close() {
814 GBool
FileStream::fillBuf() {
817 bufPos
+= bufEnd
- buf
;
818 bufPtr
= bufEnd
= buf
;
819 if (limited
&& bufPos
>= start
+ length
) {
822 if (limited
&& bufPos
+ fileStreamBufSize
> start
+ length
) {
823 n
= start
+ length
- bufPos
;
825 n
= fileStreamBufSize
;
827 n
= file
->read(buf
, n
, offset
);
833 if (bufPtr
>= bufEnd
) {
839 void FileStream::setPos(Goffset pos
, int dir
) {
843 offset
= bufPos
= pos
;
851 bufPtr
= bufEnd
= buf
;
854 void FileStream::moveStart(Goffset delta
) {
856 bufPtr
= bufEnd
= buf
;
860 //------------------------------------------------------------------------
862 //------------------------------------------------------------------------
864 CachedFileStream::CachedFileStream(CachedFile
*ccA
, Goffset startA
,
865 GBool limitedA
, Goffset lengthA
, Object
*dictA
)
866 : BaseStream(dictA
, lengthA
)
872 bufPtr
= bufEnd
= buf
;
878 CachedFileStream::~CachedFileStream()
884 BaseStream
*CachedFileStream::copy() {
886 return new CachedFileStream(cc
, start
, limited
, length
, &dict
);
889 Stream
*CachedFileStream::makeSubStream(Goffset startA
, GBool limitedA
,
890 Goffset lengthA
, Object
*dictA
)
893 return new CachedFileStream(cc
, startA
, limitedA
, lengthA
, dictA
);
896 void CachedFileStream::reset()
898 savePos
= (Guint
)cc
->tell();
899 cc
->seek(start
, SEEK_SET
);
902 bufPtr
= bufEnd
= buf
;
906 void CachedFileStream::close()
909 cc
->seek(savePos
, SEEK_SET
);
914 GBool
CachedFileStream::fillBuf()
918 bufPos
+= bufEnd
- buf
;
919 bufPtr
= bufEnd
= buf
;
920 if (limited
&& bufPos
>= start
+ length
) {
923 if (limited
&& bufPos
+ cachedStreamBufSize
> start
+ length
) {
924 n
= start
+ length
- bufPos
;
926 n
= cachedStreamBufSize
- (bufPos
% cachedStreamBufSize
);
928 n
= cc
->read(buf
, 1, n
);
930 if (bufPtr
>= bufEnd
) {
936 void CachedFileStream::setPos(Goffset pos
, int dir
)
941 cc
->seek(pos
, SEEK_SET
);
944 cc
->seek(0, SEEK_END
);
945 size
= (Guint
)cc
->tell();
950 cc
->seek(-(int)pos
, SEEK_END
);
951 bufPos
= (Guint
)cc
->tell();
954 bufPtr
= bufEnd
= buf
;
957 void CachedFileStream::moveStart(Goffset delta
)
960 bufPtr
= bufEnd
= buf
;
964 //------------------------------------------------------------------------
966 //------------------------------------------------------------------------
968 MemStream::MemStream(char *bufA
, Goffset startA
, Goffset lengthA
, Object
*dictA
):
969 BaseStream(dictA
, lengthA
) {
973 bufEnd
= buf
+ start
+ length
;
974 bufPtr
= buf
+ start
;
978 MemStream::~MemStream() {
984 BaseStream
*MemStream::copy() {
985 return new MemStream(buf
, start
, length
, &dict
);
988 Stream
*MemStream::makeSubStream(Goffset startA
, GBool limited
,
989 Goffset lengthA
, Object
*dictA
) {
993 if (!limited
|| startA
+ lengthA
> start
+ length
) {
994 newLength
= start
+ length
- startA
;
998 subStr
= new MemStream(buf
, startA
, newLength
, dictA
);
1002 void MemStream::reset() {
1003 bufPtr
= buf
+ start
;
1006 void MemStream::close() {
1009 int MemStream::getChars(int nChars
, Guchar
*buffer
) {
1015 if (bufEnd
- bufPtr
< nChars
) {
1016 n
= (int)(bufEnd
- bufPtr
);
1020 memcpy(buffer
, bufPtr
, n
);
1025 void MemStream::setPos(Goffset pos
, int dir
) {
1031 i
= start
+ length
- pos
;
1035 } else if (i
> start
+ length
) {
1041 void MemStream::moveStart(Goffset delta
) {
1044 bufPtr
= buf
+ start
;
1047 //------------------------------------------------------------------------
1049 //------------------------------------------------------------------------
1051 EmbedStream::EmbedStream(Stream
*strA
, Object
*dictA
,
1052 GBool limitedA
, Goffset lengthA
):
1053 BaseStream(dictA
, lengthA
) {
1059 EmbedStream::~EmbedStream() {
1062 BaseStream
*EmbedStream::copy() {
1063 error(errInternal
, -1, "Called copy() on EmbedStream");
1067 Stream
*EmbedStream::makeSubStream(Goffset start
, GBool limitedA
,
1068 Goffset lengthA
, Object
*dictA
) {
1069 error(errInternal
, -1, "Called makeSubStream() on EmbedStream");
1073 int EmbedStream::getChar() {
1074 if (limited
&& !length
) {
1078 return str
->getChar();
1081 int EmbedStream::lookChar() {
1082 if (limited
&& !length
) {
1085 return str
->lookChar();
1088 int EmbedStream::getChars(int nChars
, Guchar
*buffer
) {
1092 if (limited
&& length
< nChars
) {
1095 return str
->doGetChars(nChars
, buffer
);
1098 void EmbedStream::setPos(Goffset pos
, int dir
) {
1099 error(errInternal
, -1, "Internal: called setPos() on EmbedStream");
1102 Goffset
EmbedStream::getStart() {
1103 error(errInternal
, -1, "Internal: called getStart() on EmbedStream");
1107 void EmbedStream::moveStart(Goffset delta
) {
1108 error(errInternal
, -1, "Internal: called moveStart() on EmbedStream");
1111 //------------------------------------------------------------------------
1113 //------------------------------------------------------------------------
1115 ASCIIHexStream::ASCIIHexStream(Stream
*strA
):
1116 FilterStream(strA
) {
1121 ASCIIHexStream::~ASCIIHexStream() {
1125 void ASCIIHexStream::reset() {
1131 int ASCIIHexStream::lookChar() {
1141 c1
= str
->getChar();
1142 } while (isspace(c1
));
1149 c2
= str
->getChar();
1150 } while (isspace(c2
));
1155 if (c1
>= '0' && c1
<= '9') {
1156 x
= (c1
- '0') << 4;
1157 } else if (c1
>= 'A' && c1
<= 'F') {
1158 x
= (c1
- 'A' + 10) << 4;
1159 } else if (c1
>= 'a' && c1
<= 'f') {
1160 x
= (c1
- 'a' + 10) << 4;
1161 } else if (c1
== EOF
) {
1165 error(errSyntaxError
, getPos(),
1166 "Illegal character <{0:02x}> in ASCIIHex stream", c1
);
1169 if (c2
>= '0' && c2
<= '9') {
1171 } else if (c2
>= 'A' && c2
<= 'F') {
1173 } else if (c2
>= 'a' && c2
<= 'f') {
1175 } else if (c2
== EOF
) {
1179 error(errSyntaxError
, getPos(),
1180 "Illegal character <{0:02x}> in ASCIIHex stream", c2
);
1186 GooString
*ASCIIHexStream::getPSFilter(int psLevel
, const char *indent
) {
1192 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1195 s
->append(indent
)->append("/ASCIIHexDecode filter\n");
1199 GBool
ASCIIHexStream::isBinary(GBool last
) {
1200 return str
->isBinary(gFalse
);
1203 //------------------------------------------------------------------------
1205 //------------------------------------------------------------------------
1207 ASCII85Stream::ASCII85Stream(Stream
*strA
):
1208 FilterStream(strA
) {
1213 ASCII85Stream::~ASCII85Stream() {
1217 void ASCII85Stream::reset() {
1223 int ASCII85Stream::lookChar() {
1232 c
[0] = str
->getChar();
1233 } while (Lexer::isSpace(c
[0]));
1234 if (c
[0] == '~' || c
[0] == EOF
) {
1238 } else if (c
[0] == 'z') {
1239 b
[0] = b
[1] = b
[2] = b
[3] = 0;
1242 for (k
= 1; k
< 5; ++k
) {
1244 c
[k
] = str
->getChar();
1245 } while (Lexer::isSpace(c
[k
]));
1246 if (c
[k
] == '~' || c
[k
] == EOF
)
1250 if (k
< 5 && (c
[k
] == '~' || c
[k
] == EOF
)) {
1251 for (++k
; k
< 5; ++k
)
1256 for (k
= 0; k
< 5; ++k
)
1257 t
= t
* 85 + (c
[k
] - 0x21);
1258 for (k
= 3; k
>= 0; --k
) {
1259 b
[k
] = (int)(t
& 0xff);
1267 GooString
*ASCII85Stream::getPSFilter(int psLevel
, const char *indent
) {
1273 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1276 s
->append(indent
)->append("/ASCII85Decode filter\n");
1280 GBool
ASCII85Stream::isBinary(GBool last
) {
1281 return str
->isBinary(gFalse
);
1284 //------------------------------------------------------------------------
1286 //------------------------------------------------------------------------
1288 LZWStream::LZWStream(Stream
*strA
, int predictor
, int columns
, int colors
,
1289 int bits
, int earlyA
):
1290 FilterStream(strA
) {
1291 if (predictor
!= 1) {
1292 pred
= new StreamPredictor(this, predictor
, columns
, colors
, bits
);
1293 if (!pred
->isOk()) {
1306 LZWStream::~LZWStream() {
1313 int LZWStream::getChar() {
1315 return pred
->getChar();
1320 if (seqIndex
>= seqLength
) {
1321 if (!processNextCode()) {
1325 return seqBuf
[seqIndex
++];
1328 int LZWStream::lookChar() {
1330 return pred
->lookChar();
1335 if (seqIndex
>= seqLength
) {
1336 if (!processNextCode()) {
1340 return seqBuf
[seqIndex
];
1343 void LZWStream::getRawChars(int nChars
, int *buffer
) {
1344 for (int i
= 0; i
< nChars
; ++i
)
1345 buffer
[i
] = doGetRawChar();
1348 int LZWStream::getRawChar() {
1349 return doGetRawChar();
1352 int LZWStream::getChars(int nChars
, Guchar
*buffer
) {
1356 return pred
->getChars(nChars
, buffer
);
1362 while (n
< nChars
) {
1363 if (seqIndex
>= seqLength
) {
1364 if (!processNextCode()) {
1368 m
= seqLength
- seqIndex
;
1369 if (m
> nChars
- n
) {
1372 memcpy(buffer
+ n
, seqBuf
+ seqIndex
, m
);
1379 void LZWStream::reset() {
1386 GBool
LZWStream::processNextCode() {
1396 // check for eod and clear-table codes
1399 if (code
== EOF
|| code
== 257) {
1407 if (nextCode
>= 4097) {
1408 error(errSyntaxError
, getPos(),
1409 "Bad LZW stream - expected clear-table code");
1413 // process the next code
1414 nextLength
= seqLength
+ 1;
1418 } else if (code
< nextCode
) {
1419 seqLength
= table
[code
].length
;
1420 for (i
= seqLength
- 1, j
= code
; i
> 0; --i
) {
1421 seqBuf
[i
] = table
[j
].tail
;
1425 } else if (code
== nextCode
) {
1426 seqBuf
[seqLength
] = newChar
;
1429 error(errSyntaxError
, getPos(), "Bad LZW stream - unexpected code");
1433 newChar
= seqBuf
[0];
1437 table
[nextCode
].length
= nextLength
;
1438 table
[nextCode
].head
= prevCode
;
1439 table
[nextCode
].tail
= newChar
;
1441 if (nextCode
+ early
== 512)
1443 else if (nextCode
+ early
== 1024)
1445 else if (nextCode
+ early
== 2048)
1456 void LZWStream::clearTable() {
1459 seqIndex
= seqLength
= 0;
1463 int LZWStream::getCode() {
1467 while (inputBits
< nextBits
) {
1468 if ((c
= str
->getChar()) == EOF
)
1470 inputBuf
= (inputBuf
<< 8) | (c
& 0xff);
1473 code
= (inputBuf
>> (inputBits
- nextBits
)) & ((1 << nextBits
) - 1);
1474 inputBits
-= nextBits
;
1478 GooString
*LZWStream::getPSFilter(int psLevel
, const char *indent
) {
1481 if (psLevel
< 2 || pred
) {
1484 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1487 s
->append(indent
)->append("<< ");
1489 s
->append("/EarlyChange 0 ");
1491 s
->append(">> /LZWDecode filter\n");
1495 GBool
LZWStream::isBinary(GBool last
) {
1496 return str
->isBinary(gTrue
);
1499 //------------------------------------------------------------------------
1501 //------------------------------------------------------------------------
1503 RunLengthStream::RunLengthStream(Stream
*strA
):
1504 FilterStream(strA
) {
1505 bufPtr
= bufEnd
= buf
;
1509 RunLengthStream::~RunLengthStream() {
1513 void RunLengthStream::reset() {
1515 bufPtr
= bufEnd
= buf
;
1519 int RunLengthStream::getChars(int nChars
, Guchar
*buffer
) {
1523 while (n
< nChars
) {
1524 if (bufPtr
>= bufEnd
) {
1529 m
= (int)(bufEnd
- bufPtr
);
1530 if (m
> nChars
- n
) {
1533 memcpy(buffer
+ n
, bufPtr
, m
);
1540 GooString
*RunLengthStream::getPSFilter(int psLevel
, const char *indent
) {
1546 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1549 s
->append(indent
)->append("/RunLengthDecode filter\n");
1553 GBool
RunLengthStream::isBinary(GBool last
) {
1554 return str
->isBinary(gTrue
);
1557 GBool
RunLengthStream::fillBuf() {
1564 if (c
== 0x80 || c
== EOF
) {
1570 for (i
= 0; i
< n
; ++i
)
1571 buf
[i
] = (char)str
->getChar();
1575 for (i
= 0; i
< n
; ++i
)
1583 //------------------------------------------------------------------------
1585 //------------------------------------------------------------------------
1587 CCITTFaxStream::CCITTFaxStream(Stream
*strA
, int encodingA
, GBool endOfLineA
,
1588 GBool byteAlignA
, int columnsA
, int rowsA
,
1589 GBool endOfBlockA
, GBool blackA
):
1590 FilterStream(strA
) {
1591 encoding
= encodingA
;
1592 endOfLine
= endOfLineA
;
1593 byteAlign
= byteAlignA
;
1597 } else if (columns
> INT_MAX
- 2) {
1598 columns
= INT_MAX
- 2;
1601 endOfBlock
= endOfBlockA
;
1603 // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = columns
1604 // ---> max codingLine size = columns + 1
1605 // refLine has one extra guard entry at the end
1606 // ---> max refLine size = columns + 2
1607 codingLine
= (int *)gmallocn_checkoverflow(columns
+ 1, sizeof(int));
1608 refLine
= (int *)gmallocn_checkoverflow(columns
+ 2, sizeof(int));
1610 if (codingLine
!= NULL
&& refLine
!= NULL
) {
1612 codingLine
[0] = columns
;
1617 nextLine2D
= encoding
< 0;
1625 CCITTFaxStream::~CCITTFaxStream() {
1631 void CCITTFaxStream::ccittReset(GBool unfiltered
) {
1633 str
->unfilteredReset();
1638 nextLine2D
= encoding
< 0;
1645 void CCITTFaxStream::unfilteredReset() {
1649 void CCITTFaxStream::reset() {
1654 if (codingLine
!= NULL
&& refLine
!= NULL
) {
1656 codingLine
[0] = columns
;
1661 // skip any initial zero bits and end-of-line marker, and get the 2D
1663 while ((code1
= lookBits(12)) == 0) {
1666 if (code1
== 0x001) {
1671 nextLine2D
= !lookBits(1);
1676 inline void CCITTFaxStream::addPixels(int a1
, int blackPixels
) {
1677 if (a1
> codingLine
[a0i
]) {
1679 error(errSyntaxError
, getPos(),
1680 "CCITTFax row is wrong length ({0:d})", a1
);
1684 if ((a0i
& 1) ^ blackPixels
) {
1687 codingLine
[a0i
] = a1
;
1691 inline void CCITTFaxStream::addPixelsNeg(int a1
, int blackPixels
) {
1692 if (a1
> codingLine
[a0i
]) {
1694 error(errSyntaxError
, getPos(),
1695 "CCITTFax row is wrong length ({0:d})", a1
);
1699 if ((a0i
& 1) ^ blackPixels
) {
1702 codingLine
[a0i
] = a1
;
1703 } else if (a1
< codingLine
[a0i
]) {
1705 error(errSyntaxError
, getPos(), "Invalid CCITTFax code");
1709 while (a0i
> 0 && a1
<= codingLine
[a0i
- 1]) {
1712 codingLine
[a0i
] = a1
;
1716 int CCITTFaxStream::lookChar() {
1717 int code1
, code2
, code3
;
1718 int b1i
, blackPixels
, i
, bits
;
1725 // read the next row
1726 if (outputBits
== 0) {
1728 // if at eof just return EOF
1737 for (i
= 0; i
< columns
&& codingLine
[i
] < columns
; ++i
) {
1738 refLine
[i
] = codingLine
[i
];
1740 for (; i
< columns
+ 2; ++i
) {
1741 refLine
[i
] = columns
;
1748 // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1]
1750 // exception at left edge:
1751 // codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible
1752 // exception at right edge:
1753 // refLine[b1i] = refLine[b1i+1] = columns is possible
1754 while (codingLine
[a0i
] < columns
&& !err
) {
1755 code1
= getTwoDimCode();
1758 if (likely(b1i
+ 1 < columns
+ 2)) {
1759 addPixels(refLine
[b1i
+ 1], blackPixels
);
1760 if (refLine
[b1i
+ 1] < columns
) {
1769 code1
+= code3
= getBlackCode();
1770 } while (code3
>= 64);
1772 code2
+= code3
= getWhiteCode();
1773 } while (code3
>= 64);
1776 code1
+= code3
= getWhiteCode();
1777 } while (code3
>= 64);
1779 code2
+= code3
= getBlackCode();
1780 } while (code3
>= 64);
1782 addPixels(codingLine
[a0i
] + code1
, blackPixels
);
1783 if (codingLine
[a0i
] < columns
) {
1784 addPixels(codingLine
[a0i
] + code2
, blackPixels
^ 1);
1786 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1788 if (unlikely(b1i
> columns
+ 1)) {
1789 error(errSyntaxError
, getPos(),
1790 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1797 if (unlikely(b1i
> columns
+ 1)) {
1798 error(errSyntaxError
, getPos(),
1799 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1803 addPixels(refLine
[b1i
] + 3, blackPixels
);
1805 if (codingLine
[a0i
] < columns
) {
1807 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1809 if (unlikely(b1i
> columns
+ 1)) {
1810 error(errSyntaxError
, getPos(),
1811 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1819 if (unlikely(b1i
> columns
+ 1)) {
1820 error(errSyntaxError
, getPos(),
1821 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1825 addPixels(refLine
[b1i
] + 2, blackPixels
);
1827 if (codingLine
[a0i
] < columns
) {
1829 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1831 if (unlikely(b1i
> columns
+ 1)) {
1832 error(errSyntaxError
, getPos(),
1833 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1841 if (unlikely(b1i
> columns
+ 1)) {
1842 error(errSyntaxError
, getPos(),
1843 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1847 addPixels(refLine
[b1i
] + 1, blackPixels
);
1849 if (codingLine
[a0i
] < columns
) {
1851 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1853 if (unlikely(b1i
> columns
+ 1)) {
1854 error(errSyntaxError
, getPos(),
1855 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1863 if (unlikely(b1i
> columns
+ 1)) {
1864 error(errSyntaxError
, getPos(),
1865 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1869 addPixels(refLine
[b1i
], blackPixels
);
1871 if (codingLine
[a0i
] < columns
) {
1873 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1875 if (unlikely(b1i
> columns
+ 1)) {
1876 error(errSyntaxError
, getPos(),
1877 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1885 if (unlikely(b1i
> columns
+ 1)) {
1886 error(errSyntaxError
, getPos(),
1887 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1891 addPixelsNeg(refLine
[b1i
] - 3, blackPixels
);
1893 if (codingLine
[a0i
] < columns
) {
1899 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1901 if (unlikely(b1i
> columns
+ 1)) {
1902 error(errSyntaxError
, getPos(),
1903 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1911 if (unlikely(b1i
> columns
+ 1)) {
1912 error(errSyntaxError
, getPos(),
1913 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1917 addPixelsNeg(refLine
[b1i
] - 2, blackPixels
);
1919 if (codingLine
[a0i
] < columns
) {
1925 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1927 if (unlikely(b1i
> columns
+ 1)) {
1928 error(errSyntaxError
, getPos(),
1929 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1937 if (unlikely(b1i
> columns
+ 1)) {
1938 error(errSyntaxError
, getPos(),
1939 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1943 addPixelsNeg(refLine
[b1i
] - 1, blackPixels
);
1945 if (codingLine
[a0i
] < columns
) {
1951 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1953 if (unlikely(b1i
> columns
+ 1)) {
1954 error(errSyntaxError
, getPos(),
1955 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1963 addPixels(columns
, 0);
1967 error(errSyntaxError
, getPos(),
1968 "Bad 2D code {0:04x} in CCITTFax stream", code1
);
1969 addPixels(columns
, 0);
1980 while (codingLine
[a0i
] < columns
) {
1984 code1
+= code3
= getBlackCode();
1985 } while (code3
>= 64);
1988 code1
+= code3
= getWhiteCode();
1989 } while (code3
>= 64);
1991 addPixels(codingLine
[a0i
] + code1
, blackPixels
);
1996 // check for end-of-line marker, skipping over any extra zero bits
1997 // (if EncodedByteAlign is true and EndOfLine is false, there can
1998 // be "false" EOL markers -- i.e., if the last n unused bits in
1999 // row i are set to zero, and the first 11-n bits in row i+1
2000 // happen to be zero -- so we don't look for EOL markers in this
2003 if (!endOfBlock
&& row
== rows
- 1) {
2005 } else if (endOfLine
|| !byteAlign
) {
2006 code1
= lookBits(12);
2008 while (code1
!= EOF
&& code1
!= 0x001) {
2010 code1
= lookBits(12);
2013 while (code1
== 0) {
2015 code1
= lookBits(12);
2018 if (code1
== 0x001) {
2024 // byte-align the row
2025 // (Adobe apparently doesn't do byte alignment after EOL markers
2026 // -- I've seen CCITT image data streams in two different formats,
2027 // both with the byteAlign flag set:
2028 // 1. xx:x0:01:yy:yy
2029 // 2. xx:00:1y:yy:yy
2030 // where xx is the previous line, yy is the next line, and colons
2032 if (byteAlign
&& !gotEOL
) {
2036 // check for end of stream
2037 if (lookBits(1) == EOF
) {
2041 // get 2D encoding tag
2042 if (!eof
&& encoding
> 0) {
2043 nextLine2D
= !lookBits(1);
2047 // check for end-of-block marker
2048 if (endOfBlock
&& !endOfLine
&& byteAlign
) {
2049 // in this case, we didn't check for an EOL code above, so we
2050 // need to check here
2051 code1
= lookBits(24);
2052 if (code1
== 0x001001) {
2057 if (endOfBlock
&& gotEOL
) {
2058 code1
= lookBits(12);
2059 if (code1
== 0x001) {
2065 if (encoding
>= 0) {
2066 for (i
= 0; i
< 4; ++i
) {
2067 code1
= lookBits(12);
2068 if (code1
!= 0x001) {
2069 error(errSyntaxError
, getPos(),
2070 "Bad RTC code in CCITTFax stream");
2082 // look for an end-of-line marker after an error -- we only do
2083 // this if we know the stream contains end-of-line markers because
2084 // the "just plow on" technique tends to work better otherwise
2085 } else if (err
&& endOfLine
) {
2087 code1
= lookBits(13);
2092 if ((code1
>> 1) == 0x001) {
2100 nextLine2D
= !(code1
& 1);
2104 // set up for output
2105 if (codingLine
[0] > 0) {
2106 outputBits
= codingLine
[a0i
= 0];
2108 outputBits
= codingLine
[a0i
= 1];
2115 if (outputBits
>= 8) {
2116 buf
= (a0i
& 1) ? 0x00 : 0xff;
2118 if (outputBits
== 0 && codingLine
[a0i
] < columns
) {
2120 outputBits
= codingLine
[a0i
] - codingLine
[a0i
- 1];
2126 if (outputBits
> bits
) {
2129 buf
|= 0xff >> (8 - bits
);
2136 buf
|= 0xff >> (8 - outputBits
);
2140 if (codingLine
[a0i
] < columns
) {
2142 if (unlikely(a0i
> columns
)) {
2143 error(errSyntaxError
, getPos(),
2144 "Bad bits {0:04x} in CCITTFax stream", bits
);
2148 outputBits
= codingLine
[a0i
] - codingLine
[a0i
- 1];
2149 } else if (bits
> 0) {
2162 short CCITTFaxStream::getTwoDimCode() {
2167 code
= 0; // make gcc happy
2169 if ((code
= lookBits(7)) != EOF
) {
2170 p
= &twoDimTab1
[code
];
2177 for (n
= 1; n
<= 7; ++n
) {
2178 if ((code
= lookBits(n
)) == EOF
) {
2184 p
= &twoDimTab1
[code
];
2191 error(errSyntaxError
, getPos(),
2192 "Bad two dim code ({0:04x}) in CCITTFax stream", code
);
2196 short CCITTFaxStream::getWhiteCode() {
2201 code
= 0; // make gcc happy
2203 code
= lookBits(12);
2207 if ((code
>> 5) == 0) {
2208 p
= &whiteTab1
[code
];
2210 p
= &whiteTab2
[code
>> 3];
2217 for (n
= 1; n
<= 9; ++n
) {
2225 p
= &whiteTab2
[code
];
2231 for (n
= 11; n
<= 12; ++n
) {
2239 p
= &whiteTab1
[code
];
2246 error(errSyntaxError
, getPos(),
2247 "Bad white code ({0:04x}) in CCITTFax stream", code
);
2248 // eat a bit and return a positive number so that the caller doesn't
2249 // go into an infinite loop
2254 short CCITTFaxStream::getBlackCode() {
2259 code
= 0; // make gcc happy
2261 code
= lookBits(13);
2265 if ((code
>> 7) == 0) {
2266 p
= &blackTab1
[code
];
2267 } else if ((code
>> 9) == 0 && (code
>> 7) != 0) {
2268 p
= &blackTab2
[(code
>> 1) - 64];
2270 p
= &blackTab3
[code
>> 7];
2277 for (n
= 2; n
<= 6; ++n
) {
2285 p
= &blackTab3
[code
];
2291 for (n
= 7; n
<= 12; ++n
) {
2300 p
= &blackTab2
[code
- 64];
2307 for (n
= 10; n
<= 13; ++n
) {
2315 p
= &blackTab1
[code
];
2322 error(errSyntaxError
, getPos(),
2323 "Bad black code ({0:04x}) in CCITTFax stream", code
);
2324 // eat a bit and return a positive number so that the caller doesn't
2325 // go into an infinite loop
2330 short CCITTFaxStream::lookBits(int n
) {
2333 while (inputBits
< n
) {
2334 if ((c
= str
->getChar()) == EOF
) {
2335 if (inputBits
== 0) {
2338 // near the end of the stream, the caller may ask for more bits
2339 // than are available, but there may still be a valid code in
2340 // however many bits are available -- we need to return correct
2341 // data in this case
2342 return (inputBuf
<< (n
- inputBits
)) & (0xffffffff >> (32 - n
));
2344 inputBuf
= (inputBuf
<< 8) + c
;
2347 return (inputBuf
>> (inputBits
- n
)) & (0xffffffff >> (32 - n
));
2350 GooString
*CCITTFaxStream::getPSFilter(int psLevel
, const char *indent
) {
2357 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
2360 s
->append(indent
)->append("<< ");
2361 if (encoding
!= 0) {
2362 sprintf(s1
, "/K %d ", encoding
);
2366 s
->append("/EndOfLine true ");
2369 s
->append("/EncodedByteAlign true ");
2371 sprintf(s1
, "/Columns %d ", columns
);
2374 sprintf(s1
, "/Rows %d ", rows
);
2378 s
->append("/EndOfBlock false ");
2381 s
->append("/BlackIs1 true ");
2383 s
->append(">> /CCITTFaxDecode filter\n");
2387 GBool
CCITTFaxStream::isBinary(GBool last
) {
2388 return str
->isBinary(gTrue
);
2391 #ifndef ENABLE_LIBJPEG
2393 //------------------------------------------------------------------------
2395 //------------------------------------------------------------------------
2397 // IDCT constants (20.12 fixed point format)
2398 #define dctCos1 4017 // cos(pi/16)
2399 #define dctSin1 799 // sin(pi/16)
2400 #define dctCos3 3406 // cos(3*pi/16)
2401 #define dctSin3 2276 // sin(3*pi/16)
2402 #define dctCos6 1567 // cos(6*pi/16)
2403 #define dctSin6 3784 // sin(6*pi/16)
2404 #define dctSqrt2 5793 // sqrt(2)
2405 #define dctSqrt1d2 2896 // sqrt(2) / 2
2407 // color conversion parameters (16.16 fixed point format)
2408 #define dctCrToR 91881 // 1.4020
2409 #define dctCbToG -22553 // -0.3441363
2410 #define dctCrToG -46802 // -0.71413636
2411 #define dctCbToB 116130 // 1.772
2413 // clip [-256,511] --> [0,255]
2414 #define dctClipOffset 256
2415 #define dctClipLength 768
2416 static Guchar dctClip
[dctClipLength
];
2417 static int dctClipInit
= 0;
2419 // zig zag decode map
2420 static const int dctZigZag
[64] = {
2426 5, 12, 19, 26, 33, 40,
2427 48, 41, 34, 27, 20, 13, 6,
2428 7, 14, 21, 28, 35, 42, 49, 56,
2429 57, 50, 43, 36, 29, 22, 15,
2430 23, 30, 37, 44, 51, 58,
2438 DCTStream::DCTStream(Stream
*strA
, int colorXformA
, Object
*dict
, int recursion
):
2439 FilterStream(strA
) {
2442 colorXform
= colorXformA
;
2443 progressive
= interleaved
= gFalse
;
2445 mcuWidth
= mcuHeight
= 0;
2449 for (i
= 0; i
< 4; ++i
) {
2450 for (j
= 0; j
< 32; ++j
) {
2451 rowBuf
[i
][j
] = NULL
;
2457 for (i
= -256; i
< 0; ++i
)
2458 dctClip
[dctClipOffset
+ i
] = 0;
2459 for (i
= 0; i
< 256; ++i
)
2460 dctClip
[dctClipOffset
+ i
] = i
;
2461 for (i
= 256; i
< 512; ++i
)
2462 dctClip
[dctClipOffset
+ i
] = 255;
2467 DCTStream::~DCTStream() {
2472 void DCTStream::dctReset(GBool unfiltered
) {
2474 str
->unfilteredReset();
2478 progressive
= interleaved
= gFalse
;
2482 numDCHuffTables
= 0;
2483 numACHuffTables
= 0;
2484 gotJFIFMarker
= gFalse
;
2485 gotAdobeMarker
= gFalse
;
2486 restartInterval
= 0;
2489 void DCTStream::unfilteredReset() {
2493 void DCTStream::reset() {
2498 if (!readHeader()) {
2504 if (numComps
== 1) {
2505 compInfo
[0].hSample
= compInfo
[0].vSample
= 1;
2507 mcuWidth
= compInfo
[0].hSample
;
2508 mcuHeight
= compInfo
[0].vSample
;
2509 for (i
= 1; i
< numComps
; ++i
) {
2510 if (compInfo
[i
].hSample
> mcuWidth
) {
2511 mcuWidth
= compInfo
[i
].hSample
;
2513 if (compInfo
[i
].vSample
> mcuHeight
) {
2514 mcuHeight
= compInfo
[i
].vSample
;
2520 // figure out color transform
2521 if (colorXform
== -1) {
2522 if (numComps
== 3) {
2523 if (gotJFIFMarker
) {
2525 } else if (compInfo
[0].id
== 82 && compInfo
[1].id
== 71 &&
2526 compInfo
[2].id
== 66) { // ASCII "RGB"
2536 if (progressive
|| !interleaved
) {
2538 // allocate a buffer for the whole image
2539 bufWidth
= ((width
+ mcuWidth
- 1) / mcuWidth
) * mcuWidth
;
2540 bufHeight
= ((height
+ mcuHeight
- 1) / mcuHeight
) * mcuHeight
;
2541 if (bufWidth
<= 0 || bufHeight
<= 0 ||
2542 bufWidth
> INT_MAX
/ bufWidth
/ (int)sizeof(int)) {
2543 error(errSyntaxError
, getPos(), "Invalid image size in DCT stream");
2547 for (i
= 0; i
< numComps
; ++i
) {
2548 frameBuf
[i
] = (int *)gmallocn(bufWidth
* bufHeight
, sizeof(int));
2549 memset(frameBuf
[i
], 0, bufWidth
* bufHeight
* sizeof(int));
2552 // read the image data
2554 restartMarker
= 0xd0;
2557 } while (readHeader());
2562 // initialize counters
2569 // allocate a buffer for one row of MCUs
2570 bufWidth
= ((width
+ mcuWidth
- 1) / mcuWidth
) * mcuWidth
;
2571 for (i
= 0; i
< numComps
; ++i
) {
2572 for (j
= 0; j
< mcuHeight
; ++j
) {
2573 rowBuf
[i
][j
] = (Guchar
*)gmallocn(bufWidth
, sizeof(Guchar
));
2577 // initialize counters
2583 restartMarker
= 0xd0;
2588 void DCTStream::close() {
2591 for (i
= 0; i
< 4; ++i
) {
2592 for (j
= 0; j
< 32; ++j
) {
2593 gfree(rowBuf
[i
][j
]);
2594 rowBuf
[i
][j
] = NULL
;
2599 FilterStream::close();
2602 int DCTStream::getChar() {
2608 if (progressive
|| !interleaved
) {
2609 c
= frameBuf
[comp
][y
* bufWidth
+ x
];
2610 if (++comp
== numComps
) {
2618 if (dy
>= mcuHeight
) {
2619 if (!readMCURow()) {
2627 c
= rowBuf
[comp
][dy
][x
];
2628 if (++comp
== numComps
) {
2643 int DCTStream::lookChar() {
2647 if (progressive
|| !interleaved
) {
2648 return frameBuf
[comp
][y
* bufWidth
+ x
];
2650 if (dy
>= mcuHeight
) {
2651 if (!readMCURow()) {
2659 return rowBuf
[comp
][dy
][x
];
2663 void DCTStream::restart() {
2667 restartCtr
= restartInterval
;
2668 for (i
= 0; i
< numComps
; ++i
) {
2669 compInfo
[i
].prevDC
= 0;
2674 // Read one row of MCUs from a sequential JPEG stream.
2675 GBool
DCTStream::readMCURow() {
2679 int pY
, pCb
, pCr
, pR
, pG
, pB
;
2680 int h
, v
, horiz
, vert
, hSub
, vSub
;
2681 int x1
, x2
, y2
, x3
, y3
, x4
, y4
, x5
, y5
, cc
, i
;
2684 for (x1
= 0; x1
< width
; x1
+= mcuWidth
) {
2686 // deal with restart marker
2687 if (restartInterval
> 0 && restartCtr
== 0) {
2689 if (c
!= restartMarker
) {
2690 error(errSyntaxError
, getPos(),
2691 "Bad DCT data: incorrect restart marker");
2694 if (++restartMarker
== 0xd8)
2695 restartMarker
= 0xd0;
2700 for (cc
= 0; cc
< numComps
; ++cc
) {
2701 h
= compInfo
[cc
].hSample
;
2702 v
= compInfo
[cc
].vSample
;
2703 horiz
= mcuWidth
/ h
;
2704 vert
= mcuHeight
/ v
;
2707 for (y2
= 0; y2
< mcuHeight
; y2
+= vert
) {
2708 for (x2
= 0; x2
< mcuWidth
; x2
+= horiz
) {
2709 if (unlikely(scanInfo
.dcHuffTable
[cc
] >= 4) || unlikely(scanInfo
.acHuffTable
[cc
] >= 4)) {
2712 if (!readDataUnit(&dcHuffTables
[scanInfo
.dcHuffTable
[cc
]],
2713 &acHuffTables
[scanInfo
.acHuffTable
[cc
]],
2714 &compInfo
[cc
].prevDC
,
2718 transformDataUnit(quantTables
[compInfo
[cc
].quantTable
],
2720 if (hSub
== 1 && vSub
== 1) {
2721 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2722 p1
= &rowBuf
[cc
][y2
+y3
][x1
+x2
];
2732 } else if (hSub
== 2 && vSub
== 2) {
2733 for (y3
= 0, i
= 0; y3
< 16; y3
+= 2, i
+= 8) {
2734 p1
= &rowBuf
[cc
][y2
+y3
][x1
+x2
];
2735 p2
= &rowBuf
[cc
][y2
+y3
+1][x1
+x2
];
2736 p1
[0] = p1
[1] = p2
[0] = p2
[1] = data2
[i
];
2737 p1
[2] = p1
[3] = p2
[2] = p2
[3] = data2
[i
+1];
2738 p1
[4] = p1
[5] = p2
[4] = p2
[5] = data2
[i
+2];
2739 p1
[6] = p1
[7] = p2
[6] = p2
[7] = data2
[i
+3];
2740 p1
[8] = p1
[9] = p2
[8] = p2
[9] = data2
[i
+4];
2741 p1
[10] = p1
[11] = p2
[10] = p2
[11] = data2
[i
+5];
2742 p1
[12] = p1
[13] = p2
[12] = p2
[13] = data2
[i
+6];
2743 p1
[14] = p1
[15] = p2
[14] = p2
[15] = data2
[i
+7];
2747 for (y3
= 0, y4
= 0; y3
< 8; ++y3
, y4
+= vSub
) {
2748 for (x3
= 0, x4
= 0; x3
< 8; ++x3
, x4
+= hSub
) {
2749 for (y5
= 0; y5
< vSub
; ++y5
)
2750 for (x5
= 0; x5
< hSub
; ++x5
)
2751 rowBuf
[cc
][y2
+y4
+y5
][x1
+x2
+x4
+x5
] = data2
[i
];
2761 // color space conversion
2763 // convert YCbCr to RGB
2764 if (numComps
== 3) {
2765 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2766 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2767 pY
= rowBuf
[0][y2
][x1
+x2
];
2768 pCb
= rowBuf
[1][y2
][x1
+x2
] - 128;
2769 pCr
= rowBuf
[2][y2
][x1
+x2
] - 128;
2770 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2771 rowBuf
[0][y2
][x1
+x2
] = dctClip
[dctClipOffset
+ pR
];
2772 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+ 32768) >> 16;
2773 rowBuf
[1][y2
][x1
+x2
] = dctClip
[dctClipOffset
+ pG
];
2774 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2775 rowBuf
[2][y2
][x1
+x2
] = dctClip
[dctClipOffset
+ pB
];
2778 // convert YCbCrK to CMYK (K is passed through unchanged)
2779 } else if (numComps
== 4) {
2780 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2781 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2782 pY
= rowBuf
[0][y2
][x1
+x2
];
2783 pCb
= rowBuf
[1][y2
][x1
+x2
] - 128;
2784 pCr
= rowBuf
[2][y2
][x1
+x2
] - 128;
2785 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2786 rowBuf
[0][y2
][x1
+x2
] = 255 - dctClip
[dctClipOffset
+ pR
];
2787 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+ 32768) >> 16;
2788 rowBuf
[1][y2
][x1
+x2
] = 255 - dctClip
[dctClipOffset
+ pG
];
2789 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2790 rowBuf
[2][y2
][x1
+x2
] = 255 - dctClip
[dctClipOffset
+ pB
];
2799 // Read one scan from a progressive or non-interleaved JPEG stream.
2800 void DCTStream::readScan() {
2802 int x1
, y1
, dx1
, dy1
, x2
, y2
, y3
, cc
, i
;
2803 int h
, v
, horiz
, vert
, vSub
;
2807 if (scanInfo
.numComps
== 1) {
2808 for (cc
= 0; cc
< numComps
; ++cc
) {
2809 if (scanInfo
.comp
[cc
]) {
2813 dx1
= mcuWidth
/ compInfo
[cc
].hSample
;
2814 dy1
= mcuHeight
/ compInfo
[cc
].vSample
;
2820 for (y1
= 0; y1
< height
; y1
+= dy1
) {
2821 for (x1
= 0; x1
< width
; x1
+= dx1
) {
2823 // deal with restart marker
2824 if (restartInterval
> 0 && restartCtr
== 0) {
2826 if (c
!= restartMarker
) {
2827 error(errSyntaxError
, getPos(),
2828 "Bad DCT data: incorrect restart marker");
2831 if (++restartMarker
== 0xd8) {
2832 restartMarker
= 0xd0;
2838 for (cc
= 0; cc
< numComps
; ++cc
) {
2839 if (!scanInfo
.comp
[cc
]) {
2843 h
= compInfo
[cc
].hSample
;
2844 v
= compInfo
[cc
].vSample
;
2845 horiz
= mcuWidth
/ h
;
2846 vert
= mcuHeight
/ v
;
2848 for (y2
= 0; y2
< dy1
; y2
+= vert
) {
2849 for (x2
= 0; x2
< dx1
; x2
+= horiz
) {
2851 // pull out the current values
2852 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2853 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2862 p1
+= bufWidth
* vSub
;
2865 // read one data unit
2867 if (!readProgressiveDataUnit(
2868 &dcHuffTables
[scanInfo
.dcHuffTable
[cc
]],
2869 &acHuffTables
[scanInfo
.acHuffTable
[cc
]],
2870 &compInfo
[cc
].prevDC
,
2875 if (!readDataUnit(&dcHuffTables
[scanInfo
.dcHuffTable
[cc
]],
2876 &acHuffTables
[scanInfo
.acHuffTable
[cc
]],
2877 &compInfo
[cc
].prevDC
,
2883 // add the data unit into frameBuf
2884 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2885 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2894 p1
+= bufWidth
* vSub
;
2904 // Read one data unit from a sequential JPEG stream.
2905 GBool
DCTStream::readDataUnit(DCTHuffTable
*dcHuffTable
,
2906 DCTHuffTable
*acHuffTable
,
2907 int *prevDC
, int data
[64]) {
2912 if ((size
= readHuffSym(dcHuffTable
)) == 9999) {
2916 if ((amp
= readAmp(size
)) == 9999) {
2922 data
[0] = *prevDC
+= amp
;
2923 for (i
= 1; i
< 64; ++i
) {
2929 while ((c
= readHuffSym(acHuffTable
)) == 0xf0 && run
< 0x30) {
2938 run
+= (c
>> 4) & 0x0f;
2940 amp
= readAmp(size
);
2954 // Read one data unit from a sequential JPEG stream.
2955 GBool
DCTStream::readProgressiveDataUnit(DCTHuffTable
*dcHuffTable
,
2956 DCTHuffTable
*acHuffTable
,
2957 int *prevDC
, int data
[64]) {
2958 int run
, size
, amp
, bit
, c
;
2961 // get the DC coefficient
2962 i
= scanInfo
.firstCoeff
;
2964 if (scanInfo
.ah
== 0) {
2965 if ((size
= readHuffSym(dcHuffTable
)) == 9999) {
2969 if ((amp
= readAmp(size
)) == 9999) {
2975 data
[0] += (*prevDC
+= amp
) << scanInfo
.al
;
2977 if ((bit
= readBit()) == 9999) {
2980 data
[0] += bit
<< scanInfo
.al
;
2984 if (scanInfo
.lastCoeff
== 0) {
2988 // check for an EOB run
2990 while (i
<= scanInfo
.lastCoeff
) {
2993 if ((bit
= readBit()) == EOF
) {
2997 data
[j
] += 1 << scanInfo
.al
;
3005 // read the AC coefficients
3006 while (i
<= scanInfo
.lastCoeff
) {
3007 if ((c
= readHuffSym(acHuffTable
)) == 9999) {
3014 while (k
< 16 && i
<= scanInfo
.lastCoeff
) {
3019 if ((bit
= readBit()) == EOF
) {
3023 data
[j
] += 1 << scanInfo
.al
;
3029 } else if ((c
& 0x0f) == 0x00) {
3032 for (k
= 0; k
< j
; ++k
) {
3033 if ((bit
= readBit()) == EOF
) {
3036 eobRun
= (eobRun
<< 1) | bit
;
3039 while (i
<= scanInfo
.lastCoeff
) {
3042 if ((bit
= readBit()) == EOF
) {
3046 data
[j
] += 1 << scanInfo
.al
;
3053 // zero run and one AC coefficient
3055 run
= (c
>> 4) & 0x0f;
3057 if ((amp
= readAmp(size
)) == 9999) {
3060 j
= 0; // make gcc happy
3061 for (k
= 0; k
<= run
&& i
<= scanInfo
.lastCoeff
; ++k
) {
3063 while (data
[j
] != 0 && i
<= scanInfo
.lastCoeff
) {
3064 if ((bit
= readBit()) == EOF
) {
3068 data
[j
] += 1 << scanInfo
.al
;
3073 data
[j
] = amp
<< scanInfo
.al
;
3080 // Decode a progressive JPEG image.
3081 void DCTStream::decodeImage() {
3084 Gushort
*quantTable
;
3085 int pY
, pCb
, pCr
, pR
, pG
, pB
;
3086 int x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
, x5
, y5
, cc
, i
;
3087 int h
, v
, horiz
, vert
, hSub
, vSub
;
3090 for (y1
= 0; y1
< bufHeight
; y1
+= mcuHeight
) {
3091 for (x1
= 0; x1
< bufWidth
; x1
+= mcuWidth
) {
3092 for (cc
= 0; cc
< numComps
; ++cc
) {
3093 quantTable
= quantTables
[compInfo
[cc
].quantTable
];
3094 h
= compInfo
[cc
].hSample
;
3095 v
= compInfo
[cc
].vSample
;
3096 horiz
= mcuWidth
/ h
;
3097 vert
= mcuHeight
/ v
;
3100 for (y2
= 0; y2
< mcuHeight
; y2
+= vert
) {
3101 for (x2
= 0; x2
< mcuWidth
; x2
+= horiz
) {
3103 // pull out the coded data unit
3104 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
3105 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
3107 dataIn
[i
+1] = p1
[1];
3108 dataIn
[i
+2] = p1
[2];
3109 dataIn
[i
+3] = p1
[3];
3110 dataIn
[i
+4] = p1
[4];
3111 dataIn
[i
+5] = p1
[5];
3112 dataIn
[i
+6] = p1
[6];
3113 dataIn
[i
+7] = p1
[7];
3114 p1
+= bufWidth
* vSub
;
3118 transformDataUnit(quantTable
, dataIn
, dataOut
);
3120 // store back into frameBuf, doing replication for
3121 // subsampled components
3122 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
3123 if (hSub
== 1 && vSub
== 1) {
3124 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
3125 p1
[0] = dataOut
[i
] & 0xff;
3126 p1
[1] = dataOut
[i
+1] & 0xff;
3127 p1
[2] = dataOut
[i
+2] & 0xff;
3128 p1
[3] = dataOut
[i
+3] & 0xff;
3129 p1
[4] = dataOut
[i
+4] & 0xff;
3130 p1
[5] = dataOut
[i
+5] & 0xff;
3131 p1
[6] = dataOut
[i
+6] & 0xff;
3132 p1
[7] = dataOut
[i
+7] & 0xff;
3135 } else if (hSub
== 2 && vSub
== 2) {
3137 for (y3
= 0, i
= 0; y3
< 16; y3
+= 2, i
+= 8) {
3138 p1
[0] = p1
[1] = p2
[0] = p2
[1] = dataOut
[i
] & 0xff;
3139 p1
[2] = p1
[3] = p2
[2] = p2
[3] = dataOut
[i
+1] & 0xff;
3140 p1
[4] = p1
[5] = p2
[4] = p2
[5] = dataOut
[i
+2] & 0xff;
3141 p1
[6] = p1
[7] = p2
[6] = p2
[7] = dataOut
[i
+3] & 0xff;
3142 p1
[8] = p1
[9] = p2
[8] = p2
[9] = dataOut
[i
+4] & 0xff;
3143 p1
[10] = p1
[11] = p2
[10] = p2
[11] = dataOut
[i
+5] & 0xff;
3144 p1
[12] = p1
[13] = p2
[12] = p2
[13] = dataOut
[i
+6] & 0xff;
3145 p1
[14] = p1
[15] = p2
[14] = p2
[15] = dataOut
[i
+7] & 0xff;
3151 for (y3
= 0, y4
= 0; y3
< 8; ++y3
, y4
+= vSub
) {
3152 for (x3
= 0, x4
= 0; x3
< 8; ++x3
, x4
+= hSub
) {
3154 for (y5
= 0; y5
< vSub
; ++y5
) {
3155 for (x5
= 0; x5
< hSub
; ++x5
) {
3156 p2
[x5
] = dataOut
[i
] & 0xff;
3162 p1
+= bufWidth
* vSub
;
3169 // color space conversion
3171 // convert YCbCr to RGB
3172 if (numComps
== 3) {
3173 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
3174 p0
= &frameBuf
[0][(y1
+y2
) * bufWidth
+ x1
];
3175 p1
= &frameBuf
[1][(y1
+y2
) * bufWidth
+ x1
];
3176 p2
= &frameBuf
[2][(y1
+y2
) * bufWidth
+ x1
];
3177 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
3181 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
3182 *p0
++ = dctClip
[dctClipOffset
+ pR
];
3183 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+
3185 *p1
++ = dctClip
[dctClipOffset
+ pG
];
3186 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
3187 *p2
++ = dctClip
[dctClipOffset
+ pB
];
3190 // convert YCbCrK to CMYK (K is passed through unchanged)
3191 } else if (numComps
== 4) {
3192 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
3193 p0
= &frameBuf
[0][(y1
+y2
) * bufWidth
+ x1
];
3194 p1
= &frameBuf
[1][(y1
+y2
) * bufWidth
+ x1
];
3195 p2
= &frameBuf
[2][(y1
+y2
) * bufWidth
+ x1
];
3196 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
3200 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
3201 *p0
++ = 255 - dctClip
[dctClipOffset
+ pR
];
3202 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+
3204 *p1
++ = 255 - dctClip
[dctClipOffset
+ pG
];
3205 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
3206 *p2
++ = 255 - dctClip
[dctClipOffset
+ pB
];
3215 // Transform one data unit -- this performs the dequantization and
3216 // IDCT steps. This IDCT algorithm is taken from:
3217 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
3218 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
3219 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
3221 // The stage numbers mentioned in the comments refer to Figure 1 in this
3223 void DCTStream::transformDataUnit(Gushort
*quantTable
,
3224 int dataIn
[64], Guchar dataOut
[64]) {
3225 int v0
, v1
, v2
, v3
, v4
, v5
, v6
, v7
, t
;
3230 for (i
= 0; i
< 64; ++i
) {
3231 dataIn
[i
] *= quantTable
[i
];
3234 // inverse DCT on rows
3235 for (i
= 0; i
< 64; i
+= 8) {
3238 // check for all-zero AC coefficients
3239 if (p
[1] == 0 && p
[2] == 0 && p
[3] == 0 &&
3240 p
[4] == 0 && p
[5] == 0 && p
[6] == 0 && p
[7] == 0) {
3241 t
= (dctSqrt2
* p
[0] + 512) >> 10;
3254 v0
= (dctSqrt2
* p
[0] + 128) >> 8;
3255 v1
= (dctSqrt2
* p
[4] + 128) >> 8;
3258 v4
= (dctSqrt1d2
* (p
[1] - p
[7]) + 128) >> 8;
3259 v7
= (dctSqrt1d2
* (p
[1] + p
[7]) + 128) >> 8;
3264 t
= (v0
- v1
+ 1) >> 1;
3265 v0
= (v0
+ v1
+ 1) >> 1;
3267 t
= (v2
* dctSin6
+ v3
* dctCos6
+ 128) >> 8;
3268 v2
= (v2
* dctCos6
- v3
* dctSin6
+ 128) >> 8;
3270 t
= (v4
- v6
+ 1) >> 1;
3271 v4
= (v4
+ v6
+ 1) >> 1;
3273 t
= (v7
+ v5
+ 1) >> 1;
3274 v5
= (v7
- v5
+ 1) >> 1;
3278 t
= (v0
- v3
+ 1) >> 1;
3279 v0
= (v0
+ v3
+ 1) >> 1;
3281 t
= (v1
- v2
+ 1) >> 1;
3282 v1
= (v1
+ v2
+ 1) >> 1;
3284 t
= (v4
* dctSin3
+ v7
* dctCos3
+ 2048) >> 12;
3285 v4
= (v4
* dctCos3
- v7
* dctSin3
+ 2048) >> 12;
3287 t
= (v5
* dctSin1
+ v6
* dctCos1
+ 2048) >> 12;
3288 v5
= (v5
* dctCos1
- v6
* dctSin1
+ 2048) >> 12;
3302 // inverse DCT on columns
3303 for (i
= 0; i
< 8; ++i
) {
3306 // check for all-zero AC coefficients
3307 if (p
[1*8] == 0 && p
[2*8] == 0 && p
[3*8] == 0 &&
3308 p
[4*8] == 0 && p
[5*8] == 0 && p
[6*8] == 0 && p
[7*8] == 0) {
3309 t
= (dctSqrt2
* dataIn
[i
+0] + 8192) >> 14;
3322 v0
= (dctSqrt2
* p
[0*8] + 2048) >> 12;
3323 v1
= (dctSqrt2
* p
[4*8] + 2048) >> 12;
3326 v4
= (dctSqrt1d2
* (p
[1*8] - p
[7*8]) + 2048) >> 12;
3327 v7
= (dctSqrt1d2
* (p
[1*8] + p
[7*8]) + 2048) >> 12;
3332 t
= (v0
- v1
+ 1) >> 1;
3333 v0
= (v0
+ v1
+ 1) >> 1;
3335 t
= (v2
* dctSin6
+ v3
* dctCos6
+ 2048) >> 12;
3336 v2
= (v2
* dctCos6
- v3
* dctSin6
+ 2048) >> 12;
3338 t
= (v4
- v6
+ 1) >> 1;
3339 v4
= (v4
+ v6
+ 1) >> 1;
3341 t
= (v7
+ v5
+ 1) >> 1;
3342 v5
= (v7
- v5
+ 1) >> 1;
3346 t
= (v0
- v3
+ 1) >> 1;
3347 v0
= (v0
+ v3
+ 1) >> 1;
3349 t
= (v1
- v2
+ 1) >> 1;
3350 v1
= (v1
+ v2
+ 1) >> 1;
3352 t
= (v4
* dctSin3
+ v7
* dctCos3
+ 2048) >> 12;
3353 v4
= (v4
* dctCos3
- v7
* dctSin3
+ 2048) >> 12;
3355 t
= (v5
* dctSin1
+ v6
* dctCos1
+ 2048) >> 12;
3356 v5
= (v5
* dctCos1
- v6
* dctSin1
+ 2048) >> 12;
3370 // convert to 8-bit integers
3371 for (i
= 0; i
< 64; ++i
) {
3372 const int ix
= dctClipOffset
+ 128 + ((dataIn
[i
] + 8) >> 4);
3373 if (unlikely(ix
< 0 || ix
>= dctClipLength
)) {
3376 dataOut
[i
] = dctClip
[ix
];
3381 int DCTStream::readHuffSym(DCTHuffTable
*table
) {
3389 // add a bit to the code
3390 if ((bit
= readBit()) == EOF
) {
3393 code
= (code
<< 1) + bit
;
3397 if (code
< table
->firstCode
[codeBits
]) {
3400 if (code
- table
->firstCode
[codeBits
] < table
->numCodes
[codeBits
]) {
3401 code
-= table
->firstCode
[codeBits
];
3402 return table
->sym
[table
->firstSym
[codeBits
] + code
];
3404 } while (codeBits
< 16);
3406 error(errSyntaxError
, getPos(), "Bad Huffman code in DCT stream");
3410 int DCTStream::readAmp(int size
) {
3415 for (bits
= 0; bits
< size
; ++bits
) {
3416 if ((bit
= readBit()) == EOF
)
3418 amp
= (amp
<< 1) + bit
;
3420 if (amp
< (1 << (size
- 1)))
3421 amp
-= (1 << size
) - 1;
3425 int DCTStream::readBit() {
3429 if (inputBits
== 0) {
3430 if ((c
= str
->getChar()) == EOF
)
3434 c2
= str
->getChar();
3435 } while (c2
== 0xff);
3437 error(errSyntaxError
, getPos(), "Bad DCT data: missing 00 after ff");
3444 bit
= (inputBuf
>> (inputBits
- 1)) & 1;
3449 GBool
DCTStream::readHeader() {
3460 case 0xc0: // SOF0 (sequential)
3461 case 0xc1: // SOF1 (extended sequential)
3462 if (!readBaselineSOF()) {
3466 case 0xc2: // SOF2 (progressive)
3467 if (!readProgressiveSOF()) {
3472 if (!readHuffmanTables()) {
3481 if (!readScanInfo()) {
3487 if (!readQuantTables()) {
3492 if (!readRestartInterval()) {
3497 if (!readJFIFMarker()) {
3502 if (!readAdobeMarker()) {
3507 error(errSyntaxError
, getPos(), "Bad DCT header");
3510 // skip APPn / COM / etc.
3513 for (i
= 0; i
< n
; ++i
) {
3517 error(errSyntaxError
, getPos(), "Unknown DCT marker <{0:02x}>", c
);
3527 GBool
DCTStream::readBaselineSOF() {
3534 prec
= str
->getChar();
3537 numComps
= str
->getChar();
3538 if (numComps
<= 0 || numComps
> 4) {
3539 error(errSyntaxError
, getPos(), "Bad number of components in DCT stream");
3544 error(errSyntaxError
, getPos(), "Bad DCT precision {0:d}", prec
);
3547 for (i
= 0; i
< numComps
; ++i
) {
3548 compInfo
[i
].id
= str
->getChar();
3550 compInfo
[i
].hSample
= (c
>> 4) & 0x0f;
3551 compInfo
[i
].vSample
= c
& 0x0f;
3552 compInfo
[i
].quantTable
= str
->getChar();
3553 if (compInfo
[i
].hSample
< 1 || compInfo
[i
].hSample
> 4 ||
3554 compInfo
[i
].vSample
< 1 || compInfo
[i
].vSample
> 4) {
3555 error(errSyntaxError
, getPos(), "Bad DCT sampling factor");
3558 if (compInfo
[i
].quantTable
< 0 || compInfo
[i
].quantTable
> 3) {
3559 error(errSyntaxError
, getPos(), "Bad DCT quant table selector");
3563 progressive
= gFalse
;
3567 GBool
DCTStream::readProgressiveSOF() {
3574 prec
= str
->getChar();
3577 numComps
= str
->getChar();
3579 error(errSyntaxError
, getPos(), "Bad DCT precision {0:d}", prec
);
3582 for (i
= 0; i
< numComps
; ++i
) {
3583 compInfo
[i
].id
= str
->getChar();
3585 compInfo
[i
].hSample
= (c
>> 4) & 0x0f;
3586 compInfo
[i
].vSample
= c
& 0x0f;
3587 compInfo
[i
].quantTable
= str
->getChar();
3588 if (compInfo
[i
].hSample
< 1 || compInfo
[i
].hSample
> 4 ||
3589 compInfo
[i
].vSample
< 1 || compInfo
[i
].vSample
> 4) {
3590 error(errSyntaxError
, getPos(), "Bad DCT sampling factor");
3593 if (compInfo
[i
].quantTable
< 0 || compInfo
[i
].quantTable
> 3) {
3594 error(errSyntaxError
, getPos(), "Bad DCT quant table selector");
3598 progressive
= gTrue
;
3602 GBool
DCTStream::readScanInfo() {
3607 length
= read16() - 2;
3608 scanInfo
.numComps
= str
->getChar();
3609 if (scanInfo
.numComps
<= 0 || scanInfo
.numComps
> 4) {
3610 error(errSyntaxError
, getPos(), "Bad number of components in DCT stream");
3611 scanInfo
.numComps
= 0;
3615 if (length
!= 2 * scanInfo
.numComps
+ 3) {
3616 error(errSyntaxError
, getPos(), "Bad DCT scan info block");
3619 interleaved
= scanInfo
.numComps
== numComps
;
3620 for (j
= 0; j
< numComps
; ++j
) {
3621 scanInfo
.comp
[j
] = gFalse
;
3622 scanInfo
.dcHuffTable
[j
] = 0;
3623 scanInfo
.acHuffTable
[j
] = 0;
3625 for (i
= 0; i
< scanInfo
.numComps
; ++i
) {
3626 id
= str
->getChar();
3627 // some (broken) DCT streams reuse ID numbers, but at least they
3628 // keep the components in order, so we check compInfo[i] first to
3629 // work around the problem
3630 if (id
== compInfo
[i
].id
) {
3633 for (j
= 0; j
< numComps
; ++j
) {
3634 if (id
== compInfo
[j
].id
) {
3638 if (j
== numComps
) {
3639 error(errSyntaxError
, getPos(),
3640 "Bad DCT component ID in scan info block");
3644 scanInfo
.comp
[j
] = gTrue
;
3646 scanInfo
.dcHuffTable
[j
] = (c
>> 4) & 0x0f;
3647 scanInfo
.acHuffTable
[j
] = c
& 0x0f;
3649 scanInfo
.firstCoeff
= str
->getChar();
3650 scanInfo
.lastCoeff
= str
->getChar();
3651 if (scanInfo
.firstCoeff
< 0 || scanInfo
.lastCoeff
> 63 ||
3652 scanInfo
.firstCoeff
> scanInfo
.lastCoeff
) {
3653 error(errSyntaxError
, getPos(),
3654 "Bad DCT coefficient numbers in scan info block");
3658 scanInfo
.ah
= (c
>> 4) & 0x0f;
3659 scanInfo
.al
= c
& 0x0f;
3663 GBool
DCTStream::readQuantTables() {
3664 int length
, prec
, i
, index
;
3666 length
= read16() - 2;
3667 while (length
> 0) {
3668 index
= str
->getChar();
3669 prec
= (index
>> 4) & 0x0f;
3671 if (prec
> 1 || index
>= 4) {
3672 error(errSyntaxError
, getPos(), "Bad DCT quantization table");
3675 if (index
== numQuantTables
) {
3676 numQuantTables
= index
+ 1;
3678 for (i
= 0; i
< 64; ++i
) {
3680 quantTables
[index
][dctZigZag
[i
]] = read16();
3682 quantTables
[index
][dctZigZag
[i
]] = str
->getChar();
3694 GBool
DCTStream::readHuffmanTables() {
3703 length
= read16() - 2;
3704 while (length
> 0) {
3705 index
= str
->getChar();
3707 if ((index
& 0x0f) >= 4) {
3708 error(errSyntaxError
, getPos(), "Bad DCT Huffman table");
3713 if (index
>= numACHuffTables
)
3714 numACHuffTables
= index
+1;
3715 tbl
= &acHuffTables
[index
];
3718 if (index
>= numDCHuffTables
)
3719 numDCHuffTables
= index
+1;
3720 tbl
= &dcHuffTables
[index
];
3724 for (i
= 1; i
<= 16; ++i
) {
3726 tbl
->firstSym
[i
] = sym
;
3727 tbl
->firstCode
[i
] = code
;
3728 tbl
->numCodes
[i
] = c
;
3730 code
= (code
+ c
) << 1;
3733 for (i
= 0; i
< sym
; ++i
)
3734 tbl
->sym
[i
] = str
->getChar();
3740 GBool
DCTStream::readRestartInterval() {
3745 error(errSyntaxError
, getPos(), "Bad DCT restart interval");
3748 restartInterval
= read16();
3752 GBool
DCTStream::readJFIFMarker() {
3760 for (i
= 0; i
< 5; ++i
) {
3761 if ((c
= str
->getChar()) == EOF
) {
3762 error(errSyntaxError
, getPos(), "Bad DCT APP0 marker");
3768 if (!memcmp(buf
, "JFIF\0", 5)) {
3769 gotJFIFMarker
= gTrue
;
3772 while (length
> 0) {
3773 if (str
->getChar() == EOF
) {
3774 error(errSyntaxError
, getPos(), "Bad DCT APP0 marker");
3782 GBool
DCTStream::readAdobeMarker() {
3791 for (i
= 0; i
< 12; ++i
) {
3792 if ((c
= str
->getChar()) == EOF
) {
3797 if (strncmp(buf
, "Adobe", 5)) {
3800 colorXform
= buf
[11];
3801 gotAdobeMarker
= gTrue
;
3802 for (i
= 14; i
< length
; ++i
) {
3803 if (str
->getChar() == EOF
) {
3810 error(errSyntaxError
, getPos(), "Bad DCT Adobe APP14 marker");
3814 GBool
DCTStream::readTrailer() {
3818 if (c
!= 0xd9) { // EOI
3819 error(errSyntaxError
, getPos(), "Bad DCT trailer");
3825 int DCTStream::readMarker() {
3831 } while (c
!= 0xff && c
!= EOF
);
3835 } while (c
== 0x00);
3839 int DCTStream::read16() {
3842 if ((c1
= str
->getChar()) == EOF
)
3844 if ((c2
= str
->getChar()) == EOF
)
3846 return (c1
<< 8) + c2
;
3849 GooString
*DCTStream::getPSFilter(int psLevel
, const char *indent
) {
3855 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
3858 s
->append(indent
)->append("<< >> /DCTDecode filter\n");
3862 GBool
DCTStream::isBinary(GBool last
) {
3863 return str
->isBinary(gTrue
);
3869 //------------------------------------------------------------------------
3871 //------------------------------------------------------------------------
3873 int FlateStream::codeLenCodeMap
[flateMaxCodeLenCodes
] = {
3874 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3877 FlateDecode
FlateStream::lengthDecode
[flateMaxLitCodes
-257] = {
3911 FlateDecode
FlateStream::distDecode
[flateMaxDistCodes
] = {
3944 static FlateCode flateFixedLitCodeTabCodes
[512] = {
4459 FlateHuffmanTab
FlateStream::fixedLitCodeTab
= {
4460 flateFixedLitCodeTabCodes
, 9
4463 static FlateCode flateFixedDistCodeTabCodes
[32] = {
4498 FlateHuffmanTab
FlateStream::fixedDistCodeTab
= {
4499 flateFixedDistCodeTabCodes
, 5
4502 FlateStream::FlateStream(Stream
*strA
, int predictor
, int columns
,
4503 int colors
, int bits
):
4504 FilterStream(strA
) {
4505 if (predictor
!= 1) {
4506 pred
= new StreamPredictor(this, predictor
, columns
, colors
, bits
);
4507 if (!pred
->isOk()) {
4514 litCodeTab
.codes
= NULL
;
4515 distCodeTab
.codes
= NULL
;
4516 memset(buf
, 0, flateWindow
);
4519 FlateStream::~FlateStream() {
4520 if (litCodeTab
.codes
!= fixedLitCodeTab
.codes
) {
4521 gfree(litCodeTab
.codes
);
4523 if (distCodeTab
.codes
!= fixedDistCodeTab
.codes
) {
4524 gfree(distCodeTab
.codes
);
4532 void FlateStream::flateReset(GBool unfiltered
) {
4534 str
->unfilteredReset();
4542 compressedBlock
= gFalse
;
4547 void FlateStream::unfilteredReset() {
4551 void FlateStream::reset() {
4557 //~ need to look at window size?
4558 endOfBlock
= eof
= gTrue
;
4559 cmf
= str
->getChar();
4560 flg
= str
->getChar();
4561 if (cmf
== EOF
|| flg
== EOF
)
4563 if ((cmf
& 0x0f) != 0x08) {
4564 error(errSyntaxError
, getPos(), "Unknown compression method in flate stream");
4567 if ((((cmf
<< 8) + flg
) % 31) != 0) {
4568 error(errSyntaxError
, getPos(), "Bad FCHECK in flate stream");
4572 error(errSyntaxError
, getPos(), "FDICT bit set in flate stream");
4579 int FlateStream::getChar() {
4581 return pred
->getChar();
4583 return doGetRawChar();
4586 int FlateStream::getChars(int nChars
, Guchar
*buffer
) {
4588 return pred
->getChars(nChars
, buffer
);
4590 for (int i
= 0; i
< nChars
; ++i
) {
4591 const int c
= doGetRawChar();
4592 if (likely(c
!= EOF
)) buffer
[i
] = c
;
4599 int FlateStream::lookChar() {
4603 return pred
->lookChar();
4605 while (remain
== 0) {
4606 if (endOfBlock
&& eof
)
4614 void FlateStream::getRawChars(int nChars
, int *buffer
) {
4615 for (int i
= 0; i
< nChars
; ++i
)
4616 buffer
[i
] = doGetRawChar();
4619 int FlateStream::getRawChar() {
4620 return doGetRawChar();
4623 GooString
*FlateStream::getPSFilter(int psLevel
, const char *indent
) {
4626 if (psLevel
< 3 || pred
) {
4629 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
4632 s
->append(indent
)->append("<< >> /FlateDecode filter\n");
4636 GBool
FlateStream::isBinary(GBool last
) {
4637 return str
->isBinary(gTrue
);
4640 void FlateStream::readSome() {
4651 if (compressedBlock
) {
4652 if ((code1
= getHuffmanCodeWord(&litCodeTab
)) == EOF
)
4657 } else if (code1
== 256) {
4662 code2
= lengthDecode
[code1
].bits
;
4663 if (code2
> 0 && (code2
= getCodeWord(code2
)) == EOF
)
4665 len
= lengthDecode
[code1
].first
+ code2
;
4666 if ((code1
= getHuffmanCodeWord(&distCodeTab
)) == EOF
)
4668 code2
= distDecode
[code1
].bits
;
4669 if (code2
> 0 && (code2
= getCodeWord(code2
)) == EOF
)
4671 dist
= distDecode
[code1
].first
+ code2
;
4673 j
= (index
- dist
) & flateMask
;
4674 for (k
= 0; k
< len
; ++k
) {
4676 i
= (i
+ 1) & flateMask
;
4677 j
= (j
+ 1) & flateMask
;
4683 len
= (blockLen
< flateWindow
) ? blockLen
: flateWindow
;
4684 for (i
= 0, j
= index
; i
< len
; ++i
, j
= (j
+ 1) & flateMask
) {
4685 if ((c
= str
->getChar()) == EOF
) {
4686 endOfBlock
= eof
= gTrue
;
4700 error(errSyntaxError
, getPos(), "Unexpected end of file in flate stream");
4701 endOfBlock
= eof
= gTrue
;
4705 GBool
FlateStream::startBlock() {
4710 // free the code tables from the previous block
4711 if (litCodeTab
.codes
!= fixedLitCodeTab
.codes
) {
4712 gfree(litCodeTab
.codes
);
4714 litCodeTab
.codes
= NULL
;
4715 if (distCodeTab
.codes
!= fixedDistCodeTab
.codes
) {
4716 gfree(distCodeTab
.codes
);
4718 distCodeTab
.codes
= NULL
;
4720 // read block header
4721 blockHdr
= getCodeWord(3);
4726 // uncompressed block
4727 if (blockHdr
== 0) {
4728 compressedBlock
= gFalse
;
4729 if ((c
= str
->getChar()) == EOF
)
4731 blockLen
= c
& 0xff;
4732 if ((c
= str
->getChar()) == EOF
)
4734 blockLen
|= (c
& 0xff) << 8;
4735 if ((c
= str
->getChar()) == EOF
)
4738 if ((c
= str
->getChar()) == EOF
)
4740 check
|= (c
& 0xff) << 8;
4741 if (check
!= (~blockLen
& 0xffff))
4742 error(errSyntaxError
, getPos(), "Bad uncompressed block length in flate stream");
4746 // compressed block with fixed codes
4747 } else if (blockHdr
== 1) {
4748 compressedBlock
= gTrue
;
4751 // compressed block with dynamic codes
4752 } else if (blockHdr
== 2) {
4753 compressedBlock
= gTrue
;
4754 if (!readDynamicCodes()) {
4758 // unknown block type
4763 endOfBlock
= gFalse
;
4767 error(errSyntaxError
, getPos(), "Bad block header in flate stream");
4768 endOfBlock
= eof
= gTrue
;
4772 void FlateStream::loadFixedCodes() {
4773 litCodeTab
.codes
= fixedLitCodeTab
.codes
;
4774 litCodeTab
.maxLen
= fixedLitCodeTab
.maxLen
;
4775 distCodeTab
.codes
= fixedDistCodeTab
.codes
;
4776 distCodeTab
.maxLen
= fixedDistCodeTab
.maxLen
;
4779 GBool
FlateStream::readDynamicCodes() {
4780 int numCodeLenCodes
;
4783 int codeLenCodeLengths
[flateMaxCodeLenCodes
];
4784 FlateHuffmanTab codeLenCodeTab
;
4785 int len
, repeat
, code
;
4788 codeLenCodeTab
.codes
= NULL
;
4791 if ((numLitCodes
= getCodeWord(5)) == EOF
) {
4795 if ((numDistCodes
= getCodeWord(5)) == EOF
) {
4799 if ((numCodeLenCodes
= getCodeWord(4)) == EOF
) {
4802 numCodeLenCodes
+= 4;
4803 if (numLitCodes
> flateMaxLitCodes
||
4804 numDistCodes
> flateMaxDistCodes
||
4805 numCodeLenCodes
> flateMaxCodeLenCodes
) {
4809 // build the code length code table
4810 for (i
= 0; i
< flateMaxCodeLenCodes
; ++i
) {
4811 codeLenCodeLengths
[i
] = 0;
4813 for (i
= 0; i
< numCodeLenCodes
; ++i
) {
4814 if ((codeLenCodeLengths
[codeLenCodeMap
[i
]] = getCodeWord(3)) == -1) {
4818 compHuffmanCodes(codeLenCodeLengths
, flateMaxCodeLenCodes
, &codeLenCodeTab
);
4820 // build the literal and distance code tables
4824 while (i
< numLitCodes
+ numDistCodes
) {
4825 if ((code
= getHuffmanCodeWord(&codeLenCodeTab
)) == EOF
) {
4829 if ((repeat
= getCodeWord(2)) == EOF
) {
4833 if (i
+ repeat
> numLitCodes
+ numDistCodes
) {
4836 for (; repeat
> 0; --repeat
) {
4837 codeLengths
[i
++] = len
;
4839 } else if (code
== 17) {
4840 if ((repeat
= getCodeWord(3)) == EOF
) {
4844 if (i
+ repeat
> numLitCodes
+ numDistCodes
) {
4848 for (; repeat
> 0; --repeat
) {
4849 codeLengths
[i
++] = 0;
4851 } else if (code
== 18) {
4852 if ((repeat
= getCodeWord(7)) == EOF
) {
4856 if (i
+ repeat
> numLitCodes
+ numDistCodes
) {
4860 for (; repeat
> 0; --repeat
) {
4861 codeLengths
[i
++] = 0;
4864 codeLengths
[i
++] = len
= code
;
4867 compHuffmanCodes(codeLengths
, numLitCodes
, &litCodeTab
);
4868 compHuffmanCodes(codeLengths
+ numLitCodes
, numDistCodes
, &distCodeTab
);
4870 gfree(codeLenCodeTab
.codes
);
4874 error(errSyntaxError
, getPos(), "Bad dynamic code table in flate stream");
4875 gfree(codeLenCodeTab
.codes
);
4879 // Convert an array <lengths> of <n> lengths, in value order, into a
4880 // Huffman code lookup table.
4881 void FlateStream::compHuffmanCodes(int *lengths
, int n
, FlateHuffmanTab
*tab
) {
4882 int tabSize
, len
, code
, code2
, skip
, val
, i
, t
;
4884 // find max code length
4886 for (val
= 0; val
< n
; ++val
) {
4887 if (lengths
[val
] > tab
->maxLen
) {
4888 tab
->maxLen
= lengths
[val
];
4892 // allocate the table
4893 tabSize
= 1 << tab
->maxLen
;
4894 tab
->codes
= (FlateCode
*)gmallocn(tabSize
, sizeof(FlateCode
));
4897 for (i
= 0; i
< tabSize
; ++i
) {
4898 tab
->codes
[i
].len
= 0;
4899 tab
->codes
[i
].val
= 0;
4903 for (len
= 1, code
= 0, skip
= 2;
4905 ++len
, code
<<= 1, skip
<<= 1) {
4906 for (val
= 0; val
< n
; ++val
) {
4907 if (lengths
[val
] == len
) {
4909 // bit-reverse the code
4912 for (i
= 0; i
< len
; ++i
) {
4913 code2
= (code2
<< 1) | (t
& 1);
4917 // fill in the table entries
4918 for (i
= code2
; i
< tabSize
; i
+= skip
) {
4919 tab
->codes
[i
].len
= (Gushort
)len
;
4920 tab
->codes
[i
].val
= (Gushort
)val
;
4929 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab
*tab
) {
4933 while (codeSize
< tab
->maxLen
) {
4934 if ((c
= str
->getChar()) == EOF
) {
4937 codeBuf
|= (c
& 0xff) << codeSize
;
4940 code
= &tab
->codes
[codeBuf
& ((1 << tab
->maxLen
) - 1)];
4941 if (codeSize
== 0 || codeSize
< code
->len
|| code
->len
== 0) {
4944 codeBuf
>>= code
->len
;
4945 codeSize
-= code
->len
;
4946 return (int)code
->val
;
4949 int FlateStream::getCodeWord(int bits
) {
4952 while (codeSize
< bits
) {
4953 if ((c
= str
->getChar()) == EOF
)
4955 codeBuf
|= (c
& 0xff) << codeSize
;
4958 c
= codeBuf
& ((1 << bits
) - 1);
4965 //------------------------------------------------------------------------
4967 //------------------------------------------------------------------------
4969 EOFStream::EOFStream(Stream
*strA
):
4970 FilterStream(strA
) {
4973 EOFStream::~EOFStream() {
4977 //------------------------------------------------------------------------
4979 //------------------------------------------------------------------------
4981 BufStream::BufStream(Stream
*strA
, int bufSizeA
): FilterStream(strA
) {
4983 buf
= (int *)gmallocn(bufSize
, sizeof(int));
4986 BufStream::~BufStream() {
4991 void BufStream::reset() {
4995 for (i
= 0; i
< bufSize
; ++i
) {
4996 buf
[i
] = str
->getChar();
5000 int BufStream::getChar() {
5004 for (i
= 1; i
< bufSize
; ++i
) {
5007 buf
[bufSize
- 1] = str
->getChar();
5011 int BufStream::lookChar() {
5015 int BufStream::lookChar(int idx
) {
5019 GBool
BufStream::isBinary(GBool last
) {
5020 return str
->isBinary(gTrue
);
5023 //------------------------------------------------------------------------
5024 // FixedLengthEncoder
5025 //------------------------------------------------------------------------
5027 FixedLengthEncoder::FixedLengthEncoder(Stream
*strA
, int lengthA
):
5028 FilterStream(strA
) {
5033 FixedLengthEncoder::~FixedLengthEncoder() {
5034 if (str
->isEncoder())
5038 void FixedLengthEncoder::reset() {
5043 int FixedLengthEncoder::getChar() {
5044 if (length
>= 0 && count
>= length
)
5047 return str
->getChar();
5050 int FixedLengthEncoder::lookChar() {
5051 if (length
>= 0 && count
>= length
)
5053 return str
->getChar();
5056 GBool
FixedLengthEncoder::isBinary(GBool last
) {
5057 return str
->isBinary(gTrue
);
5060 //------------------------------------------------------------------------
5062 //------------------------------------------------------------------------
5064 ASCIIHexEncoder::ASCIIHexEncoder(Stream
*strA
):
5065 FilterStream(strA
) {
5066 bufPtr
= bufEnd
= buf
;
5071 ASCIIHexEncoder::~ASCIIHexEncoder() {
5072 if (str
->isEncoder()) {
5077 void ASCIIHexEncoder::reset() {
5079 bufPtr
= bufEnd
= buf
;
5084 GBool
ASCIIHexEncoder::fillBuf() {
5085 static const char *hex
= "0123456789abcdef";
5091 bufPtr
= bufEnd
= buf
;
5092 if ((c
= str
->getChar()) == EOF
) {
5096 if (lineLen
>= 64) {
5100 *bufEnd
++ = hex
[(c
>> 4) & 0x0f];
5101 *bufEnd
++ = hex
[c
& 0x0f];
5107 //------------------------------------------------------------------------
5109 //------------------------------------------------------------------------
5111 ASCII85Encoder::ASCII85Encoder(Stream
*strA
):
5112 FilterStream(strA
) {
5113 bufPtr
= bufEnd
= buf
;
5118 ASCII85Encoder::~ASCII85Encoder() {
5119 if (str
->isEncoder())
5123 void ASCII85Encoder::reset() {
5125 bufPtr
= bufEnd
= buf
;
5130 GBool
ASCII85Encoder::fillBuf() {
5139 c0
= str
->getChar();
5140 c1
= str
->getChar();
5141 c2
= str
->getChar();
5142 c3
= str
->getChar();
5143 bufPtr
= bufEnd
= buf
;
5152 } else if (c2
== EOF
) {
5154 t
= (c0
<< 24) | (c1
<< 16);
5157 t
= (c0
<< 24) | (c1
<< 16) | (c2
<< 8);
5159 for (i
= 4; i
>= 0; --i
) {
5160 buf1
[i
] = (char)(t
% 85 + 0x21);
5163 for (i
= 0; i
<= n
; ++i
) {
5164 *bufEnd
++ = buf1
[i
];
5165 if (++lineLen
== 65) {
5175 t
= (c0
<< 24) | (c1
<< 16) | (c2
<< 8) | c3
;
5178 if (++lineLen
== 65) {
5183 for (i
= 4; i
>= 0; --i
) {
5184 buf1
[i
] = (char)(t
% 85 + 0x21);
5187 for (i
= 0; i
<= 4; ++i
) {
5188 *bufEnd
++ = buf1
[i
];
5189 if (++lineLen
== 65) {
5199 //------------------------------------------------------------------------
5201 //------------------------------------------------------------------------
5203 RunLengthEncoder::RunLengthEncoder(Stream
*strA
):
5204 FilterStream(strA
) {
5205 bufPtr
= bufEnd
= nextEnd
= buf
;
5209 RunLengthEncoder::~RunLengthEncoder() {
5210 if (str
->isEncoder())
5214 void RunLengthEncoder::reset() {
5216 bufPtr
= bufEnd
= nextEnd
= buf
;
5221 // When fillBuf finishes, buf[] looks like this:
5222 // +-----+--------------+-----------------+--
5223 // + tag | ... data ... | next 0, 1, or 2 |
5224 // +-----+--------------+-----------------+--
5226 // bufPtr bufEnd nextEnd
5228 GBool
RunLengthEncoder::fillBuf() {
5237 if (nextEnd
< bufEnd
+ 1) {
5238 if ((c1
= str
->getChar()) == EOF
) {
5243 c1
= bufEnd
[0] & 0xff;
5245 if (nextEnd
< bufEnd
+ 2) {
5246 if ((c2
= str
->getChar()) == EOF
) {
5255 c2
= bufEnd
[1] & 0xff;
5259 c
= 0; // make gcc happy
5262 while (n
< 128 && (c
= str
->getChar()) == c1
)
5264 buf
[0] = (char)(257 - n
);
5269 } else if (n
< 128) {
5276 // get up to 128 chars
5282 if ((c
= str
->getChar()) == EOF
) {
5288 if (buf
[n
] == buf
[n
-1])
5291 if (buf
[n
] == buf
[n
-1]) {
5292 buf
[0] = (char)(n
-2-1);
5294 nextEnd
= &buf
[n
+1];
5296 buf
[0] = (char)(n
-1);
5297 bufEnd
= nextEnd
= &buf
[n
+1];
5304 //------------------------------------------------------------------------
5306 //------------------------------------------------------------------------
5308 CMYKGrayEncoder::CMYKGrayEncoder(Stream
*strA
):
5309 FilterStream(strA
) {
5310 bufPtr
= bufEnd
= buf
;
5314 CMYKGrayEncoder::~CMYKGrayEncoder() {
5315 if (str
->isEncoder())
5319 void CMYKGrayEncoder::reset() {
5321 bufPtr
= bufEnd
= buf
;
5325 GBool
CMYKGrayEncoder::fillBuf() {
5332 c0
= str
->getChar();
5333 c1
= str
->getChar();
5334 c2
= str
->getChar();
5335 c3
= str
->getChar();
5340 i
= (3 * c0
+ 6 * c1
+ c2
) / 10 + c3
;
5341 if (i
> 255) i
= 255;
5342 bufPtr
= bufEnd
= buf
;
5343 *bufEnd
++ = (char) i
;
5347 //------------------------------------------------------------------------
5349 //------------------------------------------------------------------------
5351 RGBGrayEncoder::RGBGrayEncoder(Stream
*strA
):
5352 FilterStream(strA
) {
5353 bufPtr
= bufEnd
= buf
;
5357 RGBGrayEncoder::~RGBGrayEncoder() {
5358 if (str
->isEncoder())
5362 void RGBGrayEncoder::reset() {
5364 bufPtr
= bufEnd
= buf
;
5368 GBool
RGBGrayEncoder::fillBuf() {
5375 c0
= str
->getChar();
5376 c1
= str
->getChar();
5377 c2
= str
->getChar();
5382 i
= 255 - (3 * c0
+ 6 * c1
+ c2
) / 10;
5384 bufPtr
= bufEnd
= buf
;
5385 *bufEnd
++ = (char) i
;