1 //========================================================================
5 // Copyright 1996-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
33 #include "JBIG2Stream.h"
34 #include "JPXStream.h"
35 #include "Stream-CCITT.h"
38 static GBool setDJSYSFLAGS
= gFalse
;
49 //------------------------------------------------------------------------
50 // Stream (base class)
51 //------------------------------------------------------------------------
60 void Stream::close() {
63 int Stream::getRawChar() {
64 error(-1, "Internal: called getRawChar() on non-predictor stream");
68 char *Stream::getLine(char *buf
, int size
) {
72 if (lookChar() == EOF
)
74 for (i
= 0; i
< size
- 1; ++i
) {
76 if (c
== EOF
|| c
== '\n')
79 if ((c
= lookChar()) == '\n')
89 GString
*Stream::getPSFilter(int psLevel
, char *indent
) {
93 Stream
*Stream::addFilters(Object
*dict
) {
95 Object params
, params2
;
100 dict
->dictLookup("Filter", &obj
);
103 dict
->dictLookup("F", &obj
);
105 dict
->dictLookup("DecodeParms", ¶ms
);
106 if (params
.isNull()) {
108 dict
->dictLookup("DP", ¶ms
);
111 str
= makeFilter(obj
.getName(), str
, ¶ms
);
112 } else if (obj
.isArray()) {
113 for (i
= 0; i
< obj
.arrayGetLength(); ++i
) {
114 obj
.arrayGet(i
, &obj2
);
115 if (params
.isArray())
116 params
.arrayGet(i
, ¶ms2
);
120 str
= makeFilter(obj2
.getName(), str
, ¶ms2
);
122 error(getPos(), "Bad filter name");
123 str
= new EOFStream(str
);
128 } else if (!obj
.isNull()) {
129 error(getPos(), "Bad 'Filter' attribute in stream");
137 Stream
*Stream::makeFilter(char *name
, Stream
*str
, Object
*params
) {
138 int pred
; // parameters
143 GBool endOfLine
, byteAlign
, endOfBlock
, black
;
147 if (!strcmp(name
, "ASCIIHexDecode") || !strcmp(name
, "AHx")) {
148 str
= new ASCIIHexStream(str
);
149 } else if (!strcmp(name
, "ASCII85Decode") || !strcmp(name
, "A85")) {
150 str
= new ASCII85Stream(str
);
151 } else if (!strcmp(name
, "LZWDecode") || !strcmp(name
, "LZW")) {
157 if (params
->isDict()) {
158 params
->dictLookup("Predictor", &obj
);
162 params
->dictLookup("Columns", &obj
);
164 columns
= obj
.getInt();
166 params
->dictLookup("Colors", &obj
);
168 colors
= obj
.getInt();
170 params
->dictLookup("BitsPerComponent", &obj
);
174 params
->dictLookup("EarlyChange", &obj
);
176 early
= obj
.getInt();
179 str
= new LZWStream(str
, pred
, columns
, colors
, bits
, early
);
180 } else if (!strcmp(name
, "RunLengthDecode") || !strcmp(name
, "RL")) {
181 str
= new RunLengthStream(str
);
182 } else if (!strcmp(name
, "CCITTFaxDecode") || !strcmp(name
, "CCF")) {
190 if (params
->isDict()) {
191 params
->dictLookup("K", &obj
);
193 encoding
= obj
.getInt();
196 params
->dictLookup("EndOfLine", &obj
);
198 endOfLine
= obj
.getBool();
201 params
->dictLookup("EncodedByteAlign", &obj
);
203 byteAlign
= obj
.getBool();
206 params
->dictLookup("Columns", &obj
);
208 columns
= obj
.getInt();
211 params
->dictLookup("Rows", &obj
);
216 params
->dictLookup("EndOfBlock", &obj
);
218 endOfBlock
= obj
.getBool();
221 params
->dictLookup("BlackIs1", &obj
);
223 black
= obj
.getBool();
227 str
= new CCITTFaxStream(str
, encoding
, endOfLine
, byteAlign
,
228 columns
, rows
, endOfBlock
, black
);
229 } else if (!strcmp(name
, "DCTDecode") || !strcmp(name
, "DCT")) {
230 str
= new DCTStream(str
);
231 } else if (!strcmp(name
, "FlateDecode") || !strcmp(name
, "Fl")) {
236 if (params
->isDict()) {
237 params
->dictLookup("Predictor", &obj
);
241 params
->dictLookup("Columns", &obj
);
243 columns
= obj
.getInt();
245 params
->dictLookup("Colors", &obj
);
247 colors
= obj
.getInt();
249 params
->dictLookup("BitsPerComponent", &obj
);
254 str
= new FlateStream(str
, pred
, columns
, colors
, bits
);
255 } else if (!strcmp(name
, "JBIG2Decode")) {
256 if (params
->isDict()) {
257 params
->dictLookup("JBIG2Globals", &globals
);
259 str
= new JBIG2Stream(str
, &globals
);
261 } else if (!strcmp(name
, "JPXDecode")) {
262 str
= new JPXStream(str
);
264 error(getPos(), "Unknown filter '%s'", name
);
265 str
= new EOFStream(str
);
270 //------------------------------------------------------------------------
272 //------------------------------------------------------------------------
274 BaseStream::BaseStream(Object
*dictA
) {
279 BaseStream::~BaseStream() {
285 void BaseStream::doDecryption(Guchar
*fileKey
, int keyLength
,
286 int objNum
, int objGen
) {
287 decrypt
= new Decrypt(fileKey
, keyLength
, objNum
, objGen
);
290 //------------------------------------------------------------------------
292 //------------------------------------------------------------------------
294 FilterStream::FilterStream(Stream
*strA
) {
298 FilterStream::~FilterStream() {
301 void FilterStream::close() {
305 void FilterStream::setPos(Guint pos
, int dir
) {
306 error(-1, "Internal: called setPos() on FilterStream");
309 //------------------------------------------------------------------------
311 //------------------------------------------------------------------------
313 ImageStream::ImageStream(Stream
*strA
, int widthA
, int nCompsA
, int nBitsA
) {
321 nVals
= width
* nComps
;
323 imgLineSize
= (nVals
+ 7) & ~7;
327 imgLine
= (Guchar
*)gmallocn(imgLineSize
, sizeof(Guchar
));
331 ImageStream::~ImageStream() {
335 void ImageStream::reset() {
339 GBool
ImageStream::getPixel(Guchar
*pix
) {
342 if (imgIdx
>= nVals
) {
346 for (i
= 0; i
< nComps
; ++i
) {
347 pix
[i
] = imgLine
[imgIdx
++];
352 Guchar
*ImageStream::getLine() {
359 for (i
= 0; i
< nVals
; i
+= 8) {
361 imgLine
[i
+0] = (Guchar
)((c
>> 7) & 1);
362 imgLine
[i
+1] = (Guchar
)((c
>> 6) & 1);
363 imgLine
[i
+2] = (Guchar
)((c
>> 5) & 1);
364 imgLine
[i
+3] = (Guchar
)((c
>> 4) & 1);
365 imgLine
[i
+4] = (Guchar
)((c
>> 3) & 1);
366 imgLine
[i
+5] = (Guchar
)((c
>> 2) & 1);
367 imgLine
[i
+6] = (Guchar
)((c
>> 1) & 1);
368 imgLine
[i
+7] = (Guchar
)(c
& 1);
370 } else if (nBits
== 8) {
371 for (i
= 0; i
< nVals
; ++i
) {
372 imgLine
[i
] = str
->getChar();
375 bitMask
= (1 << nBits
) - 1;
378 for (i
= 0; i
< nVals
; ++i
) {
380 buf
= (buf
<< 8) | (str
->getChar() & 0xff);
383 imgLine
[i
] = (Guchar
)((buf
>> (bits
- nBits
)) & bitMask
);
390 void ImageStream::skipLine() {
393 n
= (nVals
* nBits
+ 7) >> 3;
394 for (i
= 0; i
< n
; ++i
) {
399 //------------------------------------------------------------------------
401 //------------------------------------------------------------------------
403 StreamPredictor::StreamPredictor(Stream
*strA
, int predictorA
,
404 int widthA
, int nCompsA
, int nBitsA
) {
406 predictor
= predictorA
;
413 nVals
= width
* nComps
;
414 pixBytes
= (nComps
* nBits
+ 7) >> 3;
415 rowBytes
= ((nVals
* nBits
+ 7) >> 3) + pixBytes
;
416 if (width
<= 0 || nComps
<= 0 || nBits
<= 0 ||
417 nComps
> gfxColorMaxComps
||
419 width
>= INT_MAX
/ nComps
|| // check for overflow in nVals
420 nVals
>= (INT_MAX
- 7) / nBits
) { // check for overflow in rowBytes
423 predLine
= (Guchar
*)gmalloc(rowBytes
);
424 memset(predLine
, 0, rowBytes
);
430 StreamPredictor::~StreamPredictor() {
434 int StreamPredictor::lookChar() {
435 if (predIdx
>= rowBytes
) {
436 if (!getNextLine()) {
440 return predLine
[predIdx
];
443 int StreamPredictor::getChar() {
444 if (predIdx
>= rowBytes
) {
445 if (!getNextLine()) {
449 return predLine
[predIdx
++];
452 GBool
StreamPredictor::getNextLine() {
454 Guchar upLeftBuf
[gfxColorMaxComps
* 2 + 1];
455 int left
, up
, upLeft
, p
, pa
, pb
, pc
;
457 Gulong inBuf
, outBuf
, bitMask
;
461 // get PNG optimum predictor number
462 if (predictor
>= 10) {
463 if ((curPred
= str
->getRawChar()) == EOF
) {
471 // read the raw line, apply PNG (byte) predictor
472 memset(upLeftBuf
, 0, pixBytes
+ 1);
473 for (i
= pixBytes
; i
< rowBytes
; ++i
) {
474 for (j
= pixBytes
; j
> 0; --j
) {
475 upLeftBuf
[j
] = upLeftBuf
[j
-1];
477 upLeftBuf
[0] = predLine
[i
];
478 if ((c
= str
->getRawChar()) == EOF
) {
480 // this ought to return false, but some (broken) PDF files
481 // contain truncated image data, and Adobe apparently reads the
489 predLine
[i
] = predLine
[i
- pixBytes
] + (Guchar
)c
;
492 predLine
[i
] = predLine
[i
] + (Guchar
)c
;
494 case 13: // PNG average
495 predLine
[i
] = ((predLine
[i
- pixBytes
] + predLine
[i
]) >> 1) +
498 case 14: // PNG Paeth
499 left
= predLine
[i
- pixBytes
];
501 upLeft
= upLeftBuf
[pixBytes
];
502 p
= left
+ up
- upLeft
;
503 if ((pa
= p
- left
) < 0)
505 if ((pb
= p
- up
) < 0)
507 if ((pc
= p
- upLeft
) < 0)
509 if (pa
<= pb
&& pa
<= pc
)
510 predLine
[i
] = left
+ (Guchar
)c
;
512 predLine
[i
] = up
+ (Guchar
)c
;
514 predLine
[i
] = upLeft
+ (Guchar
)c
;
517 default: // no predictor or TIFF predictor
518 predLine
[i
] = (Guchar
)c
;
523 // apply TIFF (component) predictor
524 if (predictor
== 2) {
526 inBuf
= predLine
[pixBytes
- 1];
527 for (i
= pixBytes
; i
< rowBytes
; i
+= 8) {
528 // 1-bit add is just xor
529 inBuf
= (inBuf
<< 8) | predLine
[i
];
530 predLine
[i
] ^= inBuf
>> nComps
;
532 } else if (nBits
== 8) {
533 for (i
= pixBytes
; i
< rowBytes
; ++i
) {
534 predLine
[i
] += predLine
[i
- nComps
];
537 memset(upLeftBuf
, 0, nComps
+ 1);
538 bitMask
= (1 << nBits
) - 1;
540 inBits
= outBits
= 0;
542 for (i
= 0; i
< width
; ++i
) {
543 for (kk
= 0; kk
< nComps
; ++kk
) {
544 if (inBits
< nBits
) {
545 inBuf
= (inBuf
<< 8) | (predLine
[j
++] & 0xff);
548 upLeftBuf
[kk
] = (upLeftBuf
[kk
] +
549 (inBuf
>> (inBits
- nBits
))) & bitMask
;
551 outBuf
= (outBuf
<< nBits
) | upLeftBuf
[kk
];
554 predLine
[k
++] = (Guchar
)(outBuf
>> (outBits
- 8));
560 predLine
[k
++] = (Guchar
)((outBuf
<< (8 - outBits
)) +
561 (inBuf
& ((1 << (8 - outBits
)) - 1)));
566 // reset to start of line
572 //------------------------------------------------------------------------
574 //------------------------------------------------------------------------
576 FileStream::FileStream(FILE *fA
, Guint startA
, GBool limitedA
,
577 Guint lengthA
, Object
*dictA
):
583 bufPtr
= bufEnd
= buf
;
589 FileStream::~FileStream() {
593 Stream
*FileStream::makeSubStream(Guint startA
, GBool limitedA
,
594 Guint lengthA
, Object
*dictA
) {
595 return new FileStream(f
, startA
, limitedA
, lengthA
, dictA
);
598 void FileStream::reset() {
600 savePos
= (Guint
)ftello(f
);
601 fseeko(f
, start
, SEEK_SET
);
603 savePos
= (Guint
)ftell64(f
);
604 fseek64(f
, start
, SEEK_SET
);
606 savePos
= (Guint
)ftell(f
);
607 fseek(f
, start
, SEEK_SET
);
610 bufPtr
= bufEnd
= buf
;
616 void FileStream::close() {
619 fseeko(f
, savePos
, SEEK_SET
);
621 fseek64(f
, savePos
, SEEK_SET
);
623 fseek(f
, savePos
, SEEK_SET
);
629 GBool
FileStream::fillBuf() {
633 bufPos
+= bufEnd
- buf
;
634 bufPtr
= bufEnd
= buf
;
635 if (limited
&& bufPos
>= start
+ length
) {
638 if (limited
&& bufPos
+ fileStreamBufSize
> start
+ length
) {
639 n
= start
+ length
- bufPos
;
641 n
= fileStreamBufSize
;
643 n
= fread(buf
, 1, n
, f
);
645 if (bufPtr
>= bufEnd
) {
649 for (p
= buf
; p
< bufEnd
; ++p
) {
650 *p
= (char)decrypt
->decryptByte((Guchar
)*p
);
656 void FileStream::setPos(Guint pos
, int dir
) {
661 fseeko(f
, pos
, SEEK_SET
);
663 fseek64(f
, pos
, SEEK_SET
);
665 fseek(f
, pos
, SEEK_SET
);
670 fseeko(f
, 0, SEEK_END
);
671 size
= (Guint
)ftello(f
);
673 fseek64(f
, 0, SEEK_END
);
674 size
= (Guint
)ftell64(f
);
676 fseek(f
, 0, SEEK_END
);
677 size
= (Guint
)ftell(f
);
682 //~ work around a bug in cygwin's implementation of fseek
686 fseeko(f
, -(int)pos
, SEEK_END
);
687 bufPos
= (Guint
)ftello(f
);
689 fseek64(f
, -(int)pos
, SEEK_END
);
690 bufPos
= (Guint
)ftell64(f
);
692 fseek(f
, -(int)pos
, SEEK_END
);
693 bufPos
= (Guint
)ftell(f
);
696 bufPtr
= bufEnd
= buf
;
699 void FileStream::moveStart(int delta
) {
701 bufPtr
= bufEnd
= buf
;
705 //------------------------------------------------------------------------
707 //------------------------------------------------------------------------
709 MemStream::MemStream(char *bufA
, Guint startA
, Guint lengthA
, Object
*dictA
):
714 bufEnd
= buf
+ start
+ length
;
715 bufPtr
= buf
+ start
;
719 MemStream::~MemStream() {
725 Stream
*MemStream::makeSubStream(Guint startA
, GBool limited
,
726 Guint lengthA
, Object
*dictA
) {
730 if (!limited
|| startA
+ lengthA
> start
+ length
) {
731 newLength
= start
+ length
- startA
;
735 subStr
= new MemStream(buf
, startA
, newLength
, dictA
);
739 void MemStream::reset() {
740 bufPtr
= buf
+ start
;
746 void MemStream::close() {
749 void MemStream::setPos(Guint pos
, int dir
) {
755 i
= start
+ length
- pos
;
759 } else if (i
> start
+ length
) {
765 void MemStream::moveStart(int delta
) {
768 bufPtr
= buf
+ start
;
771 void MemStream::doDecryption(Guchar
*fileKey
, int keyLength
,
772 int objNum
, int objGen
) {
776 this->BaseStream::doDecryption(fileKey
, keyLength
, objNum
, objGen
);
778 newBuf
= (char *)gmalloc(length
);
779 for (p
= buf
+ start
, q
= newBuf
; p
< bufEnd
; ++p
, ++q
) {
780 *q
= (char)decrypt
->decryptByte((Guchar
)*p
);
782 bufEnd
= newBuf
+ length
;
783 bufPtr
= newBuf
+ (bufPtr
- (buf
+ start
));
790 //------------------------------------------------------------------------
792 //------------------------------------------------------------------------
794 EmbedStream::EmbedStream(Stream
*strA
, Object
*dictA
,
795 GBool limitedA
, Guint lengthA
):
802 EmbedStream::~EmbedStream() {
805 Stream
*EmbedStream::makeSubStream(Guint start
, GBool limitedA
,
806 Guint lengthA
, Object
*dictA
) {
807 error(-1, "Internal: called makeSubStream() on EmbedStream");
811 int EmbedStream::getChar() {
812 if (limited
&& !length
) {
816 return str
->getChar();
819 int EmbedStream::lookChar() {
820 if (limited
&& !length
) {
823 return str
->lookChar();
826 void EmbedStream::setPos(Guint pos
, int dir
) {
827 error(-1, "Internal: called setPos() on EmbedStream");
830 Guint
EmbedStream::getStart() {
831 error(-1, "Internal: called getStart() on EmbedStream");
835 void EmbedStream::moveStart(int delta
) {
836 error(-1, "Internal: called moveStart() on EmbedStream");
839 //------------------------------------------------------------------------
841 //------------------------------------------------------------------------
843 ASCIIHexStream::ASCIIHexStream(Stream
*strA
):
849 ASCIIHexStream::~ASCIIHexStream() {
853 void ASCIIHexStream::reset() {
859 int ASCIIHexStream::lookChar() {
870 } while (isspace(c1
));
878 } while (isspace(c2
));
883 if (c1
>= '0' && c1
<= '9') {
885 } else if (c1
>= 'A' && c1
<= 'F') {
886 x
= (c1
- 'A' + 10) << 4;
887 } else if (c1
>= 'a' && c1
<= 'f') {
888 x
= (c1
- 'a' + 10) << 4;
889 } else if (c1
== EOF
) {
893 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1
);
896 if (c2
>= '0' && c2
<= '9') {
898 } else if (c2
>= 'A' && c2
<= 'F') {
900 } else if (c2
>= 'a' && c2
<= 'f') {
902 } else if (c2
== EOF
) {
906 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2
);
912 GString
*ASCIIHexStream::getPSFilter(int psLevel
, char *indent
) {
918 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
921 s
->append(indent
)->append("/ASCIIHexDecode filter\n");
925 GBool
ASCIIHexStream::isBinary(GBool last
) {
926 return str
->isBinary(gFalse
);
929 //------------------------------------------------------------------------
931 //------------------------------------------------------------------------
933 ASCII85Stream::ASCII85Stream(Stream
*strA
):
939 ASCII85Stream::~ASCII85Stream() {
943 void ASCII85Stream::reset() {
949 int ASCII85Stream::lookChar() {
958 c
[0] = str
->getChar();
959 } while (Lexer::isSpace(c
[0]));
960 if (c
[0] == '~' || c
[0] == EOF
) {
964 } else if (c
[0] == 'z') {
965 b
[0] = b
[1] = b
[2] = b
[3] = 0;
968 for (k
= 1; k
< 5; ++k
) {
970 c
[k
] = str
->getChar();
971 } while (Lexer::isSpace(c
[k
]));
972 if (c
[k
] == '~' || c
[k
] == EOF
)
976 if (k
< 5 && (c
[k
] == '~' || c
[k
] == EOF
)) {
977 for (++k
; k
< 5; ++k
)
982 for (k
= 0; k
< 5; ++k
)
983 t
= t
* 85 + (c
[k
] - 0x21);
984 for (k
= 3; k
>= 0; --k
) {
985 b
[k
] = (int)(t
& 0xff);
993 GString
*ASCII85Stream::getPSFilter(int psLevel
, char *indent
) {
999 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1002 s
->append(indent
)->append("/ASCII85Decode filter\n");
1006 GBool
ASCII85Stream::isBinary(GBool last
) {
1007 return str
->isBinary(gFalse
);
1010 //------------------------------------------------------------------------
1012 //------------------------------------------------------------------------
1014 LZWStream::LZWStream(Stream
*strA
, int predictor
, int columns
, int colors
,
1015 int bits
, int earlyA
):
1016 FilterStream(strA
) {
1017 if (predictor
!= 1) {
1018 pred
= new StreamPredictor(this, predictor
, columns
, colors
, bits
);
1019 if (!pred
->isOk()) {
1032 LZWStream::~LZWStream() {
1039 int LZWStream::getChar() {
1041 return pred
->getChar();
1046 if (seqIndex
>= seqLength
) {
1047 if (!processNextCode()) {
1051 return seqBuf
[seqIndex
++];
1054 int LZWStream::lookChar() {
1056 return pred
->lookChar();
1061 if (seqIndex
>= seqLength
) {
1062 if (!processNextCode()) {
1066 return seqBuf
[seqIndex
];
1069 int LZWStream::getRawChar() {
1073 if (seqIndex
>= seqLength
) {
1074 if (!processNextCode()) {
1078 return seqBuf
[seqIndex
++];
1081 void LZWStream::reset() {
1088 GBool
LZWStream::processNextCode() {
1098 // check for eod and clear-table codes
1101 if (code
== EOF
|| code
== 257) {
1109 if (nextCode
>= 4097) {
1110 error(getPos(), "Bad LZW stream - expected clear-table code");
1114 // process the next code
1115 nextLength
= seqLength
+ 1;
1119 } else if (code
< nextCode
) {
1120 seqLength
= table
[code
].length
;
1121 for (i
= seqLength
- 1, j
= code
; i
> 0; --i
) {
1122 seqBuf
[i
] = table
[j
].tail
;
1126 } else if (code
== nextCode
) {
1127 seqBuf
[seqLength
] = newChar
;
1130 error(getPos(), "Bad LZW stream - unexpected code");
1134 newChar
= seqBuf
[0];
1138 table
[nextCode
].length
= nextLength
;
1139 table
[nextCode
].head
= prevCode
;
1140 table
[nextCode
].tail
= newChar
;
1142 if (nextCode
+ early
== 512)
1144 else if (nextCode
+ early
== 1024)
1146 else if (nextCode
+ early
== 2048)
1157 void LZWStream::clearTable() {
1160 seqIndex
= seqLength
= 0;
1164 int LZWStream::getCode() {
1168 while (inputBits
< nextBits
) {
1169 if ((c
= str
->getChar()) == EOF
)
1171 inputBuf
= (inputBuf
<< 8) | (c
& 0xff);
1174 code
= (inputBuf
>> (inputBits
- nextBits
)) & ((1 << nextBits
) - 1);
1175 inputBits
-= nextBits
;
1179 GString
*LZWStream::getPSFilter(int psLevel
, char *indent
) {
1182 if (psLevel
< 2 || pred
) {
1185 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1188 s
->append(indent
)->append("<< ");
1190 s
->append("/EarlyChange 0 ");
1192 s
->append(">> /LZWDecode filter\n");
1196 GBool
LZWStream::isBinary(GBool last
) {
1197 return str
->isBinary(gTrue
);
1200 //------------------------------------------------------------------------
1202 //------------------------------------------------------------------------
1204 RunLengthStream::RunLengthStream(Stream
*strA
):
1205 FilterStream(strA
) {
1206 bufPtr
= bufEnd
= buf
;
1210 RunLengthStream::~RunLengthStream() {
1214 void RunLengthStream::reset() {
1216 bufPtr
= bufEnd
= buf
;
1220 GString
*RunLengthStream::getPSFilter(int psLevel
, char *indent
) {
1226 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1229 s
->append(indent
)->append("/RunLengthDecode filter\n");
1233 GBool
RunLengthStream::isBinary(GBool last
) {
1234 return str
->isBinary(gTrue
);
1237 GBool
RunLengthStream::fillBuf() {
1244 if (c
== 0x80 || c
== EOF
) {
1250 for (i
= 0; i
< n
; ++i
)
1251 buf
[i
] = (char)str
->getChar();
1255 for (i
= 0; i
< n
; ++i
)
1263 //------------------------------------------------------------------------
1265 //------------------------------------------------------------------------
1267 CCITTFaxStream::CCITTFaxStream(Stream
*strA
, int encodingA
, GBool endOfLineA
,
1268 GBool byteAlignA
, int columnsA
, int rowsA
,
1269 GBool endOfBlockA
, GBool blackA
):
1270 FilterStream(strA
) {
1271 encoding
= encodingA
;
1272 endOfLine
= endOfLineA
;
1273 byteAlign
= byteAlignA
;
1277 } else if (columns
> INT_MAX
- 2) {
1278 columns
= INT_MAX
- 2;
1281 endOfBlock
= endOfBlockA
;
1283 // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = columns
1284 // ---> max codingLine size = columns + 1
1285 // refLine has one extra guard entry at the end
1286 // ---> max refLine size = columns + 2
1287 codingLine
= (int *)gmallocn(columns
+ 1, sizeof(int));
1288 refLine
= (int *)gmallocn(columns
+ 2, sizeof(int));
1292 nextLine2D
= encoding
< 0;
1294 codingLine
[0] = columns
;
1301 CCITTFaxStream::~CCITTFaxStream() {
1307 void CCITTFaxStream::reset() {
1313 nextLine2D
= encoding
< 0;
1315 codingLine
[0] = columns
;
1320 // skip any initial zero bits and end-of-line marker, and get the 2D
1322 while ((code1
= lookBits(12)) == 0) {
1325 if (code1
== 0x001) {
1329 nextLine2D
= !lookBits(1);
1334 inline void CCITTFaxStream::addPixels(int a1
, int blackPixels
) {
1335 if (a1
> codingLine
[a0i
]) {
1337 error(getPos(), "CCITTFax row is wrong length (%d)", a1
);
1341 if ((a0i
& 1) ^ blackPixels
) {
1344 codingLine
[a0i
] = a1
;
1348 inline void CCITTFaxStream::addPixelsNeg(int a1
, int blackPixels
) {
1349 if (a1
> codingLine
[a0i
]) {
1351 error(getPos(), "CCITTFax row is wrong length (%d)", a1
);
1355 if ((a0i
& 1) ^ blackPixels
) {
1358 codingLine
[a0i
] = a1
;
1359 } else if (a1
< codingLine
[a0i
]) {
1361 error(getPos(), "Invalid CCITTFax code");
1365 while (a0i
> 0 && a1
<= codingLine
[a0i
- 1]) {
1368 codingLine
[a0i
] = a1
;
1373 int CCITTFaxStream::lookChar() {
1374 short code1
, code2
, code3
;
1375 int b1i
, blackPixels
, i
, bits
;
1382 // read the next row
1383 if (outputBits
== 0) {
1385 // if at eof just return EOF
1394 for (i
= 0; codingLine
[i
] < columns
; ++i
)
1395 refLine
[i
] = codingLine
[i
];
1396 refLine
[i
++] = columns
;
1397 refLine
[i
] = columns
;
1403 // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1]
1405 // exception at left edge:
1406 // codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible
1407 // exception at right edge:
1408 // refLine[b1i] = refLine[b1i+1] = columns is possible
1409 while (codingLine
[a0i
] < columns
) {
1410 code1
= getTwoDimCode();
1413 addPixels(refLine
[b1i
+ 1], blackPixels
);
1414 if (refLine
[b1i
+ 1] < columns
) {
1422 code1
+= code3
= getBlackCode();
1423 } while (code3
>= 64);
1425 code2
+= code3
= getWhiteCode();
1426 } while (code3
>= 64);
1429 code1
+= code3
= getWhiteCode();
1430 } while (code3
>= 64);
1432 code2
+= code3
= getBlackCode();
1433 } while (code3
>= 64);
1435 addPixels(codingLine
[a0i
] + code1
, blackPixels
);
1436 if (codingLine
[a0i
] < columns
) {
1437 addPixels(codingLine
[a0i
] + code2
, blackPixels
^ 1);
1439 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1444 addPixels(refLine
[b1i
] + 3, blackPixels
);
1446 if (codingLine
[a0i
] < columns
) {
1448 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1454 addPixels(refLine
[b1i
] + 2, blackPixels
);
1456 if (codingLine
[a0i
] < columns
) {
1458 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1464 addPixels(refLine
[b1i
] + 1, blackPixels
);
1466 if (codingLine
[a0i
] < columns
) {
1468 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1474 addPixels(refLine
[b1i
], blackPixels
);
1476 if (codingLine
[a0i
] < columns
) {
1478 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1484 addPixelsNeg(refLine
[b1i
] - 3, blackPixels
);
1486 if (codingLine
[a0i
] < columns
) {
1492 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1498 addPixelsNeg(refLine
[b1i
] - 2, blackPixels
);
1500 if (codingLine
[a0i
] < columns
) {
1506 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1512 addPixelsNeg(refLine
[b1i
] - 1, blackPixels
);
1514 if (codingLine
[a0i
] < columns
) {
1520 while (refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < columns
) {
1526 addPixels(columns
, 0);
1530 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1
);
1531 addPixels(columns
, 0);
1542 while (codingLine
[a0i
] < columns
) {
1546 code1
+= code3
= getBlackCode();
1547 } while (code3
>= 64);
1550 code1
+= code3
= getWhiteCode();
1551 } while (code3
>= 64);
1553 addPixels(codingLine
[a0i
] + code1
, blackPixels
);
1558 // byte-align the row
1563 // check for end-of-line marker, skipping over any extra zero bits
1565 if (!endOfBlock
&& row
== rows
- 1) {
1568 code1
= lookBits(12);
1569 while (code1
== 0) {
1571 code1
= lookBits(12);
1573 if (code1
== 0x001) {
1576 } else if (code1
== EOF
) {
1581 // get 2D encoding tag
1582 if (!eof
&& encoding
> 0) {
1583 nextLine2D
= !lookBits(1);
1587 // check for end-of-block marker
1588 if (endOfBlock
&& gotEOL
) {
1589 code1
= lookBits(12);
1590 if (code1
== 0x001) {
1596 if (encoding
>= 0) {
1597 for (i
= 0; i
< 4; ++i
) {
1598 code1
= lookBits(12);
1599 if (code1
!= 0x001) {
1600 error(getPos(), "Bad RTC code in CCITTFax stream");
1612 // look for an end-of-line marker after an error -- we only do
1613 // this if we know the stream contains end-of-line markers because
1614 // the "just plow on" technique tends to work better otherwise
1615 } else if (err
&& endOfLine
) {
1617 code1
= lookBits(13);
1622 if ((code1
>> 1) == 0x001) {
1630 nextLine2D
= !(code1
& 1);
1634 // set up for output
1635 if (codingLine
[0] > 0) {
1636 outputBits
= codingLine
[a0i
= 0];
1638 outputBits
= codingLine
[a0i
= 1];
1645 if (outputBits
>= 8) {
1646 buf
= (a0i
& 1) ? 0x00 : 0xff;
1648 if (outputBits
== 0 && codingLine
[a0i
] < columns
) {
1650 outputBits
= codingLine
[a0i
] - codingLine
[a0i
- 1];
1656 if (outputBits
> bits
) {
1659 buf
|= 0xff >> (8 - bits
);
1666 buf
|= 0xff >> (8 - outputBits
);
1670 if (codingLine
[a0i
] < columns
) {
1672 outputBits
= codingLine
[a0i
] - codingLine
[a0i
- 1];
1673 } else if (bits
> 0) {
1686 short CCITTFaxStream::getTwoDimCode() {
1691 code
= 0; // make gcc happy
1694 p
= &twoDimTab1
[code
];
1700 for (n
= 1; n
<= 7; ++n
) {
1705 p
= &twoDimTab1
[code
];
1712 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code
);
1716 short CCITTFaxStream::getWhiteCode() {
1721 code
= 0; // make gcc happy
1723 code
= lookBits(12);
1727 if ((code
>> 5) == 0) {
1728 p
= &whiteTab1
[code
];
1730 p
= &whiteTab2
[code
>> 3];
1737 for (n
= 1; n
<= 9; ++n
) {
1745 p
= &whiteTab2
[code
];
1751 for (n
= 11; n
<= 12; ++n
) {
1759 p
= &whiteTab1
[code
];
1766 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code
);
1767 // eat a bit and return a positive number so that the caller doesn't
1768 // go into an infinite loop
1773 short CCITTFaxStream::getBlackCode() {
1778 code
= 0; // make gcc happy
1780 code
= lookBits(13);
1784 if ((code
>> 7) == 0) {
1785 p
= &blackTab1
[code
];
1786 } else if ((code
>> 9) == 0 && (code
>> 7) != 0) {
1787 p
= &blackTab2
[(code
>> 1) - 64];
1789 p
= &blackTab3
[code
>> 7];
1796 for (n
= 2; n
<= 6; ++n
) {
1804 p
= &blackTab3
[code
];
1810 for (n
= 7; n
<= 12; ++n
) {
1819 p
= &blackTab2
[code
- 64];
1826 for (n
= 10; n
<= 13; ++n
) {
1834 p
= &blackTab1
[code
];
1841 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code
);
1842 // eat a bit and return a positive number so that the caller doesn't
1843 // go into an infinite loop
1848 short CCITTFaxStream::lookBits(int n
) {
1851 while (inputBits
< n
) {
1852 if ((c
= str
->getChar()) == EOF
) {
1853 if (inputBits
== 0) {
1856 // near the end of the stream, the caller may ask for more bits
1857 // than are available, but there may still be a valid code in
1858 // however many bits are available -- we need to return correct
1859 // data in this case
1860 return (inputBuf
<< (n
- inputBits
)) & (0xffff >> (16 - n
));
1862 inputBuf
= (inputBuf
<< 8) + c
;
1865 return (inputBuf
>> (inputBits
- n
)) & (0xffff >> (16 - n
));
1868 GString
*CCITTFaxStream::getPSFilter(int psLevel
, char *indent
) {
1875 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
1878 s
->append(indent
)->append("<< ");
1879 if (encoding
!= 0) {
1880 sprintf(s1
, "/K %d ", encoding
);
1884 s
->append("/EndOfLine true ");
1887 s
->append("/EncodedByteAlign true ");
1889 sprintf(s1
, "/Columns %d ", columns
);
1892 sprintf(s1
, "/Rows %d ", rows
);
1896 s
->append("/EndOfBlock false ");
1899 s
->append("/BlackIs1 true ");
1901 s
->append(">> /CCITTFaxDecode filter\n");
1905 GBool
CCITTFaxStream::isBinary(GBool last
) {
1906 return str
->isBinary(gTrue
);
1909 //------------------------------------------------------------------------
1911 //------------------------------------------------------------------------
1913 // IDCT constants (20.12 fixed point format)
1914 #define dctCos1 4017 // cos(pi/16)
1915 #define dctSin1 799 // sin(pi/16)
1916 #define dctCos3 3406 // cos(3*pi/16)
1917 #define dctSin3 2276 // sin(3*pi/16)
1918 #define dctCos6 1567 // cos(6*pi/16)
1919 #define dctSin6 3784 // sin(6*pi/16)
1920 #define dctSqrt2 5793 // sqrt(2)
1921 #define dctSqrt1d2 2896 // sqrt(2) / 2
1923 // color conversion parameters (16.16 fixed point format)
1924 #define dctCrToR 91881 // 1.4020
1925 #define dctCbToG -22553 // -0.3441363
1926 #define dctCrToG -46802 // -0.71413636
1927 #define dctCbToB 116130 // 1.772
1929 // clip [-256,511] --> [0,255]
1930 #define dctClipOffset 256
1931 static Guchar dctClip
[768];
1932 static int dctClipInit
= 0;
1934 // zig zag decode map
1935 static int dctZigZag
[64] = {
1941 5, 12, 19, 26, 33, 40,
1942 48, 41, 34, 27, 20, 13, 6,
1943 7, 14, 21, 28, 35, 42, 49, 56,
1944 57, 50, 43, 36, 29, 22, 15,
1945 23, 30, 37, 44, 51, 58,
1953 DCTStream::DCTStream(Stream
*strA
):
1954 FilterStream(strA
) {
1957 progressive
= interleaved
= gFalse
;
1959 mcuWidth
= mcuHeight
= 0;
1963 for (i
= 0; i
< 4; ++i
) {
1964 for (j
= 0; j
< 32; ++j
) {
1965 rowBuf
[i
][j
] = NULL
;
1971 for (i
= -256; i
< 0; ++i
)
1972 dctClip
[dctClipOffset
+ i
] = 0;
1973 for (i
= 0; i
< 256; ++i
)
1974 dctClip
[dctClipOffset
+ i
] = i
;
1975 for (i
= 256; i
< 512; ++i
)
1976 dctClip
[dctClipOffset
+ i
] = 255;
1981 DCTStream::~DCTStream() {
1985 if (progressive
|| !interleaved
) {
1986 for (i
= 0; i
< numComps
; ++i
) {
1990 for (i
= 0; i
< numComps
; ++i
) {
1991 for (j
= 0; j
< mcuHeight
; ++j
) {
1992 gfree(rowBuf
[i
][j
]);
1998 void DCTStream::reset() {
2003 progressive
= interleaved
= gFalse
;
2007 numDCHuffTables
= 0;
2008 numACHuffTables
= 0;
2010 gotJFIFMarker
= gFalse
;
2011 gotAdobeMarker
= gFalse
;
2012 restartInterval
= 0;
2014 if (!readHeader()) {
2020 if (numComps
== 1) {
2021 compInfo
[0].hSample
= compInfo
[0].vSample
= 1;
2023 mcuWidth
= compInfo
[0].hSample
;
2024 mcuHeight
= compInfo
[0].vSample
;
2025 for (i
= 1; i
< numComps
; ++i
) {
2026 if (compInfo
[i
].hSample
> mcuWidth
) {
2027 mcuWidth
= compInfo
[i
].hSample
;
2029 if (compInfo
[i
].vSample
> mcuHeight
) {
2030 mcuHeight
= compInfo
[i
].vSample
;
2036 // figure out color transform
2037 if (!gotAdobeMarker
&& numComps
== 3) {
2038 if (gotJFIFMarker
) {
2040 } else if (compInfo
[0].id
== 82 && compInfo
[1].id
== 71 &&
2041 compInfo
[2].id
== 66) { // ASCII "RGB"
2048 if (progressive
|| !interleaved
) {
2050 // allocate a buffer for the whole image
2051 bufWidth
= ((width
+ mcuWidth
- 1) / mcuWidth
) * mcuWidth
;
2052 bufHeight
= ((height
+ mcuHeight
- 1) / mcuHeight
) * mcuHeight
;
2053 if (bufWidth
<= 0 || bufHeight
<= 0 ||
2054 bufWidth
> INT_MAX
/ bufWidth
/ (int)sizeof(int)) {
2055 error(getPos(), "Invalid image size in DCT stream");
2059 for (i
= 0; i
< numComps
; ++i
) {
2060 frameBuf
[i
] = (int *)gmallocn(bufWidth
* bufHeight
, sizeof(int));
2061 memset(frameBuf
[i
], 0, bufWidth
* bufHeight
* sizeof(int));
2064 // read the image data
2066 restartMarker
= 0xd0;
2069 } while (readHeader());
2074 // initialize counters
2081 // allocate a buffer for one row of MCUs
2082 bufWidth
= ((width
+ mcuWidth
- 1) / mcuWidth
) * mcuWidth
;
2083 for (i
= 0; i
< numComps
; ++i
) {
2084 for (j
= 0; j
< mcuHeight
; ++j
) {
2085 rowBuf
[i
][j
] = (Guchar
*)gmallocn(bufWidth
, sizeof(Guchar
));
2089 // initialize counters
2095 restartMarker
= 0xd0;
2100 int DCTStream::getChar() {
2106 if (progressive
|| !interleaved
) {
2107 c
= frameBuf
[comp
][y
* bufWidth
+ x
];
2108 if (++comp
== numComps
) {
2116 if (dy
>= mcuHeight
) {
2117 if (!readMCURow()) {
2125 c
= rowBuf
[comp
][dy
][x
];
2126 if (++comp
== numComps
) {
2141 int DCTStream::lookChar() {
2145 if (progressive
|| !interleaved
) {
2146 return frameBuf
[comp
][y
* bufWidth
+ x
];
2148 if (dy
>= mcuHeight
) {
2149 if (!readMCURow()) {
2157 return rowBuf
[comp
][dy
][x
];
2161 void DCTStream::restart() {
2165 restartCtr
= restartInterval
;
2166 for (i
= 0; i
< numComps
; ++i
) {
2167 compInfo
[i
].prevDC
= 0;
2172 // Read one row of MCUs from a sequential JPEG stream.
2173 GBool
DCTStream::readMCURow() {
2177 int pY
, pCb
, pCr
, pR
, pG
, pB
;
2178 int h
, v
, horiz
, vert
, hSub
, vSub
;
2179 int x1
, x2
, y2
, x3
, y3
, x4
, y4
, x5
, y5
, cc
, i
;
2182 for (x1
= 0; x1
< width
; x1
+= mcuWidth
) {
2184 // deal with restart marker
2185 if (restartInterval
> 0 && restartCtr
== 0) {
2187 if (c
!= restartMarker
) {
2188 error(getPos(), "Bad DCT data: incorrect restart marker");
2191 if (++restartMarker
== 0xd8)
2192 restartMarker
= 0xd0;
2197 for (cc
= 0; cc
< numComps
; ++cc
) {
2198 h
= compInfo
[cc
].hSample
;
2199 v
= compInfo
[cc
].vSample
;
2200 horiz
= mcuWidth
/ h
;
2201 vert
= mcuHeight
/ v
;
2204 for (y2
= 0; y2
< mcuHeight
; y2
+= vert
) {
2205 for (x2
= 0; x2
< mcuWidth
; x2
+= horiz
) {
2206 if (!readDataUnit(&dcHuffTables
[scanInfo
.dcHuffTable
[cc
]],
2207 &acHuffTables
[scanInfo
.acHuffTable
[cc
]],
2208 &compInfo
[cc
].prevDC
,
2212 transformDataUnit(quantTables
[compInfo
[cc
].quantTable
],
2214 if (hSub
== 1 && vSub
== 1) {
2215 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2216 p1
= &rowBuf
[cc
][y2
+y3
][x1
+x2
];
2226 } else if (hSub
== 2 && vSub
== 2) {
2227 for (y3
= 0, i
= 0; y3
< 16; y3
+= 2, i
+= 8) {
2228 p1
= &rowBuf
[cc
][y2
+y3
][x1
+x2
];
2229 p2
= &rowBuf
[cc
][y2
+y3
+1][x1
+x2
];
2230 p1
[0] = p1
[1] = p2
[0] = p2
[1] = data2
[i
];
2231 p1
[2] = p1
[3] = p2
[2] = p2
[3] = data2
[i
+1];
2232 p1
[4] = p1
[5] = p2
[4] = p2
[5] = data2
[i
+2];
2233 p1
[6] = p1
[7] = p2
[6] = p2
[7] = data2
[i
+3];
2234 p1
[8] = p1
[9] = p2
[8] = p2
[9] = data2
[i
+4];
2235 p1
[10] = p1
[11] = p2
[10] = p2
[11] = data2
[i
+5];
2236 p1
[12] = p1
[13] = p2
[12] = p2
[13] = data2
[i
+6];
2237 p1
[14] = p1
[15] = p2
[14] = p2
[15] = data2
[i
+7];
2241 for (y3
= 0, y4
= 0; y3
< 8; ++y3
, y4
+= vSub
) {
2242 for (x3
= 0, x4
= 0; x3
< 8; ++x3
, x4
+= hSub
) {
2243 for (y5
= 0; y5
< vSub
; ++y5
)
2244 for (x5
= 0; x5
< hSub
; ++x5
)
2245 rowBuf
[cc
][y2
+y4
+y5
][x1
+x2
+x4
+x5
] = data2
[i
];
2255 // color space conversion
2257 // convert YCbCr to RGB
2258 if (numComps
== 3) {
2259 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2260 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2261 pY
= rowBuf
[0][y2
][x1
+x2
];
2262 pCb
= rowBuf
[1][y2
][x1
+x2
] - 128;
2263 pCr
= rowBuf
[2][y2
][x1
+x2
] - 128;
2264 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2265 rowBuf
[0][y2
][x1
+x2
] = dctClip
[dctClipOffset
+ pR
];
2266 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+ 32768) >> 16;
2267 rowBuf
[1][y2
][x1
+x2
] = dctClip
[dctClipOffset
+ pG
];
2268 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2269 rowBuf
[2][y2
][x1
+x2
] = dctClip
[dctClipOffset
+ pB
];
2272 // convert YCbCrK to CMYK (K is passed through unchanged)
2273 } else if (numComps
== 4) {
2274 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2275 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2276 pY
= rowBuf
[0][y2
][x1
+x2
];
2277 pCb
= rowBuf
[1][y2
][x1
+x2
] - 128;
2278 pCr
= rowBuf
[2][y2
][x1
+x2
] - 128;
2279 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2280 rowBuf
[0][y2
][x1
+x2
] = 255 - dctClip
[dctClipOffset
+ pR
];
2281 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+ 32768) >> 16;
2282 rowBuf
[1][y2
][x1
+x2
] = 255 - dctClip
[dctClipOffset
+ pG
];
2283 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2284 rowBuf
[2][y2
][x1
+x2
] = 255 - dctClip
[dctClipOffset
+ pB
];
2293 // Read one scan from a progressive or non-interleaved JPEG stream.
2294 void DCTStream::readScan() {
2296 int x1
, y1
, dx1
, dy1
, x2
, y2
, y3
, cc
, i
;
2297 int h
, v
, horiz
, vert
, vSub
;
2301 if (scanInfo
.numComps
== 1) {
2302 for (cc
= 0; cc
< numComps
; ++cc
) {
2303 if (scanInfo
.comp
[cc
]) {
2307 dx1
= mcuWidth
/ compInfo
[cc
].hSample
;
2308 dy1
= mcuHeight
/ compInfo
[cc
].vSample
;
2314 for (y1
= 0; y1
< height
; y1
+= dy1
) {
2315 for (x1
= 0; x1
< width
; x1
+= dx1
) {
2317 // deal with restart marker
2318 if (restartInterval
> 0 && restartCtr
== 0) {
2320 if (c
!= restartMarker
) {
2321 error(getPos(), "Bad DCT data: incorrect restart marker");
2324 if (++restartMarker
== 0xd8) {
2325 restartMarker
= 0xd0;
2331 for (cc
= 0; cc
< numComps
; ++cc
) {
2332 if (!scanInfo
.comp
[cc
]) {
2336 h
= compInfo
[cc
].hSample
;
2337 v
= compInfo
[cc
].vSample
;
2338 horiz
= mcuWidth
/ h
;
2339 vert
= mcuHeight
/ v
;
2341 for (y2
= 0; y2
< dy1
; y2
+= vert
) {
2342 for (x2
= 0; x2
< dx1
; x2
+= horiz
) {
2344 // pull out the current values
2345 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2346 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2355 p1
+= bufWidth
* vSub
;
2358 // read one data unit
2360 if (!readProgressiveDataUnit(
2361 &dcHuffTables
[scanInfo
.dcHuffTable
[cc
]],
2362 &acHuffTables
[scanInfo
.acHuffTable
[cc
]],
2363 &compInfo
[cc
].prevDC
,
2368 if (!readDataUnit(&dcHuffTables
[scanInfo
.dcHuffTable
[cc
]],
2369 &acHuffTables
[scanInfo
.acHuffTable
[cc
]],
2370 &compInfo
[cc
].prevDC
,
2376 // add the data unit into frameBuf
2377 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2378 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2387 p1
+= bufWidth
* vSub
;
2397 // Read one data unit from a sequential JPEG stream.
2398 GBool
DCTStream::readDataUnit(DCTHuffTable
*dcHuffTable
,
2399 DCTHuffTable
*acHuffTable
,
2400 int *prevDC
, int data
[64]) {
2405 if ((size
= readHuffSym(dcHuffTable
)) == 9999) {
2409 if ((amp
= readAmp(size
)) == 9999) {
2415 data
[0] = *prevDC
+= amp
;
2416 for (i
= 1; i
< 64; ++i
) {
2422 while ((c
= readHuffSym(acHuffTable
)) == 0xf0 && run
< 0x30) {
2431 run
+= (c
>> 4) & 0x0f;
2433 amp
= readAmp(size
);
2447 // Read one data unit from a sequential JPEG stream.
2448 GBool
DCTStream::readProgressiveDataUnit(DCTHuffTable
*dcHuffTable
,
2449 DCTHuffTable
*acHuffTable
,
2450 int *prevDC
, int data
[64]) {
2451 int run
, size
, amp
, bit
, c
;
2454 // get the DC coefficient
2455 i
= scanInfo
.firstCoeff
;
2457 if (scanInfo
.ah
== 0) {
2458 if ((size
= readHuffSym(dcHuffTable
)) == 9999) {
2462 if ((amp
= readAmp(size
)) == 9999) {
2468 data
[0] += (*prevDC
+= amp
) << scanInfo
.al
;
2470 if ((bit
= readBit()) == 9999) {
2473 data
[0] += bit
<< scanInfo
.al
;
2477 if (scanInfo
.lastCoeff
== 0) {
2481 // check for an EOB run
2483 while (i
<= scanInfo
.lastCoeff
) {
2486 if ((bit
= readBit()) == EOF
) {
2490 data
[j
] += 1 << scanInfo
.al
;
2498 // read the AC coefficients
2499 while (i
<= scanInfo
.lastCoeff
) {
2500 if ((c
= readHuffSym(acHuffTable
)) == 9999) {
2512 if ((bit
= readBit()) == EOF
) {
2516 data
[j
] += 1 << scanInfo
.al
;
2522 } else if ((c
& 0x0f) == 0x00) {
2525 for (k
= 0; k
< j
; ++k
) {
2526 if ((bit
= readBit()) == EOF
) {
2529 eobRun
= (eobRun
<< 1) | bit
;
2532 while (i
<= scanInfo
.lastCoeff
) {
2535 if ((bit
= readBit()) == EOF
) {
2539 data
[j
] += 1 << scanInfo
.al
;
2546 // zero run and one AC coefficient
2548 run
= (c
>> 4) & 0x0f;
2550 if ((amp
= readAmp(size
)) == 9999) {
2556 while (data
[j
] != 0) {
2557 if ((bit
= readBit()) == EOF
) {
2561 data
[j
] += 1 << scanInfo
.al
;
2567 data
[j
] = amp
<< scanInfo
.al
;
2574 // Decode a progressive JPEG image.
2575 void DCTStream::decodeImage() {
2578 Gushort
*quantTable
;
2579 int pY
, pCb
, pCr
, pR
, pG
, pB
;
2580 int x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
, x5
, y5
, cc
, i
;
2581 int h
, v
, horiz
, vert
, hSub
, vSub
;
2584 for (y1
= 0; y1
< bufHeight
; y1
+= mcuHeight
) {
2585 for (x1
= 0; x1
< bufWidth
; x1
+= mcuWidth
) {
2586 for (cc
= 0; cc
< numComps
; ++cc
) {
2587 quantTable
= quantTables
[compInfo
[cc
].quantTable
];
2588 h
= compInfo
[cc
].hSample
;
2589 v
= compInfo
[cc
].vSample
;
2590 horiz
= mcuWidth
/ h
;
2591 vert
= mcuHeight
/ v
;
2594 for (y2
= 0; y2
< mcuHeight
; y2
+= vert
) {
2595 for (x2
= 0; x2
< mcuWidth
; x2
+= horiz
) {
2597 // pull out the coded data unit
2598 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2599 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2601 dataIn
[i
+1] = p1
[1];
2602 dataIn
[i
+2] = p1
[2];
2603 dataIn
[i
+3] = p1
[3];
2604 dataIn
[i
+4] = p1
[4];
2605 dataIn
[i
+5] = p1
[5];
2606 dataIn
[i
+6] = p1
[6];
2607 dataIn
[i
+7] = p1
[7];
2608 p1
+= bufWidth
* vSub
;
2612 transformDataUnit(quantTable
, dataIn
, dataOut
);
2614 // store back into frameBuf, doing replication for
2615 // subsampled components
2616 p1
= &frameBuf
[cc
][(y1
+y2
) * bufWidth
+ (x1
+x2
)];
2617 if (hSub
== 1 && vSub
== 1) {
2618 for (y3
= 0, i
= 0; y3
< 8; ++y3
, i
+= 8) {
2619 p1
[0] = dataOut
[i
] & 0xff;
2620 p1
[1] = dataOut
[i
+1] & 0xff;
2621 p1
[2] = dataOut
[i
+2] & 0xff;
2622 p1
[3] = dataOut
[i
+3] & 0xff;
2623 p1
[4] = dataOut
[i
+4] & 0xff;
2624 p1
[5] = dataOut
[i
+5] & 0xff;
2625 p1
[6] = dataOut
[i
+6] & 0xff;
2626 p1
[7] = dataOut
[i
+7] & 0xff;
2629 } else if (hSub
== 2 && vSub
== 2) {
2631 for (y3
= 0, i
= 0; y3
< 16; y3
+= 2, i
+= 8) {
2632 p1
[0] = p1
[1] = p2
[0] = p2
[1] = dataOut
[i
] & 0xff;
2633 p1
[2] = p1
[3] = p2
[2] = p2
[3] = dataOut
[i
+1] & 0xff;
2634 p1
[4] = p1
[5] = p2
[4] = p2
[5] = dataOut
[i
+2] & 0xff;
2635 p1
[6] = p1
[7] = p2
[6] = p2
[7] = dataOut
[i
+3] & 0xff;
2636 p1
[8] = p1
[9] = p2
[8] = p2
[9] = dataOut
[i
+4] & 0xff;
2637 p1
[10] = p1
[11] = p2
[10] = p2
[11] = dataOut
[i
+5] & 0xff;
2638 p1
[12] = p1
[13] = p2
[12] = p2
[13] = dataOut
[i
+6] & 0xff;
2639 p1
[14] = p1
[15] = p2
[14] = p2
[15] = dataOut
[i
+7] & 0xff;
2645 for (y3
= 0, y4
= 0; y3
< 8; ++y3
, y4
+= vSub
) {
2646 for (x3
= 0, x4
= 0; x3
< 8; ++x3
, x4
+= hSub
) {
2648 for (y5
= 0; y5
< vSub
; ++y5
) {
2649 for (x5
= 0; x5
< hSub
; ++x5
) {
2650 p2
[x5
] = dataOut
[i
] & 0xff;
2656 p1
+= bufWidth
* vSub
;
2663 // color space conversion
2665 // convert YCbCr to RGB
2666 if (numComps
== 3) {
2667 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2668 p0
= &frameBuf
[0][(y1
+y2
) * bufWidth
+ x1
];
2669 p1
= &frameBuf
[1][(y1
+y2
) * bufWidth
+ x1
];
2670 p2
= &frameBuf
[2][(y1
+y2
) * bufWidth
+ x1
];
2671 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2675 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2676 *p0
++ = dctClip
[dctClipOffset
+ pR
];
2677 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+
2679 *p1
++ = dctClip
[dctClipOffset
+ pG
];
2680 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2681 *p2
++ = dctClip
[dctClipOffset
+ pB
];
2684 // convert YCbCrK to CMYK (K is passed through unchanged)
2685 } else if (numComps
== 4) {
2686 for (y2
= 0; y2
< mcuHeight
; ++y2
) {
2687 p0
= &frameBuf
[0][(y1
+y2
) * bufWidth
+ x1
];
2688 p1
= &frameBuf
[1][(y1
+y2
) * bufWidth
+ x1
];
2689 p2
= &frameBuf
[2][(y1
+y2
) * bufWidth
+ x1
];
2690 for (x2
= 0; x2
< mcuWidth
; ++x2
) {
2694 pR
= ((pY
<< 16) + dctCrToR
* pCr
+ 32768) >> 16;
2695 *p0
++ = 255 - dctClip
[dctClipOffset
+ pR
];
2696 pG
= ((pY
<< 16) + dctCbToG
* pCb
+ dctCrToG
* pCr
+
2698 *p1
++ = 255 - dctClip
[dctClipOffset
+ pG
];
2699 pB
= ((pY
<< 16) + dctCbToB
* pCb
+ 32768) >> 16;
2700 *p2
++ = 255 - dctClip
[dctClipOffset
+ pB
];
2709 // Transform one data unit -- this performs the dequantization and
2710 // IDCT steps. This IDCT algorithm is taken from:
2711 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2712 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2713 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2715 // The stage numbers mentioned in the comments refer to Figure 1 in this
2717 void DCTStream::transformDataUnit(Gushort
*quantTable
,
2718 int dataIn
[64], Guchar dataOut
[64]) {
2719 int v0
, v1
, v2
, v3
, v4
, v5
, v6
, v7
, t
;
2724 for (i
= 0; i
< 64; ++i
) {
2725 dataIn
[i
] *= quantTable
[i
];
2728 // inverse DCT on rows
2729 for (i
= 0; i
< 64; i
+= 8) {
2732 // check for all-zero AC coefficients
2733 if (p
[1] == 0 && p
[2] == 0 && p
[3] == 0 &&
2734 p
[4] == 0 && p
[5] == 0 && p
[6] == 0 && p
[7] == 0) {
2735 t
= (dctSqrt2
* p
[0] + 512) >> 10;
2748 v0
= (dctSqrt2
* p
[0] + 128) >> 8;
2749 v1
= (dctSqrt2
* p
[4] + 128) >> 8;
2752 v4
= (dctSqrt1d2
* (p
[1] - p
[7]) + 128) >> 8;
2753 v7
= (dctSqrt1d2
* (p
[1] + p
[7]) + 128) >> 8;
2758 t
= (v0
- v1
+ 1) >> 1;
2759 v0
= (v0
+ v1
+ 1) >> 1;
2761 t
= (v2
* dctSin6
+ v3
* dctCos6
+ 128) >> 8;
2762 v2
= (v2
* dctCos6
- v3
* dctSin6
+ 128) >> 8;
2764 t
= (v4
- v6
+ 1) >> 1;
2765 v4
= (v4
+ v6
+ 1) >> 1;
2767 t
= (v7
+ v5
+ 1) >> 1;
2768 v5
= (v7
- v5
+ 1) >> 1;
2772 t
= (v0
- v3
+ 1) >> 1;
2773 v0
= (v0
+ v3
+ 1) >> 1;
2775 t
= (v1
- v2
+ 1) >> 1;
2776 v1
= (v1
+ v2
+ 1) >> 1;
2778 t
= (v4
* dctSin3
+ v7
* dctCos3
+ 2048) >> 12;
2779 v4
= (v4
* dctCos3
- v7
* dctSin3
+ 2048) >> 12;
2781 t
= (v5
* dctSin1
+ v6
* dctCos1
+ 2048) >> 12;
2782 v5
= (v5
* dctCos1
- v6
* dctSin1
+ 2048) >> 12;
2796 // inverse DCT on columns
2797 for (i
= 0; i
< 8; ++i
) {
2800 // check for all-zero AC coefficients
2801 if (p
[1*8] == 0 && p
[2*8] == 0 && p
[3*8] == 0 &&
2802 p
[4*8] == 0 && p
[5*8] == 0 && p
[6*8] == 0 && p
[7*8] == 0) {
2803 t
= (dctSqrt2
* dataIn
[i
+0] + 8192) >> 14;
2816 v0
= (dctSqrt2
* p
[0*8] + 2048) >> 12;
2817 v1
= (dctSqrt2
* p
[4*8] + 2048) >> 12;
2820 v4
= (dctSqrt1d2
* (p
[1*8] - p
[7*8]) + 2048) >> 12;
2821 v7
= (dctSqrt1d2
* (p
[1*8] + p
[7*8]) + 2048) >> 12;
2826 t
= (v0
- v1
+ 1) >> 1;
2827 v0
= (v0
+ v1
+ 1) >> 1;
2829 t
= (v2
* dctSin6
+ v3
* dctCos6
+ 2048) >> 12;
2830 v2
= (v2
* dctCos6
- v3
* dctSin6
+ 2048) >> 12;
2832 t
= (v4
- v6
+ 1) >> 1;
2833 v4
= (v4
+ v6
+ 1) >> 1;
2835 t
= (v7
+ v5
+ 1) >> 1;
2836 v5
= (v7
- v5
+ 1) >> 1;
2840 t
= (v0
- v3
+ 1) >> 1;
2841 v0
= (v0
+ v3
+ 1) >> 1;
2843 t
= (v1
- v2
+ 1) >> 1;
2844 v1
= (v1
+ v2
+ 1) >> 1;
2846 t
= (v4
* dctSin3
+ v7
* dctCos3
+ 2048) >> 12;
2847 v4
= (v4
* dctCos3
- v7
* dctSin3
+ 2048) >> 12;
2849 t
= (v5
* dctSin1
+ v6
* dctCos1
+ 2048) >> 12;
2850 v5
= (v5
* dctCos1
- v6
* dctSin1
+ 2048) >> 12;
2864 // convert to 8-bit integers
2865 for (i
= 0; i
< 64; ++i
) {
2866 dataOut
[i
] = dctClip
[dctClipOffset
+ 128 + ((dataIn
[i
] + 8) >> 4)];
2870 int DCTStream::readHuffSym(DCTHuffTable
*table
) {
2878 // add a bit to the code
2879 if ((bit
= readBit()) == EOF
)
2881 code
= (code
<< 1) + bit
;
2885 if (code
- table
->firstCode
[codeBits
] < table
->numCodes
[codeBits
]) {
2886 code
-= table
->firstCode
[codeBits
];
2887 return table
->sym
[table
->firstSym
[codeBits
] + code
];
2889 } while (codeBits
< 16);
2891 error(getPos(), "Bad Huffman code in DCT stream");
2895 int DCTStream::readAmp(int size
) {
2900 for (bits
= 0; bits
< size
; ++bits
) {
2901 if ((bit
= readBit()) == EOF
)
2903 amp
= (amp
<< 1) + bit
;
2905 if (amp
< (1 << (size
- 1)))
2906 amp
-= (1 << size
) - 1;
2910 int DCTStream::readBit() {
2914 if (inputBits
== 0) {
2915 if ((c
= str
->getChar()) == EOF
)
2919 c2
= str
->getChar();
2920 } while (c2
== 0xff);
2922 error(getPos(), "Bad DCT data: missing 00 after ff");
2929 bit
= (inputBuf
>> (inputBits
- 1)) & 1;
2934 GBool
DCTStream::readHeader() {
2945 case 0xc0: // SOF0 (sequential)
2946 case 0xc1: // SOF1 (extended sequential)
2947 if (!readBaselineSOF()) {
2951 case 0xc2: // SOF2 (progressive)
2952 if (!readProgressiveSOF()) {
2957 if (!readHuffmanTables()) {
2966 if (!readScanInfo()) {
2972 if (!readQuantTables()) {
2977 if (!readRestartInterval()) {
2982 if (!readJFIFMarker()) {
2987 if (!readAdobeMarker()) {
2992 error(getPos(), "Bad DCT header");
2995 // skip APPn / COM / etc.
2998 for (i
= 0; i
< n
; ++i
) {
3002 error(getPos(), "Unknown DCT marker <%02x>", c
);
3012 GBool
DCTStream::readBaselineSOF() {
3019 prec
= str
->getChar();
3022 numComps
= str
->getChar();
3023 if (numComps
<= 0 || numComps
> 4) {
3024 error(getPos(), "Bad number of components in DCT stream");
3029 error(getPos(), "Bad DCT precision %d", prec
);
3032 for (i
= 0; i
< numComps
; ++i
) {
3033 compInfo
[i
].id
= str
->getChar();
3035 compInfo
[i
].hSample
= (c
>> 4) & 0x0f;
3036 compInfo
[i
].vSample
= c
& 0x0f;
3037 compInfo
[i
].quantTable
= str
->getChar();
3039 progressive
= gFalse
;
3043 GBool
DCTStream::readProgressiveSOF() {
3050 prec
= str
->getChar();
3053 numComps
= str
->getChar();
3054 if (numComps
<= 0 || numComps
> 4) {
3055 error(getPos(), "Bad number of components in DCT stream");
3060 error(getPos(), "Bad DCT precision %d", prec
);
3063 for (i
= 0; i
< numComps
; ++i
) {
3064 compInfo
[i
].id
= str
->getChar();
3066 compInfo
[i
].hSample
= (c
>> 4) & 0x0f;
3067 compInfo
[i
].vSample
= c
& 0x0f;
3068 compInfo
[i
].quantTable
= str
->getChar();
3070 progressive
= gTrue
;
3074 GBool
DCTStream::readScanInfo() {
3079 length
= read16() - 2;
3080 scanInfo
.numComps
= str
->getChar();
3081 if (scanInfo
.numComps
<= 0 || scanInfo
.numComps
> 4) {
3082 error(getPos(), "Bad number of components in DCT stream");
3083 scanInfo
.numComps
= 0;
3087 if (length
!= 2 * scanInfo
.numComps
+ 3) {
3088 error(getPos(), "Bad DCT scan info block");
3091 interleaved
= scanInfo
.numComps
== numComps
;
3092 for (j
= 0; j
< numComps
; ++j
) {
3093 scanInfo
.comp
[j
] = gFalse
;
3095 for (i
= 0; i
< scanInfo
.numComps
; ++i
) {
3096 id
= str
->getChar();
3097 // some (broken) DCT streams reuse ID numbers, but at least they
3098 // keep the components in order, so we check compInfo[i] first to
3099 // work around the problem
3100 if (id
== compInfo
[i
].id
) {
3103 for (j
= 0; j
< numComps
; ++j
) {
3104 if (id
== compInfo
[j
].id
) {
3108 if (j
== numComps
) {
3109 error(getPos(), "Bad DCT component ID in scan info block");
3113 scanInfo
.comp
[j
] = gTrue
;
3115 scanInfo
.dcHuffTable
[j
] = (c
>> 4) & 0x0f;
3116 scanInfo
.acHuffTable
[j
] = c
& 0x0f;
3118 scanInfo
.firstCoeff
= str
->getChar();
3119 scanInfo
.lastCoeff
= str
->getChar();
3120 if (scanInfo
.firstCoeff
< 0 || scanInfo
.lastCoeff
> 63 ||
3121 scanInfo
.firstCoeff
> scanInfo
.lastCoeff
) {
3122 error(getPos(), "Bad DCT coefficient numbers in scan info block");
3126 scanInfo
.ah
= (c
>> 4) & 0x0f;
3127 scanInfo
.al
= c
& 0x0f;
3131 GBool
DCTStream::readQuantTables() {
3132 int length
, prec
, i
, index
;
3134 length
= read16() - 2;
3135 while (length
> 0) {
3136 index
= str
->getChar();
3137 prec
= (index
>> 4) & 0x0f;
3139 if (prec
> 1 || index
>= 4) {
3140 error(getPos(), "Bad DCT quantization table");
3143 if (index
== numQuantTables
) {
3144 numQuantTables
= index
+ 1;
3146 for (i
= 0; i
< 64; ++i
) {
3148 quantTables
[index
][dctZigZag
[i
]] = read16();
3150 quantTables
[index
][dctZigZag
[i
]] = str
->getChar();
3162 GBool
DCTStream::readHuffmanTables() {
3171 length
= read16() - 2;
3172 while (length
> 0) {
3173 index
= str
->getChar();
3175 if ((index
& 0x0f) >= 4) {
3176 error(getPos(), "Bad DCT Huffman table");
3181 if (index
>= numACHuffTables
)
3182 numACHuffTables
= index
+1;
3183 tbl
= &acHuffTables
[index
];
3186 if (index
>= numDCHuffTables
)
3187 numDCHuffTables
= index
+1;
3188 tbl
= &dcHuffTables
[index
];
3192 for (i
= 1; i
<= 16; ++i
) {
3194 tbl
->firstSym
[i
] = sym
;
3195 tbl
->firstCode
[i
] = code
;
3196 tbl
->numCodes
[i
] = c
;
3198 code
= (code
+ c
) << 1;
3201 for (i
= 0; i
< sym
; ++i
)
3202 tbl
->sym
[i
] = str
->getChar();
3208 GBool
DCTStream::readRestartInterval() {
3213 error(getPos(), "Bad DCT restart interval");
3216 restartInterval
= read16();
3220 GBool
DCTStream::readJFIFMarker() {
3228 for (i
= 0; i
< 5; ++i
) {
3229 if ((c
= str
->getChar()) == EOF
) {
3230 error(getPos(), "Bad DCT APP0 marker");
3236 if (!memcmp(buf
, "JFIF\0", 5)) {
3237 gotJFIFMarker
= gTrue
;
3240 while (length
> 0) {
3241 if (str
->getChar() == EOF
) {
3242 error(getPos(), "Bad DCT APP0 marker");
3250 GBool
DCTStream::readAdobeMarker() {
3259 for (i
= 0; i
< 12; ++i
) {
3260 if ((c
= str
->getChar()) == EOF
) {
3265 if (strncmp(buf
, "Adobe", 5)) {
3268 colorXform
= buf
[11];
3269 gotAdobeMarker
= gTrue
;
3270 for (i
= 14; i
< length
; ++i
) {
3271 if (str
->getChar() == EOF
) {
3278 error(getPos(), "Bad DCT Adobe APP14 marker");
3282 GBool
DCTStream::readTrailer() {
3286 if (c
!= 0xd9) { // EOI
3287 error(getPos(), "Bad DCT trailer");
3293 int DCTStream::readMarker() {
3299 } while (c
!= 0xff && c
!= EOF
);
3302 } while (c
== 0xff);
3303 } while (c
== 0x00);
3307 int DCTStream::read16() {
3310 if ((c1
= str
->getChar()) == EOF
)
3312 if ((c2
= str
->getChar()) == EOF
)
3314 return (c1
<< 8) + c2
;
3317 GString
*DCTStream::getPSFilter(int psLevel
, char *indent
) {
3323 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
3326 s
->append(indent
)->append("<< >> /DCTDecode filter\n");
3330 GBool
DCTStream::isBinary(GBool last
) {
3331 return str
->isBinary(gTrue
);
3334 //------------------------------------------------------------------------
3336 //------------------------------------------------------------------------
3338 int FlateStream::codeLenCodeMap
[flateMaxCodeLenCodes
] = {
3339 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3342 FlateDecode
FlateStream::lengthDecode
[flateMaxLitCodes
-257] = {
3376 FlateDecode
FlateStream::distDecode
[flateMaxDistCodes
] = {
3409 static FlateCode flateFixedLitCodeTabCodes
[512] = {
3924 FlateHuffmanTab
FlateStream::fixedLitCodeTab
= {
3925 flateFixedLitCodeTabCodes
, 9
3928 static FlateCode flateFixedDistCodeTabCodes
[32] = {
3963 FlateHuffmanTab
FlateStream::fixedDistCodeTab
= {
3964 flateFixedDistCodeTabCodes
, 5
3967 FlateStream::FlateStream(Stream
*strA
, int predictor
, int columns
,
3968 int colors
, int bits
):
3969 FilterStream(strA
) {
3970 if (predictor
!= 1) {
3971 pred
= new StreamPredictor(this, predictor
, columns
, colors
, bits
);
3972 if (!pred
->isOk()) {
3979 litCodeTab
.codes
= NULL
;
3980 distCodeTab
.codes
= NULL
;
3983 FlateStream::~FlateStream() {
3984 if (litCodeTab
.codes
!= fixedLitCodeTab
.codes
) {
3985 gfree(litCodeTab
.codes
);
3987 if (distCodeTab
.codes
!= fixedDistCodeTab
.codes
) {
3988 gfree(distCodeTab
.codes
);
3996 void FlateStream::reset() {
4003 compressedBlock
= gFalse
;
4010 //~ need to look at window size?
4011 endOfBlock
= eof
= gTrue
;
4012 cmf
= str
->getChar();
4013 flg
= str
->getChar();
4014 if (cmf
== EOF
|| flg
== EOF
)
4016 if ((cmf
& 0x0f) != 0x08) {
4017 error(getPos(), "Unknown compression method in flate stream");
4020 if ((((cmf
<< 8) + flg
) % 31) != 0) {
4021 error(getPos(), "Bad FCHECK in flate stream");
4025 error(getPos(), "FDICT bit set in flate stream");
4032 int FlateStream::getChar() {
4036 return pred
->getChar();
4038 while (remain
== 0) {
4039 if (endOfBlock
&& eof
)
4044 index
= (index
+ 1) & flateMask
;
4049 int FlateStream::lookChar() {
4053 return pred
->lookChar();
4055 while (remain
== 0) {
4056 if (endOfBlock
&& eof
)
4064 int FlateStream::getRawChar() {
4067 while (remain
== 0) {
4068 if (endOfBlock
&& eof
)
4073 index
= (index
+ 1) & flateMask
;
4078 GString
*FlateStream::getPSFilter(int psLevel
, char *indent
) {
4081 if (psLevel
< 3 || pred
) {
4084 if (!(s
= str
->getPSFilter(psLevel
, indent
))) {
4087 s
->append(indent
)->append("<< >> /FlateDecode filter\n");
4091 GBool
FlateStream::isBinary(GBool last
) {
4092 return str
->isBinary(gTrue
);
4095 void FlateStream::readSome() {
4106 if (compressedBlock
) {
4107 if ((code1
= getHuffmanCodeWord(&litCodeTab
)) == EOF
)
4112 } else if (code1
== 256) {
4117 code2
= lengthDecode
[code1
].bits
;
4118 if (code2
> 0 && (code2
= getCodeWord(code2
)) == EOF
)
4120 len
= lengthDecode
[code1
].first
+ code2
;
4121 if ((code1
= getHuffmanCodeWord(&distCodeTab
)) == EOF
)
4123 code2
= distDecode
[code1
].bits
;
4124 if (code2
> 0 && (code2
= getCodeWord(code2
)) == EOF
)
4126 dist
= distDecode
[code1
].first
+ code2
;
4128 j
= (index
- dist
) & flateMask
;
4129 for (k
= 0; k
< len
; ++k
) {
4131 i
= (i
+ 1) & flateMask
;
4132 j
= (j
+ 1) & flateMask
;
4138 len
= (blockLen
< flateWindow
) ? blockLen
: flateWindow
;
4139 for (i
= 0, j
= index
; i
< len
; ++i
, j
= (j
+ 1) & flateMask
) {
4140 if ((c
= str
->getChar()) == EOF
) {
4141 endOfBlock
= eof
= gTrue
;
4155 error(getPos(), "Unexpected end of file in flate stream");
4156 endOfBlock
= eof
= gTrue
;
4160 GBool
FlateStream::startBlock() {
4165 // free the code tables from the previous block
4166 if (litCodeTab
.codes
!= fixedLitCodeTab
.codes
) {
4167 gfree(litCodeTab
.codes
);
4169 litCodeTab
.codes
= NULL
;
4170 if (distCodeTab
.codes
!= fixedDistCodeTab
.codes
) {
4171 gfree(distCodeTab
.codes
);
4173 distCodeTab
.codes
= NULL
;
4175 // read block header
4176 blockHdr
= getCodeWord(3);
4181 // uncompressed block
4182 if (blockHdr
== 0) {
4183 compressedBlock
= gFalse
;
4184 if ((c
= str
->getChar()) == EOF
)
4186 blockLen
= c
& 0xff;
4187 if ((c
= str
->getChar()) == EOF
)
4189 blockLen
|= (c
& 0xff) << 8;
4190 if ((c
= str
->getChar()) == EOF
)
4193 if ((c
= str
->getChar()) == EOF
)
4195 check
|= (c
& 0xff) << 8;
4196 if (check
!= (~blockLen
& 0xffff))
4197 error(getPos(), "Bad uncompressed block length in flate stream");
4201 // compressed block with fixed codes
4202 } else if (blockHdr
== 1) {
4203 compressedBlock
= gTrue
;
4206 // compressed block with dynamic codes
4207 } else if (blockHdr
== 2) {
4208 compressedBlock
= gTrue
;
4209 if (!readDynamicCodes()) {
4213 // unknown block type
4218 endOfBlock
= gFalse
;
4222 error(getPos(), "Bad block header in flate stream");
4223 endOfBlock
= eof
= gTrue
;
4227 void FlateStream::loadFixedCodes() {
4228 litCodeTab
.codes
= fixedLitCodeTab
.codes
;
4229 litCodeTab
.maxLen
= fixedLitCodeTab
.maxLen
;
4230 distCodeTab
.codes
= fixedDistCodeTab
.codes
;
4231 distCodeTab
.maxLen
= fixedDistCodeTab
.maxLen
;
4234 GBool
FlateStream::readDynamicCodes() {
4235 int numCodeLenCodes
;
4238 int codeLenCodeLengths
[flateMaxCodeLenCodes
];
4239 FlateHuffmanTab codeLenCodeTab
;
4240 int len
, repeat
, code
;
4243 codeLenCodeTab
.codes
= NULL
;
4246 if ((numLitCodes
= getCodeWord(5)) == EOF
) {
4250 if ((numDistCodes
= getCodeWord(5)) == EOF
) {
4254 if ((numCodeLenCodes
= getCodeWord(4)) == EOF
) {
4257 numCodeLenCodes
+= 4;
4258 if (numLitCodes
> flateMaxLitCodes
||
4259 numDistCodes
> flateMaxDistCodes
||
4260 numCodeLenCodes
> flateMaxCodeLenCodes
) {
4264 // build the code length code table
4265 for (i
= 0; i
< flateMaxCodeLenCodes
; ++i
) {
4266 codeLenCodeLengths
[i
] = 0;
4268 for (i
= 0; i
< numCodeLenCodes
; ++i
) {
4269 if ((codeLenCodeLengths
[codeLenCodeMap
[i
]] = getCodeWord(3)) == -1) {
4273 compHuffmanCodes(codeLenCodeLengths
, flateMaxCodeLenCodes
, &codeLenCodeTab
);
4275 // build the literal and distance code tables
4279 while (i
< numLitCodes
+ numDistCodes
) {
4280 if ((code
= getHuffmanCodeWord(&codeLenCodeTab
)) == EOF
) {
4284 if ((repeat
= getCodeWord(2)) == EOF
) {
4288 if (i
+ repeat
> numLitCodes
+ numDistCodes
) {
4291 for (; repeat
> 0; --repeat
) {
4292 codeLengths
[i
++] = len
;
4294 } else if (code
== 17) {
4295 if ((repeat
= getCodeWord(3)) == EOF
) {
4299 if (i
+ repeat
> numLitCodes
+ numDistCodes
) {
4303 for (; repeat
> 0; --repeat
) {
4304 codeLengths
[i
++] = 0;
4306 } else if (code
== 18) {
4307 if ((repeat
= getCodeWord(7)) == EOF
) {
4311 if (i
+ repeat
> numLitCodes
+ numDistCodes
) {
4315 for (; repeat
> 0; --repeat
) {
4316 codeLengths
[i
++] = 0;
4319 codeLengths
[i
++] = len
= code
;
4322 compHuffmanCodes(codeLengths
, numLitCodes
, &litCodeTab
);
4323 compHuffmanCodes(codeLengths
+ numLitCodes
, numDistCodes
, &distCodeTab
);
4325 gfree(codeLenCodeTab
.codes
);
4329 error(getPos(), "Bad dynamic code table in flate stream");
4330 gfree(codeLenCodeTab
.codes
);
4334 // Convert an array <lengths> of <n> lengths, in value order, into a
4335 // Huffman code lookup table.
4336 void FlateStream::compHuffmanCodes(int *lengths
, int n
, FlateHuffmanTab
*tab
) {
4337 int tabSize
, len
, code
, code2
, skip
, val
, i
, t
;
4339 // find max code length
4341 for (val
= 0; val
< n
; ++val
) {
4342 if (lengths
[val
] > tab
->maxLen
) {
4343 tab
->maxLen
= lengths
[val
];
4347 // allocate the table
4348 tabSize
= 1 << tab
->maxLen
;
4349 tab
->codes
= (FlateCode
*)gmallocn(tabSize
, sizeof(FlateCode
));
4352 for (i
= 0; i
< tabSize
; ++i
) {
4353 tab
->codes
[i
].len
= 0;
4354 tab
->codes
[i
].val
= 0;
4358 for (len
= 1, code
= 0, skip
= 2;
4360 ++len
, code
<<= 1, skip
<<= 1) {
4361 for (val
= 0; val
< n
; ++val
) {
4362 if (lengths
[val
] == len
) {
4364 // bit-reverse the code
4367 for (i
= 0; i
< len
; ++i
) {
4368 code2
= (code2
<< 1) | (t
& 1);
4372 // fill in the table entries
4373 for (i
= code2
; i
< tabSize
; i
+= skip
) {
4374 tab
->codes
[i
].len
= (Gushort
)len
;
4375 tab
->codes
[i
].val
= (Gushort
)val
;
4384 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab
*tab
) {
4388 while (codeSize
< tab
->maxLen
) {
4389 if ((c
= str
->getChar()) == EOF
) {
4392 codeBuf
|= (c
& 0xff) << codeSize
;
4395 code
= &tab
->codes
[codeBuf
& ((1 << tab
->maxLen
) - 1)];
4396 if (codeSize
== 0 || codeSize
< code
->len
|| code
->len
== 0) {
4399 codeBuf
>>= code
->len
;
4400 codeSize
-= code
->len
;
4401 return (int)code
->val
;
4404 int FlateStream::getCodeWord(int bits
) {
4407 while (codeSize
< bits
) {
4408 if ((c
= str
->getChar()) == EOF
)
4410 codeBuf
|= (c
& 0xff) << codeSize
;
4413 c
= codeBuf
& ((1 << bits
) - 1);
4419 //------------------------------------------------------------------------
4421 //------------------------------------------------------------------------
4423 EOFStream::EOFStream(Stream
*strA
):
4424 FilterStream(strA
) {
4427 EOFStream::~EOFStream() {
4431 //------------------------------------------------------------------------
4432 // FixedLengthEncoder
4433 //------------------------------------------------------------------------
4435 FixedLengthEncoder::FixedLengthEncoder(Stream
*strA
, int lengthA
):
4436 FilterStream(strA
) {
4441 FixedLengthEncoder::~FixedLengthEncoder() {
4442 if (str
->isEncoder())
4446 void FixedLengthEncoder::reset() {
4451 int FixedLengthEncoder::getChar() {
4452 if (length
>= 0 && count
>= length
)
4455 return str
->getChar();
4458 int FixedLengthEncoder::lookChar() {
4459 if (length
>= 0 && count
>= length
)
4461 return str
->getChar();
4464 GBool
FixedLengthEncoder::isBinary(GBool last
) {
4465 return str
->isBinary(gTrue
);
4468 //------------------------------------------------------------------------
4470 //------------------------------------------------------------------------
4472 ASCIIHexEncoder::ASCIIHexEncoder(Stream
*strA
):
4473 FilterStream(strA
) {
4474 bufPtr
= bufEnd
= buf
;
4479 ASCIIHexEncoder::~ASCIIHexEncoder() {
4480 if (str
->isEncoder()) {
4485 void ASCIIHexEncoder::reset() {
4487 bufPtr
= bufEnd
= buf
;
4492 GBool
ASCIIHexEncoder::fillBuf() {
4493 static char *hex
= "0123456789abcdef";
4499 bufPtr
= bufEnd
= buf
;
4500 if ((c
= str
->getChar()) == EOF
) {
4504 if (lineLen
>= 64) {
4508 *bufEnd
++ = hex
[(c
>> 4) & 0x0f];
4509 *bufEnd
++ = hex
[c
& 0x0f];
4515 //------------------------------------------------------------------------
4517 //------------------------------------------------------------------------
4519 ASCII85Encoder::ASCII85Encoder(Stream
*strA
):
4520 FilterStream(strA
) {
4521 bufPtr
= bufEnd
= buf
;
4526 ASCII85Encoder::~ASCII85Encoder() {
4527 if (str
->isEncoder())
4531 void ASCII85Encoder::reset() {
4533 bufPtr
= bufEnd
= buf
;
4538 GBool
ASCII85Encoder::fillBuf() {
4547 for (n
= 0; n
< 4; ++n
) {
4548 if ((c
= str
->getChar()) == EOF
)
4552 bufPtr
= bufEnd
= buf
;
4554 if (n
== 4 && t
== 0) {
4556 if (++lineLen
== 65) {
4563 for (i
= 4; i
>= 0; --i
) {
4564 buf1
[i
] = (char)(t
% 85 + 0x21);
4567 for (i
= 0; i
<= n
; ++i
) {
4568 *bufEnd
++ = buf1
[i
];
4569 if (++lineLen
== 65) {
4581 return bufPtr
< bufEnd
;
4584 //------------------------------------------------------------------------
4586 //------------------------------------------------------------------------
4588 RunLengthEncoder::RunLengthEncoder(Stream
*strA
):
4589 FilterStream(strA
) {
4590 bufPtr
= bufEnd
= nextEnd
= buf
;
4594 RunLengthEncoder::~RunLengthEncoder() {
4595 if (str
->isEncoder())
4599 void RunLengthEncoder::reset() {
4601 bufPtr
= bufEnd
= nextEnd
= buf
;
4606 // When fillBuf finishes, buf[] looks like this:
4607 // +-----+--------------+-----------------+--
4608 // + tag | ... data ... | next 0, 1, or 2 |
4609 // +-----+--------------+-----------------+--
4611 // bufPtr bufEnd nextEnd
4613 GBool
RunLengthEncoder::fillBuf() {
4622 if (nextEnd
< bufEnd
+ 1) {
4623 if ((c1
= str
->getChar()) == EOF
) {
4628 c1
= bufEnd
[0] & 0xff;
4630 if (nextEnd
< bufEnd
+ 2) {
4631 if ((c2
= str
->getChar()) == EOF
) {
4640 c2
= bufEnd
[1] & 0xff;
4644 c
= 0; // make gcc happy
4647 while (n
< 128 && (c
= str
->getChar()) == c1
)
4649 buf
[0] = (char)(257 - n
);
4654 } else if (n
< 128) {
4661 // get up to 128 chars
4667 if ((c
= str
->getChar()) == EOF
) {
4673 if (buf
[n
] == buf
[n
-1])
4676 if (buf
[n
] == buf
[n
-1]) {
4677 buf
[0] = (char)(n
-2-1);
4679 nextEnd
= &buf
[n
+1];
4681 buf
[0] = (char)(n
-1);
4682 bufEnd
= nextEnd
= &buf
[n
+1];