1 //========================================================================
5 // Copyright 1996-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
32 #include "JBIG2Stream.h"
33 #include "JPXStream.h"
34 #include "Stream-CCITT.h"
37 static GBool setDJSYSFLAGS = gFalse;
48 //------------------------------------------------------------------------
49 // Stream (base class)
50 //------------------------------------------------------------------------
59 void Stream::close() {
62 int Stream::getRawChar() {
63 error(-1, "Internal: called getRawChar() on non-predictor stream");
67 char *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')
88 GString *Stream::getPSFilter(int psLevel, char *indent) {
92 Stream *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");
136 Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
137 int pred; // parameters
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);
260 } else if (!strcmp(name, "JPXDecode")) {
261 str = new JPXStream(str);
263 error(getPos(), "Unknown filter '%s'", name);
264 str = new EOFStream(str);
269 //------------------------------------------------------------------------
271 //------------------------------------------------------------------------
273 BaseStream::BaseStream(Object *dictA) {
278 BaseStream::~BaseStream() {
284 void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
285 int objNum, int objGen) {
286 decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
289 //------------------------------------------------------------------------
291 //------------------------------------------------------------------------
293 FilterStream::FilterStream(Stream *strA) {
297 FilterStream::~FilterStream() {
300 void FilterStream::close() {
304 void FilterStream::setPos(Guint pos, int dir) {
305 error(-1, "Internal: called setPos() on FilterStream");
308 //------------------------------------------------------------------------
310 //------------------------------------------------------------------------
312 ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
320 nVals = width * nComps;
322 imgLineSize = (nVals + 7) & ~7;
326 imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar));
330 ImageStream::~ImageStream() {
334 void ImageStream::reset() {
338 GBool ImageStream::getPixel(Guchar *pix) {
341 if (imgIdx >= nVals) {
345 for (i = 0; i < nComps; ++i) {
346 pix[i] = imgLine[imgIdx++];
351 Guchar *ImageStream::getLine() {
358 for (i = 0; i < nVals; i += 8) {
360 imgLine[i+0] = (Guchar)((c >> 7) & 1);
361 imgLine[i+1] = (Guchar)((c >> 6) & 1);
362 imgLine[i+2] = (Guchar)((c >> 5) & 1);
363 imgLine[i+3] = (Guchar)((c >> 4) & 1);
364 imgLine[i+4] = (Guchar)((c >> 3) & 1);
365 imgLine[i+5] = (Guchar)((c >> 2) & 1);
366 imgLine[i+6] = (Guchar)((c >> 1) & 1);
367 imgLine[i+7] = (Guchar)(c & 1);
369 } else if (nBits == 8) {
370 for (i = 0; i < nVals; ++i) {
371 imgLine[i] = str->getChar();
374 bitMask = (1 << nBits) - 1;
377 for (i = 0; i < nVals; ++i) {
379 buf = (buf << 8) | (str->getChar() & 0xff);
382 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
389 void ImageStream::skipLine() {
392 n = (nVals * nBits + 7) >> 3;
393 for (i = 0; i < n; ++i) {
398 //------------------------------------------------------------------------
400 //------------------------------------------------------------------------
402 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
403 int widthA, int nCompsA, int nBitsA) {
407 predictor = predictorA;
414 nVals = width * nComps;
415 totalBits = nVals * nBits;
416 if (totalBits == 0 ||
417 (totalBits / nBits) / nComps != width ||
421 pixBytes = (nComps * nBits + 7) >> 3;
422 rowBytes = ((totalBits + 7) >> 3) + pixBytes;
426 predLine = (Guchar *)gmalloc(rowBytes);
427 memset(predLine, 0, rowBytes);
433 StreamPredictor::~StreamPredictor() {
437 int StreamPredictor::lookChar() {
438 if (predIdx >= rowBytes) {
439 if (!getNextLine()) {
443 return predLine[predIdx];
446 int StreamPredictor::getChar() {
447 if (predIdx >= rowBytes) {
448 if (!getNextLine()) {
452 return predLine[predIdx++];
455 GBool StreamPredictor::getNextLine() {
457 Guchar upLeftBuf[gfxColorMaxComps * 2 + 1];
458 int left, up, upLeft, p, pa, pb, pc;
460 Gulong inBuf, outBuf, bitMask;
464 // get PNG optimum predictor number
465 if (predictor >= 10) {
466 if ((curPred = str->getRawChar()) == EOF) {
474 // read the raw line, apply PNG (byte) predictor
475 memset(upLeftBuf, 0, pixBytes + 1);
476 for (i = pixBytes; i < rowBytes; ++i) {
477 for (j = pixBytes; j > 0; --j) {
478 upLeftBuf[j] = upLeftBuf[j-1];
480 upLeftBuf[0] = predLine[i];
481 if ((c = str->getRawChar()) == EOF) {
483 // this ought to return false, but some (broken) PDF files
484 // contain truncated image data, and Adobe apparently reads the
492 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
495 predLine[i] = predLine[i] + (Guchar)c;
497 case 13: // PNG average
498 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
501 case 14: // PNG Paeth
502 left = predLine[i - pixBytes];
504 upLeft = upLeftBuf[pixBytes];
505 p = left + up - upLeft;
506 if ((pa = p - left) < 0)
508 if ((pb = p - up) < 0)
510 if ((pc = p - upLeft) < 0)
512 if (pa <= pb && pa <= pc)
513 predLine[i] = left + (Guchar)c;
515 predLine[i] = up + (Guchar)c;
517 predLine[i] = upLeft + (Guchar)c;
520 default: // no predictor or TIFF predictor
521 predLine[i] = (Guchar)c;
526 // apply TIFF (component) predictor
527 if (predictor == 2) {
529 inBuf = predLine[pixBytes - 1];
530 for (i = pixBytes; i < rowBytes; i += 8) {
531 // 1-bit add is just xor
532 inBuf = (inBuf << 8) | predLine[i];
533 predLine[i] ^= inBuf >> nComps;
535 } else if (nBits == 8) {
536 for (i = pixBytes; i < rowBytes; ++i) {
537 predLine[i] += predLine[i - nComps];
540 memset(upLeftBuf, 0, nComps + 1);
541 bitMask = (1 << nBits) - 1;
543 inBits = outBits = 0;
545 for (i = 0; i < width; ++i) {
546 for (kk = 0; kk < nComps; ++kk) {
547 if (inBits < nBits) {
548 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
551 upLeftBuf[kk] = (upLeftBuf[kk] +
552 (inBuf >> (inBits - nBits))) & bitMask;
554 outBuf = (outBuf << nBits) | upLeftBuf[kk];
557 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
563 predLine[k++] = (Guchar)((outBuf << (8 - outBits)) +
564 (inBuf & ((1 << (8 - outBits)) - 1)));
569 // reset to start of line
575 //------------------------------------------------------------------------
577 //------------------------------------------------------------------------
579 FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
580 Guint lengthA, Object *dictA):
586 bufPtr = bufEnd = buf;
592 FileStream::~FileStream() {
596 Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
597 Guint lengthA, Object *dictA) {
598 return new FileStream(f, startA, limitedA, lengthA, dictA);
601 void FileStream::reset() {
603 savePos = (Guint)ftello(f);
604 fseeko(f, start, SEEK_SET);
606 savePos = (Guint)ftell64(f);
607 fseek64(f, start, SEEK_SET);
609 savePos = (Guint)ftell(f);
610 fseek(f, start, SEEK_SET);
613 bufPtr = bufEnd = buf;
619 void FileStream::close() {
622 fseeko(f, savePos, SEEK_SET);
624 fseek64(f, savePos, SEEK_SET);
626 fseek(f, savePos, SEEK_SET);
632 GBool FileStream::fillBuf() {
636 bufPos += bufEnd - buf;
637 bufPtr = bufEnd = buf;
638 if (limited && bufPos >= start + length) {
641 if (limited && bufPos + fileStreamBufSize > start + length) {
642 n = start + length - bufPos;
644 n = fileStreamBufSize;
646 n = fread(buf, 1, n, f);
648 if (bufPtr >= bufEnd) {
652 for (p = buf; p < bufEnd; ++p) {
653 *p = (char)decrypt->decryptByte((Guchar)*p);
659 void FileStream::setPos(Guint pos, int dir) {
664 fseeko(f, pos, SEEK_SET);
666 fseek64(f, pos, SEEK_SET);
668 fseek(f, pos, SEEK_SET);
673 fseeko(f, 0, SEEK_END);
674 size = (Guint)ftello(f);
676 fseek64(f, 0, SEEK_END);
677 size = (Guint)ftell64(f);
679 fseek(f, 0, SEEK_END);
680 size = (Guint)ftell(f);
685 //~ work around a bug in cygwin's implementation of fseek
689 fseeko(f, -(int)pos, SEEK_END);
690 bufPos = (Guint)ftello(f);
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;
702 void FileStream::moveStart(int delta) {
704 bufPtr = bufEnd = buf;
708 //------------------------------------------------------------------------
710 //------------------------------------------------------------------------
712 MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA):
717 bufEnd = buf + start + length;
718 bufPtr = buf + start;
722 MemStream::~MemStream() {
728 Stream *MemStream::makeSubStream(Guint startA, GBool limited,
729 Guint lengthA, Object *dictA) {
733 if (!limited || startA + lengthA > start + length) {
734 newLength = start + length - startA;
738 subStr = new MemStream(buf, startA, newLength, dictA);
742 void MemStream::reset() {
743 bufPtr = buf + start;
749 void MemStream::close() {
752 void MemStream::setPos(Guint pos, int dir) {
758 i = start + length - pos;
762 } else if (i > start + length) {
768 void MemStream::moveStart(int delta) {
771 bufPtr = buf + start;
774 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
775 int objNum, int objGen) {
779 this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
781 newBuf = (char *)gmalloc(length);
782 for (p = buf + start, q = newBuf; p < bufEnd; ++p, ++q) {
783 *q = (char)decrypt->decryptByte((Guchar)*p);
785 bufEnd = newBuf + length;
786 bufPtr = newBuf + (bufPtr - (buf + start));
793 //------------------------------------------------------------------------
795 //------------------------------------------------------------------------
797 EmbedStream::EmbedStream(Stream *strA, Object *dictA,
798 GBool limitedA, Guint lengthA):
805 EmbedStream::~EmbedStream() {
808 Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA,
809 Guint lengthA, Object *dictA) {
810 error(-1, "Internal: called makeSubStream() on EmbedStream");
814 int EmbedStream::getChar() {
815 if (limited && !length) {
819 return str->getChar();
822 int EmbedStream::lookChar() {
823 if (limited && !length) {
826 return str->lookChar();
829 void EmbedStream::setPos(Guint pos, int dir) {
830 error(-1, "Internal: called setPos() on EmbedStream");
833 Guint EmbedStream::getStart() {
834 error(-1, "Internal: called getStart() on EmbedStream");
838 void EmbedStream::moveStart(int delta) {
839 error(-1, "Internal: called moveStart() on EmbedStream");
842 //------------------------------------------------------------------------
844 //------------------------------------------------------------------------
846 ASCIIHexStream::ASCIIHexStream(Stream *strA):
852 ASCIIHexStream::~ASCIIHexStream() {
856 void ASCIIHexStream::reset() {
862 int ASCIIHexStream::lookChar() {
873 } while (isspace(c1));
881 } while (isspace(c2));
886 if (c1 >= '0' && c1 <= '9') {
888 } else if (c1 >= 'A' && c1 <= 'F') {
889 x = (c1 - 'A' + 10) << 4;
890 } else if (c1 >= 'a' && c1 <= 'f') {
891 x = (c1 - 'a' + 10) << 4;
892 } else if (c1 == EOF) {
896 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
899 if (c2 >= '0' && c2 <= '9') {
901 } else if (c2 >= 'A' && c2 <= 'F') {
903 } else if (c2 >= 'a' && c2 <= 'f') {
905 } else if (c2 == EOF) {
909 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
915 GString *ASCIIHexStream::getPSFilter(int psLevel, char *indent) {
921 if (!(s = str->getPSFilter(psLevel, indent))) {
924 s->append(indent)->append("/ASCIIHexDecode filter\n");
928 GBool ASCIIHexStream::isBinary(GBool last) {
929 return str->isBinary(gFalse);
932 //------------------------------------------------------------------------
934 //------------------------------------------------------------------------
936 ASCII85Stream::ASCII85Stream(Stream *strA):
942 ASCII85Stream::~ASCII85Stream() {
946 void ASCII85Stream::reset() {
952 int ASCII85Stream::lookChar() {
961 c[0] = str->getChar();
962 } while (Lexer::isSpace(c[0]));
963 if (c[0] == '~' || c[0] == EOF) {
967 } else if (c[0] == 'z') {
968 b[0] = b[1] = b[2] = b[3] = 0;
971 for (k = 1; k < 5; ++k) {
973 c[k] = str->getChar();
974 } while (Lexer::isSpace(c[k]));
975 if (c[k] == '~' || c[k] == EOF)
979 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
980 for (++k; k < 5; ++k)
985 for (k = 0; k < 5; ++k)
986 t = t * 85 + (c[k] - 0x21);
987 for (k = 3; k >= 0; --k) {
988 b[k] = (int)(t & 0xff);
996 GString *ASCII85Stream::getPSFilter(int psLevel, char *indent) {
1002 if (!(s = str->getPSFilter(psLevel, indent))) {
1005 s->append(indent)->append("/ASCII85Decode filter\n");
1009 GBool ASCII85Stream::isBinary(GBool last) {
1010 return str->isBinary(gFalse);
1013 //------------------------------------------------------------------------
1015 //------------------------------------------------------------------------
1017 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
1018 int bits, int earlyA):
1019 FilterStream(strA) {
1020 if (predictor != 1) {
1021 pred = new StreamPredictor(this, predictor, columns, colors, bits);
1022 if (!pred->isOk()) {
1035 LZWStream::~LZWStream() {
1042 int LZWStream::getChar() {
1044 return pred->getChar();
1049 if (seqIndex >= seqLength) {
1050 if (!processNextCode()) {
1054 return seqBuf[seqIndex++];
1057 int LZWStream::lookChar() {
1059 return pred->lookChar();
1064 if (seqIndex >= seqLength) {
1065 if (!processNextCode()) {
1069 return seqBuf[seqIndex];
1072 int LZWStream::getRawChar() {
1076 if (seqIndex >= seqLength) {
1077 if (!processNextCode()) {
1081 return seqBuf[seqIndex++];
1084 void LZWStream::reset() {
1091 GBool LZWStream::processNextCode() {
1101 // check for eod and clear-table codes
1104 if (code == EOF || code == 257) {
1112 if (nextCode >= 4097) {
1113 error(getPos(), "Bad LZW stream - expected clear-table code");
1117 // process the next code
1118 nextLength = seqLength + 1;
1122 } else if (code < nextCode) {
1123 seqLength = table[code].length;
1124 for (i = seqLength - 1, j = code; i > 0; --i) {
1125 seqBuf[i] = table[j].tail;
1129 } else if (code == nextCode) {
1130 seqBuf[seqLength] = newChar;
1133 error(getPos(), "Bad LZW stream - unexpected code");
1137 newChar = seqBuf[0];
1141 table[nextCode].length = nextLength;
1142 table[nextCode].head = prevCode;
1143 table[nextCode].tail = newChar;
1145 if (nextCode + early == 512)
1147 else if (nextCode + early == 1024)
1149 else if (nextCode + early == 2048)
1160 void LZWStream::clearTable() {
1163 seqIndex = seqLength = 0;
1167 int LZWStream::getCode() {
1171 while (inputBits < nextBits) {
1172 if ((c = str->getChar()) == EOF)
1174 inputBuf = (inputBuf << 8) | (c & 0xff);
1177 code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
1178 inputBits -= nextBits;
1182 GString *LZWStream::getPSFilter(int psLevel, char *indent) {
1185 if (psLevel < 2 || pred) {
1188 if (!(s = str->getPSFilter(psLevel, indent))) {
1191 s->append(indent)->append("<< ");
1193 s->append("/EarlyChange 0 ");
1195 s->append(">> /LZWDecode filter\n");
1199 GBool LZWStream::isBinary(GBool last) {
1200 return str->isBinary(gTrue);
1203 //------------------------------------------------------------------------
1205 //------------------------------------------------------------------------
1207 RunLengthStream::RunLengthStream(Stream *strA):
1208 FilterStream(strA) {
1209 bufPtr = bufEnd = buf;
1213 RunLengthStream::~RunLengthStream() {
1217 void RunLengthStream::reset() {
1219 bufPtr = bufEnd = buf;
1223 GString *RunLengthStream::getPSFilter(int psLevel, char *indent) {
1229 if (!(s = str->getPSFilter(psLevel, indent))) {
1232 s->append(indent)->append("/RunLengthDecode filter\n");
1236 GBool RunLengthStream::isBinary(GBool last) {
1237 return str->isBinary(gTrue);
1240 GBool RunLengthStream::fillBuf() {
1247 if (c == 0x80 || c == EOF) {
1253 for (i = 0; i < n; ++i)
1254 buf[i] = (char)str->getChar();
1258 for (i = 0; i < n; ++i)
1266 //------------------------------------------------------------------------
1268 //------------------------------------------------------------------------
1270 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1271 GBool byteAlignA, int columnsA, int rowsA,
1272 GBool endOfBlockA, GBool blackA):
1273 FilterStream(strA) {
1274 encoding = encodingA;
1275 endOfLine = endOfLineA;
1276 byteAlign = byteAlignA;
1282 endOfBlock = endOfBlockA;
1284 refLine = (short *)gmallocn(columns + 4, sizeof(short));
1285 codingLine = (short *)gmallocn(columns + 3, sizeof(short));
1289 nextLine2D = encoding < 0;
1292 codingLine[1] = refLine[2] = columns;
1298 CCITTFaxStream::~CCITTFaxStream() {
1304 void CCITTFaxStream::reset() {
1310 nextLine2D = encoding < 0;
1313 codingLine[1] = refLine[2] = columns;
1317 // skip any initial zero bits and end-of-line marker, and get the 2D
1319 while ((code1 = lookBits(12)) == 0) {
1322 if (code1 == 0x001) {
1326 nextLine2D = !lookBits(1);
1331 int CCITTFaxStream::lookChar() {
1332 short code1, code2, code3;
1338 // if at eof just return EOF
1339 if (eof && codingLine[a0] >= columns) {
1343 // read the next row
1345 if (codingLine[a0] >= columns) {
1349 for (i = 0; codingLine[i] < columns; ++i)
1350 refLine[i] = codingLine[i];
1351 refLine[i] = refLine[i + 1] = columns;
1353 a0New = codingLine[a0 = 0] = 0;
1355 code1 = getTwoDimCode();
1358 if (refLine[b1] < columns) {
1359 a0New = refLine[b1 + 1];
1364 if ((a0 & 1) == 0) {
1367 code1 += code3 = getWhiteCode();
1368 } while (code3 >= 64);
1370 code2 += code3 = getBlackCode();
1371 } while (code3 >= 64);
1375 code1 += code3 = getBlackCode();
1376 } while (code3 >= 64);
1378 code2 += code3 = getWhiteCode();
1379 } while (code3 >= 64);
1381 if (code1 > 0 || code2 > 0) {
1382 codingLine[a0 + 1] = a0New + code1;
1384 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1386 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1391 a0New = codingLine[++a0] = refLine[b1];
1392 if (refLine[b1] < columns) {
1394 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1399 a0New = codingLine[++a0] = refLine[b1] + 1;
1400 if (refLine[b1] < columns) {
1402 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1407 if (a0 == 0 || refLine[b1] - 1 > a0New) {
1408 a0New = codingLine[++a0] = refLine[b1] - 1;
1410 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1415 a0New = codingLine[++a0] = refLine[b1] + 2;
1416 if (refLine[b1] < columns) {
1418 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1423 if (a0 == 0 || refLine[b1] - 2 > a0New) {
1424 a0New = codingLine[++a0] = refLine[b1] - 2;
1426 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1431 a0New = codingLine[++a0] = refLine[b1] + 3;
1432 if (refLine[b1] < columns) {
1434 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1439 if (a0 == 0 || refLine[b1] - 3 > a0New) {
1440 a0New = codingLine[++a0] = refLine[b1] - 3;
1442 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1448 codingLine[a0 = 0] = columns;
1451 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1455 } while (codingLine[a0] < columns);
1459 codingLine[a0 = 0] = 0;
1463 code1 += code3 = getWhiteCode();
1464 } while (code3 >= 64);
1465 codingLine[a0+1] = codingLine[a0] + code1;
1467 if (codingLine[a0] >= columns)
1471 code2 += code3 = getBlackCode();
1472 } while (code3 >= 64);
1473 codingLine[a0+1] = codingLine[a0] + code2;
1475 if (codingLine[a0] >= columns)
1480 if (codingLine[a0] != columns) {
1481 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
1482 // force the row to be the correct length
1483 while (codingLine[a0] > columns) {
1486 codingLine[++a0] = columns;
1490 // byte-align the row
1495 // check for end-of-line marker, skipping over any extra zero bits
1497 if (!endOfBlock && row == rows - 1) {
1500 code1 = lookBits(12);
1501 while (code1 == 0) {
1503 code1 = lookBits(12);
1505 if (code1 == 0x001) {
1508 } else if (code1 == EOF) {
1513 // get 2D encoding tag
1514 if (!eof && encoding > 0) {
1515 nextLine2D = !lookBits(1);
1519 // check for end-of-block marker
1520 if (endOfBlock && gotEOL) {
1521 code1 = lookBits(12);
1522 if (code1 == 0x001) {
1528 if (encoding >= 0) {
1529 for (i = 0; i < 4; ++i) {
1530 code1 = lookBits(12);
1531 if (code1 != 0x001) {
1532 error(getPos(), "Bad RTC code in CCITTFax stream");
1544 // look for an end-of-line marker after an error -- we only do
1545 // this if we know the stream contains end-of-line markers because
1546 // the "just plow on" technique tends to work better otherwise
1547 } else if (err && endOfLine) {
1554 code1 = lookBits(13);
1555 } while ((code1 >> 1) != 0x001);
1559 nextLine2D = !(code1 & 1);
1564 outputBits = codingLine[1] - codingLine[0];
1565 if (outputBits == 0) {
1567 outputBits = codingLine[2] - codingLine[1];
1574 if (outputBits >= 8) {
1575 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1576 if ((outputBits -= 8) == 0) {
1578 if (codingLine[a0] < columns) {
1579 outputBits = codingLine[a0 + 1] - codingLine[a0];
1586 if (outputBits > bits) {
1589 if ((a0 & 1) == 0) {
1590 ret |= 0xff >> (8 - i);
1596 if ((a0 & 1) == 0) {
1597 ret |= (0xff >> (8 - i)) << bits;
1601 if (codingLine[a0] < columns) {
1602 outputBits = codingLine[a0 + 1] - codingLine[a0];
1605 } while (bits > 0 && codingLine[a0] < columns);
1607 buf = black ? (ret ^ 0xff) : ret;
1611 short CCITTFaxStream::getTwoDimCode() {
1616 code = 0; // make gcc happy
1619 p = &twoDimTab1[code];
1625 for (n = 1; n <= 7; ++n) {
1630 p = &twoDimTab1[code];
1637 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1641 short CCITTFaxStream::getWhiteCode() {
1646 code = 0; // make gcc happy
1648 code = lookBits(12);
1649 if ((code >> 5) == 0) {
1650 p = &whiteTab1[code];
1652 p = &whiteTab2[code >> 3];
1659 for (n = 1; n <= 9; ++n) {
1664 p = &whiteTab2[code];
1670 for (n = 11; n <= 12; ++n) {
1675 p = &whiteTab1[code];
1682 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1683 // eat a bit and return a positive number so that the caller doesn't
1684 // go into an infinite loop
1689 short CCITTFaxStream::getBlackCode() {
1694 code = 0; // make gcc happy
1696 code = lookBits(13);
1697 if ((code >> 7) == 0) {
1698 p = &blackTab1[code];
1699 } else if ((code >> 9) == 0) {
1700 p = &blackTab2[(code >> 1) - 64];
1702 p = &blackTab3[code >> 7];
1709 for (n = 2; n <= 6; ++n) {
1714 p = &blackTab3[code];
1720 for (n = 7; n <= 12; ++n) {
1726 p = &blackTab2[code - 64];
1733 for (n = 10; n <= 13; ++n) {
1738 p = &blackTab1[code];
1745 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
1746 // eat a bit and return a positive number so that the caller doesn't
1747 // go into an infinite loop
1752 short CCITTFaxStream::lookBits(int n) {
1755 while (inputBits < n) {
1756 if ((c = str->getChar()) == EOF) {
1757 if (inputBits == 0) {
1760 // near the end of the stream, the caller may ask for more bits
1761 // than are available, but there may still be a valid code in
1762 // however many bits are available -- we need to return correct
1763 // data in this case
1764 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
1766 inputBuf = (inputBuf << 8) + c;
1769 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1772 GString *CCITTFaxStream::getPSFilter(int psLevel, char *indent) {
1779 if (!(s = str->getPSFilter(psLevel, indent))) {
1782 s->append(indent)->append("<< ");
1783 if (encoding != 0) {
1784 sprintf(s1, "/K %d ", encoding);
1788 s->append("/EndOfLine true ");
1791 s->append("/EncodedByteAlign true ");
1793 sprintf(s1, "/Columns %d ", columns);
1796 sprintf(s1, "/Rows %d ", rows);
1800 s->append("/EndOfBlock false ");
1803 s->append("/BlackIs1 true ");
1805 s->append(">> /CCITTFaxDecode filter\n");
1809 GBool CCITTFaxStream::isBinary(GBool last) {
1810 return str->isBinary(gTrue);
1813 //------------------------------------------------------------------------
1815 //------------------------------------------------------------------------
1817 // IDCT constants (20.12 fixed point format)
1818 #define dctCos1 4017 // cos(pi/16)
1819 #define dctSin1 799 // sin(pi/16)
1820 #define dctCos3 3406 // cos(3*pi/16)
1821 #define dctSin3 2276 // sin(3*pi/16)
1822 #define dctCos6 1567 // cos(6*pi/16)
1823 #define dctSin6 3784 // sin(6*pi/16)
1824 #define dctSqrt2 5793 // sqrt(2)
1825 #define dctSqrt1d2 2896 // sqrt(2) / 2
1827 // color conversion parameters (16.16 fixed point format)
1828 #define dctCrToR 91881 // 1.4020
1829 #define dctCbToG -22553 // -0.3441363
1830 #define dctCrToG -46802 // -0.71413636
1831 #define dctCbToB 116130 // 1.772
1833 // clip [-256,511] --> [0,255]
1834 #define dctClipOffset 256
1835 static Guchar dctClip[768];
1836 static int dctClipInit = 0;
1838 // zig zag decode map
1839 static int dctZigZag[64] = {
1845 5, 12, 19, 26, 33, 40,
1846 48, 41, 34, 27, 20, 13, 6,
1847 7, 14, 21, 28, 35, 42, 49, 56,
1848 57, 50, 43, 36, 29, 22, 15,
1849 23, 30, 37, 44, 51, 58,
1857 DCTStream::DCTStream(Stream *strA):
1858 FilterStream(strA) {
1861 progressive = interleaved = gFalse;
1863 mcuWidth = mcuHeight = 0;
1867 for (i = 0; i < 4; ++i) {
1868 for (j = 0; j < 32; ++j) {
1869 rowBuf[i][j] = NULL;
1875 for (i = -256; i < 0; ++i)
1876 dctClip[dctClipOffset + i] = 0;
1877 for (i = 0; i < 256; ++i)
1878 dctClip[dctClipOffset + i] = i;
1879 for (i = 256; i < 512; ++i)
1880 dctClip[dctClipOffset + i] = 255;
1885 DCTStream::~DCTStream() {
1889 if (progressive || !interleaved) {
1890 for (i = 0; i < numComps; ++i) {
1894 for (i = 0; i < numComps; ++i) {
1895 for (j = 0; j < mcuHeight; ++j) {
1896 gfree(rowBuf[i][j]);
1902 void DCTStream::reset() {
1907 progressive = interleaved = gFalse;
1911 numDCHuffTables = 0;
1912 numACHuffTables = 0;
1914 gotJFIFMarker = gFalse;
1915 gotAdobeMarker = gFalse;
1916 restartInterval = 0;
1918 if (!readHeader()) {
1924 if (numComps == 1) {
1925 compInfo[0].hSample = compInfo[0].vSample = 1;
1927 mcuWidth = compInfo[0].hSample;
1928 mcuHeight = compInfo[0].vSample;
1929 for (i = 1; i < numComps; ++i) {
1930 if (compInfo[i].hSample > mcuWidth) {
1931 mcuWidth = compInfo[i].hSample;
1933 if (compInfo[i].vSample > mcuHeight) {
1934 mcuHeight = compInfo[i].vSample;
1940 // figure out color transform
1941 if (!gotAdobeMarker && numComps == 3) {
1942 if (gotJFIFMarker) {
1944 } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
1945 compInfo[2].id == 66) { // ASCII "RGB"
1952 if (progressive || !interleaved) {
1954 // allocate a buffer for the whole image
1955 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
1956 bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
1957 for (i = 0; i < numComps; ++i) {
1958 frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int));
1959 memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
1962 // read the image data
1964 restartMarker = 0xd0;
1967 } while (readHeader());
1972 // initialize counters
1979 // allocate a buffer for one row of MCUs
1980 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
1981 for (i = 0; i < numComps; ++i) {
1982 for (j = 0; j < mcuHeight; ++j) {
1983 rowBuf[i][j] = (Guchar *)gmallocn(bufWidth, sizeof(Guchar));
1987 // initialize counters
1993 restartMarker = 0xd0;
1998 int DCTStream::getChar() {
2004 if (progressive || !interleaved) {
2005 c = frameBuf[comp][y * bufWidth + x];
2006 if (++comp == numComps) {
2014 if (dy >= mcuHeight) {
2015 if (!readMCURow()) {
2023 c = rowBuf[comp][dy][x];
2024 if (++comp == numComps) {
2039 int DCTStream::lookChar() {
2043 if (progressive || !interleaved) {
2044 return frameBuf[comp][y * bufWidth + x];
2046 if (dy >= mcuHeight) {
2047 if (!readMCURow()) {
2055 return rowBuf[comp][dy][x];
2059 void DCTStream::restart() {
2063 restartCtr = restartInterval;
2064 for (i = 0; i < numComps; ++i) {
2065 compInfo[i].prevDC = 0;
2070 // Read one row of MCUs from a sequential JPEG stream.
2071 GBool DCTStream::readMCURow() {
2075 int pY, pCb, pCr, pR, pG, pB;
2076 int h, v, horiz, vert, hSub, vSub;
2077 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2080 for (x1 = 0; x1 < width; x1 += mcuWidth) {
2082 // deal with restart marker
2083 if (restartInterval > 0 && restartCtr == 0) {
2085 if (c != restartMarker) {
2086 error(getPos(), "Bad DCT data: incorrect restart marker");
2089 if (++restartMarker == 0xd8)
2090 restartMarker = 0xd0;
2095 for (cc = 0; cc < numComps; ++cc) {
2096 h = compInfo[cc].hSample;
2097 v = compInfo[cc].vSample;
2098 horiz = mcuWidth / h;
2099 vert = mcuHeight / v;
2102 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2103 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2104 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2105 &acHuffTables[scanInfo.acHuffTable[cc]],
2106 &compInfo[cc].prevDC,
2110 transformDataUnit(quantTables[compInfo[cc].quantTable],
2112 if (hSub == 1 && vSub == 1) {
2113 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2114 p1 = &rowBuf[cc][y2+y3][x1+x2];
2124 } else if (hSub == 2 && vSub == 2) {
2125 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2126 p1 = &rowBuf[cc][y2+y3][x1+x2];
2127 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
2128 p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
2129 p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
2130 p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
2131 p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
2132 p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
2133 p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
2134 p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
2135 p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
2139 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2140 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2141 for (y5 = 0; y5 < vSub; ++y5)
2142 for (x5 = 0; x5 < hSub; ++x5)
2143 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
2153 // color space conversion
2155 // convert YCbCr to RGB
2156 if (numComps == 3) {
2157 for (y2 = 0; y2 < mcuHeight; ++y2) {
2158 for (x2 = 0; x2 < mcuWidth; ++x2) {
2159 pY = rowBuf[0][y2][x1+x2];
2160 pCb = rowBuf[1][y2][x1+x2] - 128;
2161 pCr = rowBuf[2][y2][x1+x2] - 128;
2162 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2163 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
2164 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2165 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
2166 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2167 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
2170 // convert YCbCrK to CMYK (K is passed through unchanged)
2171 } else if (numComps == 4) {
2172 for (y2 = 0; y2 < mcuHeight; ++y2) {
2173 for (x2 = 0; x2 < mcuWidth; ++x2) {
2174 pY = rowBuf[0][y2][x1+x2];
2175 pCb = rowBuf[1][y2][x1+x2] - 128;
2176 pCr = rowBuf[2][y2][x1+x2] - 128;
2177 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2178 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2179 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2180 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2181 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2182 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2191 // Read one scan from a progressive or non-interleaved JPEG stream.
2192 void DCTStream::readScan() {
2194 int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
2195 int h, v, horiz, vert, vSub;
2199 if (scanInfo.numComps == 1) {
2200 for (cc = 0; cc < numComps; ++cc) {
2201 if (scanInfo.comp[cc]) {
2205 dx1 = mcuWidth / compInfo[cc].hSample;
2206 dy1 = mcuHeight / compInfo[cc].vSample;
2212 for (y1 = 0; y1 < height; y1 += dy1) {
2213 for (x1 = 0; x1 < width; x1 += dx1) {
2215 // deal with restart marker
2216 if (restartInterval > 0 && restartCtr == 0) {
2218 if (c != restartMarker) {
2219 error(getPos(), "Bad DCT data: incorrect restart marker");
2222 if (++restartMarker == 0xd8) {
2223 restartMarker = 0xd0;
2229 for (cc = 0; cc < numComps; ++cc) {
2230 if (!scanInfo.comp[cc]) {
2234 h = compInfo[cc].hSample;
2235 v = compInfo[cc].vSample;
2236 horiz = mcuWidth / h;
2237 vert = mcuHeight / v;
2239 for (y2 = 0; y2 < dy1; y2 += vert) {
2240 for (x2 = 0; x2 < dx1; x2 += horiz) {
2242 // pull out the current values
2243 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2244 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2253 p1 += bufWidth * vSub;
2256 // read one data unit
2258 if (!readProgressiveDataUnit(
2259 &dcHuffTables[scanInfo.dcHuffTable[cc]],
2260 &acHuffTables[scanInfo.acHuffTable[cc]],
2261 &compInfo[cc].prevDC,
2266 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2267 &acHuffTables[scanInfo.acHuffTable[cc]],
2268 &compInfo[cc].prevDC,
2274 // add the data unit into frameBuf
2275 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2276 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2285 p1 += bufWidth * vSub;
2295 // Read one data unit from a sequential JPEG stream.
2296 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2297 DCTHuffTable *acHuffTable,
2298 int *prevDC, int data[64]) {
2303 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2307 if ((amp = readAmp(size)) == 9999) {
2313 data[0] = *prevDC += amp;
2314 for (i = 1; i < 64; ++i) {
2320 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
2329 run += (c >> 4) & 0x0f;
2331 amp = readAmp(size);
2345 // Read one data unit from a sequential JPEG stream.
2346 GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
2347 DCTHuffTable *acHuffTable,
2348 int *prevDC, int data[64]) {
2349 int run, size, amp, bit, c;
2352 // get the DC coefficient
2353 i = scanInfo.firstCoeff;
2355 if (scanInfo.ah == 0) {
2356 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2360 if ((amp = readAmp(size)) == 9999) {
2366 data[0] += (*prevDC += amp) << scanInfo.al;
2368 if ((bit = readBit()) == 9999) {
2371 data[0] += bit << scanInfo.al;
2375 if (scanInfo.lastCoeff == 0) {
2379 // check for an EOB run
2381 while (i <= scanInfo.lastCoeff) {
2384 if ((bit = readBit()) == EOF) {
2388 data[j] += 1 << scanInfo.al;
2396 // read the AC coefficients
2397 while (i <= scanInfo.lastCoeff) {
2398 if ((c = readHuffSym(acHuffTable)) == 9999) {
2410 if ((bit = readBit()) == EOF) {
2414 data[j] += 1 << scanInfo.al;
2420 } else if ((c & 0x0f) == 0x00) {
2423 for (k = 0; k < j; ++k) {
2424 if ((bit = readBit()) == EOF) {
2427 eobRun = (eobRun << 1) | bit;
2430 while (i <= scanInfo.lastCoeff) {
2433 if ((bit = readBit()) == EOF) {
2437 data[j] += 1 << scanInfo.al;
2444 // zero run and one AC coefficient
2446 run = (c >> 4) & 0x0f;
2448 if ((amp = readAmp(size)) == 9999) {
2454 while (data[j] != 0) {
2455 if ((bit = readBit()) == EOF) {
2459 data[j] += 1 << scanInfo.al;
2465 data[j] = amp << scanInfo.al;
2472 // Decode a progressive JPEG image.
2473 void DCTStream::decodeImage() {
2476 Gushort *quantTable;
2477 int pY, pCb, pCr, pR, pG, pB;
2478 int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2479 int h, v, horiz, vert, hSub, vSub;
2482 for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
2483 for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
2484 for (cc = 0; cc < numComps; ++cc) {
2485 quantTable = quantTables[compInfo[cc].quantTable];
2486 h = compInfo[cc].hSample;
2487 v = compInfo[cc].vSample;
2488 horiz = mcuWidth / h;
2489 vert = mcuHeight / v;
2492 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2493 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2495 // pull out the coded data unit
2496 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2497 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2499 dataIn[i+1] = p1[1];
2500 dataIn[i+2] = p1[2];
2501 dataIn[i+3] = p1[3];
2502 dataIn[i+4] = p1[4];
2503 dataIn[i+5] = p1[5];
2504 dataIn[i+6] = p1[6];
2505 dataIn[i+7] = p1[7];
2506 p1 += bufWidth * vSub;
2510 transformDataUnit(quantTable, dataIn, dataOut);
2512 // store back into frameBuf, doing replication for
2513 // subsampled components
2514 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2515 if (hSub == 1 && vSub == 1) {
2516 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2517 p1[0] = dataOut[i] & 0xff;
2518 p1[1] = dataOut[i+1] & 0xff;
2519 p1[2] = dataOut[i+2] & 0xff;
2520 p1[3] = dataOut[i+3] & 0xff;
2521 p1[4] = dataOut[i+4] & 0xff;
2522 p1[5] = dataOut[i+5] & 0xff;
2523 p1[6] = dataOut[i+6] & 0xff;
2524 p1[7] = dataOut[i+7] & 0xff;
2527 } else if (hSub == 2 && vSub == 2) {
2529 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2530 p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
2531 p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
2532 p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
2533 p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
2534 p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
2535 p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
2536 p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
2537 p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
2543 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2544 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2546 for (y5 = 0; y5 < vSub; ++y5) {
2547 for (x5 = 0; x5 < hSub; ++x5) {
2548 p2[x5] = dataOut[i] & 0xff;
2554 p1 += bufWidth * vSub;
2561 // color space conversion
2563 // convert YCbCr to RGB
2564 if (numComps == 3) {
2565 for (y2 = 0; y2 < mcuHeight; ++y2) {
2566 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2567 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2568 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2569 for (x2 = 0; x2 < mcuWidth; ++x2) {
2573 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2574 *p0++ = dctClip[dctClipOffset + pR];
2575 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2577 *p1++ = dctClip[dctClipOffset + pG];
2578 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2579 *p2++ = dctClip[dctClipOffset + pB];
2582 // convert YCbCrK to CMYK (K is passed through unchanged)
2583 } else if (numComps == 4) {
2584 for (y2 = 0; y2 < mcuHeight; ++y2) {
2585 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2586 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2587 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2588 for (x2 = 0; x2 < mcuWidth; ++x2) {
2592 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2593 *p0++ = 255 - dctClip[dctClipOffset + pR];
2594 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2596 *p1++ = 255 - dctClip[dctClipOffset + pG];
2597 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2598 *p2++ = 255 - dctClip[dctClipOffset + pB];
2607 // Transform one data unit -- this performs the dequantization and
2608 // IDCT steps. This IDCT algorithm is taken from:
2609 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2610 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2611 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2613 // The stage numbers mentioned in the comments refer to Figure 1 in this
2615 void DCTStream::transformDataUnit(Gushort *quantTable,
2616 int dataIn[64], Guchar dataOut[64]) {
2617 int v0, v1, v2, v3, v4, v5, v6, v7, t;
2622 for (i = 0; i < 64; ++i) {
2623 dataIn[i] *= quantTable[i];
2626 // inverse DCT on rows
2627 for (i = 0; i < 64; i += 8) {
2630 // check for all-zero AC coefficients
2631 if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
2632 p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
2633 t = (dctSqrt2 * p[0] + 512) >> 10;
2646 v0 = (dctSqrt2 * p[0] + 128) >> 8;
2647 v1 = (dctSqrt2 * p[4] + 128) >> 8;
2650 v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
2651 v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
2656 t = (v0 - v1+ 1) >> 1;
2657 v0 = (v0 + v1 + 1) >> 1;
2659 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2660 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2662 t = (v4 - v6 + 1) >> 1;
2663 v4 = (v4 + v6 + 1) >> 1;
2665 t = (v7 + v5 + 1) >> 1;
2666 v5 = (v7 - v5 + 1) >> 1;
2670 t = (v0 - v3 + 1) >> 1;
2671 v0 = (v0 + v3 + 1) >> 1;
2673 t = (v1 - v2 + 1) >> 1;
2674 v1 = (v1 + v2 + 1) >> 1;
2676 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2677 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2679 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2680 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2694 // inverse DCT on columns
2695 for (i = 0; i < 8; ++i) {
2698 // check for all-zero AC coefficients
2699 if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
2700 p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
2701 t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
2714 v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
2715 v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
2718 v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
2719 v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
2724 t = (v0 - v1 + 1) >> 1;
2725 v0 = (v0 + v1 + 1) >> 1;
2727 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2728 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2730 t = (v4 - v6 + 1) >> 1;
2731 v4 = (v4 + v6 + 1) >> 1;
2733 t = (v7 + v5 + 1) >> 1;
2734 v5 = (v7 - v5 + 1) >> 1;
2738 t = (v0 - v3 + 1) >> 1;
2739 v0 = (v0 + v3 + 1) >> 1;
2741 t = (v1 - v2 + 1) >> 1;
2742 v1 = (v1 + v2 + 1) >> 1;
2744 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2745 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2747 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2748 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2762 // convert to 8-bit integers
2763 for (i = 0; i < 64; ++i) {
2764 dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
2768 int DCTStream::readHuffSym(DCTHuffTable *table) {
2776 // add a bit to the code
2777 if ((bit = readBit()) == EOF)
2779 code = (code << 1) + bit;
2783 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2784 code -= table->firstCode[codeBits];
2785 return table->sym[table->firstSym[codeBits] + code];
2787 } while (codeBits < 16);
2789 error(getPos(), "Bad Huffman code in DCT stream");
2793 int DCTStream::readAmp(int size) {
2798 for (bits = 0; bits < size; ++bits) {
2799 if ((bit = readBit()) == EOF)
2801 amp = (amp << 1) + bit;
2803 if (amp < (1 << (size - 1)))
2804 amp -= (1 << size) - 1;
2808 int DCTStream::readBit() {
2812 if (inputBits == 0) {
2813 if ((c = str->getChar()) == EOF)
2817 c2 = str->getChar();
2818 } while (c2 == 0xff);
2820 error(getPos(), "Bad DCT data: missing 00 after ff");
2827 bit = (inputBuf >> (inputBits - 1)) & 1;
2832 GBool DCTStream::readHeader() {
2843 case 0xc0: // SOF0 (sequential)
2844 case 0xc1: // SOF1 (extended sequential)
2845 if (!readBaselineSOF()) {
2849 case 0xc2: // SOF2 (progressive)
2850 if (!readProgressiveSOF()) {
2855 if (!readHuffmanTables()) {
2864 if (!readScanInfo()) {
2870 if (!readQuantTables()) {
2875 if (!readRestartInterval()) {
2880 if (!readJFIFMarker()) {
2885 if (!readAdobeMarker()) {
2890 error(getPos(), "Bad DCT header");
2893 // skip APPn / COM / etc.
2896 for (i = 0; i < n; ++i) {
2900 error(getPos(), "Unknown DCT marker <%02x>", c);
2910 GBool DCTStream::readBaselineSOF() {
2917 prec = str->getChar();
2920 numComps = str->getChar();
2921 if (numComps <= 0 || numComps > 4) {
2922 error(getPos(), "Bad number of components in DCT stream", prec);
2925 if (numComps <= 0 || numComps > 4) {
2926 error(getPos(), "Bad number of components in DCT stream", prec);
2930 error(getPos(), "Bad DCT precision %d", prec);
2933 for (i = 0; i < numComps; ++i) {
2934 compInfo[i].id = str->getChar();
2936 compInfo[i].hSample = (c >> 4) & 0x0f;
2937 compInfo[i].vSample = c & 0x0f;
2938 compInfo[i].quantTable = str->getChar();
2940 progressive = gFalse;
2944 GBool DCTStream::readProgressiveSOF() {
2951 prec = str->getChar();
2954 numComps = str->getChar();
2956 error(getPos(), "Bad DCT precision %d", prec);
2959 for (i = 0; i < numComps; ++i) {
2960 compInfo[i].id = str->getChar();
2962 compInfo[i].hSample = (c >> 4) & 0x0f;
2963 compInfo[i].vSample = c & 0x0f;
2964 compInfo[i].quantTable = str->getChar();
2966 progressive = gTrue;
2970 GBool DCTStream::readScanInfo() {
2975 length = read16() - 2;
2976 scanInfo.numComps = str->getChar();
2978 if (length != 2 * scanInfo.numComps + 3) {
2979 error(getPos(), "Bad DCT scan info block");
2982 interleaved = scanInfo.numComps == numComps;
2983 for (j = 0; j < numComps; ++j) {
2984 scanInfo.comp[j] = gFalse;
2986 for (i = 0; i < scanInfo.numComps; ++i) {
2987 id = str->getChar();
2988 // some (broken) DCT streams reuse ID numbers, but at least they
2989 // keep the components in order, so we check compInfo[i] first to
2990 // work around the problem
2991 if (id == compInfo[i].id) {
2994 for (j = 0; j < numComps; ++j) {
2995 if (id == compInfo[j].id) {
2999 if (j == numComps) {
3000 error(getPos(), "Bad DCT component ID in scan info block");
3004 scanInfo.comp[j] = gTrue;
3006 scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
3007 scanInfo.acHuffTable[j] = c & 0x0f;
3009 scanInfo.firstCoeff = str->getChar();
3010 scanInfo.lastCoeff = str->getChar();
3012 scanInfo.ah = (c >> 4) & 0x0f;
3013 scanInfo.al = c & 0x0f;
3017 GBool DCTStream::readQuantTables() {
3018 int length, prec, i, index;
3020 length = read16() - 2;
3021 while (length > 0) {
3022 index = str->getChar();
3023 prec = (index >> 4) & 0x0f;
3025 if (prec > 1 || index >= 4) {
3026 error(getPos(), "Bad DCT quantization table");
3029 if (index == numQuantTables) {
3030 numQuantTables = index + 1;
3032 for (i = 0; i < 64; ++i) {
3034 quantTables[index][dctZigZag[i]] = read16();
3036 quantTables[index][dctZigZag[i]] = str->getChar();
3048 GBool DCTStream::readHuffmanTables() {
3057 length = read16() - 2;
3058 while (length > 0) {
3059 index = str->getChar();
3061 if ((index & 0x0f) >= 4) {
3062 error(getPos(), "Bad DCT Huffman table");
3067 if (index >= numACHuffTables)
3068 numACHuffTables = index+1;
3069 tbl = &acHuffTables[index];
3071 if (index >= numDCHuffTables)
3072 numDCHuffTables = index+1;
3073 tbl = &dcHuffTables[index];
3077 for (i = 1; i <= 16; ++i) {
3079 tbl->firstSym[i] = sym;
3080 tbl->firstCode[i] = code;
3081 tbl->numCodes[i] = c;
3083 code = (code + c) << 1;
3086 for (i = 0; i < sym; ++i)
3087 tbl->sym[i] = str->getChar();
3093 GBool DCTStream::readRestartInterval() {
3098 error(getPos(), "Bad DCT restart interval");
3101 restartInterval = read16();
3105 GBool DCTStream::readJFIFMarker() {
3113 for (i = 0; i < 5; ++i) {
3114 if ((c = str->getChar()) == EOF) {
3115 error(getPos(), "Bad DCT APP0 marker");
3121 if (!memcmp(buf, "JFIF\0", 5)) {
3122 gotJFIFMarker = gTrue;
3125 while (length > 0) {
3126 if (str->getChar() == EOF) {
3127 error(getPos(), "Bad DCT APP0 marker");
3135 GBool DCTStream::readAdobeMarker() {
3144 for (i = 0; i < 12; ++i) {
3145 if ((c = str->getChar()) == EOF) {
3150 if (strncmp(buf, "Adobe", 5)) {
3153 colorXform = buf[11];
3154 gotAdobeMarker = gTrue;
3155 for (i = 14; i < length; ++i) {
3156 if (str->getChar() == EOF) {
3163 error(getPos(), "Bad DCT Adobe APP14 marker");
3167 GBool DCTStream::readTrailer() {
3171 if (c != 0xd9) { // EOI
3172 error(getPos(), "Bad DCT trailer");
3178 int DCTStream::readMarker() {
3184 } while (c != 0xff && c != EOF);
3187 } while (c == 0xff);
3188 } while (c == 0x00);
3192 int DCTStream::read16() {
3195 if ((c1 = str->getChar()) == EOF)
3197 if ((c2 = str->getChar()) == EOF)
3199 return (c1 << 8) + c2;
3202 GString *DCTStream::getPSFilter(int psLevel, char *indent) {
3208 if (!(s = str->getPSFilter(psLevel, indent))) {
3211 s->append(indent)->append("<< >> /DCTDecode filter\n");
3215 GBool DCTStream::isBinary(GBool last) {
3216 return str->isBinary(gTrue);
3219 //------------------------------------------------------------------------
3221 //------------------------------------------------------------------------
3223 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
3224 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3227 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
3261 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
3294 static FlateCode flateFixedLitCodeTabCodes[512] = {
3809 FlateHuffmanTab FlateStream::fixedLitCodeTab = {
3810 flateFixedLitCodeTabCodes, 9
3813 static FlateCode flateFixedDistCodeTabCodes[32] = {
3848 FlateHuffmanTab FlateStream::fixedDistCodeTab = {
3849 flateFixedDistCodeTabCodes, 5
3852 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
3853 int colors, int bits):
3854 FilterStream(strA) {
3855 if (predictor != 1) {
3856 pred = new StreamPredictor(this, predictor, columns, colors, bits);
3857 if (!pred->isOk()) {
3864 litCodeTab.codes = NULL;
3865 distCodeTab.codes = NULL;
3868 FlateStream::~FlateStream() {
3869 if (litCodeTab.codes != fixedLitCodeTab.codes) {
3870 gfree(litCodeTab.codes);
3872 if (distCodeTab.codes != fixedDistCodeTab.codes) {
3873 gfree(distCodeTab.codes);
3881 void FlateStream::reset() {
3888 compressedBlock = gFalse;
3895 //~ need to look at window size?
3896 endOfBlock = eof = gTrue;
3897 cmf = str->getChar();
3898 flg = str->getChar();
3899 if (cmf == EOF || flg == EOF)
3901 if ((cmf & 0x0f) != 0x08) {
3902 error(getPos(), "Unknown compression method in flate stream");
3905 if ((((cmf << 8) + flg) % 31) != 0) {
3906 error(getPos(), "Bad FCHECK in flate stream");
3910 error(getPos(), "FDICT bit set in flate stream");
3917 int FlateStream::getChar() {
3921 return pred->getChar();
3923 while (remain == 0) {
3924 if (endOfBlock && eof)
3929 index = (index + 1) & flateMask;
3934 int FlateStream::lookChar() {
3938 return pred->lookChar();
3940 while (remain == 0) {
3941 if (endOfBlock && eof)
3949 int FlateStream::getRawChar() {
3952 while (remain == 0) {
3953 if (endOfBlock && eof)
3958 index = (index + 1) & flateMask;
3963 GString *FlateStream::getPSFilter(int psLevel, char *indent) {
3966 if (psLevel < 3 || pred) {
3969 if (!(s = str->getPSFilter(psLevel, indent))) {
3972 s->append(indent)->append("<< >> /FlateDecode filter\n");
3976 GBool FlateStream::isBinary(GBool last) {
3977 return str->isBinary(gTrue);
3980 void FlateStream::readSome() {
3991 if (compressedBlock) {
3992 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
3997 } else if (code1 == 256) {
4002 code2 = lengthDecode[code1].bits;
4003 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
4005 len = lengthDecode[code1].first + code2;
4006 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
4008 code2 = distDecode[code1].bits;
4009 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
4011 dist = distDecode[code1].first + code2;
4013 j = (index - dist) & flateMask;
4014 for (k = 0; k < len; ++k) {
4016 i = (i + 1) & flateMask;
4017 j = (j + 1) & flateMask;
4023 len = (blockLen < flateWindow) ? blockLen : flateWindow;
4024 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
4025 if ((c = str->getChar()) == EOF) {
4026 endOfBlock = eof = gTrue;
4040 error(getPos(), "Unexpected end of file in flate stream");
4041 endOfBlock = eof = gTrue;
4045 GBool FlateStream::startBlock() {
4050 // free the code tables from the previous block
4051 if (litCodeTab.codes != fixedLitCodeTab.codes) {
4052 gfree(litCodeTab.codes);
4054 litCodeTab.codes = NULL;
4055 if (distCodeTab.codes != fixedDistCodeTab.codes) {
4056 gfree(distCodeTab.codes);
4058 distCodeTab.codes = NULL;
4060 // read block header
4061 blockHdr = getCodeWord(3);
4066 // uncompressed block
4067 if (blockHdr == 0) {
4068 compressedBlock = gFalse;
4069 if ((c = str->getChar()) == EOF)
4071 blockLen = c & 0xff;
4072 if ((c = str->getChar()) == EOF)
4074 blockLen |= (c & 0xff) << 8;
4075 if ((c = str->getChar()) == EOF)
4078 if ((c = str->getChar()) == EOF)
4080 check |= (c & 0xff) << 8;
4081 if (check != (~blockLen & 0xffff))
4082 error(getPos(), "Bad uncompressed block length in flate stream");
4086 // compressed block with fixed codes
4087 } else if (blockHdr == 1) {
4088 compressedBlock = gTrue;
4091 // compressed block with dynamic codes
4092 } else if (blockHdr == 2) {
4093 compressedBlock = gTrue;
4094 if (!readDynamicCodes()) {
4098 // unknown block type
4103 endOfBlock = gFalse;
4107 error(getPos(), "Bad block header in flate stream");
4108 endOfBlock = eof = gTrue;
4112 void FlateStream::loadFixedCodes() {
4113 litCodeTab.codes = fixedLitCodeTab.codes;
4114 litCodeTab.maxLen = fixedLitCodeTab.maxLen;
4115 distCodeTab.codes = fixedDistCodeTab.codes;
4116 distCodeTab.maxLen = fixedDistCodeTab.maxLen;
4119 GBool FlateStream::readDynamicCodes() {
4120 int numCodeLenCodes;
4123 int codeLenCodeLengths[flateMaxCodeLenCodes];
4124 FlateHuffmanTab codeLenCodeTab;
4125 int len, repeat, code;
4128 codeLenCodeTab.codes = NULL;
4131 if ((numLitCodes = getCodeWord(5)) == EOF) {
4135 if ((numDistCodes = getCodeWord(5)) == EOF) {
4139 if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
4142 numCodeLenCodes += 4;
4143 if (numLitCodes > flateMaxLitCodes ||
4144 numDistCodes > flateMaxDistCodes ||
4145 numCodeLenCodes > flateMaxCodeLenCodes) {
4149 // build the code length code table
4150 for (i = 0; i < flateMaxCodeLenCodes; ++i) {
4151 codeLenCodeLengths[i] = 0;
4153 for (i = 0; i < numCodeLenCodes; ++i) {
4154 if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
4158 compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
4160 // build the literal and distance code tables
4164 while (i < numLitCodes + numDistCodes) {
4165 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
4169 if ((repeat = getCodeWord(2)) == EOF) {
4173 if (i + repeat > numLitCodes + numDistCodes) {
4176 for (; repeat > 0; --repeat) {
4177 codeLengths[i++] = len;
4179 } else if (code == 17) {
4180 if ((repeat = getCodeWord(3)) == EOF) {
4184 if (i + repeat > numLitCodes + numDistCodes) {
4188 for (; repeat > 0; --repeat) {
4189 codeLengths[i++] = 0;
4191 } else if (code == 18) {
4192 if ((repeat = getCodeWord(7)) == EOF) {
4196 if (i + repeat > numLitCodes + numDistCodes) {
4200 for (; repeat > 0; --repeat) {
4201 codeLengths[i++] = 0;
4204 codeLengths[i++] = len = code;
4207 compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
4208 compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
4210 gfree(codeLenCodeTab.codes);
4214 error(getPos(), "Bad dynamic code table in flate stream");
4215 gfree(codeLenCodeTab.codes);
4219 // Convert an array <lengths> of <n> lengths, in value order, into a
4220 // Huffman code lookup table.
4221 void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
4222 int tabSize, len, code, code2, skip, val, i, t;
4224 // find max code length
4226 for (val = 0; val < n; ++val) {
4227 if (lengths[val] > tab->maxLen) {
4228 tab->maxLen = lengths[val];
4232 // allocate the table
4233 tabSize = 1 << tab->maxLen;
4234 tab->codes = (FlateCode *)gmallocn(tabSize, sizeof(FlateCode));
4237 for (i = 0; i < tabSize; ++i) {
4238 tab->codes[i].len = 0;
4239 tab->codes[i].val = 0;
4243 for (len = 1, code = 0, skip = 2;
4245 ++len, code <<= 1, skip <<= 1) {
4246 for (val = 0; val < n; ++val) {
4247 if (lengths[val] == len) {
4249 // bit-reverse the code
4252 for (i = 0; i < len; ++i) {
4253 code2 = (code2 << 1) | (t & 1);
4257 // fill in the table entries
4258 for (i = code2; i < tabSize; i += skip) {
4259 tab->codes[i].len = (Gushort)len;
4260 tab->codes[i].val = (Gushort)val;
4269 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
4273 while (codeSize < tab->maxLen) {
4274 if ((c = str->getChar()) == EOF) {
4277 codeBuf |= (c & 0xff) << codeSize;
4280 code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
4281 if (codeSize == 0 || codeSize < code->len || code->len == 0) {
4284 codeBuf >>= code->len;
4285 codeSize -= code->len;
4286 return (int)code->val;
4289 int FlateStream::getCodeWord(int bits) {
4292 while (codeSize < bits) {
4293 if ((c = str->getChar()) == EOF)
4295 codeBuf |= (c & 0xff) << codeSize;
4298 c = codeBuf & ((1 << bits) - 1);
4304 //------------------------------------------------------------------------
4306 //------------------------------------------------------------------------
4308 EOFStream::EOFStream(Stream *strA):
4309 FilterStream(strA) {
4312 EOFStream::~EOFStream() {
4316 //------------------------------------------------------------------------
4317 // FixedLengthEncoder
4318 //------------------------------------------------------------------------
4320 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
4321 FilterStream(strA) {
4326 FixedLengthEncoder::~FixedLengthEncoder() {
4327 if (str->isEncoder())
4331 void FixedLengthEncoder::reset() {
4336 int FixedLengthEncoder::getChar() {
4337 if (length >= 0 && count >= length)
4340 return str->getChar();
4343 int FixedLengthEncoder::lookChar() {
4344 if (length >= 0 && count >= length)
4346 return str->getChar();
4349 GBool FixedLengthEncoder::isBinary(GBool last) {
4350 return str->isBinary(gTrue);
4353 //------------------------------------------------------------------------
4355 //------------------------------------------------------------------------
4357 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
4358 FilterStream(strA) {
4359 bufPtr = bufEnd = buf;
4364 ASCIIHexEncoder::~ASCIIHexEncoder() {
4365 if (str->isEncoder()) {
4370 void ASCIIHexEncoder::reset() {
4372 bufPtr = bufEnd = buf;
4377 GBool ASCIIHexEncoder::fillBuf() {
4378 static char *hex = "0123456789abcdef";
4384 bufPtr = bufEnd = buf;
4385 if ((c = str->getChar()) == EOF) {
4389 if (lineLen >= 64) {
4393 *bufEnd++ = hex[(c >> 4) & 0x0f];
4394 *bufEnd++ = hex[c & 0x0f];
4400 //------------------------------------------------------------------------
4402 //------------------------------------------------------------------------
4404 ASCII85Encoder::ASCII85Encoder(Stream *strA):
4405 FilterStream(strA) {
4406 bufPtr = bufEnd = buf;
4411 ASCII85Encoder::~ASCII85Encoder() {
4412 if (str->isEncoder())
4416 void ASCII85Encoder::reset() {
4418 bufPtr = bufEnd = buf;
4423 GBool ASCII85Encoder::fillBuf() {
4432 for (n = 0; n < 4; ++n) {
4433 if ((c = str->getChar()) == EOF)
4437 bufPtr = bufEnd = buf;
4439 if (n == 4 && t == 0) {
4441 if (++lineLen == 65) {
4448 for (i = 4; i >= 0; --i) {
4449 buf1[i] = (char)(t % 85 + 0x21);
4452 for (i = 0; i <= n; ++i) {
4453 *bufEnd++ = buf1[i];
4454 if (++lineLen == 65) {
4466 return bufPtr < bufEnd;
4469 //------------------------------------------------------------------------
4471 //------------------------------------------------------------------------
4473 RunLengthEncoder::RunLengthEncoder(Stream *strA):
4474 FilterStream(strA) {
4475 bufPtr = bufEnd = nextEnd = buf;
4479 RunLengthEncoder::~RunLengthEncoder() {
4480 if (str->isEncoder())
4484 void RunLengthEncoder::reset() {
4486 bufPtr = bufEnd = nextEnd = buf;
4491 // When fillBuf finishes, buf[] looks like this:
4492 // +-----+--------------+-----------------+--
4493 // + tag | ... data ... | next 0, 1, or 2 |
4494 // +-----+--------------+-----------------+--
4496 // bufPtr bufEnd nextEnd
4498 GBool RunLengthEncoder::fillBuf() {
4507 if (nextEnd < bufEnd + 1) {
4508 if ((c1 = str->getChar()) == EOF) {
4513 c1 = bufEnd[0] & 0xff;
4515 if (nextEnd < bufEnd + 2) {
4516 if ((c2 = str->getChar()) == EOF) {
4525 c2 = bufEnd[1] & 0xff;
4529 c = 0; // make gcc happy
4532 while (n < 128 && (c = str->getChar()) == c1)
4534 buf[0] = (char)(257 - n);
4539 } else if (n < 128) {
4546 // get up to 128 chars
4552 if ((c = str->getChar()) == EOF) {
4558 if (buf[n] == buf[n-1])
4561 if (buf[n] == buf[n-1]) {
4562 buf[0] = (char)(n-2-1);
4564 nextEnd = &buf[n+1];
4566 buf[0] = (char)(n-1);
4567 bufEnd = nextEnd = &buf[n+1];