1 //========================================================================
5 // Copyright 1996-2003 Glyph & Cog, LLC
7 //========================================================================
12 #ifdef USE_GCC_PRAGMAS
13 #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
) {
408 predictor
= predictorA
;
415 if (width
<= 0 || nComps
<= 0 || nBits
<= 0 ||
416 nComps
>= INT_MAX
/nBits
||
417 width
>= INT_MAX
/nComps
/nBits
) {
420 nVals
= width
* nComps
;
421 totalBits
= nVals
* nBits
;
422 if (totalBits
== 0 ||
423 (totalBits
/ nBits
) / nComps
!= width
||
427 pixBytes
= (nComps
* nBits
+ 7) >> 3;
428 rowBytes
= ((totalBits
+ 7) >> 3) + pixBytes
;
432 predLine
= (Guchar
*)gmalloc(rowBytes
);
433 memset(predLine
, 0, rowBytes
);
439 StreamPredictor::~StreamPredictor() {
443 int StreamPredictor::lookChar() {
444 if (predIdx
>= rowBytes
) {
445 if (!getNextLine()) {
449 return predLine
[predIdx
];
452 int StreamPredictor::getChar() {
453 if (predIdx
>= rowBytes
) {
454 if (!getNextLine()) {
458 return predLine
[predIdx
++];
461 GBool
StreamPredictor::getNextLine() {
463 Guchar upLeftBuf
[gfxColorMaxComps
* 2 + 1];
464 int left
, up
, upLeft
, p
, pa
, pb
, pc
;
466 Gulong inBuf
, outBuf
, bitMask
;
470 // get PNG optimum predictor number
471 if (predictor
>= 10) {
472 if ((curPred
= str
->getRawChar()) == EOF
) {
480 // read the raw line, apply PNG (byte) predictor
481 memset(upLeftBuf
, 0, pixBytes
+ 1);
482 for (i
= pixBytes
; i
< rowBytes
; ++i
) {
483 for (j
= pixBytes
; j
> 0; --j
) {
484 upLeftBuf
[j
] = upLeftBuf
[j
-1];
486 upLeftBuf
[0] = predLine
[i
];
487 if ((c
= str
->getRawChar()) == EOF
) {
489 // this ought to return false, but some (broken) PDF files
490 // contain truncated image data, and Adobe apparently reads the
498 predLine
[i
] = predLine
[i
- pixBytes
] + (Guchar
)c
;
501 predLine
[i
] = predLine
[i
] + (Guchar
)c
;
503 case 13: // PNG average
504 predLine
[i
] = ((predLine
[i
- pixBytes
] + predLine
[i
]) >> 1) +
507 case 14: // PNG Paeth
508 left
= predLine
[i
- pixBytes
];
510 upLeft
= upLeftBuf
[pixBytes
];
511 p
= left
+ up
- upLeft
;
512 if ((pa
= p
- left
) < 0)
514 if ((pb
= p
- up
) < 0)
516 if ((pc
= p
- upLeft
) < 0)
518 if (pa
<= pb
&& pa
<= pc
)
519 predLine
[i
] = left
+ (Guchar
)c
;
521 predLine
[i
] = up
+ (Guchar
)c
;
523 predLine
[i
] = upLeft
+ (Guchar
)c
;
526 default: // no predictor or TIFF predictor
527 predLine
[i
] = (Guchar
)c
;
532 // apply TIFF (component) predictor
533 if (predictor
== 2) {
535 inBuf
= predLine
[pixBytes
- 1];
536 for (i
= pixBytes
; i
< rowBytes
; i
+= 8) {
537 // 1-bit add is just xor
538 inBuf
= (inBuf
<< 8) | predLine
[i
];
539 predLine
[i
] ^= inBuf
>> nComps
;
541 } else if (nBits
== 8) {
542 for (i
= pixBytes
; i
< rowBytes
; ++i
) {
543 predLine
[i
] += predLine
[i
- nComps
];
546 memset(upLeftBuf
, 0, nComps
+ 1);
547 bitMask
= (1 << nBits
) - 1;
549 inBits
= outBits
= 0;
551 for (i
= 0; i
< width
; ++i
) {
552 for (kk
= 0; kk
< nComps
; ++kk
) {
553 if (inBits
< nBits
) {
554 inBuf
= (inBuf
<< 8) | (predLine
[j
++] & 0xff);
557 upLeftBuf
[kk
] = (upLeftBuf
[kk
] +
558 (inBuf
>> (inBits
- nBits
))) & bitMask
;
560 outBuf
= (outBuf
<< nBits
) | upLeftBuf
[kk
];
563 predLine
[k
++] = (Guchar
)(outBuf
>> (outBits
- 8));
569 predLine
[k
++] = (Guchar
)((outBuf
<< (8 - outBits
)) +
570 (inBuf
& ((1 << (8 - outBits
)) - 1)));
575 // reset to start of line
581 //------------------------------------------------------------------------
583 //------------------------------------------------------------------------
585 FileStream::FileStream(FILE *fA
, Guint startA
, GBool limitedA
,
586 Guint lengthA
, Object
*dictA
):
592 bufPtr
= bufEnd
= buf
;
598 FileStream::~FileStream() {
602 Stream
*FileStream::makeSubStream(Guint startA
, GBool limitedA
,
603 Guint lengthA
, Object
*dictA
) {
604 return new FileStream(f
, startA
, limitedA
, lengthA
, dictA
);
607 void FileStream::reset() {
609 savePos
= (Guint
)ftello(f
);
610 fseeko(f
, start
, SEEK_SET
);
612 savePos
= (Guint
)ftell64(f
);
613 fseek64(f
, start
, SEEK_SET
);
615 savePos
= (Guint
)ftell(f
);
616 fseek(f
, start
, SEEK_SET
);
619 bufPtr
= bufEnd
= buf
;
625 void FileStream::close() {
628 fseeko(f
, savePos
, SEEK_SET
);
630 fseek64(f
, savePos
, SEEK_SET
);
632 fseek(f
, savePos
, SEEK_SET
);
638 GBool
FileStream::fillBuf() {
642 bufPos
+= bufEnd
- buf
;
643 bufPtr
= bufEnd
= buf
;
644 if (limited
&& bufPos
>= start
+ length
) {
647 if (limited
&& bufPos
+ fileStreamBufSize
> start
+ length
) {
648 n
= start
+ length
- bufPos
;
650 n
= fileStreamBufSize
;
652 n
= fread(buf
, 1, n
, f
);
654 if (bufPtr
>= bufEnd
) {
658 for (p
= buf
; p
< bufEnd
; ++p
) {
659 *p
= (char)decrypt
->decryptByte((Guchar
)*p
);
665 void FileStream::setPos(Guint pos
, int dir
) {
670 fseeko(f
, pos
, SEEK_SET
);
672 fseek64(f
, pos
, SEEK_SET
);
674 fseek(f
, pos
, SEEK_SET
);
679 fseeko(f
, 0, SEEK_END
);
680 size
= (Guint
)ftello(f
);
682 fseek64(f
, 0, SEEK_END
);
683 size
= (Guint
)ftell64(f
);
685 fseek(f
, 0, SEEK_END
);
686 size
= (Guint
)ftell(f
);
691 //~ work around a bug in cygwin's implementation of fseek
695 fseeko(f
, -(int)pos
, SEEK_END
);
696 bufPos
= (Guint
)ftello(f
);
698 fseek64(f
, -(int)pos
, SEEK_END
);
699 bufPos
= (Guint
)ftell64(f
);
701 fseek(f
, -(int)pos
, SEEK_END
);
702 bufPos
= (Guint
)ftell(f
);
705 bufPtr
= bufEnd
= buf
;
708 void FileStream::moveStart(int delta
) {
710 bufPtr
= bufEnd
= buf
;
714 //------------------------------------------------------------------------
716 //------------------------------------------------------------------------
718 MemStream::MemStream(char *bufA
, Guint startA
, Guint lengthA
, Object
*dictA
):
723 bufEnd
= buf
+ start
+ length
;
724 bufPtr
= buf
+ start
;
728 MemStream::~MemStream() {
734 Stream
*MemStream::makeSubStream(Guint startA
, GBool limited
,
735 Guint lengthA
, Object
*dictA
) {
739 if (!limited
|| startA
+ lengthA
> start
+ length
) {
740 newLength
= start
+ length
- startA
;
744 subStr
= new MemStream(buf
, startA
, newLength
, dictA
);
748 void MemStream::reset() {
749 bufPtr
= buf
+ start
;
755 void MemStream::close() {
758 void MemStream::setPos(Guint pos
, int dir
) {
764 i
= start
+ length
- pos
;
768 } else if (i
> start
+ length
) {
774 void MemStream::moveStart(int delta
) {
777 bufPtr
= buf
+ start
;
780 void MemStream::doDecryption(Guchar
*fileKey
, int keyLength
,
781 int objNum
, int objGen
) {
785 this->BaseStream::doDecryption(fileKey
, keyLength
, objNum
, objGen
);
787 newBuf
= (char *)gmalloc(length
);
788 for (p
= buf
+ start
, q
= newBuf
; p
< bufEnd
; ++p
, ++q
) {
789 *q
= (char)decrypt
->decryptByte((Guchar
)*p
);
791 bufEnd
= newBuf
+ length
;
792 bufPtr
= newBuf
+ (bufPtr
- (buf
+ start
));
799 //------------------------------------------------------------------------
801 //------------------------------------------------------------------------
803 EmbedStream::EmbedStream(Stream
*strA
, Object
*dictA
,
804 GBool limitedA
, Guint lengthA
):
811 EmbedStream::~EmbedStream() {
814 Stream
*EmbedStream::makeSubStream(Guint start
, GBool limitedA
,
815 Guint lengthA
, Object
*dictA
) {
816 error(-1, "Internal: called makeSubStream() on EmbedStream");
820 int EmbedStream::getChar() {
821 if (limited
&& !length
) {
825 return str
->getChar();
828 int EmbedStream::lookChar() {
829 if (limited
&& !length
) {
832 return str
->lookChar();
835 void EmbedStream::setPos(Guint pos
, int dir
) {
836 error(-1, "Internal: called setPos() on EmbedStream");
839 Guint
EmbedStream::getStart() {
840 error(-1, "Internal: called getStart() on EmbedStream");
844 void EmbedStream::moveStart(int delta
) {
845 error(-1, "Internal: called moveStart() on EmbedStream");
848 //------------------------------------------------------------------------
850 //------------------------------------------------------------------------
852 ASCIIHexStream::ASCIIHexStream(Stream
*strA
):
858 ASCIIHexStream::~ASCIIHexStream() {
862 void ASCIIHexStream::reset() {
868 int ASCIIHexStream::lookChar() {
879 } while (isspace(c1
));
887 } while (isspace(c2
));
892 if (c1
>= '0' && c1
<= '9') {
894 } else if (c1
>= 'A' && c1
<= 'F') {
895 x
= (c1
- 'A' + 10) << 4;
896 } else if (c1
>= 'a' && c1
<= 'f') {
897 x
= (c1
- 'a' + 10) << 4;
898 } else if (c1
== EOF
) {
902 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1
);
905 if (c2
>= '0' && c2
<= '9') {
907 } else if (c2
>= 'A' && c2
<= 'F') {
909 } else if (c2
>= 'a' && c2
<= 'f') {
911 } else if (c2
== EOF
) {
915 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2
);
921 GString
*ASCIIHexStream::getPSFilter(int psLevel
, char *indent
) {
927 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
930 s
->append(indent
)->append("/ASCIIHexDecode filter\n");
934 GBool
ASCIIHexStream::isBinary(GBool last
) {
935 return str
->isBinary(gFalse
);
938 //------------------------------------------------------------------------
940 //------------------------------------------------------------------------
942 ASCII85Stream::ASCII85Stream(Stream
*strA
):
948 ASCII85Stream::~ASCII85Stream() {
952 void ASCII85Stream::reset() {
958 int ASCII85Stream::lookChar() {
967 c
[0] = str
->getChar();
968 } while (Lexer::isSpace(c
[0]));
969 if (c
[0] == '~' || c
[0] == EOF
) {
973 } else if (c
[0] == 'z') {
974 b
[0] = b
[1] = b
[2] = b
[3] = 0;
977 for (k
= 1; k
< 5; ++k
) {
979 c
[k
] = str
->getChar();
980 } while (Lexer::isSpace(c
[k
]));
981 if (c
[k
] == '~' || c
[k
] == EOF
)
985 if (k
< 5 && (c
[k
] == '~' || c
[k
] == EOF
)) {
986 for (++k
; k
< 5; ++k
)
991 for (k
= 0; k
< 5; ++k
)
992 t
= t
* 85 + (c
[k
] - 0x21);
993 for (k
= 3; k
>= 0; --k
) {
994 b
[k
] = (int)(t
& 0xff);
1002 GString
*ASCII85Stream::getPSFilter(int psLevel
, char *indent
) {
1008 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1011 s
->append(indent
)->append("/ASCII85Decode filter\n");
1015 GBool
ASCII85Stream::isBinary(GBool last
) {
1016 return str
->isBinary(gFalse
);
1019 //------------------------------------------------------------------------
1021 //------------------------------------------------------------------------
1023 LZWStream::LZWStream(Stream
*strA
, int predictor
, int columns
, int colors
,
1024 int bits
, int earlyA
):
1025 FilterStream(strA
) {
1026 if (predictor
!= 1) {
1027 pred
= new StreamPredictor(this, predictor
, columns
, colors
, bits
);
1028 if (!pred
->isOk()) {
1041 LZWStream::~LZWStream() {
1048 int LZWStream::getChar() {
1050 return pred
->getChar();
1055 if (seqIndex
>= seqLength
) {
1056 if (!processNextCode()) {
1060 return seqBuf
[seqIndex
++];
1063 int LZWStream::lookChar() {
1065 return pred
->lookChar();
1070 if (seqIndex
>= seqLength
) {
1071 if (!processNextCode()) {
1075 return seqBuf
[seqIndex
];
1078 int LZWStream::getRawChar() {
1082 if (seqIndex
>= seqLength
) {
1083 if (!processNextCode()) {
1087 return seqBuf
[seqIndex
++];
1090 void LZWStream::reset() {
1097 GBool
LZWStream::processNextCode() {
1107 // check for eod and clear-table codes
1110 if (code
== EOF
|| code
== 257) {
1118 if (nextCode
>= 4097) {
1119 error(getPos(), "Bad LZW stream - expected clear-table code");
1123 // process the next code
1124 nextLength
= seqLength
+ 1;
1128 } else if (code
< nextCode
) {
1129 seqLength
= table
[code
].length
;
1130 for (i
= seqLength
- 1, j
= code
; i
> 0; --i
) {
1131 seqBuf
[i
] = table
[j
].tail
;
1135 } else if (code
== nextCode
) {
1136 seqBuf
[seqLength
] = newChar
;
1139 error(getPos(), "Bad LZW stream - unexpected code");
1143 newChar
= seqBuf
[0];
1147 table
[nextCode
].length
= nextLength
;
1148 table
[nextCode
].head
= prevCode
;
1149 table
[nextCode
].tail
= newChar
;
1151 if (nextCode
+ early
== 512)
1153 else if (nextCode
+ early
== 1024)
1155 else if (nextCode
+ early
== 2048)
1166 void LZWStream::clearTable() {
1169 seqIndex
= seqLength
= 0;
1173 int LZWStream::getCode() {
1177 while (inputBits
< nextBits
) {
1178 if ((c
= str
->getChar()) == EOF
)
1180 inputBuf
= (inputBuf
<< 8) | (c
& 0xff);
1183 code
= (inputBuf
>> (inputBits
- nextBits
)) & ((1 << nextBits
) - 1);
1184 inputBits
-= nextBits
;
1188 GString
*LZWStream::getPSFilter(int psLevel
, char *indent
) {
1191 if (psLevel
< 2 || pred
) {
1194 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1197 s
->append(indent
)->append("<< ");
1199 s
->append("/EarlyChange 0 ");
1201 s
->append(">> /LZWDecode filter\n");
1205 GBool
LZWStream::isBinary(GBool last
) {
1206 return str
->isBinary(gTrue
);
1209 //------------------------------------------------------------------------
1211 //------------------------------------------------------------------------
1213 RunLengthStream::RunLengthStream(Stream
*strA
):
1214 FilterStream(strA
) {
1215 bufPtr
= bufEnd
= buf
;
1219 RunLengthStream::~RunLengthStream() {
1223 void RunLengthStream::reset() {
1225 bufPtr
= bufEnd
= buf
;
1229 GString
*RunLengthStream::getPSFilter(int psLevel
, char *indent
) {
1235 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1238 s
->append(indent
)->append("/RunLengthDecode filter\n");
1242 GBool
RunLengthStream::isBinary(GBool last
) {
1243 return str
->isBinary(gTrue
);
1246 GBool
RunLengthStream::fillBuf() {
1253 if (c
== 0x80 || c
== EOF
) {
1259 for (i
= 0; i
< n
; ++i
)
1260 buf
[i
] = (char)str
->getChar();
1264 for (i
= 0; i
< n
; ++i
)
1272 //------------------------------------------------------------------------
1274 //------------------------------------------------------------------------
1276 CCITTFaxStream::CCITTFaxStream(Stream
*strA
, int encodingA
, GBool endOfLineA
,
1277 GBool byteAlignA
, int columnsA
, int rowsA
,
1278 GBool endOfBlockA
, GBool blackA
):
1279 FilterStream(strA
) {
1280 encoding
= encodingA
;
1281 endOfLine
= endOfLineA
;
1282 byteAlign
= byteAlignA
;
1284 if (columns
< 1 || columns
>= (INT_MAX
/ sizeof(short))) {
1285 error(getPos(), "Bad number of columns: %d in CCITTFaxStream", columns
);
1289 endOfBlock
= endOfBlockA
;
1291 refLine
= (short *)gmallocn(columns
+ 4, sizeof(short));
1292 codingLine
= (short *)gmallocn(columns
+ 3, sizeof(short));
1296 nextLine2D
= encoding
< 0;
1299 codingLine
[1] = refLine
[2] = columns
;
1305 CCITTFaxStream::~CCITTFaxStream() {
1311 void CCITTFaxStream::reset() {
1317 nextLine2D
= encoding
< 0;
1320 codingLine
[1] = refLine
[2] = columns
;
1324 // skip any initial zero bits and end-of-line marker, and get the 2D
1326 while ((code1
= lookBits(12)) == 0) {
1329 if (code1
== 0x001) {
1333 nextLine2D
= !lookBits(1);
1338 int CCITTFaxStream::lookChar() {
1339 short code1
, code2
, code3
;
1345 // if at eof just return EOF
1346 if (eof
&& codingLine
[a0
] >= columns
) {
1350 // read the next row
1352 if (codingLine
[a0
] >= columns
) {
1356 for (i
= 0; codingLine
[i
] < columns
; ++i
)
1357 refLine
[i
] = codingLine
[i
];
1358 refLine
[i
] = refLine
[i
+ 1] = columns
;
1360 a0New
= codingLine
[a0
= 0] = 0;
1362 code1
= getTwoDimCode();
1365 if (refLine
[b1
] < columns
) {
1366 a0New
= refLine
[b1
+ 1];
1371 if ((a0
& 1) == 0) {
1374 code1
+= code3
= getWhiteCode();
1375 } while (code3
>= 64);
1377 code2
+= code3
= getBlackCode();
1378 } while (code3
>= 64);
1382 code1
+= code3
= getBlackCode();
1383 } while (code3
>= 64);
1385 code2
+= code3
= getWhiteCode();
1386 } while (code3
>= 64);
1388 if (code1
> 0 || code2
> 0) {
1389 codingLine
[a0
+ 1] = a0New
+ code1
;
1391 a0New
= codingLine
[a0
+ 1] = codingLine
[a0
] + code2
;
1393 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1398 a0New
= codingLine
[++a0
] = refLine
[b1
];
1399 if (refLine
[b1
] < columns
) {
1401 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1406 a0New
= codingLine
[++a0
] = refLine
[b1
] + 1;
1407 if (refLine
[b1
] < columns
) {
1409 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1414 if (a0
== 0 || refLine
[b1
] - 1 > a0New
) {
1415 a0New
= codingLine
[++a0
] = refLine
[b1
] - 1;
1417 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1422 a0New
= codingLine
[++a0
] = refLine
[b1
] + 2;
1423 if (refLine
[b1
] < columns
) {
1425 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1430 if (a0
== 0 || refLine
[b1
] - 2 > a0New
) {
1431 a0New
= codingLine
[++a0
] = refLine
[b1
] - 2;
1433 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1438 a0New
= codingLine
[++a0
] = refLine
[b1
] + 3;
1439 if (refLine
[b1
] < columns
) {
1441 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1446 if (a0
== 0 || refLine
[b1
] - 3 > a0New
) {
1447 a0New
= codingLine
[++a0
] = refLine
[b1
] - 3;
1449 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1455 codingLine
[a0
= 0] = columns
;
1458 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1
);
1462 } while (codingLine
[a0
] < columns
);
1466 codingLine
[a0
= 0] = 0;
1470 code1
+= code3
= getWhiteCode();
1471 } while (code3
>= 64);
1472 codingLine
[a0
+1] = codingLine
[a0
] + code1
;
1474 if (codingLine
[a0
] >= columns
)
1478 code2
+= code3
= getBlackCode();
1479 } while (code3
>= 64);
1480 codingLine
[a0
+1] = codingLine
[a0
] + code2
;
1482 if (codingLine
[a0
] >= columns
)
1487 if (codingLine
[a0
] != columns
) {
1488 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine
[a0
]);
1489 // force the row to be the correct length
1490 while (codingLine
[a0
] > columns
) {
1493 codingLine
[++a0
] = columns
;
1497 // byte-align the row
1502 // check for end-of-line marker, skipping over any extra zero bits
1504 if (!endOfBlock
&& row
== rows
- 1) {
1507 code1
= lookBits(12);
1508 while (code1
== 0) {
1510 code1
= lookBits(12);
1512 if (code1
== 0x001) {
1515 } else if (code1
== EOF
) {
1520 // get 2D encoding tag
1521 if (!eof
&& encoding
> 0) {
1522 nextLine2D
= !lookBits(1);
1526 // check for end-of-block marker
1527 if (endOfBlock
&& gotEOL
) {
1528 code1
= lookBits(12);
1529 if (code1
== 0x001) {
1535 if (encoding
>= 0) {
1536 for (i
= 0; i
< 4; ++i
) {
1537 code1
= lookBits(12);
1538 if (code1
!= 0x001) {
1539 error(getPos(), "Bad RTC code in CCITTFax stream");
1551 // look for an end-of-line marker after an error -- we only do
1552 // this if we know the stream contains end-of-line markers because
1553 // the "just plow on" technique tends to work better otherwise
1554 } else if (err
&& endOfLine
) {
1561 code1
= lookBits(13);
1562 } while ((code1
>> 1) != 0x001);
1566 nextLine2D
= !(code1
& 1);
1571 outputBits
= codingLine
[1] - codingLine
[0];
1572 if (outputBits
== 0) {
1574 outputBits
= codingLine
[2] - codingLine
[1];
1581 if (outputBits
>= 8) {
1582 ret
= ((a0
& 1) == 0) ? 0xff : 0x00;
1583 if ((outputBits
-= 8) == 0) {
1585 if (codingLine
[a0
] < columns
) {
1586 outputBits
= codingLine
[a0
+ 1] - codingLine
[a0
];
1593 if (outputBits
> bits
) {
1596 if ((a0
& 1) == 0) {
1597 ret
|= 0xff >> (8 - i
);
1603 if ((a0
& 1) == 0) {
1604 ret
|= (0xff >> (8 - i
)) << bits
;
1608 if (codingLine
[a0
] < columns
) {
1609 outputBits
= codingLine
[a0
+ 1] - codingLine
[a0
];
1612 } while (bits
> 0 && codingLine
[a0
] < columns
);
1614 buf
= black
? (ret
^ 0xff) : ret
;
1618 short CCITTFaxStream::getTwoDimCode() {
1623 code
= 0; // make gcc happy
1626 p
= &twoDimTab1
[code
];
1632 for (n
= 1; n
<= 7; ++n
) {
1637 p
= &twoDimTab1
[code
];
1644 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code
);
1648 short CCITTFaxStream::getWhiteCode() {
1653 code
= 0; // make gcc happy
1655 code
= lookBits(12);
1656 if ((code
>> 5) == 0) {
1657 p
= &whiteTab1
[code
];
1659 p
= &whiteTab2
[code
>> 3];
1666 for (n
= 1; n
<= 9; ++n
) {
1671 p
= &whiteTab2
[code
];
1677 for (n
= 11; n
<= 12; ++n
) {
1682 p
= &whiteTab1
[code
];
1689 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code
);
1690 // eat a bit and return a positive number so that the caller doesn't
1691 // go into an infinite loop
1696 short CCITTFaxStream::getBlackCode() {
1701 code
= 0; // make gcc happy
1703 code
= lookBits(13);
1704 if ((code
>> 7) == 0) {
1705 p
= &blackTab1
[code
];
1706 } else if ((code
>> 9) == 0) {
1707 p
= &blackTab2
[(code
>> 1) - 64];
1709 p
= &blackTab3
[code
>> 7];
1716 for (n
= 2; n
<= 6; ++n
) {
1721 p
= &blackTab3
[code
];
1727 for (n
= 7; n
<= 12; ++n
) {
1733 p
= &blackTab2
[code
- 64];
1740 for (n
= 10; n
<= 13; ++n
) {
1745 p
= &blackTab1
[code
];
1752 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code
);
1753 // eat a bit and return a positive number so that the caller doesn't
1754 // go into an infinite loop
1759 short CCITTFaxStream::lookBits(int n
) {
1762 while (inputBits
< n
) {
1763 if ((c
= str
->getChar()) == EOF
) {
1764 if (inputBits
== 0) {
1767 // near the end of the stream, the caller may ask for more bits
1768 // than are available, but there may still be a valid code in
1769 // however many bits are available -- we need to return correct
1770 // data in this case
1771 return (inputBuf
<< (n
- inputBits
)) & (0xffff >> (16 - n
));
1773 inputBuf
= (inputBuf
<< 8) + c
;
1776 return (inputBuf
>> (inputBits
- n
)) & (0xffff >> (16 - n
));
1779 GString
*CCITTFaxStream::getPSFilter(int psLevel
, char *indent
) {
1786 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1789 s
->append(indent
)->append("<< ");
1790 if (encoding
!= 0) {
1791 sprintf(s1
, "/K %d ", encoding
);
1795 s
->append("/EndOfLine true ");
1798 s
->append("/EncodedByteAlign true ");
1800 sprintf(s1
, "/Columns %d ", columns
);
1803 sprintf(s1
, "/Rows %d ", rows
);
1807 s
->append("/EndOfBlock false ");
1810 s
->append("/BlackIs1 true ");
1812 s
->append(">> /CCITTFaxDecode filter\n");
1816 GBool
CCITTFaxStream::isBinary(GBool last
) {
1817 return str
->isBinary(gTrue
);
1820 //------------------------------------------------------------------------
1822 //------------------------------------------------------------------------
1824 // IDCT constants (20.12 fixed point format)
1825 #define dctCos1 4017 // cos(pi/16)
1826 #define dctSin1 799 // sin(pi/16)
1827 #define dctCos3 3406 // cos(3*pi/16)
1828 #define dctSin3 2276 // sin(3*pi/16)
1829 #define dctCos6 1567 // cos(6*pi/16)
1830 #define dctSin6 3784 // sin(6*pi/16)
1831 #define dctSqrt2 5793 // sqrt(2)
1832 #define dctSqrt1d2 2896 // sqrt(2) / 2
1834 // color conversion parameters (16.16 fixed point format)
1835 #define dctCrToR 91881 // 1.4020
1836 #define dctCbToG -22553 // -0.3441363
1837 #define dctCrToG -46802 // -0.71413636
1838 #define dctCbToB 116130 // 1.772
1840 // clip [-256,511] --> [0,255]
1841 #define dctClipOffset 256
1842 static Guchar dctClip
[768];
1843 static int dctClipInit
= 0;
1845 // zig zag decode map
1846 static int dctZigZag
[64] = {
1852 5, 12, 19, 26, 33, 40,
1853 48, 41, 34, 27, 20, 13, 6,
1854 7, 14, 21, 28, 35, 42, 49, 56,
1855 57, 50, 43, 36, 29, 22, 15,
1856 23, 30, 37, 44, 51, 58,
1864 DCTStream::DCTStream(Stream
*strA
):
1865 FilterStream(strA
) {
1868 progressive
= interleaved
= gFalse
;
1870 mcuWidth
= mcuHeight
= 0;
1874 for (i
= 0; i
< 4; ++i
) {
1875 for (j
= 0; j
< 32; ++j
) {
1876 rowBuf
[i
][j
] = NULL
;
1882 for (i
= -256; i
< 0; ++i
)
1883 dctClip
[dctClipOffset
+ i
] = 0;
1884 for (i
= 0; i
< 256; ++i
)
1885 dctClip
[dctClipOffset
+ i
] = i
;
1886 for (i
= 256; i
< 512; ++i
)
1887 dctClip
[dctClipOffset
+ i
] = 255;
1892 DCTStream::~DCTStream() {
1896 if (progressive
|| !interleaved
) {
1897 for (i
= 0; i
< numComps
; ++i
) {
1901 for (i
= 0; i
< numComps
; ++i
) {
1902 for (j
= 0; j
< mcuHeight
; ++j
) {
1903 gfree(rowBuf
[i
][j
]);
1909 void DCTStream::reset() {
1914 progressive
= interleaved
= gFalse
;
1918 numDCHuffTables
= 0;
1919 numACHuffTables
= 0;
1921 gotJFIFMarker
= gFalse
;
1922 gotAdobeMarker
= gFalse
;
1923 restartInterval
= 0;
1925 if (!readHeader()) {
1931 if (numComps
== 1) {
1932 compInfo
[0].hSample
= compInfo
[0].vSample
= 1;
1934 mcuWidth
= compInfo
[0].hSample
;
1935 mcuHeight
= compInfo
[0].vSample
;
1936 for (i
= 1; i
< numComps
; ++i
) {
1937 if (compInfo
[i
].hSample
> mcuWidth
) {
1938 mcuWidth
= compInfo
[i
].hSample
;
1940 if (compInfo
[i
].vSample
> mcuHeight
) {
1941 mcuHeight
= compInfo
[i
].vSample
;
1947 // figure out color transform
1948 if (!gotAdobeMarker
&& numComps
== 3) {
1949 if (gotJFIFMarker
) {
1951 } else if (compInfo
[0].id
== 82 && compInfo
[1].id
== 71 &&
1952 compInfo
[2].id
== 66) { // ASCII "RGB"
1959 if (progressive
|| !interleaved
) {
1961 // allocate a buffer for the whole image
1962 bufWidth
= ((width
+ mcuWidth
- 1) / mcuWidth
) * mcuWidth
;
1963 bufHeight
= ((height
+ mcuHeight
- 1) / mcuHeight
) * mcuHeight
;
1964 for (i
= 0; i
< numComps
; ++i
) {
1965 frameBuf
[i
] = (int *)gmallocn(bufWidth
* bufHeight
, sizeof(int));
1966 memset(frameBuf
[i
], 0, bufWidth
* bufHeight
* sizeof(int));
1969 // read the image data
1971 restartMarker
= 0xd0;
1974 } while (readHeader());
1979 // initialize counters
1986 // allocate a buffer for one row of MCUs
1987 bufWidth
= ((width
+ mcuWidth
- 1) / mcuWidth
) * mcuWidth
;
1988 for (i
= 0; i
< numComps
; ++i
) {
1989 for (j
= 0; j
< mcuHeight
; ++j
) {
1990 rowBuf
[i
][j
] = (Guchar
*)gmallocn(bufWidth
, sizeof(Guchar
));
1994 // initialize counters
2000 restartMarker
= 0xd0;
2005 int DCTStream::getChar() {
2011 if (progressive
|| !interleaved
) {
2012 c
= frameBuf
[comp
][y
* bufWidth
+ x
];
2013 if (++comp
== numComps
) {
2021 if (dy
>= mcuHeight
) {
2022 if (!readMCURow()) {
2030 c
= rowBuf
[comp
][dy
][x
];
2031 if (++comp
== numComps
) {
2046 int DCTStream::lookChar() {
2050 if (progressive
|| !interleaved
) {
2051 return frameBuf
[comp
][y
* bufWidth
+ x
];
2053 if (dy
>= mcuHeight
) {
2054 if (!readMCURow()) {
2062 return rowBuf
[comp
][dy
][x
];
2066 void DCTStream::restart() {
2070 restartCtr
= restartInterval
;
2071 for (i
= 0; i
< numComps
; ++i
) {
2072 compInfo
[i
].prevDC
= 0;
2077 // Read one row of MCUs from a sequential JPEG stream.
2078 GBool
DCTStream::readMCURow() {
2082 int pY
, pCb
, pCr
, pR
, pG
, pB
;
2083 int h
, v
, horiz
, vert
, hSub
, vSub
;
2084 int x1
, x2
, y2
, x3
, y3
, x4
, y4
, x5
, y5
, cc
, i
;
2087 for (x1
= 0; x1
< width
; x1
+= mcuWidth
) {
2089 // deal with restart marker
2090 if (restartInterval
> 0 && restartCtr
== 0) {
2092 if (c
!= restartMarker
) {
2093 error(getPos(), "Bad DCT data: incorrect restart marker");
2096 if (++restartMarker
== 0xd8)
2097 restartMarker
= 0xd0;
2102 for (cc
= 0; cc
< numComps
; ++cc
) {
2103 h
= compInfo
[cc
].hSample
;
2104 v
= compInfo
[cc
].vSample
;
2105 horiz
= mcuWidth
/ h
;
2106 vert
= mcuHeight
/ v
;
2109 for (y2
= 0; y2
< mcuHeight
; y2
+= vert
) {
2110 for (x2
= 0; x2
< mcuWidth
; x2
+= horiz
) {
2111 if (!readDataUnit(&dcHuffTables
[scanInfo
.dcHuffTable
[cc
]],
2112 &acHuffTables
[scanInfo
.acHuffTable
[cc
]],
2113 &compInfo
[cc
].prevDC
,
2117 transformDataUnit(quantTables
[compInfo
[cc
].quantTable
],
2119 if (hSub
== 1 && vSub
== 1) {
2120 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2121 p1
= &rowBuf
[cc
][y2
+y3
][x1
+x2
];
2131 } else if (hSub
== 2 && vSub
== 2) {
2132 for (y3
= 0, i
= 0; y3
< 16; y3
+= 2, i
+= 8) {
2133 p1
= &rowBuf
[cc
][y2
+y3
][x1
+x2
];
2134 p2
= &rowBuf
[cc
][y2
+y3
+1][x1
+x2
];
2135 p1
[0] = p1
[1] = p2
[0] = p2
[1] = data2
[i
];
2136 p1
[2] = p1
[3] = p2
[2] = p2
[3] = data2
[i
+1];
2137 p1
[4] = p1
[5] = p2
[4] = p2
[5] = data2
[i
+2];
2138 p1
[6] = p1
[7] = p2
[6] = p2
[7] = data2
[i
+3];
2139 p1
[8] = p1
[9] = p2
[8] = p2
[9] = data2
[i
+4];
2140 p1
[10] = p1
[11] = p2
[10] = p2
[11] = data2
[i
+5];
2141 p1
[12] = p1
[13] = p2
[12] = p2
[13] = data2
[i
+6];
2142 p1
[14] = p1
[15] = p2
[14] = p2
[15] = data2
[i
+7];
2146 for (y3
= 0, y4
= 0; y3
< 8; ++y3
, y4
+= vSub
) {
2147 for (x3
= 0, x4
= 0; x3
< 8; ++x3
, x4
+= hSub
) {
2148 for (y5
= 0; y5
< vSub
; ++y5
)
2149 for (x5
= 0; x5
< hSub
; ++x5
)
2150 rowBuf
[cc
][y2
+y4
+y5
][x1
+x2
+x4
+x5
] = data2
[i
];
2160 // color space conversion
2162 // convert YCbCr to RGB
2163 if (numComps
== 3) {
2164 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2165 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2166 pY
= rowBuf
[0][y2
][x1
+x2
];
2167 pCb
= rowBuf
[1][y2
][x1
+x2
] - 128;
2168 pCr
= rowBuf
[2][y2
][x1
+x2
] - 128;
2169 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2170 rowBuf
[0][y2
][x1
+x2
] = dctClip
[dctClipOffset
+ pR
];
2171 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+ 32768) >> 16;
2172 rowBuf
[1][y2
][x1
+x2
] = dctClip
[dctClipOffset
+ pG
];
2173 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2174 rowBuf
[2][y2
][x1
+x2
] = dctClip
[dctClipOffset
+ pB
];
2177 // convert YCbCrK to CMYK (K is passed through unchanged)
2178 } else if (numComps
== 4) {
2179 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2180 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2181 pY
= rowBuf
[0][y2
][x1
+x2
];
2182 pCb
= rowBuf
[1][y2
][x1
+x2
] - 128;
2183 pCr
= rowBuf
[2][y2
][x1
+x2
] - 128;
2184 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2185 rowBuf
[0][y2
][x1
+x2
] = 255 - dctClip
[dctClipOffset
+ pR
];
2186 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+ 32768) >> 16;
2187 rowBuf
[1][y2
][x1
+x2
] = 255 - dctClip
[dctClipOffset
+ pG
];
2188 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2189 rowBuf
[2][y2
][x1
+x2
] = 255 - dctClip
[dctClipOffset
+ pB
];
2198 // Read one scan from a progressive or non-interleaved JPEG stream.
2199 void DCTStream::readScan() {
2201 int x1
, y1
, dx1
, dy1
, x2
, y2
, y3
, cc
, i
;
2202 int h
, v
, horiz
, vert
, vSub
;
2206 if (scanInfo
.numComps
== 1) {
2207 for (cc
= 0; cc
< numComps
; ++cc
) {
2208 if (scanInfo
.comp
[cc
]) {
2212 dx1
= mcuWidth
/ compInfo
[cc
].hSample
;
2213 dy1
= mcuHeight
/ compInfo
[cc
].vSample
;
2219 for (y1
= 0; y1
< height
; y1
+= dy1
) {
2220 for (x1
= 0; x1
< width
; x1
+= dx1
) {
2222 // deal with restart marker
2223 if (restartInterval
> 0 && restartCtr
== 0) {
2225 if (c
!= restartMarker
) {
2226 error(getPos(), "Bad DCT data: incorrect restart marker");
2229 if (++restartMarker
== 0xd8) {
2230 restartMarker
= 0xd0;
2236 for (cc
= 0; cc
< numComps
; ++cc
) {
2237 if (!scanInfo
.comp
[cc
]) {
2241 h
= compInfo
[cc
].hSample
;
2242 v
= compInfo
[cc
].vSample
;
2243 horiz
= mcuWidth
/ h
;
2244 vert
= mcuHeight
/ v
;
2246 for (y2
= 0; y2
< dy1
; y2
+= vert
) {
2247 for (x2
= 0; x2
< dx1
; x2
+= horiz
) {
2249 // pull out the current values
2250 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2251 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2260 p1
+= bufWidth
* vSub
;
2263 // read one data unit
2265 if (!readProgressiveDataUnit(
2266 &dcHuffTables
[scanInfo
.dcHuffTable
[cc
]],
2267 &acHuffTables
[scanInfo
.acHuffTable
[cc
]],
2268 &compInfo
[cc
].prevDC
,
2273 if (!readDataUnit(&dcHuffTables
[scanInfo
.dcHuffTable
[cc
]],
2274 &acHuffTables
[scanInfo
.acHuffTable
[cc
]],
2275 &compInfo
[cc
].prevDC
,
2281 // add the data unit into frameBuf
2282 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2283 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2292 p1
+= bufWidth
* vSub
;
2302 // Read one data unit from a sequential JPEG stream.
2303 GBool
DCTStream::readDataUnit(DCTHuffTable
*dcHuffTable
,
2304 DCTHuffTable
*acHuffTable
,
2305 int *prevDC
, int data
[64]) {
2310 if ((size
= readHuffSym(dcHuffTable
)) == 9999) {
2314 if ((amp
= readAmp(size
)) == 9999) {
2320 data
[0] = *prevDC
+= amp
;
2321 for (i
= 1; i
< 64; ++i
) {
2327 while ((c
= readHuffSym(acHuffTable
)) == 0xf0 && run
< 0x30) {
2336 run
+= (c
>> 4) & 0x0f;
2338 amp
= readAmp(size
);
2352 // Read one data unit from a sequential JPEG stream.
2353 GBool
DCTStream::readProgressiveDataUnit(DCTHuffTable
*dcHuffTable
,
2354 DCTHuffTable
*acHuffTable
,
2355 int *prevDC
, int data
[64]) {
2356 int run
, size
, amp
, bit
, c
;
2359 // get the DC coefficient
2360 i
= scanInfo
.firstCoeff
;
2362 if (scanInfo
.ah
== 0) {
2363 if ((size
= readHuffSym(dcHuffTable
)) == 9999) {
2367 if ((amp
= readAmp(size
)) == 9999) {
2373 data
[0] += (*prevDC
+= amp
) << scanInfo
.al
;
2375 if ((bit
= readBit()) == 9999) {
2378 data
[0] += bit
<< scanInfo
.al
;
2382 if (scanInfo
.lastCoeff
== 0) {
2386 // check for an EOB run
2388 while (i
<= scanInfo
.lastCoeff
) {
2391 if ((bit
= readBit()) == EOF
) {
2395 data
[j
] += 1 << scanInfo
.al
;
2403 // read the AC coefficients
2404 while (i
<= scanInfo
.lastCoeff
) {
2405 if ((c
= readHuffSym(acHuffTable
)) == 9999) {
2417 if ((bit
= readBit()) == EOF
) {
2421 data
[j
] += 1 << scanInfo
.al
;
2427 } else if ((c
& 0x0f) == 0x00) {
2430 for (k
= 0; k
< j
; ++k
) {
2431 if ((bit
= readBit()) == EOF
) {
2434 eobRun
= (eobRun
<< 1) | bit
;
2437 while (i
<= scanInfo
.lastCoeff
) {
2440 if ((bit
= readBit()) == EOF
) {
2444 data
[j
] += 1 << scanInfo
.al
;
2451 // zero run and one AC coefficient
2453 run
= (c
>> 4) & 0x0f;
2455 if ((amp
= readAmp(size
)) == 9999) {
2461 while (data
[j
] != 0) {
2462 if ((bit
= readBit()) == EOF
) {
2466 data
[j
] += 1 << scanInfo
.al
;
2472 data
[j
] = amp
<< scanInfo
.al
;
2479 // Decode a progressive JPEG image.
2480 void DCTStream::decodeImage() {
2483 Gushort
*quantTable
;
2484 int pY
, pCb
, pCr
, pR
, pG
, pB
;
2485 int x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
, x5
, y5
, cc
, i
;
2486 int h
, v
, horiz
, vert
, hSub
, vSub
;
2489 for (y1
= 0; y1
< bufHeight
; y1
+= mcuHeight
) {
2490 for (x1
= 0; x1
< bufWidth
; x1
+= mcuWidth
) {
2491 for (cc
= 0; cc
< numComps
; ++cc
) {
2492 quantTable
= quantTables
[compInfo
[cc
].quantTable
];
2493 h
= compInfo
[cc
].hSample
;
2494 v
= compInfo
[cc
].vSample
;
2495 horiz
= mcuWidth
/ h
;
2496 vert
= mcuHeight
/ v
;
2499 for (y2
= 0; y2
< mcuHeight
; y2
+= vert
) {
2500 for (x2
= 0; x2
< mcuWidth
; x2
+= horiz
) {
2502 // pull out the coded data unit
2503 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2504 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2506 dataIn
[i
+1] = p1
[1];
2507 dataIn
[i
+2] = p1
[2];
2508 dataIn
[i
+3] = p1
[3];
2509 dataIn
[i
+4] = p1
[4];
2510 dataIn
[i
+5] = p1
[5];
2511 dataIn
[i
+6] = p1
[6];
2512 dataIn
[i
+7] = p1
[7];
2513 p1
+= bufWidth
* vSub
;
2517 transformDataUnit(quantTable
, dataIn
, dataOut
);
2519 // store back into frameBuf, doing replication for
2520 // subsampled components
2521 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2522 if (hSub
== 1 && vSub
== 1) {
2523 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2524 p1
[0] = dataOut
[i
] & 0xff;
2525 p1
[1] = dataOut
[i
+1] & 0xff;
2526 p1
[2] = dataOut
[i
+2] & 0xff;
2527 p1
[3] = dataOut
[i
+3] & 0xff;
2528 p1
[4] = dataOut
[i
+4] & 0xff;
2529 p1
[5] = dataOut
[i
+5] & 0xff;
2530 p1
[6] = dataOut
[i
+6] & 0xff;
2531 p1
[7] = dataOut
[i
+7] & 0xff;
2534 } else if (hSub
== 2 && vSub
== 2) {
2536 for (y3
= 0, i
= 0; y3
< 16; y3
+= 2, i
+= 8) {
2537 p1
[0] = p1
[1] = p2
[0] = p2
[1] = dataOut
[i
] & 0xff;
2538 p1
[2] = p1
[3] = p2
[2] = p2
[3] = dataOut
[i
+1] & 0xff;
2539 p1
[4] = p1
[5] = p2
[4] = p2
[5] = dataOut
[i
+2] & 0xff;
2540 p1
[6] = p1
[7] = p2
[6] = p2
[7] = dataOut
[i
+3] & 0xff;
2541 p1
[8] = p1
[9] = p2
[8] = p2
[9] = dataOut
[i
+4] & 0xff;
2542 p1
[10] = p1
[11] = p2
[10] = p2
[11] = dataOut
[i
+5] & 0xff;
2543 p1
[12] = p1
[13] = p2
[12] = p2
[13] = dataOut
[i
+6] & 0xff;
2544 p1
[14] = p1
[15] = p2
[14] = p2
[15] = dataOut
[i
+7] & 0xff;
2550 for (y3
= 0, y4
= 0; y3
< 8; ++y3
, y4
+= vSub
) {
2551 for (x3
= 0, x4
= 0; x3
< 8; ++x3
, x4
+= hSub
) {
2553 for (y5
= 0; y5
< vSub
; ++y5
) {
2554 for (x5
= 0; x5
< hSub
; ++x5
) {
2555 p2
[x5
] = dataOut
[i
] & 0xff;
2561 p1
+= bufWidth
* vSub
;
2568 // color space conversion
2570 // convert YCbCr to RGB
2571 if (numComps
== 3) {
2572 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2573 p0
= &frameBuf
[0][(y1
+y2
) * bufWidth
+ x1
];
2574 p1
= &frameBuf
[1][(y1
+y2
) * bufWidth
+ x1
];
2575 p2
= &frameBuf
[2][(y1
+y2
) * bufWidth
+ x1
];
2576 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2580 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2581 *p0
++ = dctClip
[dctClipOffset
+ pR
];
2582 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+
2584 *p1
++ = dctClip
[dctClipOffset
+ pG
];
2585 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2586 *p2
++ = dctClip
[dctClipOffset
+ pB
];
2589 // convert YCbCrK to CMYK (K is passed through unchanged)
2590 } else if (numComps
== 4) {
2591 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2592 p0
= &frameBuf
[0][(y1
+y2
) * bufWidth
+ x1
];
2593 p1
= &frameBuf
[1][(y1
+y2
) * bufWidth
+ x1
];
2594 p2
= &frameBuf
[2][(y1
+y2
) * bufWidth
+ x1
];
2595 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2599 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2600 *p0
++ = 255 - dctClip
[dctClipOffset
+ pR
];
2601 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+
2603 *p1
++ = 255 - dctClip
[dctClipOffset
+ pG
];
2604 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2605 *p2
++ = 255 - dctClip
[dctClipOffset
+ pB
];
2614 // Transform one data unit -- this performs the dequantization and
2615 // IDCT steps. This IDCT algorithm is taken from:
2616 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2617 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2618 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2620 // The stage numbers mentioned in the comments refer to Figure 1 in this
2622 void DCTStream::transformDataUnit(Gushort
*quantTable
,
2623 int dataIn
[64], Guchar dataOut
[64]) {
2624 int v0
, v1
, v2
, v3
, v4
, v5
, v6
, v7
, t
;
2629 for (i
= 0; i
< 64; ++i
) {
2630 dataIn
[i
] *= quantTable
[i
];
2633 // inverse DCT on rows
2634 for (i
= 0; i
< 64; i
+= 8) {
2637 // check for all-zero AC coefficients
2638 if (p
[1] == 0 && p
[2] == 0 && p
[3] == 0 &&
2639 p
[4] == 0 && p
[5] == 0 && p
[6] == 0 && p
[7] == 0) {
2640 t
= (dctSqrt2
* p
[0] + 512) >> 10;
2653 v0
= (dctSqrt2
* p
[0] + 128) >> 8;
2654 v1
= (dctSqrt2
* p
[4] + 128) >> 8;
2657 v4
= (dctSqrt1d2
* (p
[1] - p
[7]) + 128) >> 8;
2658 v7
= (dctSqrt1d2
* (p
[1] + p
[7]) + 128) >> 8;
2663 t
= (v0
- v1
+ 1) >> 1;
2664 v0
= (v0
+ v1
+ 1) >> 1;
2666 t
= (v2
* dctSin6
+ v3
* dctCos6
+ 128) >> 8;
2667 v2
= (v2
* dctCos6
- v3
* dctSin6
+ 128) >> 8;
2669 t
= (v4
- v6
+ 1) >> 1;
2670 v4
= (v4
+ v6
+ 1) >> 1;
2672 t
= (v7
+ v5
+ 1) >> 1;
2673 v5
= (v7
- v5
+ 1) >> 1;
2677 t
= (v0
- v3
+ 1) >> 1;
2678 v0
= (v0
+ v3
+ 1) >> 1;
2680 t
= (v1
- v2
+ 1) >> 1;
2681 v1
= (v1
+ v2
+ 1) >> 1;
2683 t
= (v4
* dctSin3
+ v7
* dctCos3
+ 2048) >> 12;
2684 v4
= (v4
* dctCos3
- v7
* dctSin3
+ 2048) >> 12;
2686 t
= (v5
* dctSin1
+ v6
* dctCos1
+ 2048) >> 12;
2687 v5
= (v5
* dctCos1
- v6
* dctSin1
+ 2048) >> 12;
2701 // inverse DCT on columns
2702 for (i
= 0; i
< 8; ++i
) {
2705 // check for all-zero AC coefficients
2706 if (p
[1*8] == 0 && p
[2*8] == 0 && p
[3*8] == 0 &&
2707 p
[4*8] == 0 && p
[5*8] == 0 && p
[6*8] == 0 && p
[7*8] == 0) {
2708 t
= (dctSqrt2
* dataIn
[i
+0] + 8192) >> 14;
2721 v0
= (dctSqrt2
* p
[0*8] + 2048) >> 12;
2722 v1
= (dctSqrt2
* p
[4*8] + 2048) >> 12;
2725 v4
= (dctSqrt1d2
* (p
[1*8] - p
[7*8]) + 2048) >> 12;
2726 v7
= (dctSqrt1d2
* (p
[1*8] + p
[7*8]) + 2048) >> 12;
2731 t
= (v0
- v1
+ 1) >> 1;
2732 v0
= (v0
+ v1
+ 1) >> 1;
2734 t
= (v2
* dctSin6
+ v3
* dctCos6
+ 2048) >> 12;
2735 v2
= (v2
* dctCos6
- v3
* dctSin6
+ 2048) >> 12;
2737 t
= (v4
- v6
+ 1) >> 1;
2738 v4
= (v4
+ v6
+ 1) >> 1;
2740 t
= (v7
+ v5
+ 1) >> 1;
2741 v5
= (v7
- v5
+ 1) >> 1;
2745 t
= (v0
- v3
+ 1) >> 1;
2746 v0
= (v0
+ v3
+ 1) >> 1;
2748 t
= (v1
- v2
+ 1) >> 1;
2749 v1
= (v1
+ v2
+ 1) >> 1;
2751 t
= (v4
* dctSin3
+ v7
* dctCos3
+ 2048) >> 12;
2752 v4
= (v4
* dctCos3
- v7
* dctSin3
+ 2048) >> 12;
2754 t
= (v5
* dctSin1
+ v6
* dctCos1
+ 2048) >> 12;
2755 v5
= (v5
* dctCos1
- v6
* dctSin1
+ 2048) >> 12;
2769 // convert to 8-bit integers
2770 for (i
= 0; i
< 64; ++i
) {
2771 dataOut
[i
] = dctClip
[dctClipOffset
+ 128 + ((dataIn
[i
] + 8) >> 4)];
2775 int DCTStream::readHuffSym(DCTHuffTable
*table
) {
2783 // add a bit to the code
2784 if ((bit
= readBit()) == EOF
)
2786 code
= (code
<< 1) + bit
;
2790 if (code
- table
->firstCode
[codeBits
] < table
->numCodes
[codeBits
]) {
2791 code
-= table
->firstCode
[codeBits
];
2792 return table
->sym
[table
->firstSym
[codeBits
] + code
];
2794 } while (codeBits
< 16);
2796 error(getPos(), "Bad Huffman code in DCT stream");
2800 int DCTStream::readAmp(int size
) {
2805 for (bits
= 0; bits
< size
; ++bits
) {
2806 if ((bit
= readBit()) == EOF
)
2808 amp
= (amp
<< 1) + bit
;
2810 if (amp
< (1 << (size
- 1)))
2811 amp
-= (1 << size
) - 1;
2815 int DCTStream::readBit() {
2819 if (inputBits
== 0) {
2820 if ((c
= str
->getChar()) == EOF
)
2824 c2
= str
->getChar();
2825 } while (c2
== 0xff);
2827 error(getPos(), "Bad DCT data: missing 00 after ff");
2834 bit
= (inputBuf
>> (inputBits
- 1)) & 1;
2839 GBool
DCTStream::readHeader() {
2850 case 0xc0: // SOF0 (sequential)
2851 case 0xc1: // SOF1 (extended sequential)
2852 if (!readBaselineSOF()) {
2856 case 0xc2: // SOF2 (progressive)
2857 if (!readProgressiveSOF()) {
2862 if (!readHuffmanTables()) {
2871 if (!readScanInfo()) {
2877 if (!readQuantTables()) {
2882 if (!readRestartInterval()) {
2887 if (!readJFIFMarker()) {
2892 if (!readAdobeMarker()) {
2897 error(getPos(), "Bad DCT header");
2900 // skip APPn / COM / etc.
2903 for (i
= 0; i
< n
; ++i
) {
2907 error(getPos(), "Unknown DCT marker <%02x>", c
);
2917 GBool
DCTStream::readBaselineSOF() {
2924 prec
= str
->getChar();
2927 numComps
= str
->getChar();
2928 if (numComps
<= 0 || numComps
> 4) {
2930 error(getPos(), "Bad number of components in DCT stream", prec
);
2934 error(getPos(), "Bad DCT precision %d", prec
);
2937 for (i
= 0; i
< numComps
; ++i
) {
2938 compInfo
[i
].id
= str
->getChar();
2940 compInfo
[i
].hSample
= (c
>> 4) & 0x0f;
2941 compInfo
[i
].vSample
= c
& 0x0f;
2942 compInfo
[i
].quantTable
= str
->getChar();
2944 progressive
= gFalse
;
2948 GBool
DCTStream::readProgressiveSOF() {
2955 prec
= str
->getChar();
2958 numComps
= str
->getChar();
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();
2982 if (length
!= 2 * scanInfo
.numComps
+ 3) {
2983 error(getPos(), "Bad DCT scan info block");
2986 interleaved
= scanInfo
.numComps
== numComps
;
2987 for (j
= 0; j
< numComps
; ++j
) {
2988 scanInfo
.comp
[j
] = gFalse
;
2990 for (i
= 0; i
< scanInfo
.numComps
; ++i
) {
2991 id
= str
->getChar();
2992 // some (broken) DCT streams reuse ID numbers, but at least they
2993 // keep the components in order, so we check compInfo[i] first to
2994 // work around the problem
2995 if (id
== compInfo
[i
].id
) {
2998 for (j
= 0; j
< numComps
; ++j
) {
2999 if (id
== compInfo
[j
].id
) {
3003 if (j
== numComps
) {
3004 error(getPos(), "Bad DCT component ID in scan info block");
3008 scanInfo
.comp
[j
] = gTrue
;
3010 scanInfo
.dcHuffTable
[j
] = (c
>> 4) & 0x0f;
3011 scanInfo
.acHuffTable
[j
] = c
& 0x0f;
3013 scanInfo
.firstCoeff
= str
->getChar();
3014 scanInfo
.lastCoeff
= str
->getChar();
3016 scanInfo
.ah
= (c
>> 4) & 0x0f;
3017 scanInfo
.al
= c
& 0x0f;
3021 GBool
DCTStream::readQuantTables() {
3022 int length
, prec
, i
, index
;
3024 length
= read16() - 2;
3025 while (length
> 0) {
3026 index
= str
->getChar();
3027 prec
= (index
>> 4) & 0x0f;
3029 if (prec
> 1 || index
>= 4) {
3030 error(getPos(), "Bad DCT quantization table");
3033 if (index
== numQuantTables
) {
3034 numQuantTables
= index
+ 1;
3036 for (i
= 0; i
< 64; ++i
) {
3038 quantTables
[index
][dctZigZag
[i
]] = read16();
3040 quantTables
[index
][dctZigZag
[i
]] = str
->getChar();
3052 GBool
DCTStream::readHuffmanTables() {
3061 length
= read16() - 2;
3062 while (length
> 0) {
3063 index
= str
->getChar();
3065 if ((index
& 0x0f) >= 4 || (index
& ~0x1f)) {
3066 error(getPos(), "Bad DCT Huffman table");
3071 if (index
>= numACHuffTables
)
3072 numACHuffTables
= index
+1;
3073 tbl
= &acHuffTables
[index
];
3075 if (index
>= numDCHuffTables
)
3076 numDCHuffTables
= index
+1;
3077 tbl
= &dcHuffTables
[index
];
3081 for (i
= 1; i
<= 16; ++i
) {
3083 tbl
->firstSym
[i
] = sym
;
3084 tbl
->firstCode
[i
] = code
;
3085 tbl
->numCodes
[i
] = c
;
3087 code
= (code
+ c
) << 1;
3090 for (i
= 0; i
< sym
; ++i
)
3091 tbl
->sym
[i
] = str
->getChar();
3097 GBool
DCTStream::readRestartInterval() {
3102 error(getPos(), "Bad DCT restart interval");
3105 restartInterval
= read16();
3109 GBool
DCTStream::readJFIFMarker() {
3117 for (i
= 0; i
< 5; ++i
) {
3118 if ((c
= str
->getChar()) == EOF
) {
3119 error(getPos(), "Bad DCT APP0 marker");
3125 if (!memcmp(buf
, "JFIF\0", 5)) {
3126 gotJFIFMarker
= gTrue
;
3129 while (length
> 0) {
3130 if (str
->getChar() == EOF
) {
3131 error(getPos(), "Bad DCT APP0 marker");
3139 GBool
DCTStream::readAdobeMarker() {
3148 for (i
= 0; i
< 12; ++i
) {
3149 if ((c
= str
->getChar()) == EOF
) {
3154 if (strncmp(buf
, "Adobe", 5)) {
3157 colorXform
= buf
[11];
3158 gotAdobeMarker
= gTrue
;
3159 for (i
= 14; i
< length
; ++i
) {
3160 if (str
->getChar() == EOF
) {
3167 error(getPos(), "Bad DCT Adobe APP14 marker");
3171 GBool
DCTStream::readTrailer() {
3175 if (c
!= 0xd9) { // EOI
3176 error(getPos(), "Bad DCT trailer");
3182 int DCTStream::readMarker() {
3188 } while (c
!= 0xff && c
!= EOF
);
3191 if (c
== EOF
) return EOF
;
3192 } while (c
== 0xff);
3193 } while (c
== 0x00);
3197 int DCTStream::read16() {
3200 if ((c1
= str
->getChar()) == EOF
)
3202 if ((c2
= str
->getChar()) == EOF
)
3204 return (c1
<< 8) + c2
;
3207 GString
*DCTStream::getPSFilter(int psLevel
, char *indent
) {
3213 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
3216 s
->append(indent
)->append("<< >> /DCTDecode filter\n");
3220 GBool
DCTStream::isBinary(GBool last
) {
3221 return str
->isBinary(gTrue
);
3224 //------------------------------------------------------------------------
3226 //------------------------------------------------------------------------
3228 int FlateStream::codeLenCodeMap
[flateMaxCodeLenCodes
] = {
3229 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3232 FlateDecode
FlateStream::lengthDecode
[flateMaxLitCodes
-257] = {
3266 FlateDecode
FlateStream::distDecode
[flateMaxDistCodes
] = {
3299 static FlateCode flateFixedLitCodeTabCodes
[512] = {
3814 FlateHuffmanTab
FlateStream::fixedLitCodeTab
= {
3815 flateFixedLitCodeTabCodes
, 9
3818 static FlateCode flateFixedDistCodeTabCodes
[32] = {
3853 FlateHuffmanTab
FlateStream::fixedDistCodeTab
= {
3854 flateFixedDistCodeTabCodes
, 5
3857 FlateStream::FlateStream(Stream
*strA
, int predictor
, int columns
,
3858 int colors
, int bits
):
3859 FilterStream(strA
) {
3860 if (predictor
!= 1) {
3861 pred
= new StreamPredictor(this, predictor
, columns
, colors
, bits
);
3862 if (!pred
->isOk()) {
3869 litCodeTab
.codes
= NULL
;
3870 distCodeTab
.codes
= NULL
;
3873 FlateStream::~FlateStream() {
3874 if (litCodeTab
.codes
!= fixedLitCodeTab
.codes
) {
3875 gfree(litCodeTab
.codes
);
3877 if (distCodeTab
.codes
!= fixedDistCodeTab
.codes
) {
3878 gfree(distCodeTab
.codes
);
3886 void FlateStream::reset() {
3893 compressedBlock
= gFalse
;
3900 //~ need to look at window size?
3901 endOfBlock
= eof
= gTrue
;
3902 cmf
= str
->getChar();
3903 flg
= str
->getChar();
3904 if (cmf
== EOF
|| flg
== EOF
)
3906 if ((cmf
& 0x0f) != 0x08) {
3907 error(getPos(), "Unknown compression method in flate stream");
3910 if ((((cmf
<< 8) + flg
) % 31) != 0) {
3911 error(getPos(), "Bad FCHECK in flate stream");
3915 error(getPos(), "FDICT bit set in flate stream");
3922 int FlateStream::getChar() {
3926 return pred
->getChar();
3928 while (remain
== 0) {
3929 if (endOfBlock
&& eof
)
3934 index
= (index
+ 1) & flateMask
;
3939 int FlateStream::lookChar() {
3943 return pred
->lookChar();
3945 while (remain
== 0) {
3946 if (endOfBlock
&& eof
)
3954 int FlateStream::getRawChar() {
3957 while (remain
== 0) {
3958 if (endOfBlock
&& eof
)
3963 index
= (index
+ 1) & flateMask
;
3968 GString
*FlateStream::getPSFilter(int psLevel
, char *indent
) {
3971 if (psLevel
< 3 || pred
) {
3974 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
3977 s
->append(indent
)->append("<< >> /FlateDecode filter\n");
3981 GBool
FlateStream::isBinary(GBool last
) {
3982 return str
->isBinary(gTrue
);
3985 void FlateStream::readSome() {
3996 if (compressedBlock
) {
3997 if ((code1
= getHuffmanCodeWord(&litCodeTab
)) == EOF
)
4002 } else if (code1
== 256) {
4007 code2
= lengthDecode
[code1
].bits
;
4008 if (code2
> 0 && (code2
= getCodeWord(code2
)) == EOF
)
4010 len
= lengthDecode
[code1
].first
+ code2
;
4011 if ((code1
= getHuffmanCodeWord(&distCodeTab
)) == EOF
)
4013 code2
= distDecode
[code1
].bits
;
4014 if (code2
> 0 && (code2
= getCodeWord(code2
)) == EOF
)
4016 dist
= distDecode
[code1
].first
+ code2
;
4018 j
= (index
- dist
) & flateMask
;
4019 for (k
= 0; k
< len
; ++k
) {
4021 i
= (i
+ 1) & flateMask
;
4022 j
= (j
+ 1) & flateMask
;
4028 len
= (blockLen
< flateWindow
) ? blockLen
: flateWindow
;
4029 for (i
= 0, j
= index
; i
< len
; ++i
, j
= (j
+ 1) & flateMask
) {
4030 if ((c
= str
->getChar()) == EOF
) {
4031 endOfBlock
= eof
= gTrue
;
4045 error(getPos(), "Unexpected end of file in flate stream");
4046 endOfBlock
= eof
= gTrue
;
4050 GBool
FlateStream::startBlock() {
4055 // free the code tables from the previous block
4056 if (litCodeTab
.codes
!= fixedLitCodeTab
.codes
) {
4057 gfree(litCodeTab
.codes
);
4059 litCodeTab
.codes
= NULL
;
4060 if (distCodeTab
.codes
!= fixedDistCodeTab
.codes
) {
4061 gfree(distCodeTab
.codes
);
4063 distCodeTab
.codes
= NULL
;
4065 // read block header
4066 blockHdr
= getCodeWord(3);
4071 // uncompressed block
4072 if (blockHdr
== 0) {
4073 compressedBlock
= gFalse
;
4074 if ((c
= str
->getChar()) == EOF
)
4076 blockLen
= c
& 0xff;
4077 if ((c
= str
->getChar()) == EOF
)
4079 blockLen
|= (c
& 0xff) << 8;
4080 if ((c
= str
->getChar()) == EOF
)
4083 if ((c
= str
->getChar()) == EOF
)
4085 check
|= (c
& 0xff) << 8;
4086 if (check
!= (~blockLen
& 0xffff))
4087 error(getPos(), "Bad uncompressed block length in flate stream");
4091 // compressed block with fixed codes
4092 } else if (blockHdr
== 1) {
4093 compressedBlock
= gTrue
;
4096 // compressed block with dynamic codes
4097 } else if (blockHdr
== 2) {
4098 compressedBlock
= gTrue
;
4099 if (!readDynamicCodes()) {
4103 // unknown block type
4108 endOfBlock
= gFalse
;
4112 error(getPos(), "Bad block header in flate stream");
4113 endOfBlock
= eof
= gTrue
;
4117 void FlateStream::loadFixedCodes() {
4118 litCodeTab
.codes
= fixedLitCodeTab
.codes
;
4119 litCodeTab
.maxLen
= fixedLitCodeTab
.maxLen
;
4120 distCodeTab
.codes
= fixedDistCodeTab
.codes
;
4121 distCodeTab
.maxLen
= fixedDistCodeTab
.maxLen
;
4124 GBool
FlateStream::readDynamicCodes() {
4125 int numCodeLenCodes
;
4128 int codeLenCodeLengths
[flateMaxCodeLenCodes
];
4129 FlateHuffmanTab codeLenCodeTab
;
4130 int len
, repeat
, code
;
4133 codeLenCodeTab
.codes
= NULL
;
4136 if ((numLitCodes
= getCodeWord(5)) == EOF
) {
4140 if ((numDistCodes
= getCodeWord(5)) == EOF
) {
4144 if ((numCodeLenCodes
= getCodeWord(4)) == EOF
) {
4147 numCodeLenCodes
+= 4;
4148 if (numLitCodes
> flateMaxLitCodes
||
4149 numDistCodes
> flateMaxDistCodes
||
4150 numCodeLenCodes
> flateMaxCodeLenCodes
) {
4154 // build the code length code table
4155 for (i
= 0; i
< flateMaxCodeLenCodes
; ++i
) {
4156 codeLenCodeLengths
[i
] = 0;
4158 for (i
= 0; i
< numCodeLenCodes
; ++i
) {
4159 if ((codeLenCodeLengths
[codeLenCodeMap
[i
]] = getCodeWord(3)) == -1) {
4163 compHuffmanCodes(codeLenCodeLengths
, flateMaxCodeLenCodes
, &codeLenCodeTab
);
4165 // build the literal and distance code tables
4169 while (i
< numLitCodes
+ numDistCodes
) {
4170 if ((code
= getHuffmanCodeWord(&codeLenCodeTab
)) == EOF
) {
4174 if ((repeat
= getCodeWord(2)) == EOF
) {
4178 if (i
+ repeat
> numLitCodes
+ numDistCodes
) {
4181 for (; repeat
> 0; --repeat
) {
4182 codeLengths
[i
++] = len
;
4184 } else if (code
== 17) {
4185 if ((repeat
= getCodeWord(3)) == EOF
) {
4189 if (i
+ repeat
> numLitCodes
+ numDistCodes
) {
4193 for (; repeat
> 0; --repeat
) {
4194 codeLengths
[i
++] = 0;
4196 } else if (code
== 18) {
4197 if ((repeat
= getCodeWord(7)) == EOF
) {
4201 if (i
+ repeat
> numLitCodes
+ numDistCodes
) {
4205 for (; repeat
> 0; --repeat
) {
4206 codeLengths
[i
++] = 0;
4209 codeLengths
[i
++] = len
= code
;
4212 compHuffmanCodes(codeLengths
, numLitCodes
, &litCodeTab
);
4213 compHuffmanCodes(codeLengths
+ numLitCodes
, numDistCodes
, &distCodeTab
);
4215 gfree(codeLenCodeTab
.codes
);
4219 error(getPos(), "Bad dynamic code table in flate stream");
4220 gfree(codeLenCodeTab
.codes
);
4224 // Convert an array <lengths> of <n> lengths, in value order, into a
4225 // Huffman code lookup table.
4226 void FlateStream::compHuffmanCodes(int *lengths
, int n
, FlateHuffmanTab
*tab
) {
4227 int tabSize
, len
, code
, code2
, skip
, val
, i
, t
;
4229 // find max code length
4231 for (val
= 0; val
< n
; ++val
) {
4232 if (lengths
[val
] > tab
->maxLen
) {
4233 tab
->maxLen
= lengths
[val
];
4237 // allocate the table
4238 tabSize
= 1 << tab
->maxLen
;
4239 tab
->codes
= (FlateCode
*)gmallocn(tabSize
, sizeof(FlateCode
));
4242 for (i
= 0; i
< tabSize
; ++i
) {
4243 tab
->codes
[i
].len
= 0;
4244 tab
->codes
[i
].val
= 0;
4248 for (len
= 1, code
= 0, skip
= 2;
4250 ++len
, code
<<= 1, skip
<<= 1) {
4251 for (val
= 0; val
< n
; ++val
) {
4252 if (lengths
[val
] == len
) {
4254 // bit-reverse the code
4257 for (i
= 0; i
< len
; ++i
) {
4258 code2
= (code2
<< 1) | (t
& 1);
4262 // fill in the table entries
4263 for (i
= code2
; i
< tabSize
; i
+= skip
) {
4264 tab
->codes
[i
].len
= (Gushort
)len
;
4265 tab
->codes
[i
].val
= (Gushort
)val
;
4274 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab
*tab
) {
4278 while (codeSize
< tab
->maxLen
) {
4279 if ((c
= str
->getChar()) == EOF
) {
4282 codeBuf
|= (c
& 0xff) << codeSize
;
4285 code
= &tab
->codes
[codeBuf
& ((1 << tab
->maxLen
) - 1)];
4286 if (codeSize
== 0 || codeSize
< code
->len
|| code
->len
== 0) {
4289 codeBuf
>>= code
->len
;
4290 codeSize
-= code
->len
;
4291 return (int)code
->val
;
4294 int FlateStream::getCodeWord(int bits
) {
4297 while (codeSize
< bits
) {
4298 if ((c
= str
->getChar()) == EOF
)
4300 codeBuf
|= (c
& 0xff) << codeSize
;
4303 c
= codeBuf
& ((1 << bits
) - 1);
4309 //------------------------------------------------------------------------
4311 //------------------------------------------------------------------------
4313 EOFStream::EOFStream(Stream
*strA
):
4314 FilterStream(strA
) {
4317 EOFStream::~EOFStream() {
4321 //------------------------------------------------------------------------
4322 // FixedLengthEncoder
4323 //------------------------------------------------------------------------
4325 FixedLengthEncoder::FixedLengthEncoder(Stream
*strA
, int lengthA
):
4326 FilterStream(strA
) {
4331 FixedLengthEncoder::~FixedLengthEncoder() {
4332 if (str
->isEncoder())
4336 void FixedLengthEncoder::reset() {
4341 int FixedLengthEncoder::getChar() {
4342 if (length
>= 0 && count
>= length
)
4345 return str
->getChar();
4348 int FixedLengthEncoder::lookChar() {
4349 if (length
>= 0 && count
>= length
)
4351 return str
->getChar();
4354 GBool
FixedLengthEncoder::isBinary(GBool last
) {
4355 return str
->isBinary(gTrue
);
4358 //------------------------------------------------------------------------
4360 //------------------------------------------------------------------------
4362 ASCIIHexEncoder::ASCIIHexEncoder(Stream
*strA
):
4363 FilterStream(strA
) {
4364 bufPtr
= bufEnd
= buf
;
4369 ASCIIHexEncoder::~ASCIIHexEncoder() {
4370 if (str
->isEncoder()) {
4375 void ASCIIHexEncoder::reset() {
4377 bufPtr
= bufEnd
= buf
;
4382 GBool
ASCIIHexEncoder::fillBuf() {
4383 static char *hex
= "0123456789abcdef";
4389 bufPtr
= bufEnd
= buf
;
4390 if ((c
= str
->getChar()) == EOF
) {
4394 if (lineLen
>= 64) {
4398 *bufEnd
++ = hex
[(c
>> 4) & 0x0f];
4399 *bufEnd
++ = hex
[c
& 0x0f];
4405 //------------------------------------------------------------------------
4407 //------------------------------------------------------------------------
4409 ASCII85Encoder::ASCII85Encoder(Stream
*strA
):
4410 FilterStream(strA
) {
4411 bufPtr
= bufEnd
= buf
;
4416 ASCII85Encoder::~ASCII85Encoder() {
4417 if (str
->isEncoder())
4421 void ASCII85Encoder::reset() {
4423 bufPtr
= bufEnd
= buf
;
4428 GBool
ASCII85Encoder::fillBuf() {
4437 for (n
= 0; n
< 4; ++n
) {
4438 if ((c
= str
->getChar()) == EOF
)
4442 bufPtr
= bufEnd
= buf
;
4444 if (n
== 4 && t
== 0) {
4446 if (++lineLen
== 65) {
4453 for (i
= 4; i
>= 0; --i
) {
4454 buf1
[i
] = (char)(t
% 85 + 0x21);
4457 for (i
= 0; i
<= n
; ++i
) {
4458 *bufEnd
++ = buf1
[i
];
4459 if (++lineLen
== 65) {
4471 return bufPtr
< bufEnd
;
4474 //------------------------------------------------------------------------
4476 //------------------------------------------------------------------------
4478 RunLengthEncoder::RunLengthEncoder(Stream
*strA
):
4479 FilterStream(strA
) {
4480 bufPtr
= bufEnd
= nextEnd
= buf
;
4484 RunLengthEncoder::~RunLengthEncoder() {
4485 if (str
->isEncoder())
4489 void RunLengthEncoder::reset() {
4491 bufPtr
= bufEnd
= nextEnd
= buf
;
4496 // When fillBuf finishes, buf[] looks like this:
4497 // +-----+--------------+-----------------+--
4498 // + tag | ... data ... | next 0, 1, or 2 |
4499 // +-----+--------------+-----------------+--
4501 // bufPtr bufEnd nextEnd
4503 GBool
RunLengthEncoder::fillBuf() {
4512 if (nextEnd
< bufEnd
+ 1) {
4513 if ((c1
= str
->getChar()) == EOF
) {
4518 c1
= bufEnd
[0] & 0xff;
4520 if (nextEnd
< bufEnd
+ 2) {
4521 if ((c2
= str
->getChar()) == EOF
) {
4530 c2
= bufEnd
[1] & 0xff;
4534 c
= 0; // make gcc happy
4537 while (n
< 128 && (c
= str
->getChar()) == c1
)
4539 buf
[0] = (char)(257 - n
);
4544 } else if (n
< 128) {
4551 // get up to 128 chars
4557 if ((c
= str
->getChar()) == EOF
) {
4563 if (buf
[n
] == buf
[n
-1])
4566 if (buf
[n
] == buf
[n
-1]) {
4567 buf
[0] = (char)(n
-2-1);
4569 nextEnd
= &buf
[n
+1];
4571 buf
[0] = (char)(n
-1);
4572 bufEnd
= nextEnd
= &buf
[n
+1];