1 //========================================================================
5 // Copyright 1996-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
33 #include "JBIG2Stream.h"
34 #include "JPXStream.h"
35 #include "Stream-CCITT.h"
38 static GBool setDJSYSFLAGS
= gFalse
;
49 //------------------------------------------------------------------------
50 // Stream (base class)
51 //------------------------------------------------------------------------
60 void Stream::close() {
63 int Stream::getRawChar() {
64 error(-1, "Internal: called getRawChar() on non-predictor stream");
68 char *Stream::getLine(char *buf
, int size
) {
72 if (lookChar() == EOF
)
74 for (i
= 0; i
< size
- 1; ++i
) {
76 if (c
== EOF
|| c
== '\n')
79 if ((c
= lookChar()) == '\n')
89 GString
*Stream::getPSFilter(int psLevel
, char *indent
) {
93 Stream
*Stream::addFilters(Object
*dict
) {
95 Object params
, params2
;
100 dict
->dictLookup("Filter", &obj
);
103 dict
->dictLookup("F", &obj
);
105 dict
->dictLookup("DecodeParms", ¶ms
);
106 if (params
.isNull()) {
108 dict
->dictLookup("DP", ¶ms
);
111 str
= makeFilter(obj
.getName(), str
, ¶ms
);
112 } else if (obj
.isArray()) {
113 for (i
= 0; i
< obj
.arrayGetLength(); ++i
) {
114 obj
.arrayGet(i
, &obj2
);
115 if (params
.isArray())
116 params
.arrayGet(i
, ¶ms2
);
120 str
= makeFilter(obj2
.getName(), str
, ¶ms2
);
122 error(getPos(), "Bad filter name");
123 str
= new EOFStream(str
);
128 } else if (!obj
.isNull()) {
129 error(getPos(), "Bad 'Filter' attribute in stream");
137 Stream
*Stream::makeFilter(char *name
, Stream
*str
, Object
*params
) {
138 int pred
; // parameters
143 GBool endOfLine
, byteAlign
, endOfBlock
, black
;
147 if (!strcmp(name
, "ASCIIHexDecode") || !strcmp(name
, "AHx")) {
148 str
= new ASCIIHexStream(str
);
149 } else if (!strcmp(name
, "ASCII85Decode") || !strcmp(name
, "A85")) {
150 str
= new ASCII85Stream(str
);
151 } else if (!strcmp(name
, "LZWDecode") || !strcmp(name
, "LZW")) {
157 if (params
->isDict()) {
158 params
->dictLookup("Predictor", &obj
);
162 params
->dictLookup("Columns", &obj
);
164 columns
= obj
.getInt();
166 params
->dictLookup("Colors", &obj
);
168 colors
= obj
.getInt();
170 params
->dictLookup("BitsPerComponent", &obj
);
174 params
->dictLookup("EarlyChange", &obj
);
176 early
= obj
.getInt();
179 str
= new LZWStream(str
, pred
, columns
, colors
, bits
, early
);
180 } else if (!strcmp(name
, "RunLengthDecode") || !strcmp(name
, "RL")) {
181 str
= new RunLengthStream(str
);
182 } else if (!strcmp(name
, "CCITTFaxDecode") || !strcmp(name
, "CCF")) {
190 if (params
->isDict()) {
191 params
->dictLookup("K", &obj
);
193 encoding
= obj
.getInt();
196 params
->dictLookup("EndOfLine", &obj
);
198 endOfLine
= obj
.getBool();
201 params
->dictLookup("EncodedByteAlign", &obj
);
203 byteAlign
= obj
.getBool();
206 params
->dictLookup("Columns", &obj
);
208 columns
= obj
.getInt();
211 params
->dictLookup("Rows", &obj
);
216 params
->dictLookup("EndOfBlock", &obj
);
218 endOfBlock
= obj
.getBool();
221 params
->dictLookup("BlackIs1", &obj
);
223 black
= obj
.getBool();
227 str
= new CCITTFaxStream(str
, encoding
, endOfLine
, byteAlign
,
228 columns
, rows
, endOfBlock
, black
);
229 } else if (!strcmp(name
, "DCTDecode") || !strcmp(name
, "DCT")) {
230 str
= new DCTStream(str
);
231 } else if (!strcmp(name
, "FlateDecode") || !strcmp(name
, "Fl")) {
236 if (params
->isDict()) {
237 params
->dictLookup("Predictor", &obj
);
241 params
->dictLookup("Columns", &obj
);
243 columns
= obj
.getInt();
245 params
->dictLookup("Colors", &obj
);
247 colors
= obj
.getInt();
249 params
->dictLookup("BitsPerComponent", &obj
);
254 str
= new FlateStream(str
, pred
, columns
, colors
, bits
);
255 } else if (!strcmp(name
, "JBIG2Decode")) {
256 if (params
->isDict()) {
257 params
->dictLookup("JBIG2Globals", &globals
);
259 str
= new JBIG2Stream(str
, &globals
);
261 } else if (!strcmp(name
, "JPXDecode")) {
262 str
= new JPXStream(str
);
264 error(getPos(), "Unknown filter '%s'", name
);
265 str
= new EOFStream(str
);
270 //------------------------------------------------------------------------
272 //------------------------------------------------------------------------
274 BaseStream::BaseStream(Object
*dictA
) {
279 BaseStream::~BaseStream() {
285 void BaseStream::doDecryption(Guchar
*fileKey
, int keyLength
,
286 int objNum
, int objGen
) {
287 decrypt
= new Decrypt(fileKey
, keyLength
, objNum
, objGen
);
290 //------------------------------------------------------------------------
292 //------------------------------------------------------------------------
294 FilterStream::FilterStream(Stream
*strA
) {
298 FilterStream::~FilterStream() {
301 void FilterStream::close() {
305 void FilterStream::setPos(Guint pos
, int dir
) {
306 error(-1, "Internal: called setPos() on FilterStream");
309 //------------------------------------------------------------------------
311 //------------------------------------------------------------------------
313 ImageStream::ImageStream(Stream
*strA
, int widthA
, int nCompsA
, int nBitsA
) {
321 nVals
= width
* nComps
;
323 imgLineSize
= (nVals
+ 7) & ~7;
327 imgLine
= (Guchar
*)gmallocn(imgLineSize
, sizeof(Guchar
));
331 ImageStream::~ImageStream() {
335 void ImageStream::reset() {
339 GBool
ImageStream::getPixel(Guchar
*pix
) {
342 if (imgIdx
>= nVals
) {
346 for (i
= 0; i
< nComps
; ++i
) {
347 pix
[i
] = imgLine
[imgIdx
++];
352 Guchar
*ImageStream::getLine() {
359 for (i
= 0; i
< nVals
; i
+= 8) {
361 imgLine
[i
+0] = (Guchar
)((c
>> 7) & 1);
362 imgLine
[i
+1] = (Guchar
)((c
>> 6) & 1);
363 imgLine
[i
+2] = (Guchar
)((c
>> 5) & 1);
364 imgLine
[i
+3] = (Guchar
)((c
>> 4) & 1);
365 imgLine
[i
+4] = (Guchar
)((c
>> 3) & 1);
366 imgLine
[i
+5] = (Guchar
)((c
>> 2) & 1);
367 imgLine
[i
+6] = (Guchar
)((c
>> 1) & 1);
368 imgLine
[i
+7] = (Guchar
)(c
& 1);
370 } else if (nBits
== 8) {
371 for (i
= 0; i
< nVals
; ++i
) {
372 imgLine
[i
] = str
->getChar();
375 bitMask
= (1 << nBits
) - 1;
378 for (i
= 0; i
< nVals
; ++i
) {
380 buf
= (buf
<< 8) | (str
->getChar() & 0xff);
383 imgLine
[i
] = (Guchar
)((buf
>> (bits
- nBits
)) & bitMask
);
390 void ImageStream::skipLine() {
393 n
= (nVals
* nBits
+ 7) >> 3;
394 for (i
= 0; i
< n
; ++i
) {
399 //------------------------------------------------------------------------
401 //------------------------------------------------------------------------
403 StreamPredictor::StreamPredictor(Stream
*strA
, int predictorA
,
404 int widthA
, int nCompsA
, int nBitsA
) {
406 predictor
= predictorA
;
413 nVals
= width
* nComps
;
414 if (width
<= 0 || nComps
<= 0 || nBits
<= 0 ||
415 nComps
>= INT_MAX
/ nBits
||
416 width
>= INT_MAX
/ nComps
/ nBits
||
417 nVals
* nBits
+ 7 < 0) {
420 pixBytes
= (nComps
* nBits
+ 7) >> 3;
421 rowBytes
= ((nVals
* nBits
+ 7) >> 3) + pixBytes
;
425 predLine
= (Guchar
*)gmalloc(rowBytes
);
426 memset(predLine
, 0, rowBytes
);
432 StreamPredictor::~StreamPredictor() {
436 int StreamPredictor::lookChar() {
437 if (predIdx
>= rowBytes
) {
438 if (!getNextLine()) {
442 return predLine
[predIdx
];
445 int StreamPredictor::getChar() {
446 if (predIdx
>= rowBytes
) {
447 if (!getNextLine()) {
451 return predLine
[predIdx
++];
454 GBool
StreamPredictor::getNextLine() {
456 Guchar upLeftBuf
[gfxColorMaxComps
* 2 + 1];
457 int left
, up
, upLeft
, p
, pa
, pb
, pc
;
459 Gulong inBuf
, outBuf
, bitMask
;
463 // get PNG optimum predictor number
464 if (predictor
>= 10) {
465 if ((curPred
= str
->getRawChar()) == EOF
) {
473 // read the raw line, apply PNG (byte) predictor
474 memset(upLeftBuf
, 0, pixBytes
+ 1);
475 for (i
= pixBytes
; i
< rowBytes
; ++i
) {
476 for (j
= pixBytes
; j
> 0; --j
) {
477 upLeftBuf
[j
] = upLeftBuf
[j
-1];
479 upLeftBuf
[0] = predLine
[i
];
480 if ((c
= str
->getRawChar()) == EOF
) {
482 // this ought to return false, but some (broken) PDF files
483 // contain truncated image data, and Adobe apparently reads the
491 predLine
[i
] = predLine
[i
- pixBytes
] + (Guchar
)c
;
494 predLine
[i
] = predLine
[i
] + (Guchar
)c
;
496 case 13: // PNG average
497 predLine
[i
] = ((predLine
[i
- pixBytes
] + predLine
[i
]) >> 1) +
500 case 14: // PNG Paeth
501 left
= predLine
[i
- pixBytes
];
503 upLeft
= upLeftBuf
[pixBytes
];
504 p
= left
+ up
- upLeft
;
505 if ((pa
= p
- left
) < 0)
507 if ((pb
= p
- up
) < 0)
509 if ((pc
= p
- upLeft
) < 0)
511 if (pa
<= pb
&& pa
<= pc
)
512 predLine
[i
] = left
+ (Guchar
)c
;
514 predLine
[i
] = up
+ (Guchar
)c
;
516 predLine
[i
] = upLeft
+ (Guchar
)c
;
519 default: // no predictor or TIFF predictor
520 predLine
[i
] = (Guchar
)c
;
525 // apply TIFF (component) predictor
526 if (predictor
== 2) {
528 inBuf
= predLine
[pixBytes
- 1];
529 for (i
= pixBytes
; i
< rowBytes
; i
+= 8) {
530 // 1-bit add is just xor
531 inBuf
= (inBuf
<< 8) | predLine
[i
];
532 predLine
[i
] ^= inBuf
>> nComps
;
534 } else if (nBits
== 8) {
535 for (i
= pixBytes
; i
< rowBytes
; ++i
) {
536 predLine
[i
] += predLine
[i
- nComps
];
539 memset(upLeftBuf
, 0, nComps
+ 1);
540 bitMask
= (1 << nBits
) - 1;
542 inBits
= outBits
= 0;
544 for (i
= 0; i
< width
; ++i
) {
545 for (kk
= 0; kk
< nComps
; ++kk
) {
546 if (inBits
< nBits
) {
547 inBuf
= (inBuf
<< 8) | (predLine
[j
++] & 0xff);
550 upLeftBuf
[kk
] = (upLeftBuf
[kk
] +
551 (inBuf
>> (inBits
- nBits
))) & bitMask
;
553 outBuf
= (outBuf
<< nBits
) | upLeftBuf
[kk
];
556 predLine
[k
++] = (Guchar
)(outBuf
>> (outBits
- 8));
562 predLine
[k
++] = (Guchar
)((outBuf
<< (8 - outBits
)) +
563 (inBuf
& ((1 << (8 - outBits
)) - 1)));
568 // reset to start of line
574 //------------------------------------------------------------------------
576 //------------------------------------------------------------------------
578 FileStream::FileStream(FILE *fA
, Guint startA
, GBool limitedA
,
579 Guint lengthA
, Object
*dictA
):
585 bufPtr
= bufEnd
= buf
;
591 FileStream::~FileStream() {
595 Stream
*FileStream::makeSubStream(Guint startA
, GBool limitedA
,
596 Guint lengthA
, Object
*dictA
) {
597 return new FileStream(f
, startA
, limitedA
, lengthA
, dictA
);
600 void FileStream::reset() {
602 savePos
= (Guint
)ftello(f
);
603 fseeko(f
, start
, SEEK_SET
);
605 savePos
= (Guint
)ftell64(f
);
606 fseek64(f
, start
, SEEK_SET
);
608 savePos
= (Guint
)ftell(f
);
609 fseek(f
, start
, SEEK_SET
);
612 bufPtr
= bufEnd
= buf
;
618 void FileStream::close() {
621 fseeko(f
, savePos
, SEEK_SET
);
623 fseek64(f
, savePos
, SEEK_SET
);
625 fseek(f
, savePos
, SEEK_SET
);
631 GBool
FileStream::fillBuf() {
635 bufPos
+= bufEnd
- buf
;
636 bufPtr
= bufEnd
= buf
;
637 if (limited
&& bufPos
>= start
+ length
) {
640 if (limited
&& bufPos
+ fileStreamBufSize
> start
+ length
) {
641 n
= start
+ length
- bufPos
;
643 n
= fileStreamBufSize
;
645 n
= fread(buf
, 1, n
, f
);
647 if (bufPtr
>= bufEnd
) {
651 for (p
= buf
; p
< bufEnd
; ++p
) {
652 *p
= (char)decrypt
->decryptByte((Guchar
)*p
);
658 void FileStream::setPos(Guint pos
, int dir
) {
663 fseeko(f
, pos
, SEEK_SET
);
665 fseek64(f
, pos
, SEEK_SET
);
667 fseek(f
, pos
, SEEK_SET
);
672 fseeko(f
, 0, SEEK_END
);
673 size
= (Guint
)ftello(f
);
675 fseek64(f
, 0, SEEK_END
);
676 size
= (Guint
)ftell64(f
);
678 fseek(f
, 0, SEEK_END
);
679 size
= (Guint
)ftell(f
);
684 //~ work around a bug in cygwin's implementation of fseek
688 fseeko(f
, -(int)pos
, SEEK_END
);
689 bufPos
= (Guint
)ftello(f
);
691 fseek64(f
, -(int)pos
, SEEK_END
);
692 bufPos
= (Guint
)ftell64(f
);
694 fseek(f
, -(int)pos
, SEEK_END
);
695 bufPos
= (Guint
)ftell(f
);
698 bufPtr
= bufEnd
= buf
;
701 void FileStream::moveStart(int delta
) {
703 bufPtr
= bufEnd
= buf
;
707 //------------------------------------------------------------------------
709 //------------------------------------------------------------------------
711 MemStream::MemStream(char *bufA
, Guint startA
, Guint lengthA
, Object
*dictA
):
716 bufEnd
= buf
+ start
+ length
;
717 bufPtr
= buf
+ start
;
721 MemStream::~MemStream() {
727 Stream
*MemStream::makeSubStream(Guint startA
, GBool limited
,
728 Guint lengthA
, Object
*dictA
) {
732 if (!limited
|| startA
+ lengthA
> start
+ length
) {
733 newLength
= start
+ length
- startA
;
737 subStr
= new MemStream(buf
, startA
, newLength
, dictA
);
741 void MemStream::reset() {
742 bufPtr
= buf
+ start
;
748 void MemStream::close() {
751 void MemStream::setPos(Guint pos
, int dir
) {
757 i
= start
+ length
- pos
;
761 } else if (i
> start
+ length
) {
767 void MemStream::moveStart(int delta
) {
770 bufPtr
= buf
+ start
;
773 void MemStream::doDecryption(Guchar
*fileKey
, int keyLength
,
774 int objNum
, int objGen
) {
778 this->BaseStream::doDecryption(fileKey
, keyLength
, objNum
, objGen
);
780 newBuf
= (char *)gmalloc(length
);
781 for (p
= buf
+ start
, q
= newBuf
; p
< bufEnd
; ++p
, ++q
) {
782 *q
= (char)decrypt
->decryptByte((Guchar
)*p
);
784 bufEnd
= newBuf
+ length
;
785 bufPtr
= newBuf
+ (bufPtr
- (buf
+ start
));
792 //------------------------------------------------------------------------
794 //------------------------------------------------------------------------
796 EmbedStream::EmbedStream(Stream
*strA
, Object
*dictA
,
797 GBool limitedA
, Guint lengthA
):
804 EmbedStream::~EmbedStream() {
807 Stream
*EmbedStream::makeSubStream(Guint start
, GBool limitedA
,
808 Guint lengthA
, Object
*dictA
) {
809 error(-1, "Internal: called makeSubStream() on EmbedStream");
813 int EmbedStream::getChar() {
814 if (limited
&& !length
) {
818 return str
->getChar();
821 int EmbedStream::lookChar() {
822 if (limited
&& !length
) {
825 return str
->lookChar();
828 void EmbedStream::setPos(Guint pos
, int dir
) {
829 error(-1, "Internal: called setPos() on EmbedStream");
832 Guint
EmbedStream::getStart() {
833 error(-1, "Internal: called getStart() on EmbedStream");
837 void EmbedStream::moveStart(int delta
) {
838 error(-1, "Internal: called moveStart() on EmbedStream");
841 //------------------------------------------------------------------------
843 //------------------------------------------------------------------------
845 ASCIIHexStream::ASCIIHexStream(Stream
*strA
):
851 ASCIIHexStream::~ASCIIHexStream() {
855 void ASCIIHexStream::reset() {
861 int ASCIIHexStream::lookChar() {
872 } while (isspace(c1
));
880 } while (isspace(c2
));
885 if (c1
>= '0' && c1
<= '9') {
887 } else if (c1
>= 'A' && c1
<= 'F') {
888 x
= (c1
- 'A' + 10) << 4;
889 } else if (c1
>= 'a' && c1
<= 'f') {
890 x
= (c1
- 'a' + 10) << 4;
891 } else if (c1
== EOF
) {
895 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1
);
898 if (c2
>= '0' && c2
<= '9') {
900 } else if (c2
>= 'A' && c2
<= 'F') {
902 } else if (c2
>= 'a' && c2
<= 'f') {
904 } else if (c2
== EOF
) {
908 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2
);
914 GString
*ASCIIHexStream::getPSFilter(int psLevel
, char *indent
) {
920 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
923 s
->append(indent
)->append("/ASCIIHexDecode filter\n");
927 GBool
ASCIIHexStream::isBinary(GBool last
) {
928 return str
->isBinary(gFalse
);
931 //------------------------------------------------------------------------
933 //------------------------------------------------------------------------
935 ASCII85Stream::ASCII85Stream(Stream
*strA
):
941 ASCII85Stream::~ASCII85Stream() {
945 void ASCII85Stream::reset() {
951 int ASCII85Stream::lookChar() {
960 c
[0] = str
->getChar();
961 } while (Lexer::isSpace(c
[0]));
962 if (c
[0] == '~' || c
[0] == EOF
) {
966 } else if (c
[0] == 'z') {
967 b
[0] = b
[1] = b
[2] = b
[3] = 0;
970 for (k
= 1; k
< 5; ++k
) {
972 c
[k
] = str
->getChar();
973 } while (Lexer::isSpace(c
[k
]));
974 if (c
[k
] == '~' || c
[k
] == EOF
)
978 if (k
< 5 && (c
[k
] == '~' || c
[k
] == EOF
)) {
979 for (++k
; k
< 5; ++k
)
984 for (k
= 0; k
< 5; ++k
)
985 t
= t
* 85 + (c
[k
] - 0x21);
986 for (k
= 3; k
>= 0; --k
) {
987 b
[k
] = (int)(t
& 0xff);
995 GString
*ASCII85Stream::getPSFilter(int psLevel
, char *indent
) {
1001 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1004 s
->append(indent
)->append("/ASCII85Decode filter\n");
1008 GBool
ASCII85Stream::isBinary(GBool last
) {
1009 return str
->isBinary(gFalse
);
1012 //------------------------------------------------------------------------
1014 //------------------------------------------------------------------------
1016 LZWStream::LZWStream(Stream
*strA
, int predictor
, int columns
, int colors
,
1017 int bits
, int earlyA
):
1018 FilterStream(strA
) {
1019 if (predictor
!= 1) {
1020 pred
= new StreamPredictor(this, predictor
, columns
, colors
, bits
);
1021 if (!pred
->isOk()) {
1034 LZWStream::~LZWStream() {
1041 int LZWStream::getChar() {
1043 return pred
->getChar();
1048 if (seqIndex
>= seqLength
) {
1049 if (!processNextCode()) {
1053 return seqBuf
[seqIndex
++];
1056 int LZWStream::lookChar() {
1058 return pred
->lookChar();
1063 if (seqIndex
>= seqLength
) {
1064 if (!processNextCode()) {
1068 return seqBuf
[seqIndex
];
1071 int LZWStream::getRawChar() {
1075 if (seqIndex
>= seqLength
) {
1076 if (!processNextCode()) {
1080 return seqBuf
[seqIndex
++];
1083 void LZWStream::reset() {
1090 GBool
LZWStream::processNextCode() {
1100 // check for eod and clear-table codes
1103 if (code
== EOF
|| code
== 257) {
1111 if (nextCode
>= 4097) {
1112 error(getPos(), "Bad LZW stream - expected clear-table code");
1116 // process the next code
1117 nextLength
= seqLength
+ 1;
1121 } else if (code
< nextCode
) {
1122 seqLength
= table
[code
].length
;
1123 for (i
= seqLength
- 1, j
= code
; i
> 0; --i
) {
1124 seqBuf
[i
] = table
[j
].tail
;
1128 } else if (code
== nextCode
) {
1129 seqBuf
[seqLength
] = newChar
;
1132 error(getPos(), "Bad LZW stream - unexpected code");
1136 newChar
= seqBuf
[0];
1140 table
[nextCode
].length
= nextLength
;
1141 table
[nextCode
].head
= prevCode
;
1142 table
[nextCode
].tail
= newChar
;
1144 if (nextCode
+ early
== 512)
1146 else if (nextCode
+ early
== 1024)
1148 else if (nextCode
+ early
== 2048)
1159 void LZWStream::clearTable() {
1162 seqIndex
= seqLength
= 0;
1166 int LZWStream::getCode() {
1170 while (inputBits
< nextBits
) {
1171 if ((c
= str
->getChar()) == EOF
)
1173 inputBuf
= (inputBuf
<< 8) | (c
& 0xff);
1176 code
= (inputBuf
>> (inputBits
- nextBits
)) & ((1 << nextBits
) - 1);
1177 inputBits
-= nextBits
;
1181 GString
*LZWStream::getPSFilter(int psLevel
, char *indent
) {
1184 if (psLevel
< 2 || pred
) {
1187 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1190 s
->append(indent
)->append("<< ");
1192 s
->append("/EarlyChange 0 ");
1194 s
->append(">> /LZWDecode filter\n");
1198 GBool
LZWStream::isBinary(GBool last
) {
1199 return str
->isBinary(gTrue
);
1202 //------------------------------------------------------------------------
1204 //------------------------------------------------------------------------
1206 RunLengthStream::RunLengthStream(Stream
*strA
):
1207 FilterStream(strA
) {
1208 bufPtr
= bufEnd
= buf
;
1212 RunLengthStream::~RunLengthStream() {
1216 void RunLengthStream::reset() {
1218 bufPtr
= bufEnd
= buf
;
1222 GString
*RunLengthStream::getPSFilter(int psLevel
, char *indent
) {
1228 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1231 s
->append(indent
)->append("/RunLengthDecode filter\n");
1235 GBool
RunLengthStream::isBinary(GBool last
) {
1236 return str
->isBinary(gTrue
);
1239 GBool
RunLengthStream::fillBuf() {
1246 if (c
== 0x80 || c
== EOF
) {
1252 for (i
= 0; i
< n
; ++i
)
1253 buf
[i
] = (char)str
->getChar();
1257 for (i
= 0; i
< n
; ++i
)
1265 //------------------------------------------------------------------------
1267 //------------------------------------------------------------------------
1269 CCITTFaxStream::CCITTFaxStream(Stream
*strA
, int encodingA
, GBool endOfLineA
,
1270 GBool byteAlignA
, int columnsA
, int rowsA
,
1271 GBool endOfBlockA
, GBool blackA
):
1272 FilterStream(strA
) {
1273 encoding
= encodingA
;
1274 endOfLine
= endOfLineA
;
1275 byteAlign
= byteAlignA
;
1280 if (columns
+ 4 <= 0) {
1281 columns
= INT_MAX
- 4;
1284 endOfBlock
= endOfBlockA
;
1286 refLine
= (short *)gmallocn(columns
+ 4, sizeof(short));
1287 codingLine
= (short *)gmallocn(columns
+ 3, sizeof(short));
1291 nextLine2D
= encoding
< 0;
1294 codingLine
[1] = refLine
[2] = columns
;
1300 CCITTFaxStream::~CCITTFaxStream() {
1306 void CCITTFaxStream::reset() {
1312 nextLine2D
= encoding
< 0;
1315 codingLine
[1] = refLine
[2] = columns
;
1319 // skip any initial zero bits and end-of-line marker, and get the 2D
1321 while ((code1
= lookBits(12)) == 0) {
1324 if (code1
== 0x001) {
1328 nextLine2D
= !lookBits(1);
1333 int CCITTFaxStream::lookChar() {
1334 short code1
, code2
, code3
;
1340 // if at eof just return EOF
1341 if (eof
&& codingLine
[a0
] >= columns
) {
1345 // read the next row
1347 if (codingLine
[a0
] >= columns
) {
1351 for (i
= 0; codingLine
[i
] < columns
; ++i
)
1352 refLine
[i
] = codingLine
[i
];
1353 refLine
[i
] = refLine
[i
+ 1] = columns
;
1355 a0New
= codingLine
[a0
= 0] = 0;
1357 code1
= getTwoDimCode();
1360 if (refLine
[b1
] < columns
) {
1361 a0New
= refLine
[b1
+ 1];
1366 if ((a0
& 1) == 0) {
1369 code1
+= code3
= getWhiteCode();
1370 } while (code3
>= 64);
1372 code2
+= code3
= getBlackCode();
1373 } while (code3
>= 64);
1377 code1
+= code3
= getBlackCode();
1378 } while (code3
>= 64);
1380 code2
+= code3
= getWhiteCode();
1381 } while (code3
>= 64);
1383 if (code1
> 0 || code2
> 0) {
1384 codingLine
[a0
+ 1] = a0New
+ code1
;
1386 a0New
= codingLine
[a0
+ 1] = codingLine
[a0
] + code2
;
1388 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1393 a0New
= codingLine
[++a0
] = refLine
[b1
];
1394 if (refLine
[b1
] < columns
) {
1396 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1401 a0New
= codingLine
[++a0
] = refLine
[b1
] + 1;
1402 if (refLine
[b1
] < columns
) {
1404 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1409 if (a0
== 0 || refLine
[b1
] - 1 > a0New
) {
1410 a0New
= codingLine
[++a0
] = refLine
[b1
] - 1;
1412 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1417 a0New
= codingLine
[++a0
] = refLine
[b1
] + 2;
1418 if (refLine
[b1
] < columns
) {
1420 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1425 if (a0
== 0 || refLine
[b1
] - 2 > a0New
) {
1426 a0New
= codingLine
[++a0
] = refLine
[b1
] - 2;
1428 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1433 a0New
= codingLine
[++a0
] = refLine
[b1
] + 3;
1434 if (refLine
[b1
] < columns
) {
1436 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1441 if (a0
== 0 || refLine
[b1
] - 3 > a0New
) {
1442 a0New
= codingLine
[++a0
] = refLine
[b1
] - 3;
1444 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1450 codingLine
[a0
= 0] = columns
;
1453 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1
);
1457 } while (codingLine
[a0
] < columns
);
1461 codingLine
[a0
= 0] = 0;
1465 code1
+= code3
= getWhiteCode();
1466 } while (code3
>= 64);
1467 codingLine
[a0
+1] = codingLine
[a0
] + code1
;
1469 if (codingLine
[a0
] >= columns
)
1473 code2
+= code3
= getBlackCode();
1474 } while (code3
>= 64);
1475 codingLine
[a0
+1] = codingLine
[a0
] + code2
;
1477 if (codingLine
[a0
] >= columns
)
1482 if (codingLine
[a0
] != columns
) {
1483 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine
[a0
]);
1484 // force the row to be the correct length
1485 while (codingLine
[a0
] > columns
) {
1488 codingLine
[++a0
] = columns
;
1492 // byte-align the row
1497 // check for end-of-line marker, skipping over any extra zero bits
1499 if (!endOfBlock
&& row
== rows
- 1) {
1502 code1
= lookBits(12);
1503 while (code1
== 0) {
1505 code1
= lookBits(12);
1507 if (code1
== 0x001) {
1510 } else if (code1
== EOF
) {
1515 // get 2D encoding tag
1516 if (!eof
&& encoding
> 0) {
1517 nextLine2D
= !lookBits(1);
1521 // check for end-of-block marker
1522 if (endOfBlock
&& gotEOL
) {
1523 code1
= lookBits(12);
1524 if (code1
== 0x001) {
1530 if (encoding
>= 0) {
1531 for (i
= 0; i
< 4; ++i
) {
1532 code1
= lookBits(12);
1533 if (code1
!= 0x001) {
1534 error(getPos(), "Bad RTC code in CCITTFax stream");
1546 // look for an end-of-line marker after an error -- we only do
1547 // this if we know the stream contains end-of-line markers because
1548 // the "just plow on" technique tends to work better otherwise
1549 } else if (err
&& endOfLine
) {
1556 code1
= lookBits(13);
1557 } while ((code1
>> 1) != 0x001);
1561 nextLine2D
= !(code1
& 1);
1566 outputBits
= codingLine
[1] - codingLine
[0];
1567 if (outputBits
== 0) {
1569 outputBits
= codingLine
[2] - codingLine
[1];
1576 if (outputBits
>= 8) {
1577 ret
= ((a0
& 1) == 0) ? 0xff : 0x00;
1578 if ((outputBits
-= 8) == 0) {
1580 if (codingLine
[a0
] < columns
) {
1581 outputBits
= codingLine
[a0
+ 1] - codingLine
[a0
];
1588 if (outputBits
> bits
) {
1591 if ((a0
& 1) == 0) {
1592 ret
|= 0xff >> (8 - i
);
1598 if ((a0
& 1) == 0) {
1599 ret
|= (0xff >> (8 - i
)) << bits
;
1603 if (codingLine
[a0
] < columns
) {
1604 outputBits
= codingLine
[a0
+ 1] - codingLine
[a0
];
1607 } while (bits
> 0 && codingLine
[a0
] < columns
);
1609 buf
= black
? (ret
^ 0xff) : ret
;
1613 short CCITTFaxStream::getTwoDimCode() {
1618 code
= 0; // make gcc happy
1621 p
= &twoDimTab1
[code
];
1627 for (n
= 1; n
<= 7; ++n
) {
1632 p
= &twoDimTab1
[code
];
1639 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code
);
1643 short CCITTFaxStream::getWhiteCode() {
1648 code
= 0; // make gcc happy
1650 code
= lookBits(12);
1651 if ((code
>> 5) == 0) {
1652 p
= &whiteTab1
[code
];
1654 p
= &whiteTab2
[code
>> 3];
1661 for (n
= 1; n
<= 9; ++n
) {
1666 p
= &whiteTab2
[code
];
1672 for (n
= 11; n
<= 12; ++n
) {
1677 p
= &whiteTab1
[code
];
1684 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code
);
1685 // eat a bit and return a positive number so that the caller doesn't
1686 // go into an infinite loop
1691 short CCITTFaxStream::getBlackCode() {
1696 code
= 0; // make gcc happy
1698 code
= lookBits(13);
1699 if ((code
>> 7) == 0) {
1700 p
= &blackTab1
[code
];
1701 } else if ((code
>> 9) == 0) {
1702 p
= &blackTab2
[(code
>> 1) - 64];
1704 p
= &blackTab3
[code
>> 7];
1711 for (n
= 2; n
<= 6; ++n
) {
1716 p
= &blackTab3
[code
];
1722 for (n
= 7; n
<= 12; ++n
) {
1728 p
= &blackTab2
[code
- 64];
1735 for (n
= 10; n
<= 13; ++n
) {
1740 p
= &blackTab1
[code
];
1747 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code
);
1748 // eat a bit and return a positive number so that the caller doesn't
1749 // go into an infinite loop
1754 short CCITTFaxStream::lookBits(int n
) {
1757 while (inputBits
< n
) {
1758 if ((c
= str
->getChar()) == EOF
) {
1759 if (inputBits
== 0) {
1762 // near the end of the stream, the caller may ask for more bits
1763 // than are available, but there may still be a valid code in
1764 // however many bits are available -- we need to return correct
1765 // data in this case
1766 return (inputBuf
<< (n
- inputBits
)) & (0xffff >> (16 - n
));
1768 inputBuf
= (inputBuf
<< 8) + c
;
1771 return (inputBuf
>> (inputBits
- n
)) & (0xffff >> (16 - n
));
1774 GString
*CCITTFaxStream::getPSFilter(int psLevel
, char *indent
) {
1781 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1784 s
->append(indent
)->append("<< ");
1785 if (encoding
!= 0) {
1786 sprintf(s1
, "/K %d ", encoding
);
1790 s
->append("/EndOfLine true ");
1793 s
->append("/EncodedByteAlign true ");
1795 sprintf(s1
, "/Columns %d ", columns
);
1798 sprintf(s1
, "/Rows %d ", rows
);
1802 s
->append("/EndOfBlock false ");
1805 s
->append("/BlackIs1 true ");
1807 s
->append(">> /CCITTFaxDecode filter\n");
1811 GBool
CCITTFaxStream::isBinary(GBool last
) {
1812 return str
->isBinary(gTrue
);
1815 //------------------------------------------------------------------------
1817 //------------------------------------------------------------------------
1819 // IDCT constants (20.12 fixed point format)
1820 #define dctCos1 4017 // cos(pi/16)
1821 #define dctSin1 799 // sin(pi/16)
1822 #define dctCos3 3406 // cos(3*pi/16)
1823 #define dctSin3 2276 // sin(3*pi/16)
1824 #define dctCos6 1567 // cos(6*pi/16)
1825 #define dctSin6 3784 // sin(6*pi/16)
1826 #define dctSqrt2 5793 // sqrt(2)
1827 #define dctSqrt1d2 2896 // sqrt(2) / 2
1829 // color conversion parameters (16.16 fixed point format)
1830 #define dctCrToR 91881 // 1.4020
1831 #define dctCbToG -22553 // -0.3441363
1832 #define dctCrToG -46802 // -0.71413636
1833 #define dctCbToB 116130 // 1.772
1835 // clip [-256,511] --> [0,255]
1836 #define dctClipOffset 256
1837 static Guchar dctClip
[768];
1838 static int dctClipInit
= 0;
1840 // zig zag decode map
1841 static int dctZigZag
[64] = {
1847 5, 12, 19, 26, 33, 40,
1848 48, 41, 34, 27, 20, 13, 6,
1849 7, 14, 21, 28, 35, 42, 49, 56,
1850 57, 50, 43, 36, 29, 22, 15,
1851 23, 30, 37, 44, 51, 58,
1859 DCTStream::DCTStream(Stream
*strA
):
1860 FilterStream(strA
) {
1863 progressive
= interleaved
= gFalse
;
1865 mcuWidth
= mcuHeight
= 0;
1869 for (i
= 0; i
< 4; ++i
) {
1870 for (j
= 0; j
< 32; ++j
) {
1871 rowBuf
[i
][j
] = NULL
;
1877 for (i
= -256; i
< 0; ++i
)
1878 dctClip
[dctClipOffset
+ i
] = 0;
1879 for (i
= 0; i
< 256; ++i
)
1880 dctClip
[dctClipOffset
+ i
] = i
;
1881 for (i
= 256; i
< 512; ++i
)
1882 dctClip
[dctClipOffset
+ i
] = 255;
1887 DCTStream::~DCTStream() {
1891 if (progressive
|| !interleaved
) {
1892 for (i
= 0; i
< numComps
; ++i
) {
1896 for (i
= 0; i
< numComps
; ++i
) {
1897 for (j
= 0; j
< mcuHeight
; ++j
) {
1898 gfree(rowBuf
[i
][j
]);
1904 void DCTStream::reset() {
1909 progressive
= interleaved
= gFalse
;
1913 numDCHuffTables
= 0;
1914 numACHuffTables
= 0;
1916 gotJFIFMarker
= gFalse
;
1917 gotAdobeMarker
= gFalse
;
1918 restartInterval
= 0;
1920 if (!readHeader()) {
1926 if (numComps
== 1) {
1927 compInfo
[0].hSample
= compInfo
[0].vSample
= 1;
1929 mcuWidth
= compInfo
[0].hSample
;
1930 mcuHeight
= compInfo
[0].vSample
;
1931 for (i
= 1; i
< numComps
; ++i
) {
1932 if (compInfo
[i
].hSample
> mcuWidth
) {
1933 mcuWidth
= compInfo
[i
].hSample
;
1935 if (compInfo
[i
].vSample
> mcuHeight
) {
1936 mcuHeight
= compInfo
[i
].vSample
;
1942 // figure out color transform
1943 if (!gotAdobeMarker
&& numComps
== 3) {
1944 if (gotJFIFMarker
) {
1946 } else if (compInfo
[0].id
== 82 && compInfo
[1].id
== 71 &&
1947 compInfo
[2].id
== 66) { // ASCII "RGB"
1954 if (progressive
|| !interleaved
) {
1956 // allocate a buffer for the whole image
1957 bufWidth
= ((width
+ mcuWidth
- 1) / mcuWidth
) * mcuWidth
;
1958 bufHeight
= ((height
+ mcuHeight
- 1) / mcuHeight
) * mcuHeight
;
1959 for (i
= 0; i
< numComps
; ++i
) {
1960 frameBuf
[i
] = (int *)gmallocn(bufWidth
* bufHeight
, sizeof(int));
1961 memset(frameBuf
[i
], 0, bufWidth
* bufHeight
* sizeof(int));
1964 // read the image data
1966 restartMarker
= 0xd0;
1969 } while (readHeader());
1974 // initialize counters
1981 // allocate a buffer for one row of MCUs
1982 bufWidth
= ((width
+ mcuWidth
- 1) / mcuWidth
) * mcuWidth
;
1983 for (i
= 0; i
< numComps
; ++i
) {
1984 for (j
= 0; j
< mcuHeight
; ++j
) {
1985 rowBuf
[i
][j
] = (Guchar
*)gmallocn(bufWidth
, sizeof(Guchar
));
1989 // initialize counters
1995 restartMarker
= 0xd0;
2000 int DCTStream::getChar() {
2006 if (progressive
|| !interleaved
) {
2007 c
= frameBuf
[comp
][y
* bufWidth
+ x
];
2008 if (++comp
== numComps
) {
2016 if (dy
>= mcuHeight
) {
2017 if (!readMCURow()) {
2025 c
= rowBuf
[comp
][dy
][x
];
2026 if (++comp
== numComps
) {
2041 int DCTStream::lookChar() {
2045 if (progressive
|| !interleaved
) {
2046 return frameBuf
[comp
][y
* bufWidth
+ x
];
2048 if (dy
>= mcuHeight
) {
2049 if (!readMCURow()) {
2057 return rowBuf
[comp
][dy
][x
];
2061 void DCTStream::restart() {
2065 restartCtr
= restartInterval
;
2066 for (i
= 0; i
< numComps
; ++i
) {
2067 compInfo
[i
].prevDC
= 0;
2072 // Read one row of MCUs from a sequential JPEG stream.
2073 GBool
DCTStream::readMCURow() {
2077 int pY
, pCb
, pCr
, pR
, pG
, pB
;
2078 int h
, v
, horiz
, vert
, hSub
, vSub
;
2079 int x1
, x2
, y2
, x3
, y3
, x4
, y4
, x5
, y5
, cc
, i
;
2082 for (x1
= 0; x1
< width
; x1
+= mcuWidth
) {
2084 // deal with restart marker
2085 if (restartInterval
> 0 && restartCtr
== 0) {
2087 if (c
!= restartMarker
) {
2088 error(getPos(), "Bad DCT data: incorrect restart marker");
2091 if (++restartMarker
== 0xd8)
2092 restartMarker
= 0xd0;
2097 for (cc
= 0; cc
< numComps
; ++cc
) {
2098 h
= compInfo
[cc
].hSample
;
2099 v
= compInfo
[cc
].vSample
;
2100 horiz
= mcuWidth
/ h
;
2101 vert
= mcuHeight
/ v
;
2104 for (y2
= 0; y2
< mcuHeight
; y2
+= vert
) {
2105 for (x2
= 0; x2
< mcuWidth
; x2
+= horiz
) {
2106 if (!readDataUnit(&dcHuffTables
[scanInfo
.dcHuffTable
[cc
]],
2107 &acHuffTables
[scanInfo
.acHuffTable
[cc
]],
2108 &compInfo
[cc
].prevDC
,
2112 transformDataUnit(quantTables
[compInfo
[cc
].quantTable
],
2114 if (hSub
== 1 && vSub
== 1) {
2115 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2116 p1
= &rowBuf
[cc
][y2
+y3
][x1
+x2
];
2126 } else if (hSub
== 2 && vSub
== 2) {
2127 for (y3
= 0, i
= 0; y3
< 16; y3
+= 2, i
+= 8) {
2128 p1
= &rowBuf
[cc
][y2
+y3
][x1
+x2
];
2129 p2
= &rowBuf
[cc
][y2
+y3
+1][x1
+x2
];
2130 p1
[0] = p1
[1] = p2
[0] = p2
[1] = data2
[i
];
2131 p1
[2] = p1
[3] = p2
[2] = p2
[3] = data2
[i
+1];
2132 p1
[4] = p1
[5] = p2
[4] = p2
[5] = data2
[i
+2];
2133 p1
[6] = p1
[7] = p2
[6] = p2
[7] = data2
[i
+3];
2134 p1
[8] = p1
[9] = p2
[8] = p2
[9] = data2
[i
+4];
2135 p1
[10] = p1
[11] = p2
[10] = p2
[11] = data2
[i
+5];
2136 p1
[12] = p1
[13] = p2
[12] = p2
[13] = data2
[i
+6];
2137 p1
[14] = p1
[15] = p2
[14] = p2
[15] = data2
[i
+7];
2141 for (y3
= 0, y4
= 0; y3
< 8; ++y3
, y4
+= vSub
) {
2142 for (x3
= 0, x4
= 0; x3
< 8; ++x3
, x4
+= hSub
) {
2143 for (y5
= 0; y5
< vSub
; ++y5
)
2144 for (x5
= 0; x5
< hSub
; ++x5
)
2145 rowBuf
[cc
][y2
+y4
+y5
][x1
+x2
+x4
+x5
] = data2
[i
];
2155 // color space conversion
2157 // convert YCbCr to RGB
2158 if (numComps
== 3) {
2159 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2160 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2161 pY
= rowBuf
[0][y2
][x1
+x2
];
2162 pCb
= rowBuf
[1][y2
][x1
+x2
] - 128;
2163 pCr
= rowBuf
[2][y2
][x1
+x2
] - 128;
2164 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2165 rowBuf
[0][y2
][x1
+x2
] = dctClip
[dctClipOffset
+ pR
];
2166 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+ 32768) >> 16;
2167 rowBuf
[1][y2
][x1
+x2
] = dctClip
[dctClipOffset
+ pG
];
2168 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2169 rowBuf
[2][y2
][x1
+x2
] = dctClip
[dctClipOffset
+ pB
];
2172 // convert YCbCrK to CMYK (K is passed through unchanged)
2173 } else if (numComps
== 4) {
2174 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2175 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2176 pY
= rowBuf
[0][y2
][x1
+x2
];
2177 pCb
= rowBuf
[1][y2
][x1
+x2
] - 128;
2178 pCr
= rowBuf
[2][y2
][x1
+x2
] - 128;
2179 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2180 rowBuf
[0][y2
][x1
+x2
] = 255 - dctClip
[dctClipOffset
+ pR
];
2181 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+ 32768) >> 16;
2182 rowBuf
[1][y2
][x1
+x2
] = 255 - dctClip
[dctClipOffset
+ pG
];
2183 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2184 rowBuf
[2][y2
][x1
+x2
] = 255 - dctClip
[dctClipOffset
+ pB
];
2193 // Read one scan from a progressive or non-interleaved JPEG stream.
2194 void DCTStream::readScan() {
2196 int x1
, y1
, dx1
, dy1
, x2
, y2
, y3
, cc
, i
;
2197 int h
, v
, horiz
, vert
, vSub
;
2201 if (scanInfo
.numComps
== 1) {
2202 for (cc
= 0; cc
< numComps
; ++cc
) {
2203 if (scanInfo
.comp
[cc
]) {
2207 dx1
= mcuWidth
/ compInfo
[cc
].hSample
;
2208 dy1
= mcuHeight
/ compInfo
[cc
].vSample
;
2214 for (y1
= 0; y1
< height
; y1
+= dy1
) {
2215 for (x1
= 0; x1
< width
; x1
+= dx1
) {
2217 // deal with restart marker
2218 if (restartInterval
> 0 && restartCtr
== 0) {
2220 if (c
!= restartMarker
) {
2221 error(getPos(), "Bad DCT data: incorrect restart marker");
2224 if (++restartMarker
== 0xd8) {
2225 restartMarker
= 0xd0;
2231 for (cc
= 0; cc
< numComps
; ++cc
) {
2232 if (!scanInfo
.comp
[cc
]) {
2236 h
= compInfo
[cc
].hSample
;
2237 v
= compInfo
[cc
].vSample
;
2238 horiz
= mcuWidth
/ h
;
2239 vert
= mcuHeight
/ v
;
2241 for (y2
= 0; y2
< dy1
; y2
+= vert
) {
2242 for (x2
= 0; x2
< dx1
; x2
+= horiz
) {
2244 // pull out the current values
2245 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2246 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2255 p1
+= bufWidth
* vSub
;
2258 // read one data unit
2260 if (!readProgressiveDataUnit(
2261 &dcHuffTables
[scanInfo
.dcHuffTable
[cc
]],
2262 &acHuffTables
[scanInfo
.acHuffTable
[cc
]],
2263 &compInfo
[cc
].prevDC
,
2268 if (!readDataUnit(&dcHuffTables
[scanInfo
.dcHuffTable
[cc
]],
2269 &acHuffTables
[scanInfo
.acHuffTable
[cc
]],
2270 &compInfo
[cc
].prevDC
,
2276 // add the data unit into frameBuf
2277 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2278 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2287 p1
+= bufWidth
* vSub
;
2297 // Read one data unit from a sequential JPEG stream.
2298 GBool
DCTStream::readDataUnit(DCTHuffTable
*dcHuffTable
,
2299 DCTHuffTable
*acHuffTable
,
2300 int *prevDC
, int data
[64]) {
2305 if ((size
= readHuffSym(dcHuffTable
)) == 9999) {
2309 if ((amp
= readAmp(size
)) == 9999) {
2315 data
[0] = *prevDC
+= amp
;
2316 for (i
= 1; i
< 64; ++i
) {
2322 while ((c
= readHuffSym(acHuffTable
)) == 0xf0 && run
< 0x30) {
2331 run
+= (c
>> 4) & 0x0f;
2333 amp
= readAmp(size
);
2347 // Read one data unit from a sequential JPEG stream.
2348 GBool
DCTStream::readProgressiveDataUnit(DCTHuffTable
*dcHuffTable
,
2349 DCTHuffTable
*acHuffTable
,
2350 int *prevDC
, int data
[64]) {
2351 int run
, size
, amp
, bit
, c
;
2354 // get the DC coefficient
2355 i
= scanInfo
.firstCoeff
;
2357 if (scanInfo
.ah
== 0) {
2358 if ((size
= readHuffSym(dcHuffTable
)) == 9999) {
2362 if ((amp
= readAmp(size
)) == 9999) {
2368 data
[0] += (*prevDC
+= amp
) << scanInfo
.al
;
2370 if ((bit
= readBit()) == 9999) {
2373 data
[0] += bit
<< scanInfo
.al
;
2377 if (scanInfo
.lastCoeff
== 0) {
2381 // check for an EOB run
2383 while (i
<= scanInfo
.lastCoeff
) {
2386 if ((bit
= readBit()) == EOF
) {
2390 data
[j
] += 1 << scanInfo
.al
;
2398 // read the AC coefficients
2399 while (i
<= scanInfo
.lastCoeff
) {
2400 if ((c
= readHuffSym(acHuffTable
)) == 9999) {
2412 if ((bit
= readBit()) == EOF
) {
2416 data
[j
] += 1 << scanInfo
.al
;
2422 } else if ((c
& 0x0f) == 0x00) {
2425 for (k
= 0; k
< j
; ++k
) {
2426 if ((bit
= readBit()) == EOF
) {
2429 eobRun
= (eobRun
<< 1) | bit
;
2432 while (i
<= scanInfo
.lastCoeff
) {
2435 if ((bit
= readBit()) == EOF
) {
2439 data
[j
] += 1 << scanInfo
.al
;
2446 // zero run and one AC coefficient
2448 run
= (c
>> 4) & 0x0f;
2450 if ((amp
= readAmp(size
)) == 9999) {
2456 while (data
[j
] != 0) {
2457 if ((bit
= readBit()) == EOF
) {
2461 data
[j
] += 1 << scanInfo
.al
;
2467 data
[j
] = amp
<< scanInfo
.al
;
2474 // Decode a progressive JPEG image.
2475 void DCTStream::decodeImage() {
2478 Gushort
*quantTable
;
2479 int pY
, pCb
, pCr
, pR
, pG
, pB
;
2480 int x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
, x5
, y5
, cc
, i
;
2481 int h
, v
, horiz
, vert
, hSub
, vSub
;
2484 for (y1
= 0; y1
< bufHeight
; y1
+= mcuHeight
) {
2485 for (x1
= 0; x1
< bufWidth
; x1
+= mcuWidth
) {
2486 for (cc
= 0; cc
< numComps
; ++cc
) {
2487 quantTable
= quantTables
[compInfo
[cc
].quantTable
];
2488 h
= compInfo
[cc
].hSample
;
2489 v
= compInfo
[cc
].vSample
;
2490 horiz
= mcuWidth
/ h
;
2491 vert
= mcuHeight
/ v
;
2494 for (y2
= 0; y2
< mcuHeight
; y2
+= vert
) {
2495 for (x2
= 0; x2
< mcuWidth
; x2
+= horiz
) {
2497 // pull out the coded data unit
2498 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2499 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2501 dataIn
[i
+1] = p1
[1];
2502 dataIn
[i
+2] = p1
[2];
2503 dataIn
[i
+3] = p1
[3];
2504 dataIn
[i
+4] = p1
[4];
2505 dataIn
[i
+5] = p1
[5];
2506 dataIn
[i
+6] = p1
[6];
2507 dataIn
[i
+7] = p1
[7];
2508 p1
+= bufWidth
* vSub
;
2512 transformDataUnit(quantTable
, dataIn
, dataOut
);
2514 // store back into frameBuf, doing replication for
2515 // subsampled components
2516 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2517 if (hSub
== 1 && vSub
== 1) {
2518 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2519 p1
[0] = dataOut
[i
] & 0xff;
2520 p1
[1] = dataOut
[i
+1] & 0xff;
2521 p1
[2] = dataOut
[i
+2] & 0xff;
2522 p1
[3] = dataOut
[i
+3] & 0xff;
2523 p1
[4] = dataOut
[i
+4] & 0xff;
2524 p1
[5] = dataOut
[i
+5] & 0xff;
2525 p1
[6] = dataOut
[i
+6] & 0xff;
2526 p1
[7] = dataOut
[i
+7] & 0xff;
2529 } else if (hSub
== 2 && vSub
== 2) {
2531 for (y3
= 0, i
= 0; y3
< 16; y3
+= 2, i
+= 8) {
2532 p1
[0] = p1
[1] = p2
[0] = p2
[1] = dataOut
[i
] & 0xff;
2533 p1
[2] = p1
[3] = p2
[2] = p2
[3] = dataOut
[i
+1] & 0xff;
2534 p1
[4] = p1
[5] = p2
[4] = p2
[5] = dataOut
[i
+2] & 0xff;
2535 p1
[6] = p1
[7] = p2
[6] = p2
[7] = dataOut
[i
+3] & 0xff;
2536 p1
[8] = p1
[9] = p2
[8] = p2
[9] = dataOut
[i
+4] & 0xff;
2537 p1
[10] = p1
[11] = p2
[10] = p2
[11] = dataOut
[i
+5] & 0xff;
2538 p1
[12] = p1
[13] = p2
[12] = p2
[13] = dataOut
[i
+6] & 0xff;
2539 p1
[14] = p1
[15] = p2
[14] = p2
[15] = dataOut
[i
+7] & 0xff;
2545 for (y3
= 0, y4
= 0; y3
< 8; ++y3
, y4
+= vSub
) {
2546 for (x3
= 0, x4
= 0; x3
< 8; ++x3
, x4
+= hSub
) {
2548 for (y5
= 0; y5
< vSub
; ++y5
) {
2549 for (x5
= 0; x5
< hSub
; ++x5
) {
2550 p2
[x5
] = dataOut
[i
] & 0xff;
2556 p1
+= bufWidth
* vSub
;
2563 // color space conversion
2565 // convert YCbCr to RGB
2566 if (numComps
== 3) {
2567 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2568 p0
= &frameBuf
[0][(y1
+y2
) * bufWidth
+ x1
];
2569 p1
= &frameBuf
[1][(y1
+y2
) * bufWidth
+ x1
];
2570 p2
= &frameBuf
[2][(y1
+y2
) * bufWidth
+ x1
];
2571 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2575 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2576 *p0
++ = dctClip
[dctClipOffset
+ pR
];
2577 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+
2579 *p1
++ = dctClip
[dctClipOffset
+ pG
];
2580 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2581 *p2
++ = dctClip
[dctClipOffset
+ pB
];
2584 // convert YCbCrK to CMYK (K is passed through unchanged)
2585 } else if (numComps
== 4) {
2586 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2587 p0
= &frameBuf
[0][(y1
+y2
) * bufWidth
+ x1
];
2588 p1
= &frameBuf
[1][(y1
+y2
) * bufWidth
+ x1
];
2589 p2
= &frameBuf
[2][(y1
+y2
) * bufWidth
+ x1
];
2590 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2594 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2595 *p0
++ = 255 - dctClip
[dctClipOffset
+ pR
];
2596 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+
2598 *p1
++ = 255 - dctClip
[dctClipOffset
+ pG
];
2599 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2600 *p2
++ = 255 - dctClip
[dctClipOffset
+ pB
];
2609 // Transform one data unit -- this performs the dequantization and
2610 // IDCT steps. This IDCT algorithm is taken from:
2611 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2612 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2613 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2615 // The stage numbers mentioned in the comments refer to Figure 1 in this
2617 void DCTStream::transformDataUnit(Gushort
*quantTable
,
2618 int dataIn
[64], Guchar dataOut
[64]) {
2619 int v0
, v1
, v2
, v3
, v4
, v5
, v6
, v7
, t
;
2624 for (i
= 0; i
< 64; ++i
) {
2625 dataIn
[i
] *= quantTable
[i
];
2628 // inverse DCT on rows
2629 for (i
= 0; i
< 64; i
+= 8) {
2632 // check for all-zero AC coefficients
2633 if (p
[1] == 0 && p
[2] == 0 && p
[3] == 0 &&
2634 p
[4] == 0 && p
[5] == 0 && p
[6] == 0 && p
[7] == 0) {
2635 t
= (dctSqrt2
* p
[0] + 512) >> 10;
2648 v0
= (dctSqrt2
* p
[0] + 128) >> 8;
2649 v1
= (dctSqrt2
* p
[4] + 128) >> 8;
2652 v4
= (dctSqrt1d2
* (p
[1] - p
[7]) + 128) >> 8;
2653 v7
= (dctSqrt1d2
* (p
[1] + p
[7]) + 128) >> 8;
2658 t
= (v0
- v1
+ 1) >> 1;
2659 v0
= (v0
+ v1
+ 1) >> 1;
2661 t
= (v2
* dctSin6
+ v3
* dctCos6
+ 128) >> 8;
2662 v2
= (v2
* dctCos6
- v3
* dctSin6
+ 128) >> 8;
2664 t
= (v4
- v6
+ 1) >> 1;
2665 v4
= (v4
+ v6
+ 1) >> 1;
2667 t
= (v7
+ v5
+ 1) >> 1;
2668 v5
= (v7
- v5
+ 1) >> 1;
2672 t
= (v0
- v3
+ 1) >> 1;
2673 v0
= (v0
+ v3
+ 1) >> 1;
2675 t
= (v1
- v2
+ 1) >> 1;
2676 v1
= (v1
+ v2
+ 1) >> 1;
2678 t
= (v4
* dctSin3
+ v7
* dctCos3
+ 2048) >> 12;
2679 v4
= (v4
* dctCos3
- v7
* dctSin3
+ 2048) >> 12;
2681 t
= (v5
* dctSin1
+ v6
* dctCos1
+ 2048) >> 12;
2682 v5
= (v5
* dctCos1
- v6
* dctSin1
+ 2048) >> 12;
2696 // inverse DCT on columns
2697 for (i
= 0; i
< 8; ++i
) {
2700 // check for all-zero AC coefficients
2701 if (p
[1*8] == 0 && p
[2*8] == 0 && p
[3*8] == 0 &&
2702 p
[4*8] == 0 && p
[5*8] == 0 && p
[6*8] == 0 && p
[7*8] == 0) {
2703 t
= (dctSqrt2
* dataIn
[i
+0] + 8192) >> 14;
2716 v0
= (dctSqrt2
* p
[0*8] + 2048) >> 12;
2717 v1
= (dctSqrt2
* p
[4*8] + 2048) >> 12;
2720 v4
= (dctSqrt1d2
* (p
[1*8] - p
[7*8]) + 2048) >> 12;
2721 v7
= (dctSqrt1d2
* (p
[1*8] + p
[7*8]) + 2048) >> 12;
2726 t
= (v0
- v1
+ 1) >> 1;
2727 v0
= (v0
+ v1
+ 1) >> 1;
2729 t
= (v2
* dctSin6
+ v3
* dctCos6
+ 2048) >> 12;
2730 v2
= (v2
* dctCos6
- v3
* dctSin6
+ 2048) >> 12;
2732 t
= (v4
- v6
+ 1) >> 1;
2733 v4
= (v4
+ v6
+ 1) >> 1;
2735 t
= (v7
+ v5
+ 1) >> 1;
2736 v5
= (v7
- v5
+ 1) >> 1;
2740 t
= (v0
- v3
+ 1) >> 1;
2741 v0
= (v0
+ v3
+ 1) >> 1;
2743 t
= (v1
- v2
+ 1) >> 1;
2744 v1
= (v1
+ v2
+ 1) >> 1;
2746 t
= (v4
* dctSin3
+ v7
* dctCos3
+ 2048) >> 12;
2747 v4
= (v4
* dctCos3
- v7
* dctSin3
+ 2048) >> 12;
2749 t
= (v5
* dctSin1
+ v6
* dctCos1
+ 2048) >> 12;
2750 v5
= (v5
* dctCos1
- v6
* dctSin1
+ 2048) >> 12;
2764 // convert to 8-bit integers
2765 for (i
= 0; i
< 64; ++i
) {
2766 dataOut
[i
] = dctClip
[dctClipOffset
+ 128 + ((dataIn
[i
] + 8) >> 4)];
2770 int DCTStream::readHuffSym(DCTHuffTable
*table
) {
2778 // add a bit to the code
2779 if ((bit
= readBit()) == EOF
)
2781 code
= (code
<< 1) + bit
;
2785 if (code
- table
->firstCode
[codeBits
] < table
->numCodes
[codeBits
]) {
2786 code
-= table
->firstCode
[codeBits
];
2787 return table
->sym
[table
->firstSym
[codeBits
] + code
];
2789 } while (codeBits
< 16);
2791 error(getPos(), "Bad Huffman code in DCT stream");
2795 int DCTStream::readAmp(int size
) {
2800 for (bits
= 0; bits
< size
; ++bits
) {
2801 if ((bit
= readBit()) == EOF
)
2803 amp
= (amp
<< 1) + bit
;
2805 if (amp
< (1 << (size
- 1)))
2806 amp
-= (1 << size
) - 1;
2810 int DCTStream::readBit() {
2814 if (inputBits
== 0) {
2815 if ((c
= str
->getChar()) == EOF
)
2819 c2
= str
->getChar();
2820 } while (c2
== 0xff);
2822 error(getPos(), "Bad DCT data: missing 00 after ff");
2829 bit
= (inputBuf
>> (inputBits
- 1)) & 1;
2834 GBool
DCTStream::readHeader() {
2845 case 0xc0: // SOF0 (sequential)
2846 case 0xc1: // SOF1 (extended sequential)
2847 if (!readBaselineSOF()) {
2851 case 0xc2: // SOF2 (progressive)
2852 if (!readProgressiveSOF()) {
2857 if (!readHuffmanTables()) {
2866 if (!readScanInfo()) {
2872 if (!readQuantTables()) {
2877 if (!readRestartInterval()) {
2882 if (!readJFIFMarker()) {
2887 if (!readAdobeMarker()) {
2892 error(getPos(), "Bad DCT header");
2895 // skip APPn / COM / etc.
2898 for (i
= 0; i
< n
; ++i
) {
2902 error(getPos(), "Unknown DCT marker <%02x>", c
);
2912 GBool
DCTStream::readBaselineSOF() {
2919 prec
= str
->getChar();
2922 numComps
= str
->getChar();
2923 if (numComps
<= 0 || numComps
> 4) {
2924 error(getPos(), "Bad number of components in DCT stream");
2929 error(getPos(), "Bad DCT precision %d", prec
);
2932 for (i
= 0; i
< numComps
; ++i
) {
2933 compInfo
[i
].id
= str
->getChar();
2935 compInfo
[i
].hSample
= (c
>> 4) & 0x0f;
2936 compInfo
[i
].vSample
= c
& 0x0f;
2937 compInfo
[i
].quantTable
= str
->getChar();
2939 progressive
= gFalse
;
2943 GBool
DCTStream::readProgressiveSOF() {
2950 prec
= str
->getChar();
2953 numComps
= str
->getChar();
2954 if (numComps
<= 0 || numComps
> 4) {
2955 error(getPos(), "Bad number of components in DCT stream");
2960 error(getPos(), "Bad DCT precision %d", prec
);
2963 for (i
= 0; i
< numComps
; ++i
) {
2964 compInfo
[i
].id
= str
->getChar();
2966 compInfo
[i
].hSample
= (c
>> 4) & 0x0f;
2967 compInfo
[i
].vSample
= c
& 0x0f;
2968 compInfo
[i
].quantTable
= str
->getChar();
2970 progressive
= gTrue
;
2974 GBool
DCTStream::readScanInfo() {
2979 length
= read16() - 2;
2980 scanInfo
.numComps
= str
->getChar();
2981 if (scanInfo
.numComps
<= 0 || scanInfo
.numComps
> 4) {
2982 error(getPos(), "Bad number of components in DCT stream");
2983 scanInfo
.numComps
= 0;
2987 if (length
!= 2 * scanInfo
.numComps
+ 3) {
2988 error(getPos(), "Bad DCT scan info block");
2991 interleaved
= scanInfo
.numComps
== numComps
;
2992 for (j
= 0; j
< numComps
; ++j
) {
2993 scanInfo
.comp
[j
] = gFalse
;
2995 for (i
= 0; i
< scanInfo
.numComps
; ++i
) {
2996 id
= str
->getChar();
2997 // some (broken) DCT streams reuse ID numbers, but at least they
2998 // keep the components in order, so we check compInfo[i] first to
2999 // work around the problem
3000 if (id
== compInfo
[i
].id
) {
3003 for (j
= 0; j
< numComps
; ++j
) {
3004 if (id
== compInfo
[j
].id
) {
3008 if (j
== numComps
) {
3009 error(getPos(), "Bad DCT component ID in scan info block");
3013 scanInfo
.comp
[j
] = gTrue
;
3015 scanInfo
.dcHuffTable
[j
] = (c
>> 4) & 0x0f;
3016 scanInfo
.acHuffTable
[j
] = c
& 0x0f;
3018 scanInfo
.firstCoeff
= str
->getChar();
3019 scanInfo
.lastCoeff
= str
->getChar();
3021 scanInfo
.ah
= (c
>> 4) & 0x0f;
3022 scanInfo
.al
= c
& 0x0f;
3026 GBool
DCTStream::readQuantTables() {
3027 int length
, prec
, i
, index
;
3029 length
= read16() - 2;
3030 while (length
> 0) {
3031 index
= str
->getChar();
3032 prec
= (index
>> 4) & 0x0f;
3034 if (prec
> 1 || index
>= 4) {
3035 error(getPos(), "Bad DCT quantization table");
3038 if (index
== numQuantTables
) {
3039 numQuantTables
= index
+ 1;
3041 for (i
= 0; i
< 64; ++i
) {
3043 quantTables
[index
][dctZigZag
[i
]] = read16();
3045 quantTables
[index
][dctZigZag
[i
]] = str
->getChar();
3057 GBool
DCTStream::readHuffmanTables() {
3066 length
= read16() - 2;
3067 while (length
> 0) {
3068 index
= str
->getChar();
3070 if ((index
& 0x0f) >= 4) {
3071 error(getPos(), "Bad DCT Huffman table");
3076 if (index
>= numACHuffTables
)
3077 numACHuffTables
= index
+1;
3078 tbl
= &acHuffTables
[index
];
3081 if (index
>= numDCHuffTables
)
3082 numDCHuffTables
= index
+1;
3083 tbl
= &dcHuffTables
[index
];
3087 for (i
= 1; i
<= 16; ++i
) {
3089 tbl
->firstSym
[i
] = sym
;
3090 tbl
->firstCode
[i
] = code
;
3091 tbl
->numCodes
[i
] = c
;
3093 code
= (code
+ c
) << 1;
3096 for (i
= 0; i
< sym
; ++i
)
3097 tbl
->sym
[i
] = str
->getChar();
3103 GBool
DCTStream::readRestartInterval() {
3108 error(getPos(), "Bad DCT restart interval");
3111 restartInterval
= read16();
3115 GBool
DCTStream::readJFIFMarker() {
3123 for (i
= 0; i
< 5; ++i
) {
3124 if ((c
= str
->getChar()) == EOF
) {
3125 error(getPos(), "Bad DCT APP0 marker");
3131 if (!memcmp(buf
, "JFIF\0", 5)) {
3132 gotJFIFMarker
= gTrue
;
3135 while (length
> 0) {
3136 if (str
->getChar() == EOF
) {
3137 error(getPos(), "Bad DCT APP0 marker");
3145 GBool
DCTStream::readAdobeMarker() {
3154 for (i
= 0; i
< 12; ++i
) {
3155 if ((c
= str
->getChar()) == EOF
) {
3160 if (strncmp(buf
, "Adobe", 5)) {
3163 colorXform
= buf
[11];
3164 gotAdobeMarker
= gTrue
;
3165 for (i
= 14; i
< length
; ++i
) {
3166 if (str
->getChar() == EOF
) {
3173 error(getPos(), "Bad DCT Adobe APP14 marker");
3177 GBool
DCTStream::readTrailer() {
3181 if (c
!= 0xd9) { // EOI
3182 error(getPos(), "Bad DCT trailer");
3188 int DCTStream::readMarker() {
3194 } while (c
!= 0xff && c
!= EOF
);
3197 } while (c
== 0xff);
3198 } while (c
== 0x00);
3202 int DCTStream::read16() {
3205 if ((c1
= str
->getChar()) == EOF
)
3207 if ((c2
= str
->getChar()) == EOF
)
3209 return (c1
<< 8) + c2
;
3212 GString
*DCTStream::getPSFilter(int psLevel
, char *indent
) {
3218 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
3221 s
->append(indent
)->append("<< >> /DCTDecode filter\n");
3225 GBool
DCTStream::isBinary(GBool last
) {
3226 return str
->isBinary(gTrue
);
3229 //------------------------------------------------------------------------
3231 //------------------------------------------------------------------------
3233 int FlateStream::codeLenCodeMap
[flateMaxCodeLenCodes
] = {
3234 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3237 FlateDecode
FlateStream::lengthDecode
[flateMaxLitCodes
-257] = {
3271 FlateDecode
FlateStream::distDecode
[flateMaxDistCodes
] = {
3304 static FlateCode flateFixedLitCodeTabCodes
[512] = {
3819 FlateHuffmanTab
FlateStream::fixedLitCodeTab
= {
3820 flateFixedLitCodeTabCodes
, 9
3823 static FlateCode flateFixedDistCodeTabCodes
[32] = {
3858 FlateHuffmanTab
FlateStream::fixedDistCodeTab
= {
3859 flateFixedDistCodeTabCodes
, 5
3862 FlateStream::FlateStream(Stream
*strA
, int predictor
, int columns
,
3863 int colors
, int bits
):
3864 FilterStream(strA
) {
3865 if (predictor
!= 1) {
3866 pred
= new StreamPredictor(this, predictor
, columns
, colors
, bits
);
3867 if (!pred
->isOk()) {
3874 litCodeTab
.codes
= NULL
;
3875 distCodeTab
.codes
= NULL
;
3878 FlateStream::~FlateStream() {
3879 if (litCodeTab
.codes
!= fixedLitCodeTab
.codes
) {
3880 gfree(litCodeTab
.codes
);
3882 if (distCodeTab
.codes
!= fixedDistCodeTab
.codes
) {
3883 gfree(distCodeTab
.codes
);
3891 void FlateStream::reset() {
3898 compressedBlock
= gFalse
;
3905 //~ need to look at window size?
3906 endOfBlock
= eof
= gTrue
;
3907 cmf
= str
->getChar();
3908 flg
= str
->getChar();
3909 if (cmf
== EOF
|| flg
== EOF
)
3911 if ((cmf
& 0x0f) != 0x08) {
3912 error(getPos(), "Unknown compression method in flate stream");
3915 if ((((cmf
<< 8) + flg
) % 31) != 0) {
3916 error(getPos(), "Bad FCHECK in flate stream");
3920 error(getPos(), "FDICT bit set in flate stream");
3927 int FlateStream::getChar() {
3931 return pred
->getChar();
3933 while (remain
== 0) {
3934 if (endOfBlock
&& eof
)
3939 index
= (index
+ 1) & flateMask
;
3944 int FlateStream::lookChar() {
3948 return pred
->lookChar();
3950 while (remain
== 0) {
3951 if (endOfBlock
&& eof
)
3959 int FlateStream::getRawChar() {
3962 while (remain
== 0) {
3963 if (endOfBlock
&& eof
)
3968 index
= (index
+ 1) & flateMask
;
3973 GString
*FlateStream::getPSFilter(int psLevel
, char *indent
) {
3976 if (psLevel
< 3 || pred
) {
3979 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
3982 s
->append(indent
)->append("<< >> /FlateDecode filter\n");
3986 GBool
FlateStream::isBinary(GBool last
) {
3987 return str
->isBinary(gTrue
);
3990 void FlateStream::readSome() {
4001 if (compressedBlock
) {
4002 if ((code1
= getHuffmanCodeWord(&litCodeTab
)) == EOF
)
4007 } else if (code1
== 256) {
4012 code2
= lengthDecode
[code1
].bits
;
4013 if (code2
> 0 && (code2
= getCodeWord(code2
)) == EOF
)
4015 len
= lengthDecode
[code1
].first
+ code2
;
4016 if ((code1
= getHuffmanCodeWord(&distCodeTab
)) == EOF
)
4018 code2
= distDecode
[code1
].bits
;
4019 if (code2
> 0 && (code2
= getCodeWord(code2
)) == EOF
)
4021 dist
= distDecode
[code1
].first
+ code2
;
4023 j
= (index
- dist
) & flateMask
;
4024 for (k
= 0; k
< len
; ++k
) {
4026 i
= (i
+ 1) & flateMask
;
4027 j
= (j
+ 1) & flateMask
;
4033 len
= (blockLen
< flateWindow
) ? blockLen
: flateWindow
;
4034 for (i
= 0, j
= index
; i
< len
; ++i
, j
= (j
+ 1) & flateMask
) {
4035 if ((c
= str
->getChar()) == EOF
) {
4036 endOfBlock
= eof
= gTrue
;
4050 error(getPos(), "Unexpected end of file in flate stream");
4051 endOfBlock
= eof
= gTrue
;
4055 GBool
FlateStream::startBlock() {
4060 // free the code tables from the previous block
4061 if (litCodeTab
.codes
!= fixedLitCodeTab
.codes
) {
4062 gfree(litCodeTab
.codes
);
4064 litCodeTab
.codes
= NULL
;
4065 if (distCodeTab
.codes
!= fixedDistCodeTab
.codes
) {
4066 gfree(distCodeTab
.codes
);
4068 distCodeTab
.codes
= NULL
;
4070 // read block header
4071 blockHdr
= getCodeWord(3);
4076 // uncompressed block
4077 if (blockHdr
== 0) {
4078 compressedBlock
= gFalse
;
4079 if ((c
= str
->getChar()) == EOF
)
4081 blockLen
= c
& 0xff;
4082 if ((c
= str
->getChar()) == EOF
)
4084 blockLen
|= (c
& 0xff) << 8;
4085 if ((c
= str
->getChar()) == EOF
)
4088 if ((c
= str
->getChar()) == EOF
)
4090 check
|= (c
& 0xff) << 8;
4091 if (check
!= (~blockLen
& 0xffff))
4092 error(getPos(), "Bad uncompressed block length in flate stream");
4096 // compressed block with fixed codes
4097 } else if (blockHdr
== 1) {
4098 compressedBlock
= gTrue
;
4101 // compressed block with dynamic codes
4102 } else if (blockHdr
== 2) {
4103 compressedBlock
= gTrue
;
4104 if (!readDynamicCodes()) {
4108 // unknown block type
4113 endOfBlock
= gFalse
;
4117 error(getPos(), "Bad block header in flate stream");
4118 endOfBlock
= eof
= gTrue
;
4122 void FlateStream::loadFixedCodes() {
4123 litCodeTab
.codes
= fixedLitCodeTab
.codes
;
4124 litCodeTab
.maxLen
= fixedLitCodeTab
.maxLen
;
4125 distCodeTab
.codes
= fixedDistCodeTab
.codes
;
4126 distCodeTab
.maxLen
= fixedDistCodeTab
.maxLen
;
4129 GBool
FlateStream::readDynamicCodes() {
4130 int numCodeLenCodes
;
4133 int codeLenCodeLengths
[flateMaxCodeLenCodes
];
4134 FlateHuffmanTab codeLenCodeTab
;
4135 int len
, repeat
, code
;
4138 codeLenCodeTab
.codes
= NULL
;
4141 if ((numLitCodes
= getCodeWord(5)) == EOF
) {
4145 if ((numDistCodes
= getCodeWord(5)) == EOF
) {
4149 if ((numCodeLenCodes
= getCodeWord(4)) == EOF
) {
4152 numCodeLenCodes
+= 4;
4153 if (numLitCodes
> flateMaxLitCodes
||
4154 numDistCodes
> flateMaxDistCodes
||
4155 numCodeLenCodes
> flateMaxCodeLenCodes
) {
4159 // build the code length code table
4160 for (i
= 0; i
< flateMaxCodeLenCodes
; ++i
) {
4161 codeLenCodeLengths
[i
] = 0;
4163 for (i
= 0; i
< numCodeLenCodes
; ++i
) {
4164 if ((codeLenCodeLengths
[codeLenCodeMap
[i
]] = getCodeWord(3)) == -1) {
4168 compHuffmanCodes(codeLenCodeLengths
, flateMaxCodeLenCodes
, &codeLenCodeTab
);
4170 // build the literal and distance code tables
4174 while (i
< numLitCodes
+ numDistCodes
) {
4175 if ((code
= getHuffmanCodeWord(&codeLenCodeTab
)) == EOF
) {
4179 if ((repeat
= getCodeWord(2)) == EOF
) {
4183 if (i
+ repeat
> numLitCodes
+ numDistCodes
) {
4186 for (; repeat
> 0; --repeat
) {
4187 codeLengths
[i
++] = len
;
4189 } else if (code
== 17) {
4190 if ((repeat
= getCodeWord(3)) == EOF
) {
4194 if (i
+ repeat
> numLitCodes
+ numDistCodes
) {
4198 for (; repeat
> 0; --repeat
) {
4199 codeLengths
[i
++] = 0;
4201 } else if (code
== 18) {
4202 if ((repeat
= getCodeWord(7)) == EOF
) {
4206 if (i
+ repeat
> numLitCodes
+ numDistCodes
) {
4210 for (; repeat
> 0; --repeat
) {
4211 codeLengths
[i
++] = 0;
4214 codeLengths
[i
++] = len
= code
;
4217 compHuffmanCodes(codeLengths
, numLitCodes
, &litCodeTab
);
4218 compHuffmanCodes(codeLengths
+ numLitCodes
, numDistCodes
, &distCodeTab
);
4220 gfree(codeLenCodeTab
.codes
);
4224 error(getPos(), "Bad dynamic code table in flate stream");
4225 gfree(codeLenCodeTab
.codes
);
4229 // Convert an array <lengths> of <n> lengths, in value order, into a
4230 // Huffman code lookup table.
4231 void FlateStream::compHuffmanCodes(int *lengths
, int n
, FlateHuffmanTab
*tab
) {
4232 int tabSize
, len
, code
, code2
, skip
, val
, i
, t
;
4234 // find max code length
4236 for (val
= 0; val
< n
; ++val
) {
4237 if (lengths
[val
] > tab
->maxLen
) {
4238 tab
->maxLen
= lengths
[val
];
4242 // allocate the table
4243 tabSize
= 1 << tab
->maxLen
;
4244 tab
->codes
= (FlateCode
*)gmallocn(tabSize
, sizeof(FlateCode
));
4247 for (i
= 0; i
< tabSize
; ++i
) {
4248 tab
->codes
[i
].len
= 0;
4249 tab
->codes
[i
].val
= 0;
4253 for (len
= 1, code
= 0, skip
= 2;
4255 ++len
, code
<<= 1, skip
<<= 1) {
4256 for (val
= 0; val
< n
; ++val
) {
4257 if (lengths
[val
] == len
) {
4259 // bit-reverse the code
4262 for (i
= 0; i
< len
; ++i
) {
4263 code2
= (code2
<< 1) | (t
& 1);
4267 // fill in the table entries
4268 for (i
= code2
; i
< tabSize
; i
+= skip
) {
4269 tab
->codes
[i
].len
= (Gushort
)len
;
4270 tab
->codes
[i
].val
= (Gushort
)val
;
4279 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab
*tab
) {
4283 while (codeSize
< tab
->maxLen
) {
4284 if ((c
= str
->getChar()) == EOF
) {
4287 codeBuf
|= (c
& 0xff) << codeSize
;
4290 code
= &tab
->codes
[codeBuf
& ((1 << tab
->maxLen
) - 1)];
4291 if (codeSize
== 0 || codeSize
< code
->len
|| code
->len
== 0) {
4294 codeBuf
>>= code
->len
;
4295 codeSize
-= code
->len
;
4296 return (int)code
->val
;
4299 int FlateStream::getCodeWord(int bits
) {
4302 while (codeSize
< bits
) {
4303 if ((c
= str
->getChar()) == EOF
)
4305 codeBuf
|= (c
& 0xff) << codeSize
;
4308 c
= codeBuf
& ((1 << bits
) - 1);
4314 //------------------------------------------------------------------------
4316 //------------------------------------------------------------------------
4318 EOFStream::EOFStream(Stream
*strA
):
4319 FilterStream(strA
) {
4322 EOFStream::~EOFStream() {
4326 //------------------------------------------------------------------------
4327 // FixedLengthEncoder
4328 //------------------------------------------------------------------------
4330 FixedLengthEncoder::FixedLengthEncoder(Stream
*strA
, int lengthA
):
4331 FilterStream(strA
) {
4336 FixedLengthEncoder::~FixedLengthEncoder() {
4337 if (str
->isEncoder())
4341 void FixedLengthEncoder::reset() {
4346 int FixedLengthEncoder::getChar() {
4347 if (length
>= 0 && count
>= length
)
4350 return str
->getChar();
4353 int FixedLengthEncoder::lookChar() {
4354 if (length
>= 0 && count
>= length
)
4356 return str
->getChar();
4359 GBool
FixedLengthEncoder::isBinary(GBool last
) {
4360 return str
->isBinary(gTrue
);
4363 //------------------------------------------------------------------------
4365 //------------------------------------------------------------------------
4367 ASCIIHexEncoder::ASCIIHexEncoder(Stream
*strA
):
4368 FilterStream(strA
) {
4369 bufPtr
= bufEnd
= buf
;
4374 ASCIIHexEncoder::~ASCIIHexEncoder() {
4375 if (str
->isEncoder()) {
4380 void ASCIIHexEncoder::reset() {
4382 bufPtr
= bufEnd
= buf
;
4387 GBool
ASCIIHexEncoder::fillBuf() {
4388 static char *hex
= "0123456789abcdef";
4394 bufPtr
= bufEnd
= buf
;
4395 if ((c
= str
->getChar()) == EOF
) {
4399 if (lineLen
>= 64) {
4403 *bufEnd
++ = hex
[(c
>> 4) & 0x0f];
4404 *bufEnd
++ = hex
[c
& 0x0f];
4410 //------------------------------------------------------------------------
4412 //------------------------------------------------------------------------
4414 ASCII85Encoder::ASCII85Encoder(Stream
*strA
):
4415 FilterStream(strA
) {
4416 bufPtr
= bufEnd
= buf
;
4421 ASCII85Encoder::~ASCII85Encoder() {
4422 if (str
->isEncoder())
4426 void ASCII85Encoder::reset() {
4428 bufPtr
= bufEnd
= buf
;
4433 GBool
ASCII85Encoder::fillBuf() {
4442 for (n
= 0; n
< 4; ++n
) {
4443 if ((c
= str
->getChar()) == EOF
)
4447 bufPtr
= bufEnd
= buf
;
4449 if (n
== 4 && t
== 0) {
4451 if (++lineLen
== 65) {
4458 for (i
= 4; i
>= 0; --i
) {
4459 buf1
[i
] = (char)(t
% 85 + 0x21);
4462 for (i
= 0; i
<= n
; ++i
) {
4463 *bufEnd
++ = buf1
[i
];
4464 if (++lineLen
== 65) {
4476 return bufPtr
< bufEnd
;
4479 //------------------------------------------------------------------------
4481 //------------------------------------------------------------------------
4483 RunLengthEncoder::RunLengthEncoder(Stream
*strA
):
4484 FilterStream(strA
) {
4485 bufPtr
= bufEnd
= nextEnd
= buf
;
4489 RunLengthEncoder::~RunLengthEncoder() {
4490 if (str
->isEncoder())
4494 void RunLengthEncoder::reset() {
4496 bufPtr
= bufEnd
= nextEnd
= buf
;
4501 // When fillBuf finishes, buf[] looks like this:
4502 // +-----+--------------+-----------------+--
4503 // + tag | ... data ... | next 0, 1, or 2 |
4504 // +-----+--------------+-----------------+--
4506 // bufPtr bufEnd nextEnd
4508 GBool
RunLengthEncoder::fillBuf() {
4517 if (nextEnd
< bufEnd
+ 1) {
4518 if ((c1
= str
->getChar()) == EOF
) {
4523 c1
= bufEnd
[0] & 0xff;
4525 if (nextEnd
< bufEnd
+ 2) {
4526 if ((c2
= str
->getChar()) == EOF
) {
4535 c2
= bufEnd
[1] & 0xff;
4539 c
= 0; // make gcc happy
4542 while (n
< 128 && (c
= str
->getChar()) == c1
)
4544 buf
[0] = (char)(257 - n
);
4549 } else if (n
< 128) {
4556 // get up to 128 chars
4562 if ((c
= str
->getChar()) == EOF
) {
4568 if (buf
[n
] == buf
[n
-1])
4571 if (buf
[n
] == buf
[n
-1]) {
4572 buf
[0] = (char)(n
-2-1);
4574 nextEnd
= &buf
[n
+1];
4576 buf
[0] = (char)(n
-1);
4577 bufEnd
= nextEnd
= &buf
[n
+1];