26#include "xpdf_config.h"
33#include "JBIG2Stream.h"
34#include "Stream-CCITT.h"
37static GBool setDJSYSFLAGS = gFalse;
62int Stream::getRawChar() {
63 error(-1,
"Internal: called getRawChar() on non-predictor stream");
67char *Stream::getLine(
char *buf,
int size) {
71 if (lookChar() == EOF)
73 for (i = 0; i < size - 1; ++i) {
75 if (c == EOF || c ==
'\n')
78 if ((c = lookChar()) ==
'\n')
88GString *Stream::getPSFilter(
const char *) {
92Stream *Stream::addFilters(Object *dict) {
94 Object params, params2;
99 dict->dictLookup(
"Filter", &obj);
102 dict->dictLookup(
"F", &obj);
104 dict->dictLookup(
"DecodeParms", ¶ms);
105 if (params.isNull()) {
107 dict->dictLookup(
"DP", ¶ms);
110 str = makeFilter(obj.getName(), str, ¶ms);
111 }
else if (obj.isArray()) {
112 for (i = 0; i < obj.arrayGetLength(); ++i) {
113 obj.arrayGet(i, &obj2);
114 if (params.isArray())
115 params.arrayGet(i, ¶ms2);
119 str = makeFilter(obj2.getName(), str, ¶ms2);
121 error(getPos(),
"Bad filter name");
122 str =
new EOFStream(str);
127 }
else if (!obj.isNull()) {
128 error(getPos(),
"Bad 'Filter' attribute in stream");
136Stream *Stream::makeFilter(
const char *name, Stream *str, Object *params) {
142 GBool endOfLine, byteAlign, endOfBlock, black;
146 if (!strcmp(name,
"ASCIIHexDecode") || !strcmp(name,
"AHx")) {
147 str =
new ASCIIHexStream(str);
148 }
else if (!strcmp(name,
"ASCII85Decode") || !strcmp(name,
"A85")) {
149 str =
new ASCII85Stream(str);
150 }
else if (!strcmp(name,
"LZWDecode") || !strcmp(name,
"LZW")) {
156 if (params->isDict()) {
157 params->dictLookup(
"Predictor", &obj);
161 params->dictLookup(
"Columns", &obj);
163 columns = obj.getInt();
165 params->dictLookup(
"Colors", &obj);
167 colors = obj.getInt();
169 params->dictLookup(
"BitsPerComponent", &obj);
173 params->dictLookup(
"EarlyChange", &obj);
175 early = obj.getInt();
178 str =
new LZWStream(str, pred, columns, colors, bits, early);
179 }
else if (!strcmp(name,
"RunLengthDecode") || !strcmp(name,
"RL")) {
180 str =
new RunLengthStream(str);
181 }
else if (!strcmp(name,
"CCITTFaxDecode") || !strcmp(name,
"CCF")) {
189 if (params->isDict()) {
190 params->dictLookup(
"K", &obj);
192 encoding = obj.getInt();
195 params->dictLookup(
"EndOfLine", &obj);
197 endOfLine = obj.getBool();
200 params->dictLookup(
"EncodedByteAlign", &obj);
202 byteAlign = obj.getBool();
205 params->dictLookup(
"Columns", &obj);
207 columns = obj.getInt();
210 params->dictLookup(
"Rows", &obj);
215 params->dictLookup(
"EndOfBlock", &obj);
217 endOfBlock = obj.getBool();
220 params->dictLookup(
"BlackIs1", &obj);
222 black = obj.getBool();
226 str =
new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
227 columns, rows, endOfBlock, black);
228 }
else if (!strcmp(name,
"DCTDecode") || !strcmp(name,
"DCT")) {
229 str =
new DCTStream(str);
230 }
else if (!strcmp(name,
"FlateDecode") || !strcmp(name,
"Fl")) {
235 if (params->isDict()) {
236 params->dictLookup(
"Predictor", &obj);
240 params->dictLookup(
"Columns", &obj);
242 columns = obj.getInt();
244 params->dictLookup(
"Colors", &obj);
246 colors = obj.getInt();
248 params->dictLookup(
"BitsPerComponent", &obj);
253 str =
new FlateStream(str, pred, columns, colors, bits);
254 }
else if (!strcmp(name,
"JBIG2Decode")) {
255 if (params->isDict()) {
256 params->dictLookup(
"JBIG2Globals", &globals);
258 str =
new JBIG2Stream(str, &globals);
261 error(getPos(),
"Unknown filter '%s'", name);
262 str =
new EOFStream(str);
271BaseStream::BaseStream(Object *dictA) {
278BaseStream::~BaseStream() {
287void BaseStream::doDecryption(Guchar *fileKey,
int keyLength,
288 int objNum,
int objGen) {
289 decrypt =
new Decrypt(fileKey, keyLength, objNum, objGen);
297FilterStream::FilterStream(Stream *strA) {
301FilterStream::~FilterStream() {
304void FilterStream::close() {
308void FilterStream::setPos(Guint ,
int ) {
309 error(-1,
"Internal: called setPos() on FilterStream");
316ImageStream::ImageStream(Stream *strA,
int widthA,
int nCompsA,
int nBitsA) {
324 nVals = width * nComps;
326 imgLineSize = (nVals + 7) & ~7;
330 imgLine = (Guchar *)gmalloc(imgLineSize *
sizeof(Guchar));
334ImageStream::~ImageStream() {
338void ImageStream::reset() {
342GBool ImageStream::getPixel(Guchar *pix) {
345 if (imgIdx >= nVals) {
349 for (i = 0; i < nComps; ++i) {
350 pix[i] = imgLine[imgIdx++];
355Guchar *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);
393void ImageStream::skipLine() {
396 n = (nVals * nBits + 7) >> 3;
397 for (i = 0; i < n; ++i) {
406StreamPredictor::StreamPredictor(Stream *strA,
int predictorA,
407 int widthA,
int nCompsA,
int nBitsA) {
409 predictor = predictorA;
416 nVals = width * nComps;
417 pixBytes = (nComps * nBits + 7) >> 3;
418 rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
419 if (width <= 0 || nComps <= 0 || nBits <= 0 ||
422 width >= INT_MAX / nComps ||
423 nVals >= (INT_MAX - 7) / nBits)
426 predLine = (Guchar *)gmalloc(rowBytes);
427 memset(predLine, 0, rowBytes);
433StreamPredictor::~StreamPredictor() {
437int StreamPredictor::lookChar() {
438 if (predIdx >= rowBytes) {
439 if (!getNextLine()) {
443 return predLine[predIdx];
446int StreamPredictor::getChar() {
447 if (predIdx >= rowBytes) {
448 if (!getNextLine()) {
452 return predLine[predIdx++];
455GBool StreamPredictor::getNextLine() {
458 int left, up, upLeft, p, pa, pb, pc;
460 Gulong inBuf, outBuf, bitMask;
465 if (predictor == 15) {
466 if ((curPred = str->getRawChar()) == EOF) {
475 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
476 for (i = pixBytes; i < rowBytes; ++i) {
477 upLeftBuf[3] = upLeftBuf[2];
478 upLeftBuf[2] = upLeftBuf[1];
479 upLeftBuf[1] = upLeftBuf[0];
480 upLeftBuf[0] = predLine[i];
481 if ((c = str->getRawChar()) == EOF) {
486 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
489 predLine[i] = predLine[i] + (Guchar)c;
492 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
496 left = predLine[i - pixBytes];
498 upLeft = upLeftBuf[pixBytes];
499 p = left + up - upLeft;
500 if ((pa = p - left) < 0)
502 if ((pb = p - up) < 0)
504 if ((pc = p - upLeft) < 0)
506 if (pa <= pb && pa <= pc)
507 predLine[i] = left + (Guchar)c;
509 predLine[i] = up + (Guchar)c;
511 predLine[i] = upLeft + (Guchar)c;
515 predLine[i] = (Guchar)c;
522 if (predictor == 2) {
524 inBuf = predLine[pixBytes - 1];
525 for (i = pixBytes; i < rowBytes; i += 8) {
527 inBuf = (inBuf << 8) | predLine[i];
528 predLine[i] ^= inBuf >> nComps;
530 }
else if (nBits == 8) {
531 for (i = pixBytes; i < rowBytes; ++i) {
532 predLine[i] += predLine[i - nComps];
535 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
536 bitMask = (1 << nBits) - 1;
538 inBits = outBits = 0;
540 for (i = 0; i < nVals; ++i) {
541 if (inBits < nBits) {
542 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
545 upLeftBuf[3] = upLeftBuf[2];
546 upLeftBuf[2] = upLeftBuf[1];
547 upLeftBuf[1] = upLeftBuf[0];
548 upLeftBuf[0] = (upLeftBuf[nComps] +
549 (inBuf >> (inBits - nBits))) & bitMask;
550 outBuf = (outBuf << nBits) | upLeftBuf[0];
554 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
558 predLine[k++] = (Guchar)(outBuf << (8 - outBits));
573FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
574 Guint lengthA, Object *dictA):
580 bufPtr = bufEnd = buf;
586FileStream::~FileStream() {
590Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
591 Guint lengthA, Object *dictA) {
592 return new FileStream(f, startA, limitedA, lengthA, dictA);
595void FileStream::reset() {
597 savePos = (Guint)ftello(f);
598 fseeko(f, start, SEEK_SET);
599#elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
600 savePos = (Guint)ftell64(f);
601 fseek64(f, start, SEEK_SET);
603 savePos = (Guint)ftell(f);
604 fseek(f, start, SEEK_SET);
607 bufPtr = bufEnd = buf;
615void FileStream::close() {
618 fseeko(f, savePos, SEEK_SET);
619#elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
620 fseek64(f, savePos, SEEK_SET);
622 fseek(f, savePos, SEEK_SET);
628GBool FileStream::fillBuf() {
634 bufPos += bufEnd - buf;
635 bufPtr = bufEnd = buf;
636 if (limited && bufPos >= start + length) {
639 if (limited && bufPos + fileStreamBufSize > start + length) {
640 n = start + length - bufPos;
642 n = fileStreamBufSize;
644 n = fread(buf, 1, n, f);
646 if (bufPtr >= bufEnd) {
651 for (p = buf; p < bufEnd; ++p) {
652 *p = (char)decrypt->decryptByte((Guchar)*p);
659void FileStream::setPos(Guint pos,
int dir) {
664 fseeko(f, pos, SEEK_SET);
665#elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
666 fseek64(f, pos, SEEK_SET);
668 fseek(f, pos, SEEK_SET);
673 fseeko(f, 0, SEEK_END);
674 size = (Guint)ftello(f);
675#elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
676 fseek64(f, 0, SEEK_END);
677 size = (Guint)ftell64(f);
679 fseek(f, 0, SEEK_END);
680 size = (Guint)ftell(f);
689 fseeko(f, -(
int)pos, SEEK_END);
690 bufPos = (Guint)ftello(f);
691#elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
692 fseek64(f, -(
int)pos, SEEK_END);
693 bufPos = (Guint)ftell64(f);
695 fseek(f, -(
int)pos, SEEK_END);
696 bufPos = (Guint)ftell(f);
699 bufPtr = bufEnd = buf;
702void FileStream::moveStart(
int delta) {
704 bufPtr = bufEnd = buf;
712MemStream::MemStream(
char *bufA, Guint lengthA, Object *dictA):
717 bufEnd = buf + length;
721MemStream::~MemStream() {
727Stream *MemStream::makeSubStream(Guint start, GBool limited,
728 Guint lengthA, Object *dictA) {
731 if (!limited || start + lengthA > length) {
732 newLength = length - start;
736 return new MemStream(buf + start, newLength, dictA);
739void MemStream::reset() {
748void MemStream::close() {
751void MemStream::setPos(Guint pos,
int dir) {
762 bufPtr = bufEnd - pos;
767void MemStream::moveStart(
int delta) {
773void MemStream::doDecryption(Guchar *fileKey,
int keyLength,
774 int objNum,
int objGen) {
778 this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
780 newBuf = (
char *)gmalloc(bufEnd - buf);
781 for (p = buf, q = newBuf; p < bufEnd; ++p, ++q) {
782 *q = (char)decrypt->decryptByte((Guchar)*p);
784 bufEnd = newBuf + (bufEnd - buf);
785 bufPtr = newBuf + (bufPtr - buf);
796EmbedStream::EmbedStream(Stream *strA, Object *dictA):
801EmbedStream::~EmbedStream() {
804Stream *EmbedStream::makeSubStream(Guint , GBool ,
806 error(-1,
"Internal: called makeSubStream() on EmbedStream");
810void EmbedStream::setPos(Guint ,
int ) {
811 error(-1,
"Internal: called setPos() on EmbedStream");
814Guint EmbedStream::getStart() {
815 error(-1,
"Internal: called getStart() on EmbedStream");
819void EmbedStream::moveStart(
int ) {
820 error(-1,
"Internal: called moveStart() on EmbedStream");
827ASCIIHexStream::ASCIIHexStream(Stream *strA):
833ASCIIHexStream::~ASCIIHexStream() {
837void ASCIIHexStream::reset() {
843int ASCIIHexStream::lookChar() {
854 }
while (isspace(c1));
862 }
while (isspace(c2));
867 if (c1 >=
'0' && c1 <=
'9') {
869 }
else if (c1 >=
'A' && c1 <=
'F') {
870 x = (c1 -
'A' + 10) << 4;
871 }
else if (c1 >=
'a' && c1 <=
'f') {
872 x = (c1 -
'a' + 10) << 4;
873 }
else if (c1 == EOF) {
877 error(getPos(),
"Illegal character <%02x> in ASCIIHex stream", c1);
880 if (c2 >=
'0' && c2 <=
'9') {
882 }
else if (c2 >=
'A' && c2 <=
'F') {
884 }
else if (c2 >=
'a' && c2 <=
'f') {
886 }
else if (c2 == EOF) {
890 error(getPos(),
"Illegal character <%02x> in ASCIIHex stream", c2);
896GString *ASCIIHexStream::getPSFilter(
const char *indent) {
899 if (!(s = str->getPSFilter(indent))) {
902 s->append(indent)->append(
"/ASCIIHexDecode filter\n");
906GBool ASCIIHexStream::isBinary(GBool ) {
907 return str->isBinary(gFalse);
914ASCII85Stream::ASCII85Stream(Stream *strA):
920ASCII85Stream::~ASCII85Stream() {
924void ASCII85Stream::reset() {
930int ASCII85Stream::lookChar() {
939 c[0] = str->getChar();
940 }
while (c[0] ==
'\n' || c[0] ==
'\r');
941 if (c[0] ==
'~' || c[0] == EOF) {
945 }
else if (c[0] ==
'z') {
946 b[0] = b[1] = b[2] = b[3] = 0;
949 for (k = 1; k < 5; ++k) {
951 c[k] = str->getChar();
952 }
while (c[k] ==
'\n' || c[k] ==
'\r');
953 if (c[k] ==
'~' || c[k] == EOF)
957 if (k < 5 && (c[k] ==
'~' || c[k] == EOF)) {
958 for (++k; k < 5; ++k)
963 for (k = 0; k < 5; ++k)
964 t = t * 85 + (c[k] - 0x21);
965 for (k = 3; k >= 0; --k) {
966 b[k] = (int)(t & 0xff);
974GString *ASCII85Stream::getPSFilter(
const char *indent) {
977 if (!(s = str->getPSFilter(indent))) {
980 s->append(indent)->append(
"/ASCII85Decode filter\n");
984GBool ASCII85Stream::isBinary(GBool ) {
985 return str->isBinary(gFalse);
992LZWStream::LZWStream(Stream *strA,
int predictor,
int columns,
int colors,
993 int bits,
int earlyA):
995 if (predictor != 1) {
996 pred =
new StreamPredictor(
this, predictor, columns, colors, bits);
997 if ( !pred->isOk()) {
1010LZWStream::~LZWStream() {
1017int LZWStream::getChar() {
1019 return pred->getChar();
1024 if (seqIndex >= seqLength) {
1025 if (!processNextCode()) {
1029 return seqBuf[seqIndex++];
1032int LZWStream::lookChar() {
1034 return pred->lookChar();
1039 if (seqIndex >= seqLength) {
1040 if (!processNextCode()) {
1044 return seqBuf[seqIndex];
1047int LZWStream::getRawChar() {
1051 if (seqIndex >= seqLength) {
1052 if (!processNextCode()) {
1056 return seqBuf[seqIndex++];
1059void LZWStream::reset() {
1066GBool LZWStream::processNextCode() {
1079 if (code == EOF || code == 257) {
1087 if (nextCode >= 4097) {
1088 error(getPos(),
"Bad LZW stream - expected clear-table code");
1093 nextLength = seqLength + 1;
1097 }
else if (code < nextCode) {
1098 seqLength = table[code].length;
1099 for (i = seqLength - 1, j = code; i > 0; --i) {
1100 seqBuf[i] = table[j].tail;
1104 }
else if (code == nextCode) {
1105 seqBuf[seqLength] = newChar;
1108 error(getPos(),
"Bad LZW stream - unexpected code");
1112 newChar = seqBuf[0];
1116 table[nextCode].length = nextLength;
1117 table[nextCode].head = prevCode;
1118 table[nextCode].tail = newChar;
1120 if (nextCode + early == 512)
1122 else if (nextCode + early == 1024)
1124 else if (nextCode + early == 2048)
1135void LZWStream::clearTable() {
1138 seqIndex = seqLength = 0;
1142int LZWStream::getCode() {
1146 while (inputBits < nextBits) {
1147 if ((c = str->getChar()) == EOF)
1149 inputBuf = (inputBuf << 8) | (c & 0xff);
1152 code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
1153 inputBits -= nextBits;
1157GString *LZWStream::getPSFilter(
const char *indent) {
1163 if (!(s = str->getPSFilter(indent))) {
1166 s->append(indent)->append(
"/LZWDecode filter\n");
1170GBool LZWStream::isBinary(GBool ) {
1171 return str->isBinary(gTrue);
1178RunLengthStream::RunLengthStream(Stream *strA):
1179 FilterStream(strA) {
1180 bufPtr = bufEnd = buf;
1184RunLengthStream::~RunLengthStream() {
1188void RunLengthStream::reset() {
1190 bufPtr = bufEnd = buf;
1194GString *RunLengthStream::getPSFilter(
const char *indent) {
1197 if (!(s = str->getPSFilter(indent))) {
1200 s->append(indent)->append(
"/RunLengthDecode filter\n");
1204GBool RunLengthStream::isBinary(GBool ) {
1205 return str->isBinary(gTrue);
1208GBool RunLengthStream::fillBuf() {
1215 if (c == 0x80 || c == EOF) {
1221 for (i = 0; i < n; ++i)
1222 buf[i] = (
char)str->getChar();
1226 for (i = 0; i < n; ++i)
1239CCITTFaxStream::CCITTFaxStream(Stream *strA,
int encodingA, GBool endOfLineA,
1240 GBool byteAlignA,
int columnsA,
int rowsA,
1241 GBool endOfBlockA, GBool blackA):
1242 FilterStream(strA) {
1243 encoding = encodingA;
1244 endOfLine = endOfLineA;
1245 byteAlign = byteAlignA;
1247 if (columns < 1 || columns >= INT_MAX /
sizeof(
short)) {
1248 error(-1,
"invalid number of columns");
1252 endOfBlock = endOfBlockA;
1254 refLine = (
short *)gmalloc((columns + 3) *
sizeof(short));
1255 codingLine = (
short *)gmalloc((columns + 2) *
sizeof(short));
1259 nextLine2D = encoding < 0;
1262 codingLine[1] = refLine[2] = columns;
1268CCITTFaxStream::~CCITTFaxStream() {
1274void CCITTFaxStream::reset() {
1280 nextLine2D = encoding < 0;
1283 codingLine[1] = refLine[2] = columns;
1289 if (lookBits(12) == 0x001) {
1293 for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
1294 if (n == 11 && lookBits(12) == 0x001) {
1299 nextLine2D = !lookBits(1);
1304int CCITTFaxStream::lookChar() {
1305 short code1, code2, code3;
1315 if (eof && codingLine[a0] >= columns) {
1323 if (codingLine[a0] >= columns) {
1327 for (i = 0; codingLine[i] < columns; ++i)
1328 refLine[i] = codingLine[i];
1329 refLine[i] = refLine[i + 1] = columns;
1331 a0New = codingLine[a0 = 0] = 0;
1333 code1 = getTwoDimCode();
1336 if (refLine[b1] < columns) {
1337 a0New = refLine[b1 + 1];
1342 if ((a0 & 1) == 0) {
1345 code1 += code3 = getWhiteCode();
1346 }
while (code3 >= 64);
1348 code2 += code3 = getBlackCode();
1349 }
while (code3 >= 64);
1353 code1 += code3 = getBlackCode();
1354 }
while (code3 >= 64);
1356 code2 += code3 = getWhiteCode();
1357 }
while (code3 >= 64);
1359 codingLine[a0 + 1] = a0New + code1;
1361 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1363 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1367 a0New = codingLine[++a0] = refLine[b1];
1368 if (refLine[b1] < columns) {
1370 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1375 a0New = codingLine[++a0] = refLine[b1] + 1;
1376 if (refLine[b1] < columns) {
1378 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1383 a0New = codingLine[++a0] = refLine[b1] - 1;
1385 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1389 a0New = codingLine[++a0] = refLine[b1] + 2;
1390 if (refLine[b1] < columns) {
1392 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1397 a0New = codingLine[++a0] = refLine[b1] - 2;
1399 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1403 a0New = codingLine[++a0] = refLine[b1] + 3;
1404 if (refLine[b1] < columns) {
1406 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1411 a0New = codingLine[++a0] = refLine[b1] - 3;
1413 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1418 codingLine[a0 = 0] = columns;
1421 error(getPos(),
"Bad 2D code %04x in CCITTFax stream", code1);
1430 }
while (codingLine[a0] < columns);
1434 codingLine[a0 = 0] = 0;
1438 code1 += code3 = getWhiteCode();
1439 }
while (code3 >= 64);
1440 codingLine[a0+1] = codingLine[a0] + code1;
1442 if (codingLine[a0] >= columns)
1446 code2 += code3 = getBlackCode();
1447 }
while (code3 >= 64);
1448 codingLine[a0+1] = codingLine[a0] + code2;
1450 if (codingLine[a0] >= columns)
1455 if (codingLine[a0] != columns) {
1456 error(getPos(),
"CCITTFax row is wrong length (%d)", codingLine[a0]);
1469 if (!endOfBlock && row == rows - 1) {
1472 code1 = lookBits(12);
1473 while (code1 == 0) {
1475 code1 = lookBits(12);
1477 if (code1 == 0x001) {
1480 }
else if (code1 == EOF) {
1486 if (!eof && encoding > 0) {
1487 nextLine2D = !lookBits(1);
1492 if (endOfBlock && gotEOL) {
1493 code1 = lookBits(12);
1494 if (code1 == 0x001) {
1500 if (encoding >= 0) {
1501 for (i = 0; i < 4; ++i) {
1502 code1 = lookBits(12);
1503 if (code1 != 0x001) {
1504 error(getPos(),
"Bad RTC code in CCITTFax stream");
1529 code1 = look13Bits();
1530 }
while ((code1 >> 1) != 0x001);
1532 codingLine[++a0] = columns;
1535 nextLine2D = !(code1 & 1);
1541 outputBits = codingLine[1] - codingLine[0];
1542 if (outputBits == 0) {
1544 outputBits = codingLine[2] - codingLine[1];
1551 if (outputBits >= 8) {
1552 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1553 if ((outputBits -= 8) == 0) {
1555 if (codingLine[a0] < columns) {
1556 outputBits = codingLine[a0 + 1] - codingLine[a0];
1563 if (outputBits > bits) {
1566 if ((a0 & 1) == 0) {
1567 ret |= 0xff >> (8 - i);
1573 if ((a0 & 1) == 0) {
1574 ret |= (0xff >> (8 - i)) << bits;
1578 if (codingLine[a0] < columns) {
1579 outputBits = codingLine[a0 + 1] - codingLine[a0];
1582 }
while (bits > 0 && codingLine[a0] < columns);
1584 buf = black ? (ret ^ 0xff) : ret;
1588short CCITTFaxStream::getTwoDimCode() {
1596 p = &twoDimTab1[code];
1602 for (n = 1; n <= 7; ++n) {
1607 p = &twoDimTab1[code];
1614 error(getPos(),
"Bad two dim code (%04x) in CCITTFax stream", code);
1618short CCITTFaxStream::getWhiteCode() {
1625 code = lookBits(12);
1626 if ((code >> 5) == 0) {
1627 p = &whiteTab1[code];
1629 p = &whiteTab2[code >> 3];
1636 for (n = 1; n <= 9; ++n) {
1641 p = &whiteTab2[code];
1647 for (n = 11; n <= 12; ++n) {
1652 p = &whiteTab1[code];
1659 error(getPos(),
"Bad white code (%04x) in CCITTFax stream", code);
1666short CCITTFaxStream::getBlackCode() {
1673 code = lookBits(13);
1674 if ((code >> 7) == 0) {
1675 p = &blackTab1[code];
1676 }
else if ((code >> 9) == 0) {
1677 p = &blackTab2[(code >> 1) - 64];
1679 p = &blackTab3[code >> 7];
1686 for (n = 2; n <= 6; ++n) {
1691 p = &blackTab3[code];
1697 for (n = 7; n <= 12; ++n) {
1703 p = &blackTab2[code - 64];
1710 for (n = 10; n <= 13; ++n) {
1715 p = &blackTab1[code];
1722 error(getPos(),
"Bad black code (%04x) in CCITTFax stream", code);
1729short CCITTFaxStream::lookBits(
int n) {
1732 while (inputBits < n) {
1733 if ((c = str->getChar()) == EOF) {
1734 if (inputBits == 0) {
1741 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
1743 inputBuf = (inputBuf << 8) + c;
1746 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1749CCITTFaxStream::CCITTFaxStream(Stream *strA,
int encodingA, GBool endOfLineA,
1750 GBool byteAlignA,
int columnsA,
int rowsA,
1751 GBool endOfBlockA, GBool blackA):
1752 FilterStream(strA) {
1753 encoding = encodingA;
1754 endOfLine = endOfLineA;
1755 byteAlign = byteAlignA;
1759 }
else if (columns > (INT_MAX - 2)/
sizeof(
int)) {
1760 columns = (INT_MAX - 2)/
sizeof(
int);
1763 endOfBlock = endOfBlockA;
1769 codingLine = (
int *)gmalloc((columns + 1) *
sizeof(int));
1770 refLine = (
int *)gmalloc((columns + 2) *
sizeof(int));
1774 nextLine2D = encoding < 0;
1776 codingLine[0] = columns;
1783CCITTFaxStream::~CCITTFaxStream() {
1789void CCITTFaxStream::reset() {
1795 nextLine2D = encoding < 0;
1797 codingLine[0] = columns;
1804 while ((code1 = lookBits(12)) == 0) {
1807 if (code1 == 0x001) {
1811 nextLine2D = !lookBits(1);
1816inline void CCITTFaxStream::addPixels(
int a1,
int blackPixels) {
1817 if (a1 > codingLine[a0i]) {
1819 error(getPos(),
"CCITTFax row is wrong length (%d)", a1);
1823 if ((a0i & 1) ^ blackPixels) {
1826 codingLine[a0i] = a1;
1830inline void CCITTFaxStream::addPixelsNeg(
int a1,
int blackPixels) {
1831 if (a1 > codingLine[a0i]) {
1833 error(getPos(),
"CCITTFax row is wrong length (%d)", a1);
1837 if ((a0i & 1) ^ blackPixels) {
1840 codingLine[a0i] = a1;
1841 }
else if (a1 < codingLine[a0i]) {
1843 error(getPos(),
"Invalid CCITTFax code");
1847 while (a0i > 0 && a1 <= codingLine[a0i - 1]) {
1850 codingLine[a0i] = a1;
1854int CCITTFaxStream::lookChar() {
1855 short code1, code2, code3;
1856 int b1i, blackPixels, i, bits;
1864 if (outputBits == 0) {
1875 for (i = 0; codingLine[i] < columns; ++i) {
1876 refLine[i] = codingLine[i];
1878 refLine[i++] = columns;
1879 refLine[i] = columns;
1891 while (codingLine[a0i] < columns) {
1892 code1 = getTwoDimCode();
1895 addPixels(refLine[b1i + 1], blackPixels);
1896 if (refLine[b1i + 1] < columns) {
1904 code1 += code3 = getBlackCode();
1905 }
while (code3 >= 64);
1907 code2 += code3 = getWhiteCode();
1908 }
while (code3 >= 64);
1911 code1 += code3 = getWhiteCode();
1912 }
while (code3 >= 64);
1914 code2 += code3 = getBlackCode();
1915 }
while (code3 >= 64);
1917 addPixels(codingLine[a0i] + code1, blackPixels);
1918 if (codingLine[a0i] < columns) {
1919 addPixels(codingLine[a0i] + code2, blackPixels ^ 1);
1921 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1926 addPixels(refLine[b1i] + 3, blackPixels);
1928 if (codingLine[a0i] < columns) {
1930 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1936 addPixels(refLine[b1i] + 2, blackPixels);
1938 if (codingLine[a0i] < columns) {
1940 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1946 addPixels(refLine[b1i] + 1, blackPixels);
1948 if (codingLine[a0i] < columns) {
1950 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1956 addPixels(refLine[b1i], blackPixels);
1958 if (codingLine[a0i] < columns) {
1960 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1966 addPixelsNeg(refLine[b1i] - 3, blackPixels);
1968 if (codingLine[a0i] < columns) {
1974 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1980 addPixelsNeg(refLine[b1i] - 2, blackPixels);
1982 if (codingLine[a0i] < columns) {
1988 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
1994 addPixelsNeg(refLine[b1i] - 1, blackPixels);
1996 if (codingLine[a0i] < columns) {
2002 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
2008 addPixels(columns, 0);
2012 error(getPos(),
"Bad 2D code %04x in CCITTFax stream", code1);
2013 addPixels(columns, 0);
2024 while (codingLine[a0i] < columns) {
2028 code1 += code3 = getBlackCode();
2029 }
while (code3 >= 64);
2032 code1 += code3 = getWhiteCode();
2033 }
while (code3 >= 64);
2035 addPixels(codingLine[a0i] + code1, blackPixels);
2047 if (!endOfBlock && row == rows - 1) {
2050 code1 = lookBits(12);
2051 while (code1 == 0) {
2053 code1 = lookBits(12);
2055 if (code1 == 0x001) {
2058 }
else if (code1 == EOF) {
2064 if (!eof && encoding > 0) {
2065 nextLine2D = !lookBits(1);
2070 if (endOfBlock && gotEOL) {
2071 code1 = lookBits(12);
2072 if (code1 == 0x001) {
2078 if (encoding >= 0) {
2079 for (i = 0; i < 4; ++i) {
2080 code1 = lookBits(12);
2081 if (code1 != 0x001) {
2082 error(getPos(),
"Bad RTC code in CCITTFax stream");
2097 }
else if (err && endOfLine) {
2099 code1 = lookBits(13);
2104 if ((code1 >> 1) == 0x001) {
2112 nextLine2D = !(code1 & 1);
2117 if (codingLine[0] > 0) {
2118 outputBits = codingLine[a0i = 0];
2120 outputBits = codingLine[a0i = 1];
2127 if (outputBits >= 8) {
2128 buf = (a0i & 1) ? 0x00 : 0xff;
2130 if (outputBits == 0 && codingLine[a0i] < columns) {
2132 outputBits = codingLine[a0i] - codingLine[a0i - 1];
2138 if (outputBits > bits) {
2141 buf |= 0xff >> (8 - bits);
2148 buf |= 0xff >> (8 - outputBits);
2152 if (codingLine[a0i] < columns) {
2154 outputBits = codingLine[a0i] - codingLine[a0i - 1];
2155 }
else if (bits > 0) {
2168short CCITTFaxStream::getTwoDimCode() {
2176 p = &twoDimTab1[code];
2182 for (n = 1; n <= 7; ++n) {
2187 p = &twoDimTab1[code];
2194 error(getPos(),
"Bad two dim code (%04x) in CCITTFax stream", code);
2198short CCITTFaxStream::getWhiteCode() {
2205 code = lookBits(12);
2209 if ((code >> 5) == 0) {
2210 p = &whiteTab1[code];
2212 p = &whiteTab2[code >> 3];
2219 for (n = 1; n <= 9; ++n) {
2227 p = &whiteTab2[code];
2233 for (n = 11; n <= 12; ++n) {
2241 p = &whiteTab1[code];
2248 error(getPos(),
"Bad white code (%04x) in CCITTFax stream", code);
2255short CCITTFaxStream::getBlackCode() {
2262 code = lookBits(13);
2266 if ((code >> 7) == 0) {
2267 p = &blackTab1[code];
2268 }
else if ((code >> 9) == 0 && (code >> 7) != 0) {
2269 p = &blackTab2[(code >> 1) - 64];
2271 p = &blackTab3[code >> 7];
2278 for (n = 2; n <= 6; ++n) {
2286 p = &blackTab3[code];
2292 for (n = 7; n <= 12; ++n) {
2301 p = &blackTab2[code - 64];
2308 for (n = 10; n <= 13; ++n) {
2316 p = &blackTab1[code];
2323 error(getPos(),
"Bad black code (%04x) in CCITTFax stream", code);
2330short CCITTFaxStream::lookBits(
int n) {
2333 while (inputBits < n) {
2334 if ((c = str->getChar()) == EOF) {
2335 if (inputBits == 0) {
2342 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
2344 inputBuf = (inputBuf << 8) + c;
2347 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
2352GString *CCITTFaxStream::getPSFilter(
const char *indent) {
2356 if (!(s = str->getPSFilter(indent))) {
2359 s->append(indent)->append(
"<< ");
2360 if (encoding != 0) {
2361 sprintf(s1,
"/K %d ", encoding);
2365 s->append(
"/EndOfLine true ");
2368 s->append(
"/EncodedByteAlign true ");
2370 sprintf(s1,
"/Columns %d ", columns);
2373 sprintf(s1,
"/Rows %d ", rows);
2377 s->append(
"/EndOfBlock false ");
2380 s->append(
"/BlackIs1 true ");
2382 s->append(
">> /CCITTFaxDecode filter\n");
2386GBool CCITTFaxStream::isBinary(GBool ) {
2387 return str->isBinary(gTrue);
2401#define dctSqrt2 5793
2402#define dctSqrt1d2 2896
2405#define dctCrToR 91881
2406#define dctCbToG -22553
2407#define dctCrToG -46802
2408#define dctCbToB 116130
2411#define dctClipOffset 256
2412static Guchar dctClip[768];
2413static int dctClipInit = 0;
2416static int dctZigZag[64] = {
2422 5, 12, 19, 26, 33, 40,
2423 48, 41, 34, 27, 20, 13, 6,
2424 7, 14, 21, 28, 35, 42, 49, 56,
2425 57, 50, 43, 36, 29, 22, 15,
2426 23, 30, 37, 44, 51, 58,
2434DCTStream::DCTStream(Stream *strA):
2435 FilterStream(strA) {
2438 progressive = interleaved = gFalse;
2440 mcuWidth = mcuHeight = 0;
2444 for (i = 0; i < 4; ++i) {
2445 for (j = 0; j < 32; ++j) {
2446 rowBuf[i][j] = NULL;
2452 for (i = -256; i < 0; ++i)
2453 dctClip[dctClipOffset + i] = 0;
2454 for (i = 0; i < 256; ++i)
2455 dctClip[dctClipOffset + i] = i;
2456 for (i = 256; i < 512; ++i)
2457 dctClip[dctClipOffset + i] = 255;
2462DCTStream::~DCTStream() {
2466 if (progressive || !interleaved) {
2467 for (i = 0; i < numComps; ++i) {
2471 for (i = 0; i < numComps; ++i) {
2472 for (j = 0; j < mcuHeight; ++j) {
2473 gfree(rowBuf[i][j]);
2479void DCTStream::reset() {
2480 int minHSample, minVSample;
2485 progressive = interleaved = gFalse;
2489 numDCHuffTables = 0;
2490 numACHuffTables = 0;
2492 gotAdobeMarker = gFalse;
2493 restartInterval = 0;
2495 if (!readHeader()) {
2501 mcuWidth = minHSample = compInfo[0].hSample;
2502 mcuHeight = minVSample = compInfo[0].vSample;
2503 for (i = 1; i < numComps; ++i) {
2504 if (compInfo[i].hSample < minHSample)
2505 minHSample = compInfo[i].hSample;
2506 if (compInfo[i].vSample < minVSample)
2507 minVSample = compInfo[i].vSample;
2508 if (compInfo[i].hSample > mcuWidth)
2509 mcuWidth = compInfo[i].hSample;
2510 if (compInfo[i].vSample > mcuHeight)
2511 mcuHeight = compInfo[i].vSample;
2513 for (i = 0; i < numComps; ++i) {
2514 compInfo[i].hSample /= minHSample;
2515 compInfo[i].vSample /= minVSample;
2517 mcuWidth = (mcuWidth / minHSample) * 8;
2518 mcuHeight = (mcuHeight / minVSample) * 8;
2521 if (!gotAdobeMarker && numComps == 3) {
2522 if (compInfo[0].
id == 1 && compInfo[1].
id == 2 && compInfo[2].
id == 3) {
2527 if (progressive || !interleaved) {
2530 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2531 bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
2532 if (bufWidth <= 0 || bufHeight <= 0 ||
2533 bufWidth > INT_MAX / bufWidth / (
int)
sizeof(int)) {
2534 error(getPos(),
"Invalid image size in DCT stream");
2538 for (i = 0; i < numComps; ++i) {
2539 frameBuf[i] = (
int *)gmalloc(bufWidth * bufHeight *
sizeof(
int));
2540 memset(frameBuf[i], 0, bufWidth * bufHeight *
sizeof(
int));
2545 restartMarker = 0xd0;
2548 }
while (readHeader());
2561 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2562 for (i = 0; i < numComps; ++i) {
2563 for (j = 0; j < mcuHeight; ++j) {
2564 rowBuf[i][j] = (Guchar *)gmalloc(bufWidth *
sizeof(Guchar));
2574 restartMarker = 0xd0;
2579int DCTStream::getChar() {
2585 if (progressive || !interleaved) {
2586 c = frameBuf[comp][y * bufWidth + x];
2587 if (++comp == numComps) {
2595 if (dy >= mcuHeight) {
2596 if (!readMCURow()) {
2604 c = rowBuf[comp][dy][x];
2605 if (++comp == numComps) {
2620int DCTStream::lookChar() {
2624 if (progressive || !interleaved) {
2625 return frameBuf[comp][y * bufWidth + x];
2627 if (dy >= mcuHeight) {
2628 if (!readMCURow()) {
2636 return rowBuf[comp][dy][x];
2640void DCTStream::restart() {
2644 restartCtr = restartInterval;
2645 for (i = 0; i < numComps; ++i) {
2646 compInfo[i].prevDC = 0;
2652GBool DCTStream::readMCURow() {
2656 int pY, pCb, pCr, pR, pG, pB;
2657 int h, v, horiz, vert, hSub, vSub;
2658 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2661 for (x1 = 0; x1 < width; x1 += mcuWidth) {
2664 if (restartInterval > 0 && restartCtr == 0) {
2666 if (c != restartMarker) {
2667 error(getPos(),
"Bad DCT data: incorrect restart marker");
2670 if (++restartMarker == 0xd8)
2671 restartMarker = 0xd0;
2676 for (cc = 0; cc < numComps; ++cc) {
2677 h = compInfo[cc].hSample;
2678 v = compInfo[cc].vSample;
2679 horiz = mcuWidth / h;
2680 vert = mcuHeight / v;
2683 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2684 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2685 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2686 &acHuffTables[scanInfo.acHuffTable[cc]],
2687 &compInfo[cc].prevDC,
2691 transformDataUnit(quantTables[compInfo[cc].quantTable],
2693 if (hSub == 1 && vSub == 1) {
2694 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2695 p1 = &rowBuf[cc][y2+y3][x1+x2];
2705 }
else if (hSub == 2 && vSub == 2) {
2706 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2707 p1 = &rowBuf[cc][y2+y3][x1+x2];
2708 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
2709 p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
2710 p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
2711 p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
2712 p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
2713 p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
2714 p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
2715 p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
2716 p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
2720 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2721 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2722 for (y5 = 0; y5 < vSub; ++y5)
2723 for (x5 = 0; x5 < hSub; ++x5)
2724 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
2737 if (numComps == 3) {
2738 for (y2 = 0; y2 < mcuHeight; ++y2) {
2739 for (x2 = 0; x2 < mcuWidth; ++x2) {
2740 pY = rowBuf[0][y2][x1+x2];
2741 pCb = rowBuf[1][y2][x1+x2] - 128;
2742 pCr = rowBuf[2][y2][x1+x2] - 128;
2743 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2744 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
2745 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2746 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
2747 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2748 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
2752 }
else if (numComps == 4) {
2753 for (y2 = 0; y2 < mcuHeight; ++y2) {
2754 for (x2 = 0; x2 < mcuWidth; ++x2) {
2755 pY = rowBuf[0][y2][x1+x2];
2756 pCb = rowBuf[1][y2][x1+x2] - 128;
2757 pCr = rowBuf[2][y2][x1+x2] - 128;
2758 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2759 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2760 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2761 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2762 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2763 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2773void DCTStream::readScan() {
2775 int x1, y1, dy1, x2, y2, y3, cc, i;
2776 int h, v, horiz, vert, hSub, vSub;
2780 if (scanInfo.numComps == 1) {
2781 for (cc = 0; cc < numComps; ++cc) {
2782 if (scanInfo.comp[cc]) {
2786 dy1 = mcuHeight / compInfo[cc].vSample;
2791 for (y1 = 0; y1 < bufHeight; y1 += dy1) {
2792 for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
2795 if (restartInterval > 0 && restartCtr == 0) {
2797 if (c != restartMarker) {
2798 error(getPos(),
"Bad DCT data: incorrect restart marker");
2801 if (++restartMarker == 0xd8) {
2802 restartMarker = 0xd0;
2808 for (cc = 0; cc < numComps; ++cc) {
2809 if (!scanInfo.comp[cc]) {
2813 h = compInfo[cc].hSample;
2814 v = compInfo[cc].vSample;
2815 horiz = mcuWidth / h;
2816 vert = mcuHeight / v;
2819 for (y2 = 0; y2 < dy1; y2 += vert) {
2820 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2823 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2824 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2833 p1 += bufWidth * vSub;
2838 if (!readProgressiveDataUnit(
2839 &dcHuffTables[scanInfo.dcHuffTable[cc]],
2840 &acHuffTables[scanInfo.acHuffTable[cc]],
2841 &compInfo[cc].prevDC,
2846 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2847 &acHuffTables[scanInfo.acHuffTable[cc]],
2848 &compInfo[cc].prevDC,
2855 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2856 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2865 p1 += bufWidth * vSub;
2876GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2877 DCTHuffTable *acHuffTable,
2878 int *prevDC,
int data[64]) {
2883 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2887 if ((amp = readAmp(size)) == 9999) {
2893 data[0] = *prevDC += amp;
2894 for (i = 1; i < 64; ++i) {
2900 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
2909 run += (c >> 4) & 0x0f;
2911 amp = readAmp(size);
2924GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
2925 DCTHuffTable *acHuffTable,
2926 int *prevDC,
int data[64]) {
2927 int run, size, amp, bit, c;
2931 i = scanInfo.firstCoeff;
2933 if (scanInfo.ah == 0) {
2934 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2938 if ((amp = readAmp(size)) == 9999) {
2944 data[0] += (*prevDC += amp) << scanInfo.al;
2946 if ((bit = readBit()) == 9999) {
2949 data[0] += bit << scanInfo.al;
2953 if (scanInfo.lastCoeff == 0) {
2959 while (i <= scanInfo.lastCoeff) {
2962 if ((bit = readBit()) == EOF) {
2966 data[j] += 1 << scanInfo.al;
2975 while (i <= scanInfo.lastCoeff) {
2976 if ((c = readHuffSym(acHuffTable)) == 9999) {
2988 if ((bit = readBit()) == EOF) {
2992 data[j] += 1 << scanInfo.al;
2998 }
else if ((c & 0x0f) == 0x00) {
3001 for (k = 0; k < j; ++k) {
3002 if ((bit = readBit()) == EOF) {
3005 eobRun = (eobRun << 1) | bit;
3008 while (i <= scanInfo.lastCoeff) {
3011 if ((bit = readBit()) == EOF) {
3015 data[j] += 1 << scanInfo.al;
3024 run = (c >> 4) & 0x0f;
3026 if ((amp = readAmp(size)) == 9999) {
3032 while (data[j] != 0) {
3033 if ((bit = readBit()) == EOF) {
3037 data[j] += 1 << scanInfo.al;
3043 data[j] = amp << scanInfo.al;
3051void DCTStream::decodeImage() {
3055 int pY, pCb, pCr, pR, pG, pB;
3056 int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
3057 int h, v, horiz, vert, hSub, vSub;
3060 for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
3061 for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
3062 for (cc = 0; cc < numComps; ++cc) {
3063 quantTable = quantTables[compInfo[cc].quantTable];
3064 h = compInfo[cc].hSample;
3065 v = compInfo[cc].vSample;
3066 horiz = mcuWidth / h;
3067 vert = mcuHeight / v;
3070 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
3071 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
3074 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
3075 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
3077 dataIn[i+1] = p1[1];
3078 dataIn[i+2] = p1[2];
3079 dataIn[i+3] = p1[3];
3080 dataIn[i+4] = p1[4];
3081 dataIn[i+5] = p1[5];
3082 dataIn[i+6] = p1[6];
3083 dataIn[i+7] = p1[7];
3084 p1 += bufWidth * vSub;
3088 transformDataUnit(quantTable, dataIn, dataOut);
3092 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
3093 if (hSub == 1 && vSub == 1) {
3094 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
3095 p1[0] = dataOut[i] & 0xff;
3096 p1[1] = dataOut[i+1] & 0xff;
3097 p1[2] = dataOut[i+2] & 0xff;
3098 p1[3] = dataOut[i+3] & 0xff;
3099 p1[4] = dataOut[i+4] & 0xff;
3100 p1[5] = dataOut[i+5] & 0xff;
3101 p1[6] = dataOut[i+6] & 0xff;
3102 p1[7] = dataOut[i+7] & 0xff;
3105 }
else if (hSub == 2 && vSub == 2) {
3107 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
3108 p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
3109 p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
3110 p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
3111 p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
3112 p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
3113 p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
3114 p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
3115 p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
3121 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
3122 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
3124 for (y5 = 0; y5 < vSub; ++y5) {
3125 for (x5 = 0; x5 < hSub; ++x5) {
3126 p2[x5] = dataOut[i] & 0xff;
3132 p1 += bufWidth * vSub;
3142 if (numComps == 3) {
3143 for (y2 = 0; y2 < mcuHeight; ++y2) {
3144 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
3145 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
3146 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
3147 for (x2 = 0; x2 < mcuWidth; ++x2) {
3151 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
3152 *p0++ = dctClip[dctClipOffset + pR];
3153 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
3155 *p1++ = dctClip[dctClipOffset + pG];
3156 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
3157 *p2++ = dctClip[dctClipOffset + pB];
3161 }
else if (numComps == 4) {
3162 for (y2 = 0; y2 < mcuHeight; ++y2) {
3163 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
3164 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
3165 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
3166 for (x2 = 0; x2 < mcuWidth; ++x2) {
3170 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
3171 *p0++ = 255 - dctClip[dctClipOffset + pR];
3172 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
3174 *p1++ = 255 - dctClip[dctClipOffset + pG];
3175 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
3176 *p2++ = 255 - dctClip[dctClipOffset + pB];
3193void DCTStream::transformDataUnit(Guchar *quantTable,
3194 int dataIn[64], Guchar dataOut[64]) {
3195 int v0, v1, v2, v3, v4, v5, v6, v7, t;
3200 for (i = 0; i < 64; ++i) {
3201 dataIn[i] *= quantTable[i];
3205 for (i = 0; i < 64; i += 8) {
3209 if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
3210 p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
3211 t = (dctSqrt2 * p[0] + 512) >> 10;
3224 v0 = (dctSqrt2 * p[0] + 128) >> 8;
3225 v1 = (dctSqrt2 * p[4] + 128) >> 8;
3228 v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
3229 v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
3234 t = (v0 - v1+ 1) >> 1;
3235 v0 = (v0 + v1 + 1) >> 1;
3237 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
3238 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
3240 t = (v4 - v6 + 1) >> 1;
3241 v4 = (v4 + v6 + 1) >> 1;
3243 t = (v7 + v5 + 1) >> 1;
3244 v5 = (v7 - v5 + 1) >> 1;
3248 t = (v0 - v3 + 1) >> 1;
3249 v0 = (v0 + v3 + 1) >> 1;
3251 t = (v1 - v2 + 1) >> 1;
3252 v1 = (v1 + v2 + 1) >> 1;
3254 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
3255 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
3257 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
3258 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
3273 for (i = 0; i < 8; ++i) {
3277 if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
3278 p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
3279 t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
3292 v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
3293 v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
3296 v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
3297 v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
3302 t = (v0 - v1 + 1) >> 1;
3303 v0 = (v0 + v1 + 1) >> 1;
3305 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
3306 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
3308 t = (v4 - v6 + 1) >> 1;
3309 v4 = (v4 + v6 + 1) >> 1;
3311 t = (v7 + v5 + 1) >> 1;
3312 v5 = (v7 - v5 + 1) >> 1;
3316 t = (v0 - v3 + 1) >> 1;
3317 v0 = (v0 + v3 + 1) >> 1;
3319 t = (v1 - v2 + 1) >> 1;
3320 v1 = (v1 + v2 + 1) >> 1;
3322 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
3323 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
3325 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
3326 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
3341 for (i = 0; i < 64; ++i) {
3342 dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
3346int DCTStream::readHuffSym(DCTHuffTable *table) {
3355 if ((bit = readBit()) == EOF)
3357 code = (code << 1) + bit;
3361 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
3362 code -= table->firstCode[codeBits];
3363 return table->sym[table->firstSym[codeBits] + code];
3365 }
while (codeBits < 16);
3367 error(getPos(),
"Bad Huffman code in DCT stream");
3371int DCTStream::readAmp(
int size) {
3376 for (bits = 0; bits < size; ++bits) {
3377 if ((bit = readBit()) == EOF)
3379 amp = (amp << 1) + bit;
3381 if (amp < (1 << (size - 1)))
3382 amp -= (1 << size) - 1;
3386int DCTStream::readBit() {
3390 if (inputBits == 0) {
3391 if ((c = str->getChar()) == EOF)
3395 c2 = str->getChar();
3396 }
while (c2 == 0xff);
3398 error(getPos(),
"Bad DCT data: missing 00 after ff");
3405 bit = (inputBuf >> (inputBits - 1)) & 1;
3410GBool DCTStream::readHeader() {
3422 if (!readBaselineSOF()) {
3427 if (!readProgressiveSOF()) {
3432 if (!readHuffmanTables()) {
3442 if (!readScanInfo()) {
3448 if (!readQuantTables()) {
3453 if (!readRestartInterval()) {
3458 if (!readAdobeMarker()) {
3463 error(getPos(),
"Bad DCT header");
3469 for (i = 0; i < n; ++i) {
3473 error(getPos(),
"Unknown DCT marker <%02x>", c);
3483GBool DCTStream::readBaselineSOF() {
3490 prec = str->getChar();
3493 numComps = str->getChar();
3494 if (numComps <= 0 || numComps > 4) {
3496 error(getPos(),
"Bad number of components in DCT stream");
3500 error(getPos(),
"Bad DCT precision %d", prec);
3503 for (i = 0; i < numComps; ++i) {
3504 compInfo[i].id = str->getChar();
3506 compInfo[i].hSample = (c >> 4) & 0x0f;
3507 compInfo[i].vSample = c & 0x0f;
3508 compInfo[i].quantTable = str->getChar();
3510 progressive = gFalse;
3514GBool DCTStream::readProgressiveSOF() {
3521 prec = str->getChar();
3524 numComps = str->getChar();
3525 if (numComps <= 0 || numComps > 4) {
3527 error(getPos(),
"Bad number of components in DCT stream");
3531 error(getPos(),
"Bad DCT precision %d", prec);
3534 for (i = 0; i < numComps; ++i) {
3535 compInfo[i].id = str->getChar();
3537 compInfo[i].hSample = (c >> 4) & 0x0f;
3538 compInfo[i].vSample = c & 0x0f;
3539 compInfo[i].quantTable = str->getChar();
3541 progressive = gTrue;
3545GBool DCTStream::readScanInfo() {
3550 length = read16() - 2;
3551 scanInfo.numComps = str->getChar();
3552 if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) {
3553 scanInfo.numComps = 0;
3554 error(getPos(),
"Bad number of components in DCT stream");
3558 if (length != 2 * scanInfo.numComps + 3) {
3559 error(getPos(),
"Bad DCT scan info block");
3562 interleaved = scanInfo.numComps == numComps;
3563 for (j = 0; j < numComps; ++j) {
3564 scanInfo.comp[j] = gFalse;
3566 for (i = 0; i < scanInfo.numComps; ++i) {
3567 id = str->getChar();
3568 for (j = 0; j < numComps; ++j) {
3569 if (
id == compInfo[j].
id) {
3573 if (j == numComps) {
3574 error(getPos(),
"Bad DCT component ID in scan info block");
3577 scanInfo.comp[j] = gTrue;
3579 scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
3580 scanInfo.acHuffTable[j] = c & 0x0f;
3582 scanInfo.firstCoeff = str->getChar();
3583 scanInfo.lastCoeff = str->getChar();
3584 if (scanInfo.firstCoeff < 0 || scanInfo.lastCoeff > 63 ||
3585 scanInfo.firstCoeff > scanInfo.lastCoeff) {
3586 error(getPos(),
"Bad DCT coefficient numbers in scan info block");
3590 scanInfo.ah = (c >> 4) & 0x0f;
3591 scanInfo.al = c & 0x0f;
3595GBool DCTStream::readQuantTables() {
3600 length = read16() - 2;
3601 while (length > 0) {
3602 index = str->getChar();
3603 if ((index & 0xf0) || index >= 4) {
3604 error(getPos(),
"Bad DCT quantization table");
3607 if (index == numQuantTables)
3608 numQuantTables = index + 1;
3609 for (i = 0; i < 64; ++i)
3610 quantTables[index][dctZigZag[i]] = str->getChar();
3616GBool DCTStream::readHuffmanTables() {
3625 length = read16() - 2;
3626 while (length > 0) {
3627 index = str->getChar();
3629 if ((index & ~0x10) >= 4 || (index & ~0x10) < 0) {
3630 error(getPos(),
"Bad DCT Huffman table");
3635 if (index >= numACHuffTables)
3636 numACHuffTables = index+1;
3637 tbl = &acHuffTables[index];
3639 if (index >= numDCHuffTables)
3640 numDCHuffTables = index+1;
3641 tbl = &dcHuffTables[index];
3645 for (i = 1; i <= 16; ++i) {
3647 tbl->firstSym[i] = sym;
3648 tbl->firstCode[i] = code;
3649 tbl->numCodes[i] = c;
3651 code = (code + c) << 1;
3654 for (i = 0; i < sym; ++i)
3655 tbl->sym[i] = str->getChar();
3661GBool DCTStream::readRestartInterval() {
3666 error(getPos(),
"Bad DCT restart interval");
3669 restartInterval = read16();
3673GBool DCTStream::readAdobeMarker() {
3682 for (i = 0; i < 12; ++i) {
3683 if ((c = str->getChar()) == EOF) {
3688 if (strncmp(buf,
"Adobe", 5)) {
3691 colorXform = buf[11];
3692 gotAdobeMarker = gTrue;
3693 for (i = 14; i < length; ++i) {
3694 if (str->getChar() == EOF) {
3701 error(getPos(),
"Bad DCT Adobe APP14 marker");
3705GBool DCTStream::readTrailer() {
3710 error(getPos(),
"Bad DCT trailer");
3716int DCTStream::readMarker() {
3722 if(c == EOF)
return EOF;
3723 }
while (c != 0xff);
3726 if(c == EOF)
return EOF;
3727 }
while (c == 0xff);
3728 }
while (c == 0x00);
3732int DCTStream::read16() {
3735 if ((c1 = str->getChar()) == EOF)
3737 if ((c2 = str->getChar()) == EOF)
3739 return (c1 << 8) + c2;
3742GString *DCTStream::getPSFilter(
const char *indent) {
3745 if (!(s = str->getPSFilter(indent))) {
3748 s->append(indent)->append(
"<< >> /DCTDecode filter\n");
3752GBool DCTStream::isBinary(GBool ) {
3753 return str->isBinary(gTrue);
3760int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
3761 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3764FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
3796FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
3829FlateStream::FlateStream(Stream *strA,
int predictor,
int columns,
3830 int colors,
int bits):
3831 FilterStream(strA) {
3832 if (predictor != 1) {
3833 pred =
new StreamPredictor(
this, predictor, columns, colors, bits);
3834 if ( !pred->isOk()) {
3841 litCodeTab.codes = NULL;
3842 distCodeTab.codes = NULL;
3845FlateStream::~FlateStream() {
3846 gfree(litCodeTab.codes);
3847 gfree(distCodeTab.codes);
3854void FlateStream::reset() {
3861 compressedBlock = gFalse;
3869 endOfBlock = eof = gTrue;
3870 cmf = str->getChar();
3871 flg = str->getChar();
3872 if (cmf == EOF || flg == EOF)
3874 if ((cmf & 0x0f) != 0x08) {
3875 error(getPos(),
"Unknown compression method in flate stream");
3878 if ((((cmf << 8) + flg) % 31) != 0) {
3879 error(getPos(),
"Bad FCHECK in flate stream");
3883 error(getPos(),
"FDICT bit set in flate stream");
3890int FlateStream::getChar() {
3894 return pred->getChar();
3896 while (remain == 0) {
3897 if (endOfBlock && eof)
3902 index = (index + 1) & flateMask;
3907int FlateStream::lookChar() {
3911 return pred->lookChar();
3913 while (remain == 0) {
3914 if (endOfBlock && eof)
3922int FlateStream::getRawChar() {
3925 while (remain == 0) {
3926 if (endOfBlock && eof)
3931 index = (index + 1) & flateMask;
3936GString *FlateStream::getPSFilter(
const char *) {
3940GBool FlateStream::isBinary(GBool ) {
3941 return str->isBinary(gTrue);
3944void FlateStream::readSome() {
3955 if (compressedBlock) {
3956 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
3961 }
else if (code1 == 256) {
3966 code2 = lengthDecode[code1].bits;
3967 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3969 len = lengthDecode[code1].first + code2;
3970 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
3972 code2 = distDecode[code1].bits;
3973 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3975 dist = distDecode[code1].first + code2;
3977 j = (index - dist) & flateMask;
3978 for (k = 0; k < len; ++k) {
3980 i = (i + 1) & flateMask;
3981 j = (j + 1) & flateMask;
3987 len = (blockLen < flateWindow) ? blockLen : flateWindow;
3988 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
3989 if ((c = str->getChar()) == EOF) {
3990 endOfBlock = eof = gTrue;
4004 error(getPos(),
"Unexpected end of file in flate stream");
4005 endOfBlock = eof = gTrue;
4009GBool FlateStream::startBlock() {
4015 gfree(litCodeTab.codes);
4016 litCodeTab.codes = NULL;
4017 gfree(distCodeTab.codes);
4018 distCodeTab.codes = NULL;
4021 blockHdr = getCodeWord(3);
4027 if (blockHdr == 0) {
4028 compressedBlock = gFalse;
4029 if ((c = str->getChar()) == EOF)
4031 blockLen = c & 0xff;
4032 if ((c = str->getChar()) == EOF)
4034 blockLen |= (c & 0xff) << 8;
4035 if ((c = str->getChar()) == EOF)
4038 if ((c = str->getChar()) == EOF)
4040 check |= (c & 0xff) << 8;
4041 if (check != (~blockLen & 0xffff))
4042 error(getPos(),
"Bad uncompressed block length in flate stream");
4047 }
else if (blockHdr == 1) {
4048 compressedBlock = gTrue;
4052 }
else if (blockHdr == 2) {
4053 compressedBlock = gTrue;
4054 if (!readDynamicCodes()) {
4063 endOfBlock = gFalse;
4067 error(getPos(),
"Bad block header in flate stream");
4068 endOfBlock = eof = gTrue;
4072void FlateStream::loadFixedCodes() {
4076 for (i = 0; i <= 143; ++i) {
4079 for (i = 144; i <= 255; ++i) {
4082 for (i = 256; i <= 279; ++i) {
4085 for (i = 280; i <= 287; ++i) {
4088 compHuffmanCodes(codeLengths, flateMaxLitCodes, &litCodeTab);
4091 for (i = 0; i < flateMaxDistCodes; ++i) {
4094 compHuffmanCodes(codeLengths, flateMaxDistCodes, &distCodeTab);
4097GBool FlateStream::readDynamicCodes() {
4098 int numCodeLenCodes;
4101 int codeLenCodeLengths[flateMaxCodeLenCodes];
4102 FlateHuffmanTab codeLenCodeTab;
4103 int len, repeat, code;
4107 if ((numLitCodes = getCodeWord(5)) == EOF) {
4111 if ((numDistCodes = getCodeWord(5)) == EOF) {
4115 if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
4118 numCodeLenCodes += 4;
4119 if (numLitCodes > flateMaxLitCodes ||
4120 numDistCodes > flateMaxDistCodes ||
4121 numCodeLenCodes > flateMaxCodeLenCodes) {
4126 for (i = 0; i < flateMaxCodeLenCodes; ++i) {
4127 codeLenCodeLengths[i] = 0;
4129 for (i = 0; i < numCodeLenCodes; ++i) {
4130 if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
4134 compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
4140 while (i < numLitCodes + numDistCodes) {
4141 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
4145 if ((repeat = getCodeWord(2)) == EOF) {
4148 for (repeat += 3; repeat > 0; --repeat) {
4149 codeLengths[i++] = len;
4151 }
else if (code == 17) {
4152 if ((repeat = getCodeWord(3)) == EOF) {
4156 for (repeat += 3; repeat > 0; --repeat) {
4157 codeLengths[i++] = 0;
4159 }
else if (code == 18) {
4160 if ((repeat = getCodeWord(7)) == EOF) {
4164 for (repeat += 11; repeat > 0; --repeat) {
4165 codeLengths[i++] = 0;
4168 codeLengths[i++] = len = code;
4171 compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
4172 compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
4174 gfree(codeLenCodeTab.codes);
4178 error(getPos(),
"Bad dynamic code table in flate stream");
4179 gfree(codeLenCodeTab.codes);
4185void FlateStream::compHuffmanCodes(
int *lengths,
int n, FlateHuffmanTab *tab) {
4186 int tabSize, len, code, code2, skip, val, i, t;
4190 for (val = 0; val < n; ++val) {
4191 if (lengths[val] > tab->maxLen) {
4192 tab->maxLen = lengths[val];
4197 tabSize = 1 << tab->maxLen;
4198 tab->codes = (FlateCode *)gmalloc(tabSize *
sizeof(FlateCode));
4201 for (i = 0; i < tabSize; ++i) {
4202 tab->codes[i].len = 0;
4203 tab->codes[i].val = 0;
4207 for (len = 1, code = 0, skip = 2;
4209 ++len, code <<= 1, skip <<= 1) {
4210 for (val = 0; val < n; ++val) {
4211 if (lengths[val] == len) {
4216 for (i = 0; i < len; ++i) {
4217 code2 = (code2 << 1) | (t & 1);
4222 for (i = code2; i < tabSize; i += skip) {
4223 tab->codes[i].len = (Gushort)len;
4224 tab->codes[i].val = (Gushort)val;
4233int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
4237 while (codeSize < tab->maxLen) {
4238 if ((c = str->getChar()) == EOF) {
4241 codeBuf |= (c & 0xff) << codeSize;
4244 code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
4245 if (codeSize == 0 || codeSize < code->len || code->len == 0) {
4248 codeBuf >>= code->len;
4249 codeSize -= code->len;
4250 return (
int)code->val;
4253int FlateStream::getCodeWord(
int bits) {
4256 while (codeSize < bits) {
4257 if ((c = str->getChar()) == EOF)
4259 codeBuf |= (c & 0xff) << codeSize;
4262 c = codeBuf & ((1 << bits) - 1);
4272EOFStream::EOFStream(Stream *strA):
4273 FilterStream(strA) {
4276EOFStream::~EOFStream() {
4284FixedLengthEncoder::FixedLengthEncoder(Stream *strA,
int lengthA):
4285 FilterStream(strA) {
4290FixedLengthEncoder::~FixedLengthEncoder() {
4291 if (str->isEncoder())
4295void FixedLengthEncoder::reset() {
4300void FixedLengthEncoder::close() {
4303int FixedLengthEncoder::getChar() {
4304 if (length >= 0 && count >= length)
4307 return str->getChar();
4310int FixedLengthEncoder::lookChar() {
4311 if (length >= 0 && count >= length)
4313 return str->getChar();
4320ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
4321 FilterStream(strA) {
4322 bufPtr = bufEnd = buf;
4327ASCIIHexEncoder::~ASCIIHexEncoder() {
4328 if (str->isEncoder()) {
4333void ASCIIHexEncoder::reset() {
4335 bufPtr = bufEnd = buf;
4340void ASCIIHexEncoder::close() {
4343GBool ASCIIHexEncoder::fillBuf() {
4344 static const char *hex =
"0123456789abcdef";
4350 bufPtr = bufEnd = buf;
4351 if ((c = str->getChar()) == EOF) {
4355 if (lineLen >= 64) {
4359 *bufEnd++ = hex[(c >> 4) & 0x0f];
4360 *bufEnd++ = hex[c & 0x0f];
4370ASCII85Encoder::ASCII85Encoder(Stream *strA):
4371 FilterStream(strA) {
4372 bufPtr = bufEnd = buf;
4377ASCII85Encoder::~ASCII85Encoder() {
4378 if (str->isEncoder())
4382void ASCII85Encoder::reset() {
4384 bufPtr = bufEnd = buf;
4389void ASCII85Encoder::close() {
4392GBool ASCII85Encoder::fillBuf() {
4401 for (n = 0; n < 4; ++n) {
4402 if ((c = str->getChar()) == EOF)
4406 bufPtr = bufEnd = buf;
4408 if (n == 4 && t == 0) {
4410 if (++lineLen == 65) {
4417 for (i = 4; i >= 0; --i) {
4418 buf1[i] = (char)(t % 85 + 0x21);
4421 for (i = 0; i <= n; ++i) {
4422 *bufEnd++ = buf1[i];
4423 if (++lineLen == 65) {
4435 return bufPtr < bufEnd;
4442RunLengthEncoder::RunLengthEncoder(Stream *strA):
4443 FilterStream(strA) {
4444 bufPtr = bufEnd = nextEnd = buf;
4448RunLengthEncoder::~RunLengthEncoder() {
4449 if (str->isEncoder())
4453void RunLengthEncoder::reset() {
4455 bufPtr = bufEnd = nextEnd = buf;
4459void RunLengthEncoder::close() {
4470GBool RunLengthEncoder::fillBuf() {
4479 if (nextEnd < bufEnd + 1) {
4480 if ((c1 = str->getChar()) == EOF) {
4485 c1 = bufEnd[0] & 0xff;
4487 if (nextEnd < bufEnd + 2) {
4488 if ((c2 = str->getChar()) == EOF) {
4497 c2 = bufEnd[1] & 0xff;
4504 while (n < 128 && (c = str->getChar()) == c1)
4506 buf[0] = (char)(257 - n);
4511 }
else if (n < 128) {
4524 if ((c = str->getChar()) == EOF) {
4530 if (buf[n] == buf[n-1])
4533 if (buf[n] == buf[n-1]) {
4534 buf[0] = (char)(n-2-1);
4536 nextEnd = &buf[n+1];
4538 buf[0] = (char)(n-1);
4539 bufEnd = nextEnd = &buf[n+1];