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
) {
282 BaseStream::~BaseStream() {
288 void BaseStream::doDecryption(Guchar
*fileKey
, int keyLength
,
289 int objNum
, int objGen
) {
290 decrypt
= new Decrypt(fileKey
, keyLength
, objNum
, objGen
);
293 //------------------------------------------------------------------------
295 //------------------------------------------------------------------------
297 FilterStream::FilterStream(Stream
*strA
) {
301 FilterStream::~FilterStream() {
304 void FilterStream::close() {
308 void FilterStream::setPos(Guint pos
, int dir
) {
309 error(-1, "Internal: called setPos() on FilterStream");
312 //------------------------------------------------------------------------
314 //------------------------------------------------------------------------
316 ImageStream::ImageStream(Stream
*strA
, int widthA
, int nCompsA
, int nBitsA
) {
324 nVals
= width
* nComps
;
326 imgLineSize
= (nVals
+ 7) & ~7;
330 imgLine
= (Guchar
*)gmallocn(imgLineSize
, sizeof(Guchar
));
334 ImageStream::~ImageStream() {
338 void ImageStream::reset() {
342 GBool
ImageStream::getPixel(Guchar
*pix
) {
345 if (imgIdx
>= nVals
) {
349 for (i
= 0; i
< nComps
; ++i
) {
350 pix
[i
] = imgLine
[imgIdx
++];
355 Guchar
*ImageStream::getLine() {
362 for (i
= 0; i
< nVals
; i
+= 8) {
364 imgLine
[i
+0] = (Guchar
)((c
>> 7) & 1);
365 imgLine
[i
+1] = (Guchar
)((c
>> 6) & 1);
366 imgLine
[i
+2] = (Guchar
)((c
>> 5) & 1);
367 imgLine
[i
+3] = (Guchar
)((c
>> 4) & 1);
368 imgLine
[i
+4] = (Guchar
)((c
>> 3) & 1);
369 imgLine
[i
+5] = (Guchar
)((c
>> 2) & 1);
370 imgLine
[i
+6] = (Guchar
)((c
>> 1) & 1);
371 imgLine
[i
+7] = (Guchar
)(c
& 1);
373 } else if (nBits
== 8) {
374 for (i
= 0; i
< nVals
; ++i
) {
375 imgLine
[i
] = str
->getChar();
378 bitMask
= (1 << nBits
) - 1;
381 for (i
= 0; i
< nVals
; ++i
) {
383 buf
= (buf
<< 8) | (str
->getChar() & 0xff);
386 imgLine
[i
] = (Guchar
)((buf
>> (bits
- nBits
)) & bitMask
);
393 void ImageStream::skipLine() {
396 n
= (nVals
* nBits
+ 7) >> 3;
397 for (i
= 0; i
< n
; ++i
) {
402 //------------------------------------------------------------------------
404 //------------------------------------------------------------------------
406 StreamPredictor::StreamPredictor(Stream
*strA
, int predictorA
,
407 int widthA
, int nCompsA
, int nBitsA
) {
409 predictor
= predictorA
;
416 nVals
= width
* nComps
;
417 if (width
<= 0 || nComps
<= 0 || nBits
<= 0 ||
418 nComps
>= INT_MAX
/ nBits
||
419 width
>= INT_MAX
/ nComps
/ nBits
||
420 nVals
* nBits
+ 7 < 0) {
423 pixBytes
= (nComps
* nBits
+ 7) >> 3;
424 rowBytes
= ((nVals
* nBits
+ 7) >> 3) + pixBytes
;
428 predLine
= (Guchar
*)gmalloc(rowBytes
);
429 memset(predLine
, 0, rowBytes
);
435 StreamPredictor::~StreamPredictor() {
439 int StreamPredictor::lookChar() {
440 if (predIdx
>= rowBytes
) {
441 if (!getNextLine()) {
445 return predLine
[predIdx
];
448 int StreamPredictor::getChar() {
449 if (predIdx
>= rowBytes
) {
450 if (!getNextLine()) {
454 return predLine
[predIdx
++];
457 GBool
StreamPredictor::getNextLine() {
459 Guchar upLeftBuf
[gfxColorMaxComps
* 2 + 1];
460 int left
, up
, upLeft
, p
, pa
, pb
, pc
;
462 Gulong inBuf
, outBuf
, bitMask
;
466 // get PNG optimum predictor number
467 if (predictor
>= 10) {
468 if ((curPred
= str
->getRawChar()) == EOF
) {
476 // read the raw line, apply PNG (byte) predictor
477 memset(upLeftBuf
, 0, pixBytes
+ 1);
478 for (i
= pixBytes
; i
< rowBytes
; ++i
) {
479 for (j
= pixBytes
; j
> 0; --j
) {
480 upLeftBuf
[j
] = upLeftBuf
[j
-1];
482 upLeftBuf
[0] = predLine
[i
];
483 if ((c
= str
->getRawChar()) == EOF
) {
485 // this ought to return false, but some (broken) PDF files
486 // contain truncated image data, and Adobe apparently reads the
494 predLine
[i
] = predLine
[i
- pixBytes
] + (Guchar
)c
;
497 predLine
[i
] = predLine
[i
] + (Guchar
)c
;
499 case 13: // PNG average
500 predLine
[i
] = ((predLine
[i
- pixBytes
] + predLine
[i
]) >> 1) +
503 case 14: // PNG Paeth
504 left
= predLine
[i
- pixBytes
];
506 upLeft
= upLeftBuf
[pixBytes
];
507 p
= left
+ up
- upLeft
;
508 if ((pa
= p
- left
) < 0)
510 if ((pb
= p
- up
) < 0)
512 if ((pc
= p
- upLeft
) < 0)
514 if (pa
<= pb
&& pa
<= pc
)
515 predLine
[i
] = left
+ (Guchar
)c
;
517 predLine
[i
] = up
+ (Guchar
)c
;
519 predLine
[i
] = upLeft
+ (Guchar
)c
;
522 default: // no predictor or TIFF predictor
523 predLine
[i
] = (Guchar
)c
;
528 // apply TIFF (component) predictor
529 if (predictor
== 2) {
531 inBuf
= predLine
[pixBytes
- 1];
532 for (i
= pixBytes
; i
< rowBytes
; i
+= 8) {
533 // 1-bit add is just xor
534 inBuf
= (inBuf
<< 8) | predLine
[i
];
535 predLine
[i
] ^= inBuf
>> nComps
;
537 } else if (nBits
== 8) {
538 for (i
= pixBytes
; i
< rowBytes
; ++i
) {
539 predLine
[i
] += predLine
[i
- nComps
];
542 memset(upLeftBuf
, 0, nComps
+ 1);
543 bitMask
= (1 << nBits
) - 1;
545 inBits
= outBits
= 0;
547 for (i
= 0; i
< width
; ++i
) {
548 for (kk
= 0; kk
< nComps
; ++kk
) {
549 if (inBits
< nBits
) {
550 inBuf
= (inBuf
<< 8) | (predLine
[j
++] & 0xff);
553 upLeftBuf
[kk
] = (upLeftBuf
[kk
] +
554 (inBuf
>> (inBits
- nBits
))) & bitMask
;
556 outBuf
= (outBuf
<< nBits
) | upLeftBuf
[kk
];
559 predLine
[k
++] = (Guchar
)(outBuf
>> (outBits
- 8));
565 predLine
[k
++] = (Guchar
)((outBuf
<< (8 - outBits
)) +
566 (inBuf
& ((1 << (8 - outBits
)) - 1)));
571 // reset to start of line
577 //------------------------------------------------------------------------
579 //------------------------------------------------------------------------
581 FileStream::FileStream(myFILE
*fA
, Guint startA
, GBool limitedA
,
582 Guint lengthA
, Object
*dictA
):
588 bufPtr
= bufEnd
= buf
;
593 f
->preread(start
, length
);
596 FileStream::~FileStream() {
600 Stream
*FileStream::makeSubStream(Guint startA
, GBool limitedA
,
601 Guint lengthA
, Object
*dictA
) {
602 return new FileStream(f
, startA
, limitedA
, lengthA
, dictA
);
605 void FileStream::reset() {
606 savePos
= (Guint
)myftell(f
);
607 myfseek(f
, start
, SEEK_SET
);
609 bufPtr
= bufEnd
= buf
;
615 void FileStream::close() {
617 myfseek(f
, savePos
, SEEK_SET
);
622 GBool
FileStream::fillBuf() {
626 bufPos
+= bufEnd
- buf
;
627 bufPtr
= bufEnd
= buf
;
628 if (limited
&& bufPos
>= start
+ length
) {
631 if (limited
&& bufPos
+ fileStreamBufSize
> start
+ length
) {
632 n
= start
+ length
- bufPos
;
634 n
= fileStreamBufSize
;
636 n
= myfread(buf
, 1, n
, f
);
638 if (bufPtr
>= bufEnd
) {
642 for (p
= buf
; p
< bufEnd
; ++p
) {
643 *p
= (char)decrypt
->decryptByte((Guchar
)*p
);
649 void FileStream::setPos(Guint pos
, int dir
) {
653 myfseek(f
, pos
, SEEK_SET
);
656 myfseek(f
, 0, SEEK_END
);
657 size
= (Guint
)myftell(f
);
661 //~ work around a bug in cygwin's implementation of fseek
664 myfseek(f
, -(int)pos
, SEEK_END
);
665 bufPos
= (Guint
)myftell(f
);
667 bufPtr
= bufEnd
= buf
;
670 void FileStream::moveStart(int delta
) {
672 bufPtr
= bufEnd
= buf
;
676 void FileStream::preRead(int pos
, int length
) {
677 f
->preread(pos
, length
);
680 void FileStream::removeParts() {
684 //------------------------------------------------------------------------
686 //------------------------------------------------------------------------
688 MemStream::MemStream(char *bufA
, Guint startA
, Guint lengthA
, Object
*dictA
):
693 bufEnd
= buf
+ start
+ length
;
694 bufPtr
= buf
+ start
;
698 MemStream::~MemStream() {
704 Stream
*MemStream::makeSubStream(Guint startA
, GBool limited
,
705 Guint lengthA
, Object
*dictA
) {
709 if (!limited
|| startA
+ lengthA
> start
+ length
) {
710 newLength
= start
+ length
- startA
;
714 subStr
= new MemStream(buf
, startA
, newLength
, dictA
);
718 void MemStream::reset() {
719 bufPtr
= buf
+ start
;
725 void MemStream::close() {
728 void MemStream::setPos(Guint pos
, int dir
) {
734 i
= start
+ length
- pos
;
738 } else if (i
> start
+ length
) {
744 void MemStream::moveStart(int delta
) {
747 bufPtr
= buf
+ start
;
750 void MemStream::doDecryption(Guchar
*fileKey
, int keyLength
,
751 int objNum
, int objGen
) {
755 this->BaseStream::doDecryption(fileKey
, keyLength
, objNum
, objGen
);
757 newBuf
= (char *)gmalloc(length
);
758 for (p
= buf
+ start
, q
= newBuf
; p
< bufEnd
; ++p
, ++q
) {
759 *q
= (char)decrypt
->decryptByte((Guchar
)*p
);
761 bufEnd
= newBuf
+ length
;
762 bufPtr
= newBuf
+ (bufPtr
- (buf
+ start
));
769 //------------------------------------------------------------------------
771 //------------------------------------------------------------------------
773 EmbedStream::EmbedStream(Stream
*strA
, Object
*dictA
,
774 GBool limitedA
, Guint lengthA
):
781 EmbedStream::~EmbedStream() {
784 Stream
*EmbedStream::makeSubStream(Guint start
, GBool limitedA
,
785 Guint lengthA
, Object
*dictA
) {
786 error(-1, "Internal: called makeSubStream() on EmbedStream");
790 int EmbedStream::getChar() {
791 if (limited
&& !length
) {
795 return str
->getChar();
798 int EmbedStream::lookChar() {
799 if (limited
&& !length
) {
802 return str
->lookChar();
805 void EmbedStream::setPos(Guint pos
, int dir
) {
806 error(-1, "Internal: called setPos() on EmbedStream");
809 Guint
EmbedStream::getStart() {
810 error(-1, "Internal: called getStart() on EmbedStream");
814 void EmbedStream::moveStart(int delta
) {
815 error(-1, "Internal: called moveStart() on EmbedStream");
818 //------------------------------------------------------------------------
820 //------------------------------------------------------------------------
822 ASCIIHexStream::ASCIIHexStream(Stream
*strA
):
828 ASCIIHexStream::~ASCIIHexStream() {
832 void ASCIIHexStream::reset() {
838 int ASCIIHexStream::lookChar() {
849 } while (isspace(c1
));
857 } while (isspace(c2
));
862 if (c1
>= '0' && c1
<= '9') {
864 } else if (c1
>= 'A' && c1
<= 'F') {
865 x
= (c1
- 'A' + 10) << 4;
866 } else if (c1
>= 'a' && c1
<= 'f') {
867 x
= (c1
- 'a' + 10) << 4;
868 } else if (c1
== EOF
) {
872 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1
);
875 if (c2
>= '0' && c2
<= '9') {
877 } else if (c2
>= 'A' && c2
<= 'F') {
879 } else if (c2
>= 'a' && c2
<= 'f') {
881 } else if (c2
== EOF
) {
885 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2
);
891 GString
*ASCIIHexStream::getPSFilter(int psLevel
, char *indent
) {
897 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
900 s
->append(indent
)->append("/ASCIIHexDecode filter\n");
904 GBool
ASCIIHexStream::isBinary(GBool last
) {
905 return str
->isBinary(gFalse
);
908 //------------------------------------------------------------------------
910 //------------------------------------------------------------------------
912 ASCII85Stream::ASCII85Stream(Stream
*strA
):
918 ASCII85Stream::~ASCII85Stream() {
922 void ASCII85Stream::reset() {
928 int ASCII85Stream::lookChar() {
937 c
[0] = str
->getChar();
938 } while (Lexer::isSpace(c
[0]));
939 if (c
[0] == '~' || c
[0] == EOF
) {
943 } else if (c
[0] == 'z') {
944 b
[0] = b
[1] = b
[2] = b
[3] = 0;
947 for (k
= 1; k
< 5; ++k
) {
949 c
[k
] = str
->getChar();
950 } while (Lexer::isSpace(c
[k
]));
951 if (c
[k
] == '~' || c
[k
] == EOF
)
955 if (k
< 5 && (c
[k
] == '~' || c
[k
] == EOF
)) {
956 for (++k
; k
< 5; ++k
)
961 for (k
= 0; k
< 5; ++k
)
962 t
= t
* 85 + (c
[k
] - 0x21);
963 for (k
= 3; k
>= 0; --k
) {
964 b
[k
] = (int)(t
& 0xff);
972 GString
*ASCII85Stream::getPSFilter(int psLevel
, char *indent
) {
978 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
981 s
->append(indent
)->append("/ASCII85Decode filter\n");
985 GBool
ASCII85Stream::isBinary(GBool last
) {
986 return str
->isBinary(gFalse
);
989 //------------------------------------------------------------------------
991 //------------------------------------------------------------------------
993 LZWStream::LZWStream(Stream
*strA
, int predictor
, int columns
, int colors
,
994 int bits
, int earlyA
):
996 if (predictor
!= 1) {
997 pred
= new StreamPredictor(this, predictor
, columns
, colors
, bits
);
1011 LZWStream::~LZWStream() {
1018 int LZWStream::getChar() {
1020 return pred
->getChar();
1025 if (seqIndex
>= seqLength
) {
1026 if (!processNextCode()) {
1030 return seqBuf
[seqIndex
++];
1033 int LZWStream::lookChar() {
1035 return pred
->lookChar();
1040 if (seqIndex
>= seqLength
) {
1041 if (!processNextCode()) {
1045 return seqBuf
[seqIndex
];
1048 int LZWStream::getRawChar() {
1052 if (seqIndex
>= seqLength
) {
1053 if (!processNextCode()) {
1057 return seqBuf
[seqIndex
++];
1060 void LZWStream::reset() {
1067 GBool
LZWStream::processNextCode() {
1077 // check for eod and clear-table codes
1080 if (code
== EOF
|| code
== 257) {
1088 if (nextCode
>= 4097) {
1089 error(getPos(), "Bad LZW stream - expected clear-table code");
1093 // process the next code
1094 nextLength
= seqLength
+ 1;
1098 } else if (code
< nextCode
) {
1099 seqLength
= table
[code
].length
;
1100 for (i
= seqLength
- 1, j
= code
; i
> 0; --i
) {
1101 seqBuf
[i
] = table
[j
].tail
;
1105 } else if (code
== nextCode
) {
1106 seqBuf
[seqLength
] = newChar
;
1109 error(getPos(), "Bad LZW stream - unexpected code");
1113 newChar
= seqBuf
[0];
1117 table
[nextCode
].length
= nextLength
;
1118 table
[nextCode
].head
= prevCode
;
1119 table
[nextCode
].tail
= newChar
;
1121 if (nextCode
+ early
== 512)
1123 else if (nextCode
+ early
== 1024)
1125 else if (nextCode
+ early
== 2048)
1136 void LZWStream::clearTable() {
1139 seqIndex
= seqLength
= 0;
1143 int LZWStream::getCode() {
1147 while (inputBits
< nextBits
) {
1148 if ((c
= str
->getChar()) == EOF
)
1150 inputBuf
= (inputBuf
<< 8) | (c
& 0xff);
1153 code
= (inputBuf
>> (inputBits
- nextBits
)) & ((1 << nextBits
) - 1);
1154 inputBits
-= nextBits
;
1158 GString
*LZWStream::getPSFilter(int psLevel
, char *indent
) {
1161 if (psLevel
< 2 || pred
) {
1164 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1167 s
->append(indent
)->append("<< ");
1169 s
->append("/EarlyChange 0 ");
1171 s
->append(">> /LZWDecode filter\n");
1175 GBool
LZWStream::isBinary(GBool last
) {
1176 return str
->isBinary(gTrue
);
1179 //------------------------------------------------------------------------
1181 //------------------------------------------------------------------------
1183 RunLengthStream::RunLengthStream(Stream
*strA
):
1184 FilterStream(strA
) {
1185 bufPtr
= bufEnd
= buf
;
1189 RunLengthStream::~RunLengthStream() {
1193 void RunLengthStream::reset() {
1195 bufPtr
= bufEnd
= buf
;
1199 GString
*RunLengthStream::getPSFilter(int psLevel
, char *indent
) {
1205 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1208 s
->append(indent
)->append("/RunLengthDecode filter\n");
1212 GBool
RunLengthStream::isBinary(GBool last
) {
1213 return str
->isBinary(gTrue
);
1216 GBool
RunLengthStream::fillBuf() {
1223 if (c
== 0x80 || c
== EOF
) {
1229 for (i
= 0; i
< n
; ++i
)
1230 buf
[i
] = (char)str
->getChar();
1234 for (i
= 0; i
< n
; ++i
)
1242 //------------------------------------------------------------------------
1244 //------------------------------------------------------------------------
1246 CCITTFaxStream::CCITTFaxStream(Stream
*strA
, int encodingA
, GBool endOfLineA
,
1247 GBool byteAlignA
, int columnsA
, int rowsA
,
1248 GBool endOfBlockA
, GBool blackA
):
1249 FilterStream(strA
) {
1250 encoding
= encodingA
;
1251 endOfLine
= endOfLineA
;
1252 byteAlign
= byteAlignA
;
1257 if (columns
+ 4 <= 0) {
1258 columns
= INT_MAX
- 4;
1261 endOfBlock
= endOfBlockA
;
1263 refLine
= (short *)gmallocn(columns
+ 4, sizeof(short));
1264 codingLine
= (short *)gmallocn(columns
+ 3, sizeof(short));
1268 nextLine2D
= encoding
< 0;
1271 codingLine
[1] = refLine
[2] = columns
;
1277 CCITTFaxStream::~CCITTFaxStream() {
1283 void CCITTFaxStream::reset() {
1289 nextLine2D
= encoding
< 0;
1292 codingLine
[1] = refLine
[2] = columns
;
1296 // skip any initial zero bits and end-of-line marker, and get the 2D
1298 while ((code1
= lookBits(12)) == 0) {
1301 if (code1
== 0x001) {
1305 nextLine2D
= !lookBits(1);
1310 int CCITTFaxStream::lookChar() {
1311 short code1
, code2
, code3
;
1317 // if at eof just return EOF
1318 if (eof
&& codingLine
[a0
] >= columns
) {
1322 // read the next row
1324 if (codingLine
[a0
] >= columns
) {
1328 for (i
= 0; codingLine
[i
] < columns
; ++i
)
1329 refLine
[i
] = codingLine
[i
];
1330 refLine
[i
] = refLine
[i
+ 1] = columns
;
1332 a0New
= codingLine
[a0
= 0] = 0;
1334 code1
= getTwoDimCode();
1337 if (refLine
[b1
] < columns
) {
1338 a0New
= refLine
[b1
+ 1];
1343 if ((a0
& 1) == 0) {
1346 code1
+= code3
= getWhiteCode();
1347 } while (code3
>= 64);
1349 code2
+= code3
= getBlackCode();
1350 } while (code3
>= 64);
1354 code1
+= code3
= getBlackCode();
1355 } while (code3
>= 64);
1357 code2
+= code3
= getWhiteCode();
1358 } while (code3
>= 64);
1360 if (code1
> 0 || code2
> 0) {
1361 codingLine
[a0
+ 1] = a0New
+ code1
;
1363 a0New
= codingLine
[a0
+ 1] = codingLine
[a0
] + code2
;
1365 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1370 a0New
= codingLine
[++a0
] = refLine
[b1
];
1371 if (refLine
[b1
] < columns
) {
1373 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1378 a0New
= codingLine
[++a0
] = refLine
[b1
] + 1;
1379 if (refLine
[b1
] < columns
) {
1381 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1386 if (a0
== 0 || refLine
[b1
] - 1 > a0New
) {
1387 a0New
= codingLine
[++a0
] = refLine
[b1
] - 1;
1389 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1394 a0New
= codingLine
[++a0
] = refLine
[b1
] + 2;
1395 if (refLine
[b1
] < columns
) {
1397 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1402 if (a0
== 0 || refLine
[b1
] - 2 > a0New
) {
1403 a0New
= codingLine
[++a0
] = refLine
[b1
] - 2;
1405 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1410 a0New
= codingLine
[++a0
] = refLine
[b1
] + 3;
1411 if (refLine
[b1
] < columns
) {
1413 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1418 if (a0
== 0 || refLine
[b1
] - 3 > a0New
) {
1419 a0New
= codingLine
[++a0
] = refLine
[b1
] - 3;
1421 while (refLine
[b1
] <= codingLine
[a0
] && refLine
[b1
] < columns
)
1427 codingLine
[a0
= 0] = columns
;
1430 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1
);
1434 } while (codingLine
[a0
] < columns
);
1438 codingLine
[a0
= 0] = 0;
1442 code1
+= code3
= getWhiteCode();
1443 } while (code3
>= 64);
1444 codingLine
[a0
+1] = codingLine
[a0
] + code1
;
1446 if (codingLine
[a0
] >= columns
)
1450 code2
+= code3
= getBlackCode();
1451 } while (code3
>= 64);
1452 codingLine
[a0
+1] = codingLine
[a0
] + code2
;
1454 if (codingLine
[a0
] >= columns
)
1459 if (codingLine
[a0
] != columns
) {
1460 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine
[a0
]);
1461 // force the row to be the correct length
1462 while (codingLine
[a0
] > columns
) {
1465 codingLine
[++a0
] = columns
;
1469 // byte-align the row
1474 // check for end-of-line marker, skipping over any extra zero bits
1476 if (!endOfBlock
&& row
== rows
- 1) {
1479 code1
= lookBits(12);
1480 while (code1
== 0) {
1482 code1
= lookBits(12);
1484 if (code1
== 0x001) {
1487 } else if (code1
== EOF
) {
1492 // get 2D encoding tag
1493 if (!eof
&& encoding
> 0) {
1494 nextLine2D
= !lookBits(1);
1498 // check for end-of-block marker
1499 if (endOfBlock
&& gotEOL
) {
1500 code1
= lookBits(12);
1501 if (code1
== 0x001) {
1507 if (encoding
>= 0) {
1508 for (i
= 0; i
< 4; ++i
) {
1509 code1
= lookBits(12);
1510 if (code1
!= 0x001) {
1511 error(getPos(), "Bad RTC code in CCITTFax stream");
1523 // look for an end-of-line marker after an error -- we only do
1524 // this if we know the stream contains end-of-line markers because
1525 // the "just plow on" technique tends to work better otherwise
1526 } else if (err
&& endOfLine
) {
1533 code1
= lookBits(13);
1534 } while ((code1
>> 1) != 0x001);
1538 nextLine2D
= !(code1
& 1);
1543 outputBits
= codingLine
[1] - codingLine
[0];
1544 if (outputBits
== 0) {
1546 outputBits
= codingLine
[2] - codingLine
[1];
1553 if (outputBits
>= 8) {
1554 ret
= ((a0
& 1) == 0) ? 0xff : 0x00;
1555 if ((outputBits
-= 8) == 0) {
1557 if (codingLine
[a0
] < columns
) {
1558 outputBits
= codingLine
[a0
+ 1] - codingLine
[a0
];
1565 if (outputBits
> bits
) {
1568 if ((a0
& 1) == 0) {
1569 ret
|= 0xff >> (8 - i
);
1575 if ((a0
& 1) == 0) {
1576 ret
|= (0xff >> (8 - i
)) << bits
;
1580 if (codingLine
[a0
] < columns
) {
1581 outputBits
= codingLine
[a0
+ 1] - codingLine
[a0
];
1584 } while (bits
> 0 && codingLine
[a0
] < columns
);
1586 buf
= black
? (ret
^ 0xff) : ret
;
1590 short CCITTFaxStream::getTwoDimCode() {
1595 code
= 0; // make gcc happy
1598 p
= &twoDimTab1
[code
];
1604 for (n
= 1; n
<= 7; ++n
) {
1609 p
= &twoDimTab1
[code
];
1616 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code
);
1620 short CCITTFaxStream::getWhiteCode() {
1625 code
= 0; // make gcc happy
1627 code
= lookBits(12);
1628 if ((code
>> 5) == 0) {
1629 p
= &whiteTab1
[code
];
1631 p
= &whiteTab2
[code
>> 3];
1638 for (n
= 1; n
<= 9; ++n
) {
1643 p
= &whiteTab2
[code
];
1649 for (n
= 11; n
<= 12; ++n
) {
1654 p
= &whiteTab1
[code
];
1661 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code
);
1662 // eat a bit and return a positive number so that the caller doesn't
1663 // go into an infinite loop
1668 short CCITTFaxStream::getBlackCode() {
1673 code
= 0; // make gcc happy
1675 code
= lookBits(13);
1676 if ((code
>> 7) == 0) {
1677 p
= &blackTab1
[code
];
1678 } else if ((code
>> 9) == 0) {
1679 p
= &blackTab2
[(code
>> 1) - 64];
1681 p
= &blackTab3
[code
>> 7];
1688 for (n
= 2; n
<= 6; ++n
) {
1693 p
= &blackTab3
[code
];
1699 for (n
= 7; n
<= 12; ++n
) {
1705 p
= &blackTab2
[code
- 64];
1712 for (n
= 10; n
<= 13; ++n
) {
1717 p
= &blackTab1
[code
];
1724 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code
);
1725 // eat a bit and return a positive number so that the caller doesn't
1726 // go into an infinite loop
1731 short CCITTFaxStream::lookBits(int n
) {
1734 while (inputBits
< n
) {
1735 if ((c
= str
->getChar()) == EOF
) {
1736 if (inputBits
== 0) {
1739 // near the end of the stream, the caller may ask for more bits
1740 // than are available, but there may still be a valid code in
1741 // however many bits are available -- we need to return correct
1742 // data in this case
1743 return (inputBuf
<< (n
- inputBits
)) & (0xffff >> (16 - n
));
1745 inputBuf
= (inputBuf
<< 8) + c
;
1748 return (inputBuf
>> (inputBits
- n
)) & (0xffff >> (16 - n
));
1751 GString
*CCITTFaxStream::getPSFilter(int psLevel
, char *indent
) {
1758 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1761 s
->append(indent
)->append("<< ");
1762 if (encoding
!= 0) {
1763 sprintf(s1
, "/K %d ", encoding
);
1767 s
->append("/EndOfLine true ");
1770 s
->append("/EncodedByteAlign true ");
1772 sprintf(s1
, "/Columns %d ", columns
);
1775 sprintf(s1
, "/Rows %d ", rows
);
1779 s
->append("/EndOfBlock false ");
1782 s
->append("/BlackIs1 true ");
1784 s
->append(">> /CCITTFaxDecode filter\n");
1788 GBool
CCITTFaxStream::isBinary(GBool last
) {
1789 return str
->isBinary(gTrue
);
1792 //------------------------------------------------------------------------
1794 //------------------------------------------------------------------------
1796 // IDCT constants (20.12 fixed point format)
1797 #define dctCos1 4017 // cos(pi/16)
1798 #define dctSin1 799 // sin(pi/16)
1799 #define dctCos3 3406 // cos(3*pi/16)
1800 #define dctSin3 2276 // sin(3*pi/16)
1801 #define dctCos6 1567 // cos(6*pi/16)
1802 #define dctSin6 3784 // sin(6*pi/16)
1803 #define dctSqrt2 5793 // sqrt(2)
1804 #define dctSqrt1d2 2896 // sqrt(2) / 2
1806 // color conversion parameters (16.16 fixed point format)
1807 #define dctCrToR 91881 // 1.4020
1808 #define dctCbToG -22553 // -0.3441363
1809 #define dctCrToG -46802 // -0.71413636
1810 #define dctCbToB 116130 // 1.772
1812 // clip [-256,511] --> [0,255]
1813 #define dctClipOffset 256
1814 static Guchar dctClip
[768];
1815 static int dctClipInit
= 0;
1817 // zig zag decode map
1818 static int dctZigZag
[64] = {
1824 5, 12, 19, 26, 33, 40,
1825 48, 41, 34, 27, 20, 13, 6,
1826 7, 14, 21, 28, 35, 42, 49, 56,
1827 57, 50, 43, 36, 29, 22, 15,
1828 23, 30, 37, 44, 51, 58,
1836 DCTStream::DCTStream(Stream
*strA
):
1837 FilterStream(strA
) {
1840 progressive
= interleaved
= gFalse
;
1842 mcuWidth
= mcuHeight
= 0;
1846 for (i
= 0; i
< 4; ++i
) {
1847 for (j
= 0; j
< 32; ++j
) {
1848 rowBuf
[i
][j
] = NULL
;
1854 for (i
= -256; i
< 0; ++i
)
1855 dctClip
[dctClipOffset
+ i
] = 0;
1856 for (i
= 0; i
< 256; ++i
)
1857 dctClip
[dctClipOffset
+ i
] = i
;
1858 for (i
= 256; i
< 512; ++i
)
1859 dctClip
[dctClipOffset
+ i
] = 255;
1864 DCTStream::~DCTStream() {
1868 if (progressive
|| !interleaved
) {
1869 for (i
= 0; i
< numComps
; ++i
) {
1873 for (i
= 0; i
< numComps
; ++i
) {
1874 for (j
= 0; j
< mcuHeight
; ++j
) {
1875 gfree(rowBuf
[i
][j
]);
1881 void DCTStream::reset() {
1886 progressive
= interleaved
= gFalse
;
1890 numDCHuffTables
= 0;
1891 numACHuffTables
= 0;
1893 gotJFIFMarker
= gFalse
;
1894 gotAdobeMarker
= gFalse
;
1895 restartInterval
= 0;
1897 if (!readHeader()) {
1903 if (numComps
== 1) {
1904 compInfo
[0].hSample
= compInfo
[0].vSample
= 1;
1906 mcuWidth
= compInfo
[0].hSample
;
1907 mcuHeight
= compInfo
[0].vSample
;
1908 for (i
= 1; i
< numComps
; ++i
) {
1909 if (compInfo
[i
].hSample
> mcuWidth
) {
1910 mcuWidth
= compInfo
[i
].hSample
;
1912 if (compInfo
[i
].vSample
> mcuHeight
) {
1913 mcuHeight
= compInfo
[i
].vSample
;
1919 // figure out color transform
1920 if (!gotAdobeMarker
&& numComps
== 3) {
1921 if (gotJFIFMarker
) {
1923 } else if (compInfo
[0].id
== 82 && compInfo
[1].id
== 71 &&
1924 compInfo
[2].id
== 66) { // ASCII "RGB"
1931 if (progressive
|| !interleaved
) {
1933 // allocate a buffer for the whole image
1934 bufWidth
= ((width
+ mcuWidth
- 1) / mcuWidth
) * mcuWidth
;
1935 bufHeight
= ((height
+ mcuHeight
- 1) / mcuHeight
) * mcuHeight
;
1936 for (i
= 0; i
< numComps
; ++i
) {
1937 frameBuf
[i
] = (int *)gmallocn(bufWidth
* bufHeight
, sizeof(int));
1938 memset(frameBuf
[i
], 0, bufWidth
* bufHeight
* sizeof(int));
1941 // read the image data
1943 restartMarker
= 0xd0;
1946 } while (readHeader());
1951 // initialize counters
1958 // allocate a buffer for one row of MCUs
1959 bufWidth
= ((width
+ mcuWidth
- 1) / mcuWidth
) * mcuWidth
;
1960 for (i
= 0; i
< numComps
; ++i
) {
1961 for (j
= 0; j
< mcuHeight
; ++j
) {
1962 rowBuf
[i
][j
] = (Guchar
*)gmallocn(bufWidth
, sizeof(Guchar
));
1966 // initialize counters
1972 restartMarker
= 0xd0;
1977 int DCTStream::getChar() {
1983 if (progressive
|| !interleaved
) {
1984 c
= frameBuf
[comp
][y
* bufWidth
+ x
];
1985 if (++comp
== numComps
) {
1993 if (dy
>= mcuHeight
) {
1994 if (!readMCURow()) {
2002 c
= rowBuf
[comp
][dy
][x
];
2003 if (++comp
== numComps
) {
2018 int DCTStream::lookChar() {
2022 if (progressive
|| !interleaved
) {
2023 return frameBuf
[comp
][y
* bufWidth
+ x
];
2025 if (dy
>= mcuHeight
) {
2026 if (!readMCURow()) {
2034 return rowBuf
[comp
][dy
][x
];
2038 void DCTStream::restart() {
2042 restartCtr
= restartInterval
;
2043 for (i
= 0; i
< numComps
; ++i
) {
2044 compInfo
[i
].prevDC
= 0;
2049 // Read one row of MCUs from a sequential JPEG stream.
2050 GBool
DCTStream::readMCURow() {
2054 int pY
, pCb
, pCr
, pR
, pG
, pB
;
2055 int h
, v
, horiz
, vert
, hSub
, vSub
;
2056 int x1
, x2
, y2
, x3
, y3
, x4
, y4
, x5
, y5
, cc
, i
;
2059 for (x1
= 0; x1
< width
; x1
+= mcuWidth
) {
2061 // deal with restart marker
2062 if (restartInterval
> 0 && restartCtr
== 0) {
2064 if (c
!= restartMarker
) {
2065 error(getPos(), "Bad DCT data: incorrect restart marker");
2068 if (++restartMarker
== 0xd8)
2069 restartMarker
= 0xd0;
2074 for (cc
= 0; cc
< numComps
; ++cc
) {
2075 h
= compInfo
[cc
].hSample
;
2076 v
= compInfo
[cc
].vSample
;
2077 horiz
= mcuWidth
/ h
;
2078 vert
= mcuHeight
/ v
;
2081 for (y2
= 0; y2
< mcuHeight
; y2
+= vert
) {
2082 for (x2
= 0; x2
< mcuWidth
; x2
+= horiz
) {
2083 if (!readDataUnit(&dcHuffTables
[scanInfo
.dcHuffTable
[cc
]],
2084 &acHuffTables
[scanInfo
.acHuffTable
[cc
]],
2085 &compInfo
[cc
].prevDC
,
2089 transformDataUnit(quantTables
[compInfo
[cc
].quantTable
],
2091 if (hSub
== 1 && vSub
== 1) {
2092 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2093 p1
= &rowBuf
[cc
][y2
+y3
][x1
+x2
];
2103 } else if (hSub
== 2 && vSub
== 2) {
2104 for (y3
= 0, i
= 0; y3
< 16; y3
+= 2, i
+= 8) {
2105 p1
= &rowBuf
[cc
][y2
+y3
][x1
+x2
];
2106 p2
= &rowBuf
[cc
][y2
+y3
+1][x1
+x2
];
2107 p1
[0] = p1
[1] = p2
[0] = p2
[1] = data2
[i
];
2108 p1
[2] = p1
[3] = p2
[2] = p2
[3] = data2
[i
+1];
2109 p1
[4] = p1
[5] = p2
[4] = p2
[5] = data2
[i
+2];
2110 p1
[6] = p1
[7] = p2
[6] = p2
[7] = data2
[i
+3];
2111 p1
[8] = p1
[9] = p2
[8] = p2
[9] = data2
[i
+4];
2112 p1
[10] = p1
[11] = p2
[10] = p2
[11] = data2
[i
+5];
2113 p1
[12] = p1
[13] = p2
[12] = p2
[13] = data2
[i
+6];
2114 p1
[14] = p1
[15] = p2
[14] = p2
[15] = data2
[i
+7];
2118 for (y3
= 0, y4
= 0; y3
< 8; ++y3
, y4
+= vSub
) {
2119 for (x3
= 0, x4
= 0; x3
< 8; ++x3
, x4
+= hSub
) {
2120 for (y5
= 0; y5
< vSub
; ++y5
)
2121 for (x5
= 0; x5
< hSub
; ++x5
)
2122 rowBuf
[cc
][y2
+y4
+y5
][x1
+x2
+x4
+x5
] = data2
[i
];
2132 // color space conversion
2134 // convert YCbCr to RGB
2135 if (numComps
== 3) {
2136 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2137 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2138 pY
= rowBuf
[0][y2
][x1
+x2
];
2139 pCb
= rowBuf
[1][y2
][x1
+x2
] - 128;
2140 pCr
= rowBuf
[2][y2
][x1
+x2
] - 128;
2141 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2142 rowBuf
[0][y2
][x1
+x2
] = dctClip
[dctClipOffset
+ pR
];
2143 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+ 32768) >> 16;
2144 rowBuf
[1][y2
][x1
+x2
] = dctClip
[dctClipOffset
+ pG
];
2145 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2146 rowBuf
[2][y2
][x1
+x2
] = dctClip
[dctClipOffset
+ pB
];
2149 // convert YCbCrK to CMYK (K is passed through unchanged)
2150 } else if (numComps
== 4) {
2151 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2152 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2153 pY
= rowBuf
[0][y2
][x1
+x2
];
2154 pCb
= rowBuf
[1][y2
][x1
+x2
] - 128;
2155 pCr
= rowBuf
[2][y2
][x1
+x2
] - 128;
2156 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2157 rowBuf
[0][y2
][x1
+x2
] = 255 - dctClip
[dctClipOffset
+ pR
];
2158 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+ 32768) >> 16;
2159 rowBuf
[1][y2
][x1
+x2
] = 255 - dctClip
[dctClipOffset
+ pG
];
2160 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2161 rowBuf
[2][y2
][x1
+x2
] = 255 - dctClip
[dctClipOffset
+ pB
];
2170 // Read one scan from a progressive or non-interleaved JPEG stream.
2171 void DCTStream::readScan() {
2173 int x1
, y1
, dx1
, dy1
, x2
, y2
, y3
, cc
, i
;
2174 int h
, v
, horiz
, vert
, vSub
;
2178 if (scanInfo
.numComps
== 1) {
2179 for (cc
= 0; cc
< numComps
; ++cc
) {
2180 if (scanInfo
.comp
[cc
]) {
2184 dx1
= mcuWidth
/ compInfo
[cc
].hSample
;
2185 dy1
= mcuHeight
/ compInfo
[cc
].vSample
;
2191 for (y1
= 0; y1
< height
; y1
+= dy1
) {
2192 for (x1
= 0; x1
< width
; x1
+= dx1
) {
2194 // deal with restart marker
2195 if (restartInterval
> 0 && restartCtr
== 0) {
2197 if (c
!= restartMarker
) {
2198 error(getPos(), "Bad DCT data: incorrect restart marker");
2201 if (++restartMarker
== 0xd8) {
2202 restartMarker
= 0xd0;
2208 for (cc
= 0; cc
< numComps
; ++cc
) {
2209 if (!scanInfo
.comp
[cc
]) {
2213 h
= compInfo
[cc
].hSample
;
2214 v
= compInfo
[cc
].vSample
;
2215 horiz
= mcuWidth
/ h
;
2216 vert
= mcuHeight
/ v
;
2218 for (y2
= 0; y2
< dy1
; y2
+= vert
) {
2219 for (x2
= 0; x2
< dx1
; x2
+= horiz
) {
2221 // pull out the current values
2222 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2223 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2232 p1
+= bufWidth
* vSub
;
2235 // read one data unit
2237 if (!readProgressiveDataUnit(
2238 &dcHuffTables
[scanInfo
.dcHuffTable
[cc
]],
2239 &acHuffTables
[scanInfo
.acHuffTable
[cc
]],
2240 &compInfo
[cc
].prevDC
,
2245 if (!readDataUnit(&dcHuffTables
[scanInfo
.dcHuffTable
[cc
]],
2246 &acHuffTables
[scanInfo
.acHuffTable
[cc
]],
2247 &compInfo
[cc
].prevDC
,
2253 // add the data unit into frameBuf
2254 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2255 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2264 p1
+= bufWidth
* vSub
;
2274 // Read one data unit from a sequential JPEG stream.
2275 GBool
DCTStream::readDataUnit(DCTHuffTable
*dcHuffTable
,
2276 DCTHuffTable
*acHuffTable
,
2277 int *prevDC
, int data
[64]) {
2282 if ((size
= readHuffSym(dcHuffTable
)) == 9999) {
2286 if ((amp
= readAmp(size
)) == 9999) {
2292 data
[0] = *prevDC
+= amp
;
2293 for (i
= 1; i
< 64; ++i
) {
2299 while ((c
= readHuffSym(acHuffTable
)) == 0xf0 && run
< 0x30) {
2308 run
+= (c
>> 4) & 0x0f;
2310 amp
= readAmp(size
);
2324 // Read one data unit from a sequential JPEG stream.
2325 GBool
DCTStream::readProgressiveDataUnit(DCTHuffTable
*dcHuffTable
,
2326 DCTHuffTable
*acHuffTable
,
2327 int *prevDC
, int data
[64]) {
2328 int run
, size
, amp
, bit
, c
;
2331 // get the DC coefficient
2332 i
= scanInfo
.firstCoeff
;
2334 if (scanInfo
.ah
== 0) {
2335 if ((size
= readHuffSym(dcHuffTable
)) == 9999) {
2339 if ((amp
= readAmp(size
)) == 9999) {
2345 data
[0] += (*prevDC
+= amp
) << scanInfo
.al
;
2347 if ((bit
= readBit()) == 9999) {
2350 data
[0] += bit
<< scanInfo
.al
;
2354 if (scanInfo
.lastCoeff
== 0) {
2358 // check for an EOB run
2360 while (i
<= scanInfo
.lastCoeff
) {
2363 if ((bit
= readBit()) == EOF
) {
2367 data
[j
] += 1 << scanInfo
.al
;
2375 // read the AC coefficients
2376 while (i
<= scanInfo
.lastCoeff
) {
2377 if ((c
= readHuffSym(acHuffTable
)) == 9999) {
2389 if ((bit
= readBit()) == EOF
) {
2393 data
[j
] += 1 << scanInfo
.al
;
2399 } else if ((c
& 0x0f) == 0x00) {
2402 for (k
= 0; k
< j
; ++k
) {
2403 if ((bit
= readBit()) == EOF
) {
2406 eobRun
= (eobRun
<< 1) | bit
;
2409 while (i
<= scanInfo
.lastCoeff
) {
2412 if ((bit
= readBit()) == EOF
) {
2416 data
[j
] += 1 << scanInfo
.al
;
2423 // zero run and one AC coefficient
2425 run
= (c
>> 4) & 0x0f;
2427 if ((amp
= readAmp(size
)) == 9999) {
2433 while (data
[j
] != 0) {
2434 if ((bit
= readBit()) == EOF
) {
2438 data
[j
] += 1 << scanInfo
.al
;
2444 data
[j
] = amp
<< scanInfo
.al
;
2451 // Decode a progressive JPEG image.
2452 void DCTStream::decodeImage() {
2455 Gushort
*quantTable
;
2456 int pY
, pCb
, pCr
, pR
, pG
, pB
;
2457 int x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
, x5
, y5
, cc
, i
;
2458 int h
, v
, horiz
, vert
, hSub
, vSub
;
2461 for (y1
= 0; y1
< bufHeight
; y1
+= mcuHeight
) {
2462 for (x1
= 0; x1
< bufWidth
; x1
+= mcuWidth
) {
2463 for (cc
= 0; cc
< numComps
; ++cc
) {
2464 quantTable
= quantTables
[compInfo
[cc
].quantTable
];
2465 h
= compInfo
[cc
].hSample
;
2466 v
= compInfo
[cc
].vSample
;
2467 horiz
= mcuWidth
/ h
;
2468 vert
= mcuHeight
/ v
;
2471 for (y2
= 0; y2
< mcuHeight
; y2
+= vert
) {
2472 for (x2
= 0; x2
< mcuWidth
; x2
+= horiz
) {
2474 // pull out the coded data unit
2475 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2476 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2478 dataIn
[i
+1] = p1
[1];
2479 dataIn
[i
+2] = p1
[2];
2480 dataIn
[i
+3] = p1
[3];
2481 dataIn
[i
+4] = p1
[4];
2482 dataIn
[i
+5] = p1
[5];
2483 dataIn
[i
+6] = p1
[6];
2484 dataIn
[i
+7] = p1
[7];
2485 p1
+= bufWidth
* vSub
;
2489 transformDataUnit(quantTable
, dataIn
, dataOut
);
2491 // store back into frameBuf, doing replication for
2492 // subsampled components
2493 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2494 if (hSub
== 1 && vSub
== 1) {
2495 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2496 p1
[0] = dataOut
[i
] & 0xff;
2497 p1
[1] = dataOut
[i
+1] & 0xff;
2498 p1
[2] = dataOut
[i
+2] & 0xff;
2499 p1
[3] = dataOut
[i
+3] & 0xff;
2500 p1
[4] = dataOut
[i
+4] & 0xff;
2501 p1
[5] = dataOut
[i
+5] & 0xff;
2502 p1
[6] = dataOut
[i
+6] & 0xff;
2503 p1
[7] = dataOut
[i
+7] & 0xff;
2506 } else if (hSub
== 2 && vSub
== 2) {
2508 for (y3
= 0, i
= 0; y3
< 16; y3
+= 2, i
+= 8) {
2509 p1
[0] = p1
[1] = p2
[0] = p2
[1] = dataOut
[i
] & 0xff;
2510 p1
[2] = p1
[3] = p2
[2] = p2
[3] = dataOut
[i
+1] & 0xff;
2511 p1
[4] = p1
[5] = p2
[4] = p2
[5] = dataOut
[i
+2] & 0xff;
2512 p1
[6] = p1
[7] = p2
[6] = p2
[7] = dataOut
[i
+3] & 0xff;
2513 p1
[8] = p1
[9] = p2
[8] = p2
[9] = dataOut
[i
+4] & 0xff;
2514 p1
[10] = p1
[11] = p2
[10] = p2
[11] = dataOut
[i
+5] & 0xff;
2515 p1
[12] = p1
[13] = p2
[12] = p2
[13] = dataOut
[i
+6] & 0xff;
2516 p1
[14] = p1
[15] = p2
[14] = p2
[15] = dataOut
[i
+7] & 0xff;
2522 for (y3
= 0, y4
= 0; y3
< 8; ++y3
, y4
+= vSub
) {
2523 for (x3
= 0, x4
= 0; x3
< 8; ++x3
, x4
+= hSub
) {
2525 for (y5
= 0; y5
< vSub
; ++y5
) {
2526 for (x5
= 0; x5
< hSub
; ++x5
) {
2527 p2
[x5
] = dataOut
[i
] & 0xff;
2533 p1
+= bufWidth
* vSub
;
2540 // color space conversion
2542 // convert YCbCr to RGB
2543 if (numComps
== 3) {
2544 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2545 p0
= &frameBuf
[0][(y1
+y2
) * bufWidth
+ x1
];
2546 p1
= &frameBuf
[1][(y1
+y2
) * bufWidth
+ x1
];
2547 p2
= &frameBuf
[2][(y1
+y2
) * bufWidth
+ x1
];
2548 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2552 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2553 *p0
++ = dctClip
[dctClipOffset
+ pR
];
2554 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+
2556 *p1
++ = dctClip
[dctClipOffset
+ pG
];
2557 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2558 *p2
++ = dctClip
[dctClipOffset
+ pB
];
2561 // convert YCbCrK to CMYK (K is passed through unchanged)
2562 } else if (numComps
== 4) {
2563 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2564 p0
= &frameBuf
[0][(y1
+y2
) * bufWidth
+ x1
];
2565 p1
= &frameBuf
[1][(y1
+y2
) * bufWidth
+ x1
];
2566 p2
= &frameBuf
[2][(y1
+y2
) * bufWidth
+ x1
];
2567 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2571 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2572 *p0
++ = 255 - dctClip
[dctClipOffset
+ pR
];
2573 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+
2575 *p1
++ = 255 - dctClip
[dctClipOffset
+ pG
];
2576 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2577 *p2
++ = 255 - dctClip
[dctClipOffset
+ pB
];
2586 // Transform one data unit -- this performs the dequantization and
2587 // IDCT steps. This IDCT algorithm is taken from:
2588 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2589 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2590 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2592 // The stage numbers mentioned in the comments refer to Figure 1 in this
2594 void DCTStream::transformDataUnit(Gushort
*quantTable
,
2595 int dataIn
[64], Guchar dataOut
[64]) {
2596 int v0
, v1
, v2
, v3
, v4
, v5
, v6
, v7
, t
;
2601 for (i
= 0; i
< 64; ++i
) {
2602 dataIn
[i
] *= quantTable
[i
];
2605 // inverse DCT on rows
2606 for (i
= 0; i
< 64; i
+= 8) {
2609 // check for all-zero AC coefficients
2610 if (p
[1] == 0 && p
[2] == 0 && p
[3] == 0 &&
2611 p
[4] == 0 && p
[5] == 0 && p
[6] == 0 && p
[7] == 0) {
2612 t
= (dctSqrt2
* p
[0] + 512) >> 10;
2625 v0
= (dctSqrt2
* p
[0] + 128) >> 8;
2626 v1
= (dctSqrt2
* p
[4] + 128) >> 8;
2629 v4
= (dctSqrt1d2
* (p
[1] - p
[7]) + 128) >> 8;
2630 v7
= (dctSqrt1d2
* (p
[1] + p
[7]) + 128) >> 8;
2635 t
= (v0
- v1
+ 1) >> 1;
2636 v0
= (v0
+ v1
+ 1) >> 1;
2638 t
= (v2
* dctSin6
+ v3
* dctCos6
+ 128) >> 8;
2639 v2
= (v2
* dctCos6
- v3
* dctSin6
+ 128) >> 8;
2641 t
= (v4
- v6
+ 1) >> 1;
2642 v4
= (v4
+ v6
+ 1) >> 1;
2644 t
= (v7
+ v5
+ 1) >> 1;
2645 v5
= (v7
- v5
+ 1) >> 1;
2649 t
= (v0
- v3
+ 1) >> 1;
2650 v0
= (v0
+ v3
+ 1) >> 1;
2652 t
= (v1
- v2
+ 1) >> 1;
2653 v1
= (v1
+ v2
+ 1) >> 1;
2655 t
= (v4
* dctSin3
+ v7
* dctCos3
+ 2048) >> 12;
2656 v4
= (v4
* dctCos3
- v7
* dctSin3
+ 2048) >> 12;
2658 t
= (v5
* dctSin1
+ v6
* dctCos1
+ 2048) >> 12;
2659 v5
= (v5
* dctCos1
- v6
* dctSin1
+ 2048) >> 12;
2673 // inverse DCT on columns
2674 for (i
= 0; i
< 8; ++i
) {
2677 // check for all-zero AC coefficients
2678 if (p
[1*8] == 0 && p
[2*8] == 0 && p
[3*8] == 0 &&
2679 p
[4*8] == 0 && p
[5*8] == 0 && p
[6*8] == 0 && p
[7*8] == 0) {
2680 t
= (dctSqrt2
* dataIn
[i
+0] + 8192) >> 14;
2693 v0
= (dctSqrt2
* p
[0*8] + 2048) >> 12;
2694 v1
= (dctSqrt2
* p
[4*8] + 2048) >> 12;
2697 v4
= (dctSqrt1d2
* (p
[1*8] - p
[7*8]) + 2048) >> 12;
2698 v7
= (dctSqrt1d2
* (p
[1*8] + p
[7*8]) + 2048) >> 12;
2703 t
= (v0
- v1
+ 1) >> 1;
2704 v0
= (v0
+ v1
+ 1) >> 1;
2706 t
= (v2
* dctSin6
+ v3
* dctCos6
+ 2048) >> 12;
2707 v2
= (v2
* dctCos6
- v3
* dctSin6
+ 2048) >> 12;
2709 t
= (v4
- v6
+ 1) >> 1;
2710 v4
= (v4
+ v6
+ 1) >> 1;
2712 t
= (v7
+ v5
+ 1) >> 1;
2713 v5
= (v7
- v5
+ 1) >> 1;
2717 t
= (v0
- v3
+ 1) >> 1;
2718 v0
= (v0
+ v3
+ 1) >> 1;
2720 t
= (v1
- v2
+ 1) >> 1;
2721 v1
= (v1
+ v2
+ 1) >> 1;
2723 t
= (v4
* dctSin3
+ v7
* dctCos3
+ 2048) >> 12;
2724 v4
= (v4
* dctCos3
- v7
* dctSin3
+ 2048) >> 12;
2726 t
= (v5
* dctSin1
+ v6
* dctCos1
+ 2048) >> 12;
2727 v5
= (v5
* dctCos1
- v6
* dctSin1
+ 2048) >> 12;
2741 // convert to 8-bit integers
2742 for (i
= 0; i
< 64; ++i
) {
2743 dataOut
[i
] = dctClip
[dctClipOffset
+ 128 + ((dataIn
[i
] + 8) >> 4)];
2747 int DCTStream::readHuffSym(DCTHuffTable
*table
) {
2755 // add a bit to the code
2756 if ((bit
= readBit()) == EOF
)
2758 code
= (code
<< 1) + bit
;
2762 if (code
- table
->firstCode
[codeBits
] < table
->numCodes
[codeBits
]) {
2763 code
-= table
->firstCode
[codeBits
];
2764 return table
->sym
[table
->firstSym
[codeBits
] + code
];
2766 } while (codeBits
< 16);
2768 error(getPos(), "Bad Huffman code in DCT stream");
2772 int DCTStream::readAmp(int size
) {
2777 for (bits
= 0; bits
< size
; ++bits
) {
2778 if ((bit
= readBit()) == EOF
)
2780 amp
= (amp
<< 1) + bit
;
2782 if (amp
< (1 << (size
- 1)))
2783 amp
-= (1 << size
) - 1;
2787 int DCTStream::readBit() {
2791 if (inputBits
== 0) {
2792 if ((c
= str
->getChar()) == EOF
)
2796 c2
= str
->getChar();
2797 } while (c2
== 0xff);
2799 error(getPos(), "Bad DCT data: missing 00 after ff");
2806 bit
= (inputBuf
>> (inputBits
- 1)) & 1;
2811 GBool
DCTStream::readHeader() {
2822 case 0xc0: // SOF0 (sequential)
2823 case 0xc1: // SOF1 (extended sequential)
2824 if (!readBaselineSOF()) {
2828 case 0xc2: // SOF2 (progressive)
2829 if (!readProgressiveSOF()) {
2834 if (!readHuffmanTables()) {
2843 if (!readScanInfo()) {
2849 if (!readQuantTables()) {
2854 if (!readRestartInterval()) {
2859 if (!readJFIFMarker()) {
2864 if (!readAdobeMarker()) {
2869 error(getPos(), "Bad DCT header");
2872 // skip APPn / COM / etc.
2875 for (i
= 0; i
< n
; ++i
) {
2879 error(getPos(), "Unknown DCT marker <%02x>", c
);
2889 GBool
DCTStream::readBaselineSOF() {
2896 prec
= str
->getChar();
2899 numComps
= str
->getChar();
2900 if (numComps
<= 0 || numComps
> 4) {
2901 error(getPos(), "Bad number of components in DCT stream");
2906 error(getPos(), "Bad DCT precision %d", prec
);
2909 for (i
= 0; i
< numComps
; ++i
) {
2910 compInfo
[i
].id
= str
->getChar();
2912 compInfo
[i
].hSample
= (c
>> 4) & 0x0f;
2913 compInfo
[i
].vSample
= c
& 0x0f;
2914 compInfo
[i
].quantTable
= str
->getChar();
2916 progressive
= gFalse
;
2920 GBool
DCTStream::readProgressiveSOF() {
2927 prec
= str
->getChar();
2930 numComps
= str
->getChar();
2931 if (numComps
<= 0 || numComps
> 4) {
2932 error(getPos(), "Bad number of components in DCT stream");
2937 error(getPos(), "Bad DCT precision %d", prec
);
2940 for (i
= 0; i
< numComps
; ++i
) {
2941 compInfo
[i
].id
= str
->getChar();
2943 compInfo
[i
].hSample
= (c
>> 4) & 0x0f;
2944 compInfo
[i
].vSample
= c
& 0x0f;
2945 compInfo
[i
].quantTable
= str
->getChar();
2947 progressive
= gTrue
;
2951 GBool
DCTStream::readScanInfo() {
2956 length
= read16() - 2;
2957 scanInfo
.numComps
= str
->getChar();
2958 if (scanInfo
.numComps
<= 0 || scanInfo
.numComps
> 4) {
2959 error(getPos(), "Bad number of components in DCT stream");
2960 scanInfo
.numComps
= 0;
2964 if (length
!= 2 * scanInfo
.numComps
+ 3) {
2965 error(getPos(), "Bad DCT scan info block");
2968 interleaved
= scanInfo
.numComps
== numComps
;
2969 for (j
= 0; j
< numComps
; ++j
) {
2970 scanInfo
.comp
[j
] = gFalse
;
2972 for (i
= 0; i
< scanInfo
.numComps
; ++i
) {
2973 id
= str
->getChar();
2974 // some (broken) DCT streams reuse ID numbers, but at least they
2975 // keep the components in order, so we check compInfo[i] first to
2976 // work around the problem
2977 if (id
== compInfo
[i
].id
) {
2980 for (j
= 0; j
< numComps
; ++j
) {
2981 if (id
== compInfo
[j
].id
) {
2985 if (j
== numComps
) {
2986 error(getPos(), "Bad DCT component ID in scan info block");
2990 scanInfo
.comp
[j
] = gTrue
;
2992 scanInfo
.dcHuffTable
[j
] = (c
>> 4) & 0x0f;
2993 scanInfo
.acHuffTable
[j
] = c
& 0x0f;
2995 scanInfo
.firstCoeff
= str
->getChar();
2996 scanInfo
.lastCoeff
= str
->getChar();
2998 scanInfo
.ah
= (c
>> 4) & 0x0f;
2999 scanInfo
.al
= c
& 0x0f;
3003 GBool
DCTStream::readQuantTables() {
3004 int length
, prec
, i
, index
;
3006 length
= read16() - 2;
3007 while (length
> 0) {
3008 index
= str
->getChar();
3009 prec
= (index
>> 4) & 0x0f;
3011 if (prec
> 1 || index
>= 4) {
3012 error(getPos(), "Bad DCT quantization table");
3015 if (index
== numQuantTables
) {
3016 numQuantTables
= index
+ 1;
3018 for (i
= 0; i
< 64; ++i
) {
3020 quantTables
[index
][dctZigZag
[i
]] = read16();
3022 quantTables
[index
][dctZigZag
[i
]] = str
->getChar();
3034 GBool
DCTStream::readHuffmanTables() {
3043 length
= read16() - 2;
3044 while (length
> 0) {
3045 index
= str
->getChar();
3047 if ((index
& 0x0f) >= 4) {
3048 error(getPos(), "Bad DCT Huffman table");
3053 if (index
>= numACHuffTables
)
3054 numACHuffTables
= index
+1;
3055 tbl
= &acHuffTables
[index
];
3058 if (index
>= numDCHuffTables
)
3059 numDCHuffTables
= index
+1;
3060 tbl
= &dcHuffTables
[index
];
3064 for (i
= 1; i
<= 16; ++i
) {
3066 tbl
->firstSym
[i
] = sym
;
3067 tbl
->firstCode
[i
] = code
;
3068 tbl
->numCodes
[i
] = c
;
3070 code
= (code
+ c
) << 1;
3073 for (i
= 0; i
< sym
; ++i
)
3074 tbl
->sym
[i
] = str
->getChar();
3080 GBool
DCTStream::readRestartInterval() {
3085 error(getPos(), "Bad DCT restart interval");
3088 restartInterval
= read16();
3092 GBool
DCTStream::readJFIFMarker() {
3100 for (i
= 0; i
< 5; ++i
) {
3101 if ((c
= str
->getChar()) == EOF
) {
3102 error(getPos(), "Bad DCT APP0 marker");
3108 if (!memcmp(buf
, "JFIF\0", 5)) {
3109 gotJFIFMarker
= gTrue
;
3112 while (length
> 0) {
3113 if (str
->getChar() == EOF
) {
3114 error(getPos(), "Bad DCT APP0 marker");
3122 GBool
DCTStream::readAdobeMarker() {
3131 for (i
= 0; i
< 12; ++i
) {
3132 if ((c
= str
->getChar()) == EOF
) {
3137 if (strncmp(buf
, "Adobe", 5)) {
3140 colorXform
= buf
[11];
3141 gotAdobeMarker
= gTrue
;
3142 for (i
= 14; i
< length
; ++i
) {
3143 if (str
->getChar() == EOF
) {
3150 error(getPos(), "Bad DCT Adobe APP14 marker");
3154 GBool
DCTStream::readTrailer() {
3158 if (c
!= 0xd9) { // EOI
3159 error(getPos(), "Bad DCT trailer");
3165 int DCTStream::readMarker() {
3171 } while (c
!= 0xff && c
!= EOF
);
3174 } while (c
== 0xff);
3175 } while (c
== 0x00);
3179 int DCTStream::read16() {
3182 if ((c1
= str
->getChar()) == EOF
)
3184 if ((c2
= str
->getChar()) == EOF
)
3186 return (c1
<< 8) + c2
;
3189 GString
*DCTStream::getPSFilter(int psLevel
, char *indent
) {
3195 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
3198 s
->append(indent
)->append("<< >> /DCTDecode filter\n");
3202 GBool
DCTStream::isBinary(GBool last
) {
3203 return str
->isBinary(gTrue
);
3206 //------------------------------------------------------------------------
3208 //------------------------------------------------------------------------
3210 int FlateStream::codeLenCodeMap
[flateMaxCodeLenCodes
] = {
3211 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3214 FlateDecode
FlateStream::lengthDecode
[flateMaxLitCodes
-257] = {
3248 FlateDecode
FlateStream::distDecode
[flateMaxDistCodes
] = {
3281 static FlateCode flateFixedLitCodeTabCodes
[512] = {
3796 FlateHuffmanTab
FlateStream::fixedLitCodeTab
= {
3797 flateFixedLitCodeTabCodes
, 9
3800 static FlateCode flateFixedDistCodeTabCodes
[32] = {
3835 FlateHuffmanTab
FlateStream::fixedDistCodeTab
= {
3836 flateFixedDistCodeTabCodes
, 5
3839 FlateStream::FlateStream(Stream
*strA
, int predictor
, int columns
,
3840 int colors
, int bits
):
3841 FilterStream(strA
) {
3842 if (predictor
!= 1) {
3843 pred
= new StreamPredictor(this, predictor
, columns
, colors
, bits
);
3844 if (!pred
->isOk()) {
3851 litCodeTab
.codes
= NULL
;
3852 distCodeTab
.codes
= NULL
;
3855 FlateStream::~FlateStream() {
3856 if (litCodeTab
.codes
!= fixedLitCodeTab
.codes
) {
3857 gfree(litCodeTab
.codes
);
3859 if (distCodeTab
.codes
!= fixedDistCodeTab
.codes
) {
3860 gfree(distCodeTab
.codes
);
3868 void FlateStream::reset() {
3875 compressedBlock
= gFalse
;
3882 //~ need to look at window size?
3883 endOfBlock
= eof
= gTrue
;
3884 cmf
= str
->getChar();
3885 flg
= str
->getChar();
3886 if (cmf
== EOF
|| flg
== EOF
)
3888 if ((cmf
& 0x0f) != 0x08) {
3889 error(getPos(), "Unknown compression method in flate stream");
3892 if ((((cmf
<< 8) + flg
) % 31) != 0) {
3893 error(getPos(), "Bad FCHECK in flate stream");
3897 error(getPos(), "FDICT bit set in flate stream");
3904 int FlateStream::getChar() {
3908 return pred
->getChar();
3910 while (remain
== 0) {
3911 if (endOfBlock
&& eof
)
3916 index
= (index
+ 1) & flateMask
;
3921 int FlateStream::lookChar() {
3925 return pred
->lookChar();
3927 while (remain
== 0) {
3928 if (endOfBlock
&& eof
)
3936 int FlateStream::getRawChar() {
3939 while (remain
== 0) {
3940 if (endOfBlock
&& eof
)
3945 index
= (index
+ 1) & flateMask
;
3950 GString
*FlateStream::getPSFilter(int psLevel
, char *indent
) {
3953 if (psLevel
< 3 || pred
) {
3956 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
3959 s
->append(indent
)->append("<< >> /FlateDecode filter\n");
3963 GBool
FlateStream::isBinary(GBool last
) {
3964 return str
->isBinary(gTrue
);
3967 void FlateStream::readSome() {
3978 if (compressedBlock
) {
3979 if ((code1
= getHuffmanCodeWord(&litCodeTab
)) == EOF
)
3984 } else if (code1
== 256) {
3989 code2
= lengthDecode
[code1
].bits
;
3990 if (code2
> 0 && (code2
= getCodeWord(code2
)) == EOF
)
3992 len
= lengthDecode
[code1
].first
+ code2
;
3993 if ((code1
= getHuffmanCodeWord(&distCodeTab
)) == EOF
)
3995 code2
= distDecode
[code1
].bits
;
3996 if (code2
> 0 && (code2
= getCodeWord(code2
)) == EOF
)
3998 dist
= distDecode
[code1
].first
+ code2
;
4000 j
= (index
- dist
) & flateMask
;
4001 for (k
= 0; k
< len
; ++k
) {
4003 i
= (i
+ 1) & flateMask
;
4004 j
= (j
+ 1) & flateMask
;
4010 len
= (blockLen
< flateWindow
) ? blockLen
: flateWindow
;
4011 for (i
= 0, j
= index
; i
< len
; ++i
, j
= (j
+ 1) & flateMask
) {
4012 if ((c
= str
->getChar()) == EOF
) {
4013 endOfBlock
= eof
= gTrue
;
4027 error(getPos(), "Unexpected end of file in flate stream");
4028 endOfBlock
= eof
= gTrue
;
4032 GBool
FlateStream::startBlock() {
4037 // free the code tables from the previous block
4038 if (litCodeTab
.codes
!= fixedLitCodeTab
.codes
) {
4039 gfree(litCodeTab
.codes
);
4041 litCodeTab
.codes
= NULL
;
4042 if (distCodeTab
.codes
!= fixedDistCodeTab
.codes
) {
4043 gfree(distCodeTab
.codes
);
4045 distCodeTab
.codes
= NULL
;
4047 // read block header
4048 blockHdr
= getCodeWord(3);
4053 // uncompressed block
4054 if (blockHdr
== 0) {
4055 compressedBlock
= gFalse
;
4056 if ((c
= str
->getChar()) == EOF
)
4058 blockLen
= c
& 0xff;
4059 if ((c
= str
->getChar()) == EOF
)
4061 blockLen
|= (c
& 0xff) << 8;
4062 if ((c
= str
->getChar()) == EOF
)
4065 if ((c
= str
->getChar()) == EOF
)
4067 check
|= (c
& 0xff) << 8;
4068 if (check
!= (~blockLen
& 0xffff))
4069 error(getPos(), "Bad uncompressed block length in flate stream");
4073 // compressed block with fixed codes
4074 } else if (blockHdr
== 1) {
4075 compressedBlock
= gTrue
;
4078 // compressed block with dynamic codes
4079 } else if (blockHdr
== 2) {
4080 compressedBlock
= gTrue
;
4081 if (!readDynamicCodes()) {
4085 // unknown block type
4090 endOfBlock
= gFalse
;
4094 error(getPos(), "Bad block header in flate stream");
4095 endOfBlock
= eof
= gTrue
;
4099 void FlateStream::loadFixedCodes() {
4100 litCodeTab
.codes
= fixedLitCodeTab
.codes
;
4101 litCodeTab
.maxLen
= fixedLitCodeTab
.maxLen
;
4102 distCodeTab
.codes
= fixedDistCodeTab
.codes
;
4103 distCodeTab
.maxLen
= fixedDistCodeTab
.maxLen
;
4106 GBool
FlateStream::readDynamicCodes() {
4107 int numCodeLenCodes
;
4110 int codeLenCodeLengths
[flateMaxCodeLenCodes
];
4111 FlateHuffmanTab codeLenCodeTab
;
4112 int len
, repeat
, code
;
4115 codeLenCodeTab
.codes
= NULL
;
4118 if ((numLitCodes
= getCodeWord(5)) == EOF
) {
4122 if ((numDistCodes
= getCodeWord(5)) == EOF
) {
4126 if ((numCodeLenCodes
= getCodeWord(4)) == EOF
) {
4129 numCodeLenCodes
+= 4;
4130 if (numLitCodes
> flateMaxLitCodes
||
4131 numDistCodes
> flateMaxDistCodes
||
4132 numCodeLenCodes
> flateMaxCodeLenCodes
) {
4136 // build the code length code table
4137 for (i
= 0; i
< flateMaxCodeLenCodes
; ++i
) {
4138 codeLenCodeLengths
[i
] = 0;
4140 for (i
= 0; i
< numCodeLenCodes
; ++i
) {
4141 if ((codeLenCodeLengths
[codeLenCodeMap
[i
]] = getCodeWord(3)) == -1) {
4145 compHuffmanCodes(codeLenCodeLengths
, flateMaxCodeLenCodes
, &codeLenCodeTab
);
4147 // build the literal and distance code tables
4151 while (i
< numLitCodes
+ numDistCodes
) {
4152 if ((code
= getHuffmanCodeWord(&codeLenCodeTab
)) == EOF
) {
4156 if ((repeat
= getCodeWord(2)) == EOF
) {
4160 if (i
+ repeat
> numLitCodes
+ numDistCodes
) {
4163 for (; repeat
> 0; --repeat
) {
4164 codeLengths
[i
++] = len
;
4166 } else if (code
== 17) {
4167 if ((repeat
= getCodeWord(3)) == EOF
) {
4171 if (i
+ repeat
> numLitCodes
+ numDistCodes
) {
4175 for (; repeat
> 0; --repeat
) {
4176 codeLengths
[i
++] = 0;
4178 } else if (code
== 18) {
4179 if ((repeat
= getCodeWord(7)) == EOF
) {
4183 if (i
+ repeat
> numLitCodes
+ numDistCodes
) {
4187 for (; repeat
> 0; --repeat
) {
4188 codeLengths
[i
++] = 0;
4191 codeLengths
[i
++] = len
= code
;
4194 compHuffmanCodes(codeLengths
, numLitCodes
, &litCodeTab
);
4195 compHuffmanCodes(codeLengths
+ numLitCodes
, numDistCodes
, &distCodeTab
);
4197 gfree(codeLenCodeTab
.codes
);
4201 error(getPos(), "Bad dynamic code table in flate stream");
4202 gfree(codeLenCodeTab
.codes
);
4206 // Convert an array <lengths> of <n> lengths, in value order, into a
4207 // Huffman code lookup table.
4208 void FlateStream::compHuffmanCodes(int *lengths
, int n
, FlateHuffmanTab
*tab
) {
4209 int tabSize
, len
, code
, code2
, skip
, val
, i
, t
;
4211 // find max code length
4213 for (val
= 0; val
< n
; ++val
) {
4214 if (lengths
[val
] > tab
->maxLen
) {
4215 tab
->maxLen
= lengths
[val
];
4219 // allocate the table
4220 tabSize
= 1 << tab
->maxLen
;
4221 tab
->codes
= (FlateCode
*)gmallocn(tabSize
, sizeof(FlateCode
));
4224 for (i
= 0; i
< tabSize
; ++i
) {
4225 tab
->codes
[i
].len
= 0;
4226 tab
->codes
[i
].val
= 0;
4230 for (len
= 1, code
= 0, skip
= 2;
4232 ++len
, code
<<= 1, skip
<<= 1) {
4233 for (val
= 0; val
< n
; ++val
) {
4234 if (lengths
[val
] == len
) {
4236 // bit-reverse the code
4239 for (i
= 0; i
< len
; ++i
) {
4240 code2
= (code2
<< 1) | (t
& 1);
4244 // fill in the table entries
4245 for (i
= code2
; i
< tabSize
; i
+= skip
) {
4246 tab
->codes
[i
].len
= (Gushort
)len
;
4247 tab
->codes
[i
].val
= (Gushort
)val
;
4256 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab
*tab
) {
4260 while (codeSize
< tab
->maxLen
) {
4261 if ((c
= str
->getChar()) == EOF
) {
4264 codeBuf
|= (c
& 0xff) << codeSize
;
4267 code
= &tab
->codes
[codeBuf
& ((1 << tab
->maxLen
) - 1)];
4268 if (codeSize
== 0 || codeSize
< code
->len
|| code
->len
== 0) {
4271 codeBuf
>>= code
->len
;
4272 codeSize
-= code
->len
;
4273 return (int)code
->val
;
4276 int FlateStream::getCodeWord(int bits
) {
4279 while (codeSize
< bits
) {
4280 if ((c
= str
->getChar()) == EOF
)
4282 codeBuf
|= (c
& 0xff) << codeSize
;
4285 c
= codeBuf
& ((1 << bits
) - 1);
4291 //------------------------------------------------------------------------
4293 //------------------------------------------------------------------------
4295 EOFStream::EOFStream(Stream
*strA
):
4296 FilterStream(strA
) {
4299 EOFStream::~EOFStream() {
4303 //------------------------------------------------------------------------
4304 // FixedLengthEncoder
4305 //------------------------------------------------------------------------
4307 FixedLengthEncoder::FixedLengthEncoder(Stream
*strA
, int lengthA
):
4308 FilterStream(strA
) {
4313 FixedLengthEncoder::~FixedLengthEncoder() {
4314 if (str
->isEncoder())
4318 void FixedLengthEncoder::reset() {
4323 int FixedLengthEncoder::getChar() {
4324 if (length
>= 0 && count
>= length
)
4327 return str
->getChar();
4330 int FixedLengthEncoder::lookChar() {
4331 if (length
>= 0 && count
>= length
)
4333 return str
->getChar();
4336 GBool
FixedLengthEncoder::isBinary(GBool last
) {
4337 return str
->isBinary(gTrue
);
4340 //------------------------------------------------------------------------
4342 //------------------------------------------------------------------------
4344 ASCIIHexEncoder::ASCIIHexEncoder(Stream
*strA
):
4345 FilterStream(strA
) {
4346 bufPtr
= bufEnd
= buf
;
4351 ASCIIHexEncoder::~ASCIIHexEncoder() {
4352 if (str
->isEncoder()) {
4357 void ASCIIHexEncoder::reset() {
4359 bufPtr
= bufEnd
= buf
;
4364 GBool
ASCIIHexEncoder::fillBuf() {
4365 static char *hex
= "0123456789abcdef";
4371 bufPtr
= bufEnd
= buf
;
4372 if ((c
= str
->getChar()) == EOF
) {
4376 if (lineLen
>= 64) {
4380 *bufEnd
++ = hex
[(c
>> 4) & 0x0f];
4381 *bufEnd
++ = hex
[c
& 0x0f];
4387 //------------------------------------------------------------------------
4389 //------------------------------------------------------------------------
4391 ASCII85Encoder::ASCII85Encoder(Stream
*strA
):
4392 FilterStream(strA
) {
4393 bufPtr
= bufEnd
= buf
;
4398 ASCII85Encoder::~ASCII85Encoder() {
4399 if (str
->isEncoder())
4403 void ASCII85Encoder::reset() {
4405 bufPtr
= bufEnd
= buf
;
4410 GBool
ASCII85Encoder::fillBuf() {
4419 for (n
= 0; n
< 4; ++n
) {
4420 if ((c
= str
->getChar()) == EOF
)
4424 bufPtr
= bufEnd
= buf
;
4426 if (n
== 4 && t
== 0) {
4428 if (++lineLen
== 65) {
4435 for (i
= 4; i
>= 0; --i
) {
4436 buf1
[i
] = (char)(t
% 85 + 0x21);
4439 for (i
= 0; i
<= n
; ++i
) {
4440 *bufEnd
++ = buf1
[i
];
4441 if (++lineLen
== 65) {
4453 return bufPtr
< bufEnd
;
4456 //------------------------------------------------------------------------
4458 //------------------------------------------------------------------------
4460 RunLengthEncoder::RunLengthEncoder(Stream
*strA
):
4461 FilterStream(strA
) {
4462 bufPtr
= bufEnd
= nextEnd
= buf
;
4466 RunLengthEncoder::~RunLengthEncoder() {
4467 if (str
->isEncoder())
4471 void RunLengthEncoder::reset() {
4473 bufPtr
= bufEnd
= nextEnd
= buf
;
4478 // When fillBuf finishes, buf[] looks like this:
4479 // +-----+--------------+-----------------+--
4480 // + tag | ... data ... | next 0, 1, or 2 |
4481 // +-----+--------------+-----------------+--
4483 // bufPtr bufEnd nextEnd
4485 GBool
RunLengthEncoder::fillBuf() {
4494 if (nextEnd
< bufEnd
+ 1) {
4495 if ((c1
= str
->getChar()) == EOF
) {
4500 c1
= bufEnd
[0] & 0xff;
4502 if (nextEnd
< bufEnd
+ 2) {
4503 if ((c2
= str
->getChar()) == EOF
) {
4512 c2
= bufEnd
[1] & 0xff;
4516 c
= 0; // make gcc happy
4519 while (n
< 128 && (c
= str
->getChar()) == c1
)
4521 buf
[0] = (char)(257 - n
);
4526 } else if (n
< 128) {
4533 // get up to 128 chars
4539 if ((c
= str
->getChar()) == EOF
) {
4545 if (buf
[n
] == buf
[n
-1])
4548 if (buf
[n
] == buf
[n
-1]) {
4549 buf
[0] = (char)(n
-2-1);
4551 nextEnd
= &buf
[n
+1];
4553 buf
[0] = (char)(n
-1);
4554 bufEnd
= nextEnd
= &buf
[n
+1];
4562 //------------------------------------------------------------------------
4564 //------------------------------------------------------------------------
4566 StrStream::StrStream(GString
*str
, Object
*dict
):
4569 buf
= str
->getCString();
4571 bufEnd
= buf
+ str
->getLength();
4574 StrStream::~StrStream() {