1 //========================================================================
5 // Copyright 1996-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
21 extern "C" int unlink(char *filename);
34 #include "JBIG2Stream.h"
35 #include "JPXStream.h"
36 #include "Stream-CCITT.h"
39 static GBool setDJSYSFLAGS = gFalse;
50 //------------------------------------------------------------------------
51 // Stream (base class)
52 //------------------------------------------------------------------------
61 void Stream::close() {
64 int Stream::getRawChar() {
65 error(-1, "Internal: called getRawChar() on non-predictor stream");
69 char *Stream::getLine(char *buf, int size) {
73 if (lookChar() == EOF)
75 for (i = 0; i < size - 1; ++i) {
77 if (c == EOF || c == '\n')
80 if ((c = lookChar()) == '\n')
90 GString *Stream::getPSFilter(int psLevel, char *indent) {
94 Stream *Stream::addFilters(Object *dict) {
96 Object params, params2;
101 dict->dictLookup("Filter", &obj);
104 dict->dictLookup("F", &obj);
106 dict->dictLookup("DecodeParms", ¶ms);
107 if (params.isNull()) {
109 dict->dictLookup("DP", ¶ms);
112 str = makeFilter(obj.getName(), str, ¶ms);
113 } else if (obj.isArray()) {
114 for (i = 0; i < obj.arrayGetLength(); ++i) {
115 obj.arrayGet(i, &obj2);
116 if (params.isArray())
117 params.arrayGet(i, ¶ms2);
121 str = makeFilter(obj2.getName(), str, ¶ms2);
123 error(getPos(), "Bad filter name");
124 str = new EOFStream(str);
129 } else if (!obj.isNull()) {
130 error(getPos(), "Bad 'Filter' attribute in stream");
138 Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
139 int pred; // parameters
144 GBool endOfLine, byteAlign, endOfBlock, black;
148 if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
149 str = new ASCIIHexStream(str);
150 } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
151 str = new ASCII85Stream(str);
152 } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
158 if (params->isDict()) {
159 params->dictLookup("Predictor", &obj);
163 params->dictLookup("Columns", &obj);
165 columns = obj.getInt();
167 params->dictLookup("Colors", &obj);
169 colors = obj.getInt();
171 params->dictLookup("BitsPerComponent", &obj);
175 params->dictLookup("EarlyChange", &obj);
177 early = obj.getInt();
180 str = new LZWStream(str, pred, columns, colors, bits, early);
181 } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
182 str = new RunLengthStream(str);
183 } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
191 if (params->isDict()) {
192 params->dictLookup("K", &obj);
194 encoding = obj.getInt();
197 params->dictLookup("EndOfLine", &obj);
199 endOfLine = obj.getBool();
202 params->dictLookup("EncodedByteAlign", &obj);
204 byteAlign = obj.getBool();
207 params->dictLookup("Columns", &obj);
209 columns = obj.getInt();
212 params->dictLookup("Rows", &obj);
217 params->dictLookup("EndOfBlock", &obj);
219 endOfBlock = obj.getBool();
222 params->dictLookup("BlackIs1", &obj);
224 black = obj.getBool();
228 str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
229 columns, rows, endOfBlock, black);
230 } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
231 str = new DCTStream(str);
232 } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
237 if (params->isDict()) {
238 params->dictLookup("Predictor", &obj);
242 params->dictLookup("Columns", &obj);
244 columns = obj.getInt();
246 params->dictLookup("Colors", &obj);
248 colors = obj.getInt();
250 params->dictLookup("BitsPerComponent", &obj);
255 str = new FlateStream(str, pred, columns, colors, bits);
256 } else if (!strcmp(name, "JBIG2Decode")) {
257 if (params->isDict()) {
258 params->dictLookup("JBIG2Globals", &globals);
260 str = new JBIG2Stream(str, &globals);
262 } else if (!strcmp(name, "JPXDecode")) {
263 str = new JPXStream(str);
265 error(getPos(), "Unknown filter '%s'", name);
266 str = new EOFStream(str);
271 //------------------------------------------------------------------------
273 //------------------------------------------------------------------------
275 BaseStream::BaseStream(Object *dictA) {
280 BaseStream::~BaseStream() {
286 void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
287 int objNum, int objGen) {
288 decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
291 //------------------------------------------------------------------------
293 //------------------------------------------------------------------------
295 FilterStream::FilterStream(Stream *strA) {
299 FilterStream::~FilterStream() {
302 void FilterStream::close() {
306 void FilterStream::setPos(Guint pos, int dir) {
307 error(-1, "Internal: called setPos() on FilterStream");
310 //------------------------------------------------------------------------
312 //------------------------------------------------------------------------
314 ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
322 nVals = width * nComps;
324 imgLineSize = (nVals + 7) & ~7;
328 imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar));
332 ImageStream::~ImageStream() {
336 void ImageStream::reset() {
340 GBool ImageStream::getPixel(Guchar *pix) {
343 if (imgIdx >= nVals) {
347 for (i = 0; i < nComps; ++i) {
348 pix[i] = imgLine[imgIdx++];
353 Guchar *ImageStream::getLine() {
360 for (i = 0; i < nVals; i += 8) {
362 imgLine[i+0] = (Guchar)((c >> 7) & 1);
363 imgLine[i+1] = (Guchar)((c >> 6) & 1);
364 imgLine[i+2] = (Guchar)((c >> 5) & 1);
365 imgLine[i+3] = (Guchar)((c >> 4) & 1);
366 imgLine[i+4] = (Guchar)((c >> 3) & 1);
367 imgLine[i+5] = (Guchar)((c >> 2) & 1);
368 imgLine[i+6] = (Guchar)((c >> 1) & 1);
369 imgLine[i+7] = (Guchar)(c & 1);
371 } else if (nBits == 8) {
372 for (i = 0; i < nVals; ++i) {
373 imgLine[i] = str->getChar();
376 bitMask = (1 << nBits) - 1;
379 for (i = 0; i < nVals; ++i) {
381 buf = (buf << 8) | (str->getChar() & 0xff);
384 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
391 void ImageStream::skipLine() {
394 n = (nVals * nBits + 7) >> 3;
395 for (i = 0; i < n; ++i) {
400 //------------------------------------------------------------------------
402 //------------------------------------------------------------------------
404 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
405 int widthA, int nCompsA, int nBitsA) {
409 predictor = predictorA;
416 nVals = width * nComps;
417 totalBits = nVals * nBits;
418 if (totalBits == 0 ||
419 (totalBits / nBits) / nComps != width ||
423 pixBytes = (nComps * nBits + 7) >> 3;
424 rowBytes = ((totalBits + 7) >> 3) + pixBytes;
428 predLine = (Guchar *)gmalloc(rowBytes);
429 memset(predLine, 0, rowBytes);
435 StreamPredictor::~StreamPredictor() {
439 int StreamPredictor::lookChar() {
440 if (predIdx >= rowBytes) {
441 if (!getNextLine()) {
445 return predLine[predIdx];
448 int StreamPredictor::getChar() {
449 if (predIdx >= rowBytes) {
450 if (!getNextLine()) {
454 return predLine[predIdx++];
457 GBool StreamPredictor::getNextLine() {
459 Guchar upLeftBuf[gfxColorMaxComps * 2 + 1];
460 int left, up, upLeft, p, pa, pb, pc;
462 Gulong inBuf, outBuf, bitMask;
466 // get PNG optimum predictor number
467 if (predictor >= 10) {
468 if ((curPred = str->getRawChar()) == EOF) {
476 // read the raw line, apply PNG (byte) predictor
477 memset(upLeftBuf, 0, pixBytes + 1);
478 for (i = pixBytes; i < rowBytes; ++i) {
479 for (j = pixBytes; j > 0; --j) {
480 upLeftBuf[j] = upLeftBuf[j-1];
482 upLeftBuf[0] = predLine[i];
483 if ((c = str->getRawChar()) == EOF) {
485 // this ought to return false, but some (broken) PDF files
486 // contain truncated image data, and Adobe apparently reads the
494 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
497 predLine[i] = predLine[i] + (Guchar)c;
499 case 13: // PNG average
500 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
503 case 14: // PNG Paeth
504 left = predLine[i - pixBytes];
506 upLeft = upLeftBuf[pixBytes];
507 p = left + up - upLeft;
508 if ((pa = p - left) < 0)
510 if ((pb = p - up) < 0)
512 if ((pc = p - upLeft) < 0)
514 if (pa <= pb && pa <= pc)
515 predLine[i] = left + (Guchar)c;
517 predLine[i] = up + (Guchar)c;
519 predLine[i] = upLeft + (Guchar)c;
522 default: // no predictor or TIFF predictor
523 predLine[i] = (Guchar)c;
528 // apply TIFF (component) predictor
529 if (predictor == 2) {
531 inBuf = predLine[pixBytes - 1];
532 for (i = pixBytes; i < rowBytes; i += 8) {
533 // 1-bit add is just xor
534 inBuf = (inBuf << 8) | predLine[i];
535 predLine[i] ^= inBuf >> nComps;
537 } else if (nBits == 8) {
538 for (i = pixBytes; i < rowBytes; ++i) {
539 predLine[i] += predLine[i - nComps];
542 memset(upLeftBuf, 0, nComps + 1);
543 bitMask = (1 << nBits) - 1;
545 inBits = outBits = 0;
547 for (i = 0; i < width; ++i) {
548 for (kk = 0; kk < nComps; ++kk) {
549 if (inBits < nBits) {
550 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
553 upLeftBuf[kk] = (upLeftBuf[kk] +
554 (inBuf >> (inBits - nBits))) & bitMask;
556 outBuf = (outBuf << nBits) | upLeftBuf[kk];
559 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
565 predLine[k++] = (Guchar)((outBuf << (8 - outBits)) +
566 (inBuf & ((1 << (8 - outBits)) - 1)));
571 // reset to start of line
577 //------------------------------------------------------------------------
579 //------------------------------------------------------------------------
581 FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
582 Guint lengthA, Object *dictA):
588 bufPtr = bufEnd = buf;
594 FileStream::~FileStream() {
598 Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
599 Guint lengthA, Object *dictA) {
600 return new FileStream(f, startA, limitedA, lengthA, dictA);
603 void FileStream::reset() {
605 savePos = (Guint)ftello(f);
606 fseeko(f, start, SEEK_SET);
608 savePos = (Guint)ftell64(f);
609 fseek64(f, start, SEEK_SET);
611 savePos = (Guint)ftell(f);
612 fseek(f, start, SEEK_SET);
615 bufPtr = bufEnd = buf;
621 void FileStream::close() {
624 fseeko(f, savePos, SEEK_SET);
626 fseek64(f, savePos, SEEK_SET);
628 fseek(f, savePos, SEEK_SET);
634 GBool FileStream::fillBuf() {
638 bufPos += bufEnd - buf;
639 bufPtr = bufEnd = buf;
640 if (limited && bufPos >= start + length) {
643 if (limited && bufPos + fileStreamBufSize > start + length) {
644 n = start + length - bufPos;
646 n = fileStreamBufSize;
648 n = fread(buf, 1, n, f);
650 if (bufPtr >= bufEnd) {
654 for (p = buf; p < bufEnd; ++p) {
655 *p = (char)decrypt->decryptByte((Guchar)*p);
661 void FileStream::setPos(Guint pos, int dir) {
666 fseeko(f, pos, SEEK_SET);
668 fseek64(f, pos, SEEK_SET);
670 fseek(f, pos, SEEK_SET);
675 fseeko(f, 0, SEEK_END);
676 size = (Guint)ftello(f);
678 fseek64(f, 0, SEEK_END);
679 size = (Guint)ftell64(f);
681 fseek(f, 0, SEEK_END);
682 size = (Guint)ftell(f);
687 //~ work around a bug in cygwin's implementation of fseek
691 fseeko(f, -(int)pos, SEEK_END);
692 bufPos = (Guint)ftello(f);
694 fseek64(f, -(int)pos, SEEK_END);
695 bufPos = (Guint)ftell64(f);
697 fseek(f, -(int)pos, SEEK_END);
698 bufPos = (Guint)ftell(f);
701 bufPtr = bufEnd = buf;
704 void FileStream::moveStart(int delta) {
706 bufPtr = bufEnd = buf;
710 //------------------------------------------------------------------------
712 //------------------------------------------------------------------------
714 MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA):
719 bufEnd = buf + start + length;
720 bufPtr = buf + start;
724 MemStream::~MemStream() {
730 Stream *MemStream::makeSubStream(Guint startA, GBool limited,
731 Guint lengthA, Object *dictA) {
735 if (!limited || startA + lengthA > start + length) {
736 newLength = start + length - startA;
740 subStr = new MemStream(buf, startA, newLength, dictA);
744 void MemStream::reset() {
745 bufPtr = buf + start;
751 void MemStream::close() {
754 void MemStream::setPos(Guint pos, int dir) {
760 i = start + length - pos;
764 } else if (i > start + length) {
770 void MemStream::moveStart(int delta) {
773 bufPtr = buf + start;
776 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
777 int objNum, int objGen) {
781 this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
783 newBuf = (char *)gmalloc(length);
784 for (p = buf + start, q = newBuf; p < bufEnd; ++p, ++q) {
785 *q = (char)decrypt->decryptByte((Guchar)*p);
787 bufEnd = newBuf + length;
788 bufPtr = newBuf + (bufPtr - (buf + start));
795 //------------------------------------------------------------------------
797 //------------------------------------------------------------------------
799 EmbedStream::EmbedStream(Stream *strA, Object *dictA,
800 GBool limitedA, Guint lengthA):
807 EmbedStream::~EmbedStream() {
810 Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA,
811 Guint lengthA, Object *dictA) {
812 error(-1, "Internal: called makeSubStream() on EmbedStream");
816 int EmbedStream::getChar() {
817 if (limited && !length) {
821 return str->getChar();
824 int EmbedStream::lookChar() {
825 if (limited && !length) {
828 return str->lookChar();
831 void EmbedStream::setPos(Guint pos, int dir) {
832 error(-1, "Internal: called setPos() on EmbedStream");
835 Guint EmbedStream::getStart() {
836 error(-1, "Internal: called getStart() on EmbedStream");
840 void EmbedStream::moveStart(int delta) {
841 error(-1, "Internal: called moveStart() on EmbedStream");
844 //------------------------------------------------------------------------
846 //------------------------------------------------------------------------
848 ASCIIHexStream::ASCIIHexStream(Stream *strA):
854 ASCIIHexStream::~ASCIIHexStream() {
858 void ASCIIHexStream::reset() {
864 int ASCIIHexStream::lookChar() {
875 } while (isspace(c1));
883 } while (isspace(c2));
888 if (c1 >= '0' && c1 <= '9') {
890 } else if (c1 >= 'A' && c1 <= 'F') {
891 x = (c1 - 'A' + 10) << 4;
892 } else if (c1 >= 'a' && c1 <= 'f') {
893 x = (c1 - 'a' + 10) << 4;
894 } else if (c1 == EOF) {
898 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
901 if (c2 >= '0' && c2 <= '9') {
903 } else if (c2 >= 'A' && c2 <= 'F') {
905 } else if (c2 >= 'a' && c2 <= 'f') {
907 } else if (c2 == EOF) {
911 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
917 GString *ASCIIHexStream::getPSFilter(int psLevel, char *indent) {
923 if (!(s = str->getPSFilter(psLevel, indent))) {
926 s->append(indent)->append("/ASCIIHexDecode filter\n");
930 GBool ASCIIHexStream::isBinary(GBool last) {
931 return str->isBinary(gFalse);
934 //------------------------------------------------------------------------
936 //------------------------------------------------------------------------
938 ASCII85Stream::ASCII85Stream(Stream *strA):
944 ASCII85Stream::~ASCII85Stream() {
948 void ASCII85Stream::reset() {
954 int ASCII85Stream::lookChar() {
963 c[0] = str->getChar();
964 } while (Lexer::isSpace(c[0]));
965 if (c[0] == '~' || c[0] == EOF) {
969 } else if (c[0] == 'z') {
970 b[0] = b[1] = b[2] = b[3] = 0;
973 for (k = 1; k < 5; ++k) {
975 c[k] = str->getChar();
976 } while (Lexer::isSpace(c[k]));
977 if (c[k] == '~' || c[k] == EOF)
981 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
982 for (++k; k < 5; ++k)
987 for (k = 0; k < 5; ++k)
988 t = t * 85 + (c[k] - 0x21);
989 for (k = 3; k >= 0; --k) {
990 b[k] = (int)(t & 0xff);
998 GString *ASCII85Stream::getPSFilter(int psLevel, char *indent) {
1004 if (!(s = str->getPSFilter(psLevel, indent))) {
1007 s->append(indent)->append("/ASCII85Decode filter\n");
1011 GBool ASCII85Stream::isBinary(GBool last) {
1012 return str->isBinary(gFalse);
1015 //------------------------------------------------------------------------
1017 //------------------------------------------------------------------------
1019 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
1020 int bits, int earlyA):
1021 FilterStream(strA) {
1022 if (predictor != 1) {
1023 pred = new StreamPredictor(this, predictor, columns, colors, bits);
1024 if (!pred->isOk()) {
1037 LZWStream::~LZWStream() {
1044 int LZWStream::getChar() {
1046 return pred->getChar();
1051 if (seqIndex >= seqLength) {
1052 if (!processNextCode()) {
1056 return seqBuf[seqIndex++];
1059 int LZWStream::lookChar() {
1061 return pred->lookChar();
1066 if (seqIndex >= seqLength) {
1067 if (!processNextCode()) {
1071 return seqBuf[seqIndex];
1074 int LZWStream::getRawChar() {
1078 if (seqIndex >= seqLength) {
1079 if (!processNextCode()) {
1083 return seqBuf[seqIndex++];
1086 void LZWStream::reset() {
1093 GBool LZWStream::processNextCode() {
1103 // check for eod and clear-table codes
1106 if (code == EOF || code == 257) {
1114 if (nextCode >= 4097) {
1115 error(getPos(), "Bad LZW stream - expected clear-table code");
1119 // process the next code
1120 nextLength = seqLength + 1;
1124 } else if (code < nextCode) {
1125 seqLength = table[code].length;
1126 for (i = seqLength - 1, j = code; i > 0; --i) {
1127 seqBuf[i] = table[j].tail;
1131 } else if (code == nextCode) {
1132 seqBuf[seqLength] = newChar;
1135 error(getPos(), "Bad LZW stream - unexpected code");
1139 newChar = seqBuf[0];
1143 table[nextCode].length = nextLength;
1144 table[nextCode].head = prevCode;
1145 table[nextCode].tail = newChar;
1147 if (nextCode + early == 512)
1149 else if (nextCode + early == 1024)
1151 else if (nextCode + early == 2048)
1162 void LZWStream::clearTable() {
1165 seqIndex = seqLength = 0;
1169 int LZWStream::getCode() {
1173 while (inputBits < nextBits) {
1174 if ((c = str->getChar()) == EOF)
1176 inputBuf = (inputBuf << 8) | (c & 0xff);
1179 code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
1180 inputBits -= nextBits;
1184 GString *LZWStream::getPSFilter(int psLevel, char *indent) {
1187 if (psLevel < 2 || pred) {
1190 if (!(s = str->getPSFilter(psLevel, indent))) {
1193 s->append(indent)->append("<< ");
1195 s->append("/EarlyChange 0 ");
1197 s->append(">> /LZWDecode filter\n");
1201 GBool LZWStream::isBinary(GBool last) {
1202 return str->isBinary(gTrue);
1205 //------------------------------------------------------------------------
1207 //------------------------------------------------------------------------
1209 RunLengthStream::RunLengthStream(Stream *strA):
1210 FilterStream(strA) {
1211 bufPtr = bufEnd = buf;
1215 RunLengthStream::~RunLengthStream() {
1219 void RunLengthStream::reset() {
1221 bufPtr = bufEnd = buf;
1225 GString *RunLengthStream::getPSFilter(int psLevel, char *indent) {
1231 if (!(s = str->getPSFilter(psLevel, indent))) {
1234 s->append(indent)->append("/RunLengthDecode filter\n");
1238 GBool RunLengthStream::isBinary(GBool last) {
1239 return str->isBinary(gTrue);
1242 GBool RunLengthStream::fillBuf() {
1249 if (c == 0x80 || c == EOF) {
1255 for (i = 0; i < n; ++i)
1256 buf[i] = (char)str->getChar();
1260 for (i = 0; i < n; ++i)
1268 //------------------------------------------------------------------------
1270 //------------------------------------------------------------------------
1272 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1273 GBool byteAlignA, int columnsA, int rowsA,
1274 GBool endOfBlockA, GBool blackA):
1275 FilterStream(strA) {
1276 encoding = encodingA;
1277 endOfLine = endOfLineA;
1278 byteAlign = byteAlignA;
1284 endOfBlock = endOfBlockA;
1286 refLine = (short *)gmallocn(columns + 4, sizeof(short));
1287 codingLine = (short *)gmallocn(columns + 3, sizeof(short));
1291 nextLine2D = encoding < 0;
1294 codingLine[1] = refLine[2] = columns;
1300 CCITTFaxStream::~CCITTFaxStream() {
1306 void CCITTFaxStream::reset() {
1312 nextLine2D = encoding < 0;
1315 codingLine[1] = refLine[2] = columns;
1319 // skip any initial zero bits and end-of-line marker, and get the 2D
1321 while ((code1 = lookBits(12)) == 0) {
1324 if (code1 == 0x001) {
1328 nextLine2D = !lookBits(1);
1333 int CCITTFaxStream::lookChar() {
1334 short code1, code2, code3;
1340 // if at eof just return EOF
1341 if (eof && codingLine[a0] >= columns) {
1345 // read the next row
1347 if (codingLine[a0] >= columns) {
1351 for (i = 0; codingLine[i] < columns; ++i)
1352 refLine[i] = codingLine[i];
1353 refLine[i] = refLine[i + 1] = columns;
1355 a0New = codingLine[a0 = 0] = 0;
1357 code1 = getTwoDimCode();
1360 if (refLine[b1] < columns) {
1361 a0New = refLine[b1 + 1];
1366 if ((a0 & 1) == 0) {
1369 code1 += code3 = getWhiteCode();
1370 } while (code3 >= 64);
1372 code2 += code3 = getBlackCode();
1373 } while (code3 >= 64);
1377 code1 += code3 = getBlackCode();
1378 } while (code3 >= 64);
1380 code2 += code3 = getWhiteCode();
1381 } while (code3 >= 64);
1383 if (code1 > 0 || code2 > 0) {
1384 codingLine[a0 + 1] = a0New + code1;
1386 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1388 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1393 a0New = codingLine[++a0] = refLine[b1];
1394 if (refLine[b1] < columns) {
1396 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1401 a0New = codingLine[++a0] = refLine[b1] + 1;
1402 if (refLine[b1] < columns) {
1404 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1409 if (a0 == 0 || refLine[b1] - 1 > a0New) {
1410 a0New = codingLine[++a0] = refLine[b1] - 1;
1412 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1417 a0New = codingLine[++a0] = refLine[b1] + 2;
1418 if (refLine[b1] < columns) {
1420 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1425 if (a0 == 0 || refLine[b1] - 2 > a0New) {
1426 a0New = codingLine[++a0] = refLine[b1] - 2;
1428 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1433 a0New = codingLine[++a0] = refLine[b1] + 3;
1434 if (refLine[b1] < columns) {
1436 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1441 if (a0 == 0 || refLine[b1] - 3 > a0New) {
1442 a0New = codingLine[++a0] = refLine[b1] - 3;
1444 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1450 codingLine[a0 = 0] = columns;
1453 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1457 } while (codingLine[a0] < columns);
1461 codingLine[a0 = 0] = 0;
1465 code1 += code3 = getWhiteCode();
1466 } while (code3 >= 64);
1467 codingLine[a0+1] = codingLine[a0] + code1;
1469 if (codingLine[a0] >= columns)
1473 code2 += code3 = getBlackCode();
1474 } while (code3 >= 64);
1475 codingLine[a0+1] = codingLine[a0] + code2;
1477 if (codingLine[a0] >= columns)
1482 if (codingLine[a0] != columns) {
1483 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
1484 // force the row to be the correct length
1485 while (codingLine[a0] > columns) {
1488 codingLine[++a0] = columns;
1492 // byte-align the row
1497 // check for end-of-line marker, skipping over any extra zero bits
1499 if (!endOfBlock && row == rows - 1) {
1502 code1 = lookBits(12);
1503 while (code1 == 0) {
1505 code1 = lookBits(12);
1507 if (code1 == 0x001) {
1510 } else if (code1 == EOF) {
1515 // get 2D encoding tag
1516 if (!eof && encoding > 0) {
1517 nextLine2D = !lookBits(1);
1521 // check for end-of-block marker
1522 if (endOfBlock && gotEOL) {
1523 code1 = lookBits(12);
1524 if (code1 == 0x001) {
1530 if (encoding >= 0) {
1531 for (i = 0; i < 4; ++i) {
1532 code1 = lookBits(12);
1533 if (code1 != 0x001) {
1534 error(getPos(), "Bad RTC code in CCITTFax stream");
1546 // look for an end-of-line marker after an error -- we only do
1547 // this if we know the stream contains end-of-line markers because
1548 // the "just plow on" technique tends to work better otherwise
1549 } else if (err && endOfLine) {
1556 code1 = lookBits(13);
1557 } while ((code1 >> 1) != 0x001);
1561 nextLine2D = !(code1 & 1);
1566 outputBits = codingLine[1] - codingLine[0];
1567 if (outputBits == 0) {
1569 outputBits = codingLine[2] - codingLine[1];
1576 if (outputBits >= 8) {
1577 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1578 if ((outputBits -= 8) == 0) {
1580 if (codingLine[a0] < columns) {
1581 outputBits = codingLine[a0 + 1] - codingLine[a0];
1588 if (outputBits > bits) {
1591 if ((a0 & 1) == 0) {
1592 ret |= 0xff >> (8 - i);
1598 if ((a0 & 1) == 0) {
1599 ret |= (0xff >> (8 - i)) << bits;
1603 if (codingLine[a0] < columns) {
1604 outputBits = codingLine[a0 + 1] - codingLine[a0];
1607 } while (bits > 0 && codingLine[a0] < columns);
1609 buf = black ? (ret ^ 0xff) : ret;
1613 short CCITTFaxStream::getTwoDimCode() {
1618 code = 0; // make gcc happy
1621 p = &twoDimTab1[code];
1627 for (n = 1; n <= 7; ++n) {
1632 p = &twoDimTab1[code];
1639 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1643 short CCITTFaxStream::getWhiteCode() {
1648 code = 0; // make gcc happy
1650 code = lookBits(12);
1651 if ((code >> 5) == 0) {
1652 p = &whiteTab1[code];
1654 p = &whiteTab2[code >> 3];
1661 for (n = 1; n <= 9; ++n) {
1666 p = &whiteTab2[code];
1672 for (n = 11; n <= 12; ++n) {
1677 p = &whiteTab1[code];
1684 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1685 // eat a bit and return a positive number so that the caller doesn't
1686 // go into an infinite loop
1691 short CCITTFaxStream::getBlackCode() {
1696 code = 0; // make gcc happy
1698 code = lookBits(13);
1699 if ((code >> 7) == 0) {
1700 p = &blackTab1[code];
1701 } else if ((code >> 9) == 0) {
1702 p = &blackTab2[(code >> 1) - 64];
1704 p = &blackTab3[code >> 7];
1711 for (n = 2; n <= 6; ++n) {
1716 p = &blackTab3[code];
1722 for (n = 7; n <= 12; ++n) {
1728 p = &blackTab2[code - 64];
1735 for (n = 10; n <= 13; ++n) {
1740 p = &blackTab1[code];
1747 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
1748 // eat a bit and return a positive number so that the caller doesn't
1749 // go into an infinite loop
1754 short CCITTFaxStream::lookBits(int n) {
1757 while (inputBits < n) {
1758 if ((c = str->getChar()) == EOF) {
1759 if (inputBits == 0) {
1762 // near the end of the stream, the caller may ask for more bits
1763 // than are available, but there may still be a valid code in
1764 // however many bits are available -- we need to return correct
1765 // data in this case
1766 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
1768 inputBuf = (inputBuf << 8) + c;
1771 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1774 GString *CCITTFaxStream::getPSFilter(int psLevel, char *indent) {
1781 if (!(s = str->getPSFilter(psLevel, indent))) {
1784 s->append(indent)->append("<< ");
1785 if (encoding != 0) {
1786 sprintf(s1, "/K %d ", encoding);
1790 s->append("/EndOfLine true ");
1793 s->append("/EncodedByteAlign true ");
1795 sprintf(s1, "/Columns %d ", columns);
1798 sprintf(s1, "/Rows %d ", rows);
1802 s->append("/EndOfBlock false ");
1805 s->append("/BlackIs1 true ");
1807 s->append(">> /CCITTFaxDecode filter\n");
1811 GBool CCITTFaxStream::isBinary(GBool last) {
1812 return str->isBinary(gTrue);
1815 //------------------------------------------------------------------------
1817 //------------------------------------------------------------------------
1819 // IDCT constants (20.12 fixed point format)
1820 #define dctCos1 4017 // cos(pi/16)
1821 #define dctSin1 799 // sin(pi/16)
1822 #define dctCos3 3406 // cos(3*pi/16)
1823 #define dctSin3 2276 // sin(3*pi/16)
1824 #define dctCos6 1567 // cos(6*pi/16)
1825 #define dctSin6 3784 // sin(6*pi/16)
1826 #define dctSqrt2 5793 // sqrt(2)
1827 #define dctSqrt1d2 2896 // sqrt(2) / 2
1829 // color conversion parameters (16.16 fixed point format)
1830 #define dctCrToR 91881 // 1.4020
1831 #define dctCbToG -22553 // -0.3441363
1832 #define dctCrToG -46802 // -0.71413636
1833 #define dctCbToB 116130 // 1.772
1835 // clip [-256,511] --> [0,255]
1836 #define dctClipOffset 256
1837 static Guchar dctClip[768];
1838 static int dctClipInit = 0;
1840 // zig zag decode map
1841 static int dctZigZag[64] = {
1847 5, 12, 19, 26, 33, 40,
1848 48, 41, 34, 27, 20, 13, 6,
1849 7, 14, 21, 28, 35, 42, 49, 56,
1850 57, 50, 43, 36, 29, 22, 15,
1851 23, 30, 37, 44, 51, 58,
1859 DCTStream::DCTStream(Stream *strA):
1860 FilterStream(strA) {
1863 progressive = interleaved = gFalse;
1865 mcuWidth = mcuHeight = 0;
1869 for (i = 0; i < 4; ++i) {
1870 for (j = 0; j < 32; ++j) {
1871 rowBuf[i][j] = NULL;
1877 for (i = -256; i < 0; ++i)
1878 dctClip[dctClipOffset + i] = 0;
1879 for (i = 0; i < 256; ++i)
1880 dctClip[dctClipOffset + i] = i;
1881 for (i = 256; i < 512; ++i)
1882 dctClip[dctClipOffset + i] = 255;
1887 DCTStream::~DCTStream() {
1891 if (progressive || !interleaved) {
1892 for (i = 0; i < numComps; ++i) {
1896 for (i = 0; i < numComps; ++i) {
1897 for (j = 0; j < mcuHeight; ++j) {
1898 gfree(rowBuf[i][j]);
1904 void DCTStream::reset() {
1909 progressive = interleaved = gFalse;
1913 numDCHuffTables = 0;
1914 numACHuffTables = 0;
1916 gotJFIFMarker = gFalse;
1917 gotAdobeMarker = gFalse;
1918 restartInterval = 0;
1920 if (!readHeader()) {
1926 if (numComps == 1) {
1927 compInfo[0].hSample = compInfo[0].vSample = 1;
1929 mcuWidth = compInfo[0].hSample;
1930 mcuHeight = compInfo[0].vSample;
1931 for (i = 1; i < numComps; ++i) {
1932 if (compInfo[i].hSample > mcuWidth) {
1933 mcuWidth = compInfo[i].hSample;
1935 if (compInfo[i].vSample > mcuHeight) {
1936 mcuHeight = compInfo[i].vSample;
1942 // figure out color transform
1943 if (!gotAdobeMarker && numComps == 3) {
1944 if (gotJFIFMarker) {
1946 } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
1947 compInfo[2].id == 66) { // ASCII "RGB"
1954 if (progressive || !interleaved) {
1956 // allocate a buffer for the whole image
1957 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
1958 bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
1959 for (i = 0; i < numComps; ++i) {
1960 frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int));
1961 memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
1964 // read the image data
1966 restartMarker = 0xd0;
1969 } while (readHeader());
1974 // initialize counters
1981 // allocate a buffer for one row of MCUs
1982 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
1983 for (i = 0; i < numComps; ++i) {
1984 for (j = 0; j < mcuHeight; ++j) {
1985 rowBuf[i][j] = (Guchar *)gmallocn(bufWidth, sizeof(Guchar));
1989 // initialize counters
1995 restartMarker = 0xd0;
2000 int DCTStream::getChar() {
2006 if (progressive || !interleaved) {
2007 c = frameBuf[comp][y * bufWidth + x];
2008 if (++comp == numComps) {
2016 if (dy >= mcuHeight) {
2017 if (!readMCURow()) {
2025 c = rowBuf[comp][dy][x];
2026 if (++comp == numComps) {
2041 int DCTStream::lookChar() {
2045 if (progressive || !interleaved) {
2046 return frameBuf[comp][y * bufWidth + x];
2048 if (dy >= mcuHeight) {
2049 if (!readMCURow()) {
2057 return rowBuf[comp][dy][x];
2061 void DCTStream::restart() {
2065 restartCtr = restartInterval;
2066 for (i = 0; i < numComps; ++i) {
2067 compInfo[i].prevDC = 0;
2072 // Read one row of MCUs from a sequential JPEG stream.
2073 GBool DCTStream::readMCURow() {
2077 int pY, pCb, pCr, pR, pG, pB;
2078 int h, v, horiz, vert, hSub, vSub;
2079 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2082 for (x1 = 0; x1 < width; x1 += mcuWidth) {
2084 // deal with restart marker
2085 if (restartInterval > 0 && restartCtr == 0) {
2087 if (c != restartMarker) {
2088 error(getPos(), "Bad DCT data: incorrect restart marker");
2091 if (++restartMarker == 0xd8)
2092 restartMarker = 0xd0;
2097 for (cc = 0; cc < numComps; ++cc) {
2098 h = compInfo[cc].hSample;
2099 v = compInfo[cc].vSample;
2100 horiz = mcuWidth / h;
2101 vert = mcuHeight / v;
2104 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2105 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2106 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2107 &acHuffTables[scanInfo.acHuffTable[cc]],
2108 &compInfo[cc].prevDC,
2112 transformDataUnit(quantTables[compInfo[cc].quantTable],
2114 if (hSub == 1 && vSub == 1) {
2115 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2116 p1 = &rowBuf[cc][y2+y3][x1+x2];
2126 } else if (hSub == 2 && vSub == 2) {
2127 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2128 p1 = &rowBuf[cc][y2+y3][x1+x2];
2129 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
2130 p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
2131 p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
2132 p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
2133 p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
2134 p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
2135 p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
2136 p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
2137 p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
2141 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2142 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2143 for (y5 = 0; y5 < vSub; ++y5)
2144 for (x5 = 0; x5 < hSub; ++x5)
2145 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
2155 // color space conversion
2157 // convert YCbCr to RGB
2158 if (numComps == 3) {
2159 for (y2 = 0; y2 < mcuHeight; ++y2) {
2160 for (x2 = 0; x2 < mcuWidth; ++x2) {
2161 pY = rowBuf[0][y2][x1+x2];
2162 pCb = rowBuf[1][y2][x1+x2] - 128;
2163 pCr = rowBuf[2][y2][x1+x2] - 128;
2164 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2165 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
2166 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2167 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
2168 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2169 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
2172 // convert YCbCrK to CMYK (K is passed through unchanged)
2173 } else if (numComps == 4) {
2174 for (y2 = 0; y2 < mcuHeight; ++y2) {
2175 for (x2 = 0; x2 < mcuWidth; ++x2) {
2176 pY = rowBuf[0][y2][x1+x2];
2177 pCb = rowBuf[1][y2][x1+x2] - 128;
2178 pCr = rowBuf[2][y2][x1+x2] - 128;
2179 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2180 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2181 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2182 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2183 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2184 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2193 // Read one scan from a progressive or non-interleaved JPEG stream.
2194 void DCTStream::readScan() {
2196 int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
2197 int h, v, horiz, vert, vSub;
2201 if (scanInfo.numComps == 1) {
2202 for (cc = 0; cc < numComps; ++cc) {
2203 if (scanInfo.comp[cc]) {
2207 dx1 = mcuWidth / compInfo[cc].hSample;
2208 dy1 = mcuHeight / compInfo[cc].vSample;
2214 for (y1 = 0; y1 < height; y1 += dy1) {
2215 for (x1 = 0; x1 < width; x1 += dx1) {
2217 // deal with restart marker
2218 if (restartInterval > 0 && restartCtr == 0) {
2220 if (c != restartMarker) {
2221 error(getPos(), "Bad DCT data: incorrect restart marker");
2224 if (++restartMarker == 0xd8) {
2225 restartMarker = 0xd0;
2231 for (cc = 0; cc < numComps; ++cc) {
2232 if (!scanInfo.comp[cc]) {
2236 h = compInfo[cc].hSample;
2237 v = compInfo[cc].vSample;
2238 horiz = mcuWidth / h;
2239 vert = mcuHeight / v;
2241 for (y2 = 0; y2 < dy1; y2 += vert) {
2242 for (x2 = 0; x2 < dx1; x2 += horiz) {
2244 // pull out the current values
2245 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2246 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2255 p1 += bufWidth * vSub;
2258 // read one data unit
2260 if (!readProgressiveDataUnit(
2261 &dcHuffTables[scanInfo.dcHuffTable[cc]],
2262 &acHuffTables[scanInfo.acHuffTable[cc]],
2263 &compInfo[cc].prevDC,
2268 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2269 &acHuffTables[scanInfo.acHuffTable[cc]],
2270 &compInfo[cc].prevDC,
2276 // add the data unit into frameBuf
2277 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2278 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2287 p1 += bufWidth * vSub;
2297 // Read one data unit from a sequential JPEG stream.
2298 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2299 DCTHuffTable *acHuffTable,
2300 int *prevDC, int data[64]) {
2305 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2309 if ((amp = readAmp(size)) == 9999) {
2315 data[0] = *prevDC += amp;
2316 for (i = 1; i < 64; ++i) {
2322 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
2331 run += (c >> 4) & 0x0f;
2333 amp = readAmp(size);
2347 // Read one data unit from a sequential JPEG stream.
2348 GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
2349 DCTHuffTable *acHuffTable,
2350 int *prevDC, int data[64]) {
2351 int run, size, amp, bit, c;
2354 // get the DC coefficient
2355 i = scanInfo.firstCoeff;
2357 if (scanInfo.ah == 0) {
2358 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2362 if ((amp = readAmp(size)) == 9999) {
2368 data[0] += (*prevDC += amp) << scanInfo.al;
2370 if ((bit = readBit()) == 9999) {
2373 data[0] += bit << scanInfo.al;
2377 if (scanInfo.lastCoeff == 0) {
2381 // check for an EOB run
2383 while (i <= scanInfo.lastCoeff) {
2386 if ((bit = readBit()) == EOF) {
2390 data[j] += 1 << scanInfo.al;
2398 // read the AC coefficients
2399 while (i <= scanInfo.lastCoeff) {
2400 if ((c = readHuffSym(acHuffTable)) == 9999) {
2412 if ((bit = readBit()) == EOF) {
2416 data[j] += 1 << scanInfo.al;
2422 } else if ((c & 0x0f) == 0x00) {
2425 for (k = 0; k < j; ++k) {
2426 if ((bit = readBit()) == EOF) {
2429 eobRun = (eobRun << 1) | bit;
2432 while (i <= scanInfo.lastCoeff) {
2435 if ((bit = readBit()) == EOF) {
2439 data[j] += 1 << scanInfo.al;
2446 // zero run and one AC coefficient
2448 run = (c >> 4) & 0x0f;
2450 if ((amp = readAmp(size)) == 9999) {
2456 while (data[j] != 0) {
2457 if ((bit = readBit()) == EOF) {
2461 data[j] += 1 << scanInfo.al;
2467 data[j] = amp << scanInfo.al;
2474 // Decode a progressive JPEG image.
2475 void DCTStream::decodeImage() {
2478 Gushort *quantTable;
2479 int pY, pCb, pCr, pR, pG, pB;
2480 int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2481 int h, v, horiz, vert, hSub, vSub;
2484 for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
2485 for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
2486 for (cc = 0; cc < numComps; ++cc) {
2487 quantTable = quantTables[compInfo[cc].quantTable];
2488 h = compInfo[cc].hSample;
2489 v = compInfo[cc].vSample;
2490 horiz = mcuWidth / h;
2491 vert = mcuHeight / v;
2494 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2495 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2497 // pull out the coded data unit
2498 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2499 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2501 dataIn[i+1] = p1[1];
2502 dataIn[i+2] = p1[2];
2503 dataIn[i+3] = p1[3];
2504 dataIn[i+4] = p1[4];
2505 dataIn[i+5] = p1[5];
2506 dataIn[i+6] = p1[6];
2507 dataIn[i+7] = p1[7];
2508 p1 += bufWidth * vSub;
2512 transformDataUnit(quantTable, dataIn, dataOut);
2514 // store back into frameBuf, doing replication for
2515 // subsampled components
2516 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2517 if (hSub == 1 && vSub == 1) {
2518 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2519 p1[0] = dataOut[i] & 0xff;
2520 p1[1] = dataOut[i+1] & 0xff;
2521 p1[2] = dataOut[i+2] & 0xff;
2522 p1[3] = dataOut[i+3] & 0xff;
2523 p1[4] = dataOut[i+4] & 0xff;
2524 p1[5] = dataOut[i+5] & 0xff;
2525 p1[6] = dataOut[i+6] & 0xff;
2526 p1[7] = dataOut[i+7] & 0xff;
2529 } else if (hSub == 2 && vSub == 2) {
2531 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2532 p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
2533 p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
2534 p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
2535 p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
2536 p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
2537 p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
2538 p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
2539 p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
2545 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2546 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2548 for (y5 = 0; y5 < vSub; ++y5) {
2549 for (x5 = 0; x5 < hSub; ++x5) {
2550 p2[x5] = dataOut[i] & 0xff;
2556 p1 += bufWidth * vSub;
2563 // color space conversion
2565 // convert YCbCr to RGB
2566 if (numComps == 3) {
2567 for (y2 = 0; y2 < mcuHeight; ++y2) {
2568 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2569 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2570 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2571 for (x2 = 0; x2 < mcuWidth; ++x2) {
2575 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2576 *p0++ = dctClip[dctClipOffset + pR];
2577 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2579 *p1++ = dctClip[dctClipOffset + pG];
2580 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2581 *p2++ = dctClip[dctClipOffset + pB];
2584 // convert YCbCrK to CMYK (K is passed through unchanged)
2585 } else if (numComps == 4) {
2586 for (y2 = 0; y2 < mcuHeight; ++y2) {
2587 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2588 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2589 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2590 for (x2 = 0; x2 < mcuWidth; ++x2) {
2594 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2595 *p0++ = 255 - dctClip[dctClipOffset + pR];
2596 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2598 *p1++ = 255 - dctClip[dctClipOffset + pG];
2599 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2600 *p2++ = 255 - dctClip[dctClipOffset + pB];
2609 // Transform one data unit -- this performs the dequantization and
2610 // IDCT steps. This IDCT algorithm is taken from:
2611 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2612 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2613 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2615 // The stage numbers mentioned in the comments refer to Figure 1 in this
2617 void DCTStream::transformDataUnit(Gushort *quantTable,
2618 int dataIn[64], Guchar dataOut[64]) {
2619 int v0, v1, v2, v3, v4, v5, v6, v7, t;
2624 for (i = 0; i < 64; ++i) {
2625 dataIn[i] *= quantTable[i];
2628 // inverse DCT on rows
2629 for (i = 0; i < 64; i += 8) {
2632 // check for all-zero AC coefficients
2633 if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
2634 p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
2635 t = (dctSqrt2 * p[0] + 512) >> 10;
2648 v0 = (dctSqrt2 * p[0] + 128) >> 8;
2649 v1 = (dctSqrt2 * p[4] + 128) >> 8;
2652 v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
2653 v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
2658 t = (v0 - v1+ 1) >> 1;
2659 v0 = (v0 + v1 + 1) >> 1;
2661 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2662 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2664 t = (v4 - v6 + 1) >> 1;
2665 v4 = (v4 + v6 + 1) >> 1;
2667 t = (v7 + v5 + 1) >> 1;
2668 v5 = (v7 - v5 + 1) >> 1;
2672 t = (v0 - v3 + 1) >> 1;
2673 v0 = (v0 + v3 + 1) >> 1;
2675 t = (v1 - v2 + 1) >> 1;
2676 v1 = (v1 + v2 + 1) >> 1;
2678 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2679 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2681 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2682 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2696 // inverse DCT on columns
2697 for (i = 0; i < 8; ++i) {
2700 // check for all-zero AC coefficients
2701 if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
2702 p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
2703 t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
2716 v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
2717 v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
2720 v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
2721 v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
2726 t = (v0 - v1 + 1) >> 1;
2727 v0 = (v0 + v1 + 1) >> 1;
2729 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2730 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2732 t = (v4 - v6 + 1) >> 1;
2733 v4 = (v4 + v6 + 1) >> 1;
2735 t = (v7 + v5 + 1) >> 1;
2736 v5 = (v7 - v5 + 1) >> 1;
2740 t = (v0 - v3 + 1) >> 1;
2741 v0 = (v0 + v3 + 1) >> 1;
2743 t = (v1 - v2 + 1) >> 1;
2744 v1 = (v1 + v2 + 1) >> 1;
2746 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2747 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2749 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2750 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2764 // convert to 8-bit integers
2765 for (i = 0; i < 64; ++i) {
2766 dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
2770 int DCTStream::readHuffSym(DCTHuffTable *table) {
2778 // add a bit to the code
2779 if ((bit = readBit()) == EOF)
2781 code = (code << 1) + bit;
2785 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2786 code -= table->firstCode[codeBits];
2787 return table->sym[table->firstSym[codeBits] + code];
2789 } while (codeBits < 16);
2791 error(getPos(), "Bad Huffman code in DCT stream");
2795 int DCTStream::readAmp(int size) {
2800 for (bits = 0; bits < size; ++bits) {
2801 if ((bit = readBit()) == EOF)
2803 amp = (amp << 1) + bit;
2805 if (amp < (1 << (size - 1)))
2806 amp -= (1 << size) - 1;
2810 int DCTStream::readBit() {
2814 if (inputBits == 0) {
2815 if ((c = str->getChar()) == EOF)
2819 c2 = str->getChar();
2820 } while (c2 == 0xff);
2822 error(getPos(), "Bad DCT data: missing 00 after ff");
2829 bit = (inputBuf >> (inputBits - 1)) & 1;
2834 GBool DCTStream::readHeader() {
2845 case 0xc0: // SOF0 (sequential)
2846 case 0xc1: // SOF1 (extended sequential)
2847 if (!readBaselineSOF()) {
2851 case 0xc2: // SOF2 (progressive)
2852 if (!readProgressiveSOF()) {
2857 if (!readHuffmanTables()) {
2866 if (!readScanInfo()) {
2872 if (!readQuantTables()) {
2877 if (!readRestartInterval()) {
2882 if (!readJFIFMarker()) {
2887 if (!readAdobeMarker()) {
2892 error(getPos(), "Bad DCT header");
2895 // skip APPn / COM / etc.
2898 for (i = 0; i < n; ++i) {
2902 error(getPos(), "Unknown DCT marker <%02x>", c);
2912 GBool DCTStream::readBaselineSOF() {
2919 prec = str->getChar();
2922 numComps = str->getChar();
2923 if (numComps <= 0 || numComps > 4) {
2924 error(getPos(), "Bad number of components in DCT stream", prec);
2927 if (numComps <= 0 || numComps > 4) {
2928 error(getPos(), "Bad number of components in DCT stream", prec);
2932 error(getPos(), "Bad DCT precision %d", prec);
2935 for (i = 0; i < numComps; ++i) {
2936 compInfo[i].id = str->getChar();
2938 compInfo[i].hSample = (c >> 4) & 0x0f;
2939 compInfo[i].vSample = c & 0x0f;
2940 compInfo[i].quantTable = str->getChar();
2942 progressive = gFalse;
2946 GBool DCTStream::readProgressiveSOF() {
2953 prec = str->getChar();
2956 numComps = str->getChar();
2958 error(getPos(), "Bad DCT precision %d", prec);
2961 for (i = 0; i < numComps; ++i) {
2962 compInfo[i].id = str->getChar();
2964 compInfo[i].hSample = (c >> 4) & 0x0f;
2965 compInfo[i].vSample = c & 0x0f;
2966 compInfo[i].quantTable = str->getChar();
2968 progressive = gTrue;
2972 GBool DCTStream::readScanInfo() {
2977 length = read16() - 2;
2978 scanInfo.numComps = str->getChar();
2980 if (length != 2 * scanInfo.numComps + 3) {
2981 error(getPos(), "Bad DCT scan info block");
2984 interleaved = scanInfo.numComps == numComps;
2985 for (j = 0; j < numComps; ++j) {
2986 scanInfo.comp[j] = gFalse;
2988 for (i = 0; i < scanInfo.numComps; ++i) {
2989 id = str->getChar();
2990 // some (broken) DCT streams reuse ID numbers, but at least they
2991 // keep the components in order, so we check compInfo[i] first to
2992 // work around the problem
2993 if (id == compInfo[i].id) {
2996 for (j = 0; j < numComps; ++j) {
2997 if (id == compInfo[j].id) {
3001 if (j == numComps) {
3002 error(getPos(), "Bad DCT component ID in scan info block");
3006 scanInfo.comp[j] = gTrue;
3008 scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
3009 scanInfo.acHuffTable[j] = c & 0x0f;
3011 scanInfo.firstCoeff = str->getChar();
3012 scanInfo.lastCoeff = str->getChar();
3014 scanInfo.ah = (c >> 4) & 0x0f;
3015 scanInfo.al = c & 0x0f;
3019 GBool DCTStream::readQuantTables() {
3020 int length, prec, i, index;
3022 length = read16() - 2;
3023 while (length > 0) {
3024 index = str->getChar();
3025 prec = (index >> 4) & 0x0f;
3027 if (prec > 1 || index >= 4) {
3028 error(getPos(), "Bad DCT quantization table");
3031 if (index == numQuantTables) {
3032 numQuantTables = index + 1;
3034 for (i = 0; i < 64; ++i) {
3036 quantTables[index][dctZigZag[i]] = read16();
3038 quantTables[index][dctZigZag[i]] = str->getChar();
3050 GBool DCTStream::readHuffmanTables() {
3059 length = read16() - 2;
3060 while (length > 0) {
3061 index = str->getChar();
3063 if ((index & 0x0f) >= 4) {
3064 error(getPos(), "Bad DCT Huffman table");
3069 if (index >= numACHuffTables)
3070 numACHuffTables = index+1;
3071 tbl = &acHuffTables[index];
3073 if (index >= numDCHuffTables)
3074 numDCHuffTables = index+1;
3075 tbl = &dcHuffTables[index];
3079 for (i = 1; i <= 16; ++i) {
3081 tbl->firstSym[i] = sym;
3082 tbl->firstCode[i] = code;
3083 tbl->numCodes[i] = c;
3085 code = (code + c) << 1;
3088 for (i = 0; i < sym; ++i)
3089 tbl->sym[i] = str->getChar();
3095 GBool DCTStream::readRestartInterval() {
3100 error(getPos(), "Bad DCT restart interval");
3103 restartInterval = read16();
3107 GBool DCTStream::readJFIFMarker() {
3115 for (i = 0; i < 5; ++i) {
3116 if ((c = str->getChar()) == EOF) {
3117 error(getPos(), "Bad DCT APP0 marker");
3123 if (!memcmp(buf, "JFIF\0", 5)) {
3124 gotJFIFMarker = gTrue;
3127 while (length > 0) {
3128 if (str->getChar() == EOF) {
3129 error(getPos(), "Bad DCT APP0 marker");
3137 GBool DCTStream::readAdobeMarker() {
3146 for (i = 0; i < 12; ++i) {
3147 if ((c = str->getChar()) == EOF) {
3152 if (strncmp(buf, "Adobe", 5)) {
3155 colorXform = buf[11];
3156 gotAdobeMarker = gTrue;
3157 for (i = 14; i < length; ++i) {
3158 if (str->getChar() == EOF) {
3165 error(getPos(), "Bad DCT Adobe APP14 marker");
3169 GBool DCTStream::readTrailer() {
3173 if (c != 0xd9) { // EOI
3174 error(getPos(), "Bad DCT trailer");
3180 int DCTStream::readMarker() {
3186 } while (c != 0xff && c != EOF);
3189 } while (c == 0xff);
3190 } while (c == 0x00);
3194 int DCTStream::read16() {
3197 if ((c1 = str->getChar()) == EOF)
3199 if ((c2 = str->getChar()) == EOF)
3201 return (c1 << 8) + c2;
3204 GString *DCTStream::getPSFilter(int psLevel, char *indent) {
3210 if (!(s = str->getPSFilter(psLevel, indent))) {
3213 s->append(indent)->append("<< >> /DCTDecode filter\n");
3217 GBool DCTStream::isBinary(GBool last) {
3218 return str->isBinary(gTrue);
3221 //------------------------------------------------------------------------
3223 //------------------------------------------------------------------------
3225 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
3226 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3229 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
3263 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
3296 static FlateCode flateFixedLitCodeTabCodes[512] = {
3811 FlateHuffmanTab FlateStream::fixedLitCodeTab = {
3812 flateFixedLitCodeTabCodes, 9
3815 static FlateCode flateFixedDistCodeTabCodes[32] = {
3850 FlateHuffmanTab FlateStream::fixedDistCodeTab = {
3851 flateFixedDistCodeTabCodes, 5
3854 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
3855 int colors, int bits):
3856 FilterStream(strA) {
3857 if (predictor != 1) {
3858 pred = new StreamPredictor(this, predictor, columns, colors, bits);
3859 if (!pred->isOk()) {
3866 litCodeTab.codes = NULL;
3867 distCodeTab.codes = NULL;
3870 FlateStream::~FlateStream() {
3871 if (litCodeTab.codes != fixedLitCodeTab.codes) {
3872 gfree(litCodeTab.codes);
3874 if (distCodeTab.codes != fixedDistCodeTab.codes) {
3875 gfree(distCodeTab.codes);
3883 void FlateStream::reset() {
3890 compressedBlock = gFalse;
3897 //~ need to look at window size?
3898 endOfBlock = eof = gTrue;
3899 cmf = str->getChar();
3900 flg = str->getChar();
3901 if (cmf == EOF || flg == EOF)
3903 if ((cmf & 0x0f) != 0x08) {
3904 error(getPos(), "Unknown compression method in flate stream");
3907 if ((((cmf << 8) + flg) % 31) != 0) {
3908 error(getPos(), "Bad FCHECK in flate stream");
3912 error(getPos(), "FDICT bit set in flate stream");
3919 int FlateStream::getChar() {
3923 return pred->getChar();
3925 while (remain == 0) {
3926 if (endOfBlock && eof)
3931 index = (index + 1) & flateMask;
3936 int FlateStream::lookChar() {
3940 return pred->lookChar();
3942 while (remain == 0) {
3943 if (endOfBlock && eof)
3951 int FlateStream::getRawChar() {
3954 while (remain == 0) {
3955 if (endOfBlock && eof)
3960 index = (index + 1) & flateMask;
3965 GString *FlateStream::getPSFilter(int psLevel, char *indent) {
3968 if (psLevel < 3 || pred) {
3971 if (!(s = str->getPSFilter(psLevel, indent))) {
3974 s->append(indent)->append("<< >> /FlateDecode filter\n");
3978 GBool FlateStream::isBinary(GBool last) {
3979 return str->isBinary(gTrue);
3982 void FlateStream::readSome() {
3993 if (compressedBlock) {
3994 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
3999 } else if (code1 == 256) {
4004 code2 = lengthDecode[code1].bits;
4005 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
4007 len = lengthDecode[code1].first + code2;
4008 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
4010 code2 = distDecode[code1].bits;
4011 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
4013 dist = distDecode[code1].first + code2;
4015 j = (index - dist) & flateMask;
4016 for (k = 0; k < len; ++k) {
4018 i = (i + 1) & flateMask;
4019 j = (j + 1) & flateMask;
4025 len = (blockLen < flateWindow) ? blockLen : flateWindow;
4026 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
4027 if ((c = str->getChar()) == EOF) {
4028 endOfBlock = eof = gTrue;
4042 error(getPos(), "Unexpected end of file in flate stream");
4043 endOfBlock = eof = gTrue;
4047 GBool FlateStream::startBlock() {
4052 // free the code tables from the previous block
4053 if (litCodeTab.codes != fixedLitCodeTab.codes) {
4054 gfree(litCodeTab.codes);
4056 litCodeTab.codes = NULL;
4057 if (distCodeTab.codes != fixedDistCodeTab.codes) {
4058 gfree(distCodeTab.codes);
4060 distCodeTab.codes = NULL;
4062 // read block header
4063 blockHdr = getCodeWord(3);
4068 // uncompressed block
4069 if (blockHdr == 0) {
4070 compressedBlock = gFalse;
4071 if ((c = str->getChar()) == EOF)
4073 blockLen = c & 0xff;
4074 if ((c = str->getChar()) == EOF)
4076 blockLen |= (c & 0xff) << 8;
4077 if ((c = str->getChar()) == EOF)
4080 if ((c = str->getChar()) == EOF)
4082 check |= (c & 0xff) << 8;
4083 if (check != (~blockLen & 0xffff))
4084 error(getPos(), "Bad uncompressed block length in flate stream");
4088 // compressed block with fixed codes
4089 } else if (blockHdr == 1) {
4090 compressedBlock = gTrue;
4093 // compressed block with dynamic codes
4094 } else if (blockHdr == 2) {
4095 compressedBlock = gTrue;
4096 if (!readDynamicCodes()) {
4100 // unknown block type
4105 endOfBlock = gFalse;
4109 error(getPos(), "Bad block header in flate stream");
4110 endOfBlock = eof = gTrue;
4114 void FlateStream::loadFixedCodes() {
4115 litCodeTab.codes = fixedLitCodeTab.codes;
4116 litCodeTab.maxLen = fixedLitCodeTab.maxLen;
4117 distCodeTab.codes = fixedDistCodeTab.codes;
4118 distCodeTab.maxLen = fixedDistCodeTab.maxLen;
4121 GBool FlateStream::readDynamicCodes() {
4122 int numCodeLenCodes;
4125 int codeLenCodeLengths[flateMaxCodeLenCodes];
4126 FlateHuffmanTab codeLenCodeTab;
4127 int len, repeat, code;
4130 codeLenCodeTab.codes = NULL;
4133 if ((numLitCodes = getCodeWord(5)) == EOF) {
4137 if ((numDistCodes = getCodeWord(5)) == EOF) {
4141 if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
4144 numCodeLenCodes += 4;
4145 if (numLitCodes > flateMaxLitCodes ||
4146 numDistCodes > flateMaxDistCodes ||
4147 numCodeLenCodes > flateMaxCodeLenCodes) {
4151 // build the code length code table
4152 for (i = 0; i < flateMaxCodeLenCodes; ++i) {
4153 codeLenCodeLengths[i] = 0;
4155 for (i = 0; i < numCodeLenCodes; ++i) {
4156 if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
4160 compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
4162 // build the literal and distance code tables
4166 while (i < numLitCodes + numDistCodes) {
4167 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
4171 if ((repeat = getCodeWord(2)) == EOF) {
4175 if (i + repeat > numLitCodes + numDistCodes) {
4178 for (; repeat > 0; --repeat) {
4179 codeLengths[i++] = len;
4181 } else if (code == 17) {
4182 if ((repeat = getCodeWord(3)) == EOF) {
4186 if (i + repeat > numLitCodes + numDistCodes) {
4190 for (; repeat > 0; --repeat) {
4191 codeLengths[i++] = 0;
4193 } else if (code == 18) {
4194 if ((repeat = getCodeWord(7)) == EOF) {
4198 if (i + repeat > numLitCodes + numDistCodes) {
4202 for (; repeat > 0; --repeat) {
4203 codeLengths[i++] = 0;
4206 codeLengths[i++] = len = code;
4209 compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
4210 compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
4212 gfree(codeLenCodeTab.codes);
4216 error(getPos(), "Bad dynamic code table in flate stream");
4217 gfree(codeLenCodeTab.codes);
4221 // Convert an array <lengths> of <n> lengths, in value order, into a
4222 // Huffman code lookup table.
4223 void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
4224 int tabSize, len, code, code2, skip, val, i, t;
4226 // find max code length
4228 for (val = 0; val < n; ++val) {
4229 if (lengths[val] > tab->maxLen) {
4230 tab->maxLen = lengths[val];
4234 // allocate the table
4235 tabSize = 1 << tab->maxLen;
4236 tab->codes = (FlateCode *)gmallocn(tabSize, sizeof(FlateCode));
4239 for (i = 0; i < tabSize; ++i) {
4240 tab->codes[i].len = 0;
4241 tab->codes[i].val = 0;
4245 for (len = 1, code = 0, skip = 2;
4247 ++len, code <<= 1, skip <<= 1) {
4248 for (val = 0; val < n; ++val) {
4249 if (lengths[val] == len) {
4251 // bit-reverse the code
4254 for (i = 0; i < len; ++i) {
4255 code2 = (code2 << 1) | (t & 1);
4259 // fill in the table entries
4260 for (i = code2; i < tabSize; i += skip) {
4261 tab->codes[i].len = (Gushort)len;
4262 tab->codes[i].val = (Gushort)val;
4271 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
4275 while (codeSize < tab->maxLen) {
4276 if ((c = str->getChar()) == EOF) {
4279 codeBuf |= (c & 0xff) << codeSize;
4282 code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
4283 if (codeSize == 0 || codeSize < code->len || code->len == 0) {
4286 codeBuf >>= code->len;
4287 codeSize -= code->len;
4288 return (int)code->val;
4291 int FlateStream::getCodeWord(int bits) {
4294 while (codeSize < bits) {
4295 if ((c = str->getChar()) == EOF)
4297 codeBuf |= (c & 0xff) << codeSize;
4300 c = codeBuf & ((1 << bits) - 1);
4306 //------------------------------------------------------------------------
4308 //------------------------------------------------------------------------
4310 EOFStream::EOFStream(Stream *strA):
4311 FilterStream(strA) {
4314 EOFStream::~EOFStream() {
4318 //------------------------------------------------------------------------
4319 // FixedLengthEncoder
4320 //------------------------------------------------------------------------
4322 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
4323 FilterStream(strA) {
4328 FixedLengthEncoder::~FixedLengthEncoder() {
4329 if (str->isEncoder())
4333 void FixedLengthEncoder::reset() {
4338 int FixedLengthEncoder::getChar() {
4339 if (length >= 0 && count >= length)
4342 return str->getChar();
4345 int FixedLengthEncoder::lookChar() {
4346 if (length >= 0 && count >= length)
4348 return str->getChar();
4351 GBool FixedLengthEncoder::isBinary(GBool last) {
4352 return str->isBinary(gTrue);
4355 //------------------------------------------------------------------------
4357 //------------------------------------------------------------------------
4359 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
4360 FilterStream(strA) {
4361 bufPtr = bufEnd = buf;
4366 ASCIIHexEncoder::~ASCIIHexEncoder() {
4367 if (str->isEncoder()) {
4372 void ASCIIHexEncoder::reset() {
4374 bufPtr = bufEnd = buf;
4379 GBool ASCIIHexEncoder::fillBuf() {
4380 static char *hex = "0123456789abcdef";
4386 bufPtr = bufEnd = buf;
4387 if ((c = str->getChar()) == EOF) {
4391 if (lineLen >= 64) {
4395 *bufEnd++ = hex[(c >> 4) & 0x0f];
4396 *bufEnd++ = hex[c & 0x0f];
4402 //------------------------------------------------------------------------
4404 //------------------------------------------------------------------------
4406 ASCII85Encoder::ASCII85Encoder(Stream *strA):
4407 FilterStream(strA) {
4408 bufPtr = bufEnd = buf;
4413 ASCII85Encoder::~ASCII85Encoder() {
4414 if (str->isEncoder())
4418 void ASCII85Encoder::reset() {
4420 bufPtr = bufEnd = buf;
4425 GBool ASCII85Encoder::fillBuf() {
4434 for (n = 0; n < 4; ++n) {
4435 if ((c = str->getChar()) == EOF)
4439 bufPtr = bufEnd = buf;
4441 if (n == 4 && t == 0) {
4443 if (++lineLen == 65) {
4450 for (i = 4; i >= 0; --i) {
4451 buf1[i] = (char)(t % 85 + 0x21);
4454 for (i = 0; i <= n; ++i) {
4455 *bufEnd++ = buf1[i];
4456 if (++lineLen == 65) {
4468 return bufPtr < bufEnd;
4471 //------------------------------------------------------------------------
4473 //------------------------------------------------------------------------
4475 RunLengthEncoder::RunLengthEncoder(Stream *strA):
4476 FilterStream(strA) {
4477 bufPtr = bufEnd = nextEnd = buf;
4481 RunLengthEncoder::~RunLengthEncoder() {
4482 if (str->isEncoder())
4486 void RunLengthEncoder::reset() {
4488 bufPtr = bufEnd = nextEnd = buf;
4493 // When fillBuf finishes, buf[] looks like this:
4494 // +-----+--------------+-----------------+--
4495 // + tag | ... data ... | next 0, 1, or 2 |
4496 // +-----+--------------+-----------------+--
4498 // bufPtr bufEnd nextEnd
4500 GBool RunLengthEncoder::fillBuf() {
4509 if (nextEnd < bufEnd + 1) {
4510 if ((c1 = str->getChar()) == EOF) {
4515 c1 = bufEnd[0] & 0xff;
4517 if (nextEnd < bufEnd + 2) {
4518 if ((c2 = str->getChar()) == EOF) {
4527 c2 = bufEnd[1] & 0xff;
4531 c = 0; // make gcc happy
4534 while (n < 128 && (c = str->getChar()) == c1)
4536 buf[0] = (char)(257 - n);
4541 } else if (n < 128) {
4548 // get up to 128 chars
4554 if ((c = str->getChar()) == EOF) {
4560 if (buf[n] == buf[n-1])
4563 if (buf[n] == buf[n-1]) {
4564 buf[0] = (char)(n-2-1);
4566 nextEnd = &buf[n+1];
4568 buf[0] = (char)(n-1);
4569 bufEnd = nextEnd = &buf[n+1];