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) {
277 #ifndef NO_DECRYPTION
282 BaseStream::~BaseStream() {
284 #ifndef NO_DECRYPTION
290 #ifndef NO_DECRYPTION
291 void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
292 int objNum, int objGen) {
293 decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
297 //------------------------------------------------------------------------
299 //------------------------------------------------------------------------
301 FilterStream::FilterStream(Stream *strA) {
305 FilterStream::~FilterStream() {
308 void FilterStream::close() {
312 void FilterStream::setPos(Guint pos, int dir) {
313 error(-1, "Internal: called setPos() on FilterStream");
316 //------------------------------------------------------------------------
318 //------------------------------------------------------------------------
320 ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
328 nVals = width * nComps;
330 imgLineSize = (nVals + 7) & ~7;
334 imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
338 ImageStream::~ImageStream() {
342 void ImageStream::reset() {
346 GBool ImageStream::getPixel(Guchar *pix) {
349 if (imgIdx >= nVals) {
353 for (i = 0; i < nComps; ++i) {
354 pix[i] = imgLine[imgIdx++];
359 Guchar *ImageStream::getLine() {
366 for (i = 0; i < nVals; i += 8) {
368 imgLine[i+0] = (Guchar)((c >> 7) & 1);
369 imgLine[i+1] = (Guchar)((c >> 6) & 1);
370 imgLine[i+2] = (Guchar)((c >> 5) & 1);
371 imgLine[i+3] = (Guchar)((c >> 4) & 1);
372 imgLine[i+4] = (Guchar)((c >> 3) & 1);
373 imgLine[i+5] = (Guchar)((c >> 2) & 1);
374 imgLine[i+6] = (Guchar)((c >> 1) & 1);
375 imgLine[i+7] = (Guchar)(c & 1);
377 } else if (nBits == 8) {
378 for (i = 0; i < nVals; ++i) {
379 imgLine[i] = str->getChar();
382 bitMask = (1 << nBits) - 1;
385 for (i = 0; i < nVals; ++i) {
387 buf = (buf << 8) | (str->getChar() & 0xff);
390 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
397 void ImageStream::skipLine() {
400 n = (nVals * nBits + 7) >> 3;
401 for (i = 0; i < n; ++i) {
406 //------------------------------------------------------------------------
408 //------------------------------------------------------------------------
410 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
411 int widthA, int nCompsA, int nBitsA) {
413 predictor = predictorA;
418 nVals = width * nComps;
419 pixBytes = (nComps * nBits + 7) >> 3;
420 rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
421 predLine = (Guchar *)gmalloc(rowBytes);
422 memset(predLine, 0, rowBytes);
426 StreamPredictor::~StreamPredictor() {
430 int StreamPredictor::lookChar() {
431 if (predIdx >= rowBytes) {
432 if (!getNextLine()) {
436 return predLine[predIdx];
439 int StreamPredictor::getChar() {
440 if (predIdx >= rowBytes) {
441 if (!getNextLine()) {
445 return predLine[predIdx++];
448 GBool StreamPredictor::getNextLine() {
451 int left, up, upLeft, p, pa, pb, pc;
453 Gulong inBuf, outBuf, bitMask;
457 // get PNG optimum predictor number
458 if (predictor >= 10) {
459 if ((curPred = str->getRawChar()) == EOF) {
467 // read the raw line, apply PNG (byte) predictor
468 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
469 for (i = pixBytes; i < rowBytes; ++i) {
470 upLeftBuf[3] = upLeftBuf[2];
471 upLeftBuf[2] = upLeftBuf[1];
472 upLeftBuf[1] = upLeftBuf[0];
473 upLeftBuf[0] = predLine[i];
474 if ((c = str->getRawChar()) == EOF) {
479 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
482 predLine[i] = predLine[i] + (Guchar)c;
484 case 13: // PNG average
485 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
488 case 14: // PNG Paeth
489 left = predLine[i - pixBytes];
491 upLeft = upLeftBuf[pixBytes];
492 p = left + up - upLeft;
493 if ((pa = p - left) < 0)
495 if ((pb = p - up) < 0)
497 if ((pc = p - upLeft) < 0)
499 if (pa <= pb && pa <= pc)
500 predLine[i] = left + (Guchar)c;
502 predLine[i] = up + (Guchar)c;
504 predLine[i] = upLeft + (Guchar)c;
507 default: // no predictor or TIFF predictor
508 predLine[i] = (Guchar)c;
513 // apply TIFF (component) predictor
514 if (predictor == 2) {
516 inBuf = predLine[pixBytes - 1];
517 for (i = pixBytes; i < rowBytes; i += 8) {
518 // 1-bit add is just xor
519 inBuf = (inBuf << 8) | predLine[i];
520 predLine[i] ^= inBuf >> nComps;
522 } else if (nBits == 8) {
523 for (i = pixBytes; i < rowBytes; ++i) {
524 predLine[i] += predLine[i - nComps];
527 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
528 bitMask = (1 << nBits) - 1;
530 inBits = outBits = 0;
532 for (i = 0; i < nVals; ++i) {
533 if (inBits < nBits) {
534 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
537 upLeftBuf[3] = upLeftBuf[2];
538 upLeftBuf[2] = upLeftBuf[1];
539 upLeftBuf[1] = upLeftBuf[0];
540 upLeftBuf[0] = (upLeftBuf[nComps] +
541 (inBuf >> (inBits - nBits))) & bitMask;
542 outBuf = (outBuf << nBits) | upLeftBuf[0];
546 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
550 predLine[k++] = (Guchar)(outBuf << (8 - outBits));
555 // reset to start of line
561 //------------------------------------------------------------------------
563 //------------------------------------------------------------------------
565 FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
566 Guint lengthA, Object *dictA):
572 bufPtr = bufEnd = buf;
578 FileStream::~FileStream() {
582 Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
583 Guint lengthA, Object *dictA) {
584 return new FileStream(f, startA, limitedA, lengthA, dictA);
587 void FileStream::reset() {
589 savePos = (Guint)ftello(f);
590 fseeko(f, start, SEEK_SET);
592 savePos = (Guint)ftell64(f);
593 fseek64(f, start, SEEK_SET);
595 savePos = (Guint)ftell(f);
596 fseek(f, start, SEEK_SET);
599 bufPtr = bufEnd = buf;
601 #ifndef NO_DECRYPTION
607 void FileStream::close() {
610 fseeko(f, savePos, SEEK_SET);
612 fseek64(f, savePos, SEEK_SET);
614 fseek(f, savePos, SEEK_SET);
620 GBool FileStream::fillBuf() {
622 #ifndef NO_DECRYPTION
626 bufPos += bufEnd - buf;
627 bufPtr = bufEnd = buf;
628 if (limited && bufPos >= start + length) {
631 if (limited && bufPos + fileStreamBufSize > start + length) {
632 n = start + length - bufPos;
634 n = fileStreamBufSize;
636 n = fread(buf, 1, n, f);
638 if (bufPtr >= bufEnd) {
641 #ifndef NO_DECRYPTION
643 for (p = buf; p < bufEnd; ++p) {
644 *p = (char)decrypt->decryptByte((Guchar)*p);
651 void FileStream::setPos(Guint pos, int dir) {
656 fseeko(f, pos, SEEK_SET);
658 fseek64(f, pos, SEEK_SET);
660 fseek(f, pos, SEEK_SET);
665 fseeko(f, 0, SEEK_END);
666 size = (Guint)ftello(f);
668 fseek64(f, 0, SEEK_END);
669 size = (Guint)ftell64(f);
671 fseek(f, 0, SEEK_END);
672 size = (Guint)ftell(f);
677 //~ work around a bug in cygwin's implementation of fseek
681 fseeko(f, -(int)pos, SEEK_END);
682 bufPos = (Guint)ftello(f);
684 fseek64(f, -(int)pos, SEEK_END);
685 bufPos = (Guint)ftell64(f);
687 fseek(f, -(int)pos, SEEK_END);
688 bufPos = (Guint)ftell(f);
691 bufPtr = bufEnd = buf;
694 void FileStream::moveStart(int delta) {
696 bufPtr = bufEnd = buf;
700 //------------------------------------------------------------------------
702 //------------------------------------------------------------------------
704 MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA):
709 bufEnd = buf + start + length;
710 bufPtr = buf + start;
714 MemStream::~MemStream() {
720 Stream *MemStream::makeSubStream(Guint startA, GBool limited,
721 Guint lengthA, Object *dictA) {
725 if (!limited || startA + lengthA > start + length) {
726 newLength = start + length - startA;
730 subStr = new MemStream(buf, startA, newLength, dictA);
734 void MemStream::reset() {
735 bufPtr = buf + start;
736 #ifndef NO_DECRYPTION
743 void MemStream::close() {
746 void MemStream::setPos(Guint pos, int dir) {
752 i = start + length - pos;
756 } else if (i > start + length) {
762 void MemStream::moveStart(int delta) {
764 bufPtr = buf + start;
767 #ifndef NO_DECRYPTION
768 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
769 int objNum, int objGen) {
773 this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
775 newBuf = (char *)gmalloc(length);
776 for (p = buf + start, q = newBuf; p < bufEnd; ++p, ++q) {
777 *q = (char)decrypt->decryptByte((Guchar)*p);
779 bufEnd = newBuf + length;
780 bufPtr = newBuf + (bufPtr - (buf + start));
788 //------------------------------------------------------------------------
790 //------------------------------------------------------------------------
792 EmbedStream::EmbedStream(Stream *strA, Object *dictA,
793 GBool limitedA, Guint lengthA):
800 EmbedStream::~EmbedStream() {
803 Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA,
804 Guint lengthA, Object *dictA) {
805 error(-1, "Internal: called makeSubStream() on EmbedStream");
809 int EmbedStream::getChar() {
810 if (limited && !length) {
814 return str->getChar();
817 int EmbedStream::lookChar() {
818 if (limited && !length) {
821 return str->lookChar();
824 void EmbedStream::setPos(Guint pos, int dir) {
825 error(-1, "Internal: called setPos() on EmbedStream");
828 Guint EmbedStream::getStart() {
829 error(-1, "Internal: called getStart() on EmbedStream");
833 void EmbedStream::moveStart(int delta) {
834 error(-1, "Internal: called moveStart() on EmbedStream");
837 //------------------------------------------------------------------------
839 //------------------------------------------------------------------------
841 ASCIIHexStream::ASCIIHexStream(Stream *strA):
847 ASCIIHexStream::~ASCIIHexStream() {
851 void ASCIIHexStream::reset() {
857 int ASCIIHexStream::lookChar() {
868 } while (isspace(c1));
876 } while (isspace(c2));
881 if (c1 >= '0' && c1 <= '9') {
883 } else if (c1 >= 'A' && c1 <= 'F') {
884 x = (c1 - 'A' + 10) << 4;
885 } else if (c1 >= 'a' && c1 <= 'f') {
886 x = (c1 - 'a' + 10) << 4;
887 } else if (c1 == EOF) {
891 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
894 if (c2 >= '0' && c2 <= '9') {
896 } else if (c2 >= 'A' && c2 <= 'F') {
898 } else if (c2 >= 'a' && c2 <= 'f') {
900 } else if (c2 == EOF) {
904 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
910 GString *ASCIIHexStream::getPSFilter(int psLevel, char *indent) {
916 if (!(s = str->getPSFilter(psLevel, indent))) {
919 s->append(indent)->append("/ASCIIHexDecode filter\n");
923 GBool ASCIIHexStream::isBinary(GBool last) {
924 return str->isBinary(gFalse);
927 //------------------------------------------------------------------------
929 //------------------------------------------------------------------------
931 ASCII85Stream::ASCII85Stream(Stream *strA):
937 ASCII85Stream::~ASCII85Stream() {
941 void ASCII85Stream::reset() {
947 int ASCII85Stream::lookChar() {
956 c[0] = str->getChar();
957 } while (c[0] == '\n' || c[0] == '\r');
958 if (c[0] == '~' || c[0] == EOF) {
962 } else if (c[0] == 'z') {
963 b[0] = b[1] = b[2] = b[3] = 0;
966 for (k = 1; k < 5; ++k) {
968 c[k] = str->getChar();
969 } while (c[k] == '\n' || c[k] == '\r');
970 if (c[k] == '~' || c[k] == EOF)
974 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
975 for (++k; k < 5; ++k)
980 for (k = 0; k < 5; ++k)
981 t = t * 85 + (c[k] - 0x21);
982 for (k = 3; k >= 0; --k) {
983 b[k] = (int)(t & 0xff);
991 GString *ASCII85Stream::getPSFilter(int psLevel, char *indent) {
997 if (!(s = str->getPSFilter(psLevel, indent))) {
1000 s->append(indent)->append("/ASCII85Decode filter\n");
1004 GBool ASCII85Stream::isBinary(GBool last) {
1005 return str->isBinary(gFalse);
1008 //------------------------------------------------------------------------
1010 //------------------------------------------------------------------------
1012 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
1013 int bits, int earlyA):
1014 FilterStream(strA) {
1015 if (predictor != 1) {
1016 pred = new StreamPredictor(this, predictor, columns, colors, bits);
1026 LZWStream::~LZWStream() {
1033 int LZWStream::getChar() {
1035 return pred->getChar();
1040 if (seqIndex >= seqLength) {
1041 if (!processNextCode()) {
1045 return seqBuf[seqIndex++];
1048 int LZWStream::lookChar() {
1050 return pred->lookChar();
1055 if (seqIndex >= seqLength) {
1056 if (!processNextCode()) {
1060 return seqBuf[seqIndex];
1063 int LZWStream::getRawChar() {
1067 if (seqIndex >= seqLength) {
1068 if (!processNextCode()) {
1072 return seqBuf[seqIndex++];
1075 void LZWStream::reset() {
1082 GBool LZWStream::processNextCode() {
1092 // check for eod and clear-table codes
1095 if (code == EOF || code == 257) {
1103 if (nextCode >= 4097) {
1104 error(getPos(), "Bad LZW stream - expected clear-table code");
1108 // process the next code
1109 nextLength = seqLength + 1;
1113 } else if (code < nextCode) {
1114 seqLength = table[code].length;
1115 for (i = seqLength - 1, j = code; i > 0; --i) {
1116 seqBuf[i] = table[j].tail;
1120 } else if (code == nextCode) {
1121 seqBuf[seqLength] = newChar;
1124 error(getPos(), "Bad LZW stream - unexpected code");
1128 newChar = seqBuf[0];
1132 table[nextCode].length = nextLength;
1133 table[nextCode].head = prevCode;
1134 table[nextCode].tail = newChar;
1136 if (nextCode + early == 512)
1138 else if (nextCode + early == 1024)
1140 else if (nextCode + early == 2048)
1151 void LZWStream::clearTable() {
1154 seqIndex = seqLength = 0;
1158 int LZWStream::getCode() {
1162 while (inputBits < nextBits) {
1163 if ((c = str->getChar()) == EOF)
1165 inputBuf = (inputBuf << 8) | (c & 0xff);
1168 code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
1169 inputBits -= nextBits;
1173 GString *LZWStream::getPSFilter(int psLevel, char *indent) {
1176 if (psLevel < 2 || pred) {
1179 if (!(s = str->getPSFilter(psLevel, indent))) {
1182 s->append(indent)->append("/LZWDecode filter\n");
1186 GBool LZWStream::isBinary(GBool last) {
1187 return str->isBinary(gTrue);
1190 //------------------------------------------------------------------------
1192 //------------------------------------------------------------------------
1194 RunLengthStream::RunLengthStream(Stream *strA):
1195 FilterStream(strA) {
1196 bufPtr = bufEnd = buf;
1200 RunLengthStream::~RunLengthStream() {
1204 void RunLengthStream::reset() {
1206 bufPtr = bufEnd = buf;
1210 GString *RunLengthStream::getPSFilter(int psLevel, char *indent) {
1216 if (!(s = str->getPSFilter(psLevel, indent))) {
1219 s->append(indent)->append("/RunLengthDecode filter\n");
1223 GBool RunLengthStream::isBinary(GBool last) {
1224 return str->isBinary(gTrue);
1227 GBool RunLengthStream::fillBuf() {
1234 if (c == 0x80 || c == EOF) {
1240 for (i = 0; i < n; ++i)
1241 buf[i] = (char)str->getChar();
1245 for (i = 0; i < n; ++i)
1253 //------------------------------------------------------------------------
1255 //------------------------------------------------------------------------
1257 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1258 GBool byteAlignA, int columnsA, int rowsA,
1259 GBool endOfBlockA, GBool blackA):
1260 FilterStream(strA) {
1261 encoding = encodingA;
1262 endOfLine = endOfLineA;
1263 byteAlign = byteAlignA;
1266 endOfBlock = endOfBlockA;
1268 refLine = (short *)gmalloc((columns + 3) * sizeof(short));
1269 codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
1273 nextLine2D = encoding < 0;
1276 codingLine[1] = refLine[2] = columns;
1282 CCITTFaxStream::~CCITTFaxStream() {
1288 void CCITTFaxStream::reset() {
1294 nextLine2D = encoding < 0;
1297 codingLine[1] = refLine[2] = columns;
1301 // skip any initial zero bits and end-of-line marker, and get the 2D
1303 while ((code1 = lookBits(12)) == 0) {
1306 if (code1 == 0x001) {
1310 nextLine2D = !lookBits(1);
1315 int CCITTFaxStream::lookChar() {
1316 short code1, code2, code3;
1322 // if at eof just return EOF
1323 if (eof && codingLine[a0] >= columns) {
1327 // read the next row
1329 if (codingLine[a0] >= columns) {
1333 for (i = 0; codingLine[i] < columns; ++i)
1334 refLine[i] = codingLine[i];
1335 refLine[i] = refLine[i + 1] = columns;
1337 a0New = codingLine[a0 = 0] = 0;
1339 code1 = getTwoDimCode();
1342 if (refLine[b1] < columns) {
1343 a0New = refLine[b1 + 1];
1348 if ((a0 & 1) == 0) {
1351 code1 += code3 = getWhiteCode();
1352 } while (code3 >= 64);
1354 code2 += code3 = getBlackCode();
1355 } while (code3 >= 64);
1359 code1 += code3 = getBlackCode();
1360 } while (code3 >= 64);
1362 code2 += code3 = getWhiteCode();
1363 } while (code3 >= 64);
1365 if (code1 > 0 || code2 > 0) {
1366 codingLine[a0 + 1] = a0New + code1;
1368 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1370 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1375 a0New = codingLine[++a0] = refLine[b1];
1376 if (refLine[b1] < columns) {
1378 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1383 a0New = codingLine[++a0] = refLine[b1] + 1;
1384 if (refLine[b1] < columns) {
1386 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1391 a0New = codingLine[++a0] = refLine[b1] - 1;
1393 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1397 a0New = codingLine[++a0] = refLine[b1] + 2;
1398 if (refLine[b1] < columns) {
1400 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1405 a0New = codingLine[++a0] = refLine[b1] - 2;
1407 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1411 a0New = codingLine[++a0] = refLine[b1] + 3;
1412 if (refLine[b1] < columns) {
1414 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1419 a0New = codingLine[++a0] = refLine[b1] - 3;
1421 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1426 codingLine[a0 = 0] = columns;
1429 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1433 } while (codingLine[a0] < columns);
1437 codingLine[a0 = 0] = 0;
1441 code1 += code3 = getWhiteCode();
1442 } while (code3 >= 64);
1443 codingLine[a0+1] = codingLine[a0] + code1;
1445 if (codingLine[a0] >= columns)
1449 code2 += code3 = getBlackCode();
1450 } while (code3 >= 64);
1451 codingLine[a0+1] = codingLine[a0] + code2;
1453 if (codingLine[a0] >= columns)
1458 if (codingLine[a0] != columns) {
1459 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
1460 // force the row to be the correct length
1461 while (codingLine[a0] > columns) {
1464 codingLine[++a0] = columns;
1468 // byte-align the row
1473 // check for end-of-line marker, skipping over any extra zero bits
1475 if (!endOfBlock && row == rows - 1) {
1478 code1 = lookBits(12);
1479 while (code1 == 0) {
1481 code1 = lookBits(12);
1483 if (code1 == 0x001) {
1486 } else if (code1 == EOF) {
1491 // get 2D encoding tag
1492 if (!eof && encoding > 0) {
1493 nextLine2D = !lookBits(1);
1497 // check for end-of-block marker
1498 if (endOfBlock && gotEOL) {
1499 code1 = lookBits(12);
1500 if (code1 == 0x001) {
1506 if (encoding >= 0) {
1507 for (i = 0; i < 4; ++i) {
1508 code1 = lookBits(12);
1509 if (code1 != 0x001) {
1510 error(getPos(), "Bad RTC code in CCITTFax stream");
1522 // look for an end-of-line marker after an error -- we only do
1523 // this if we know the stream contains end-of-line markers because
1524 // the "just plow on" technique tends to work better otherwise
1525 } else if (err && endOfLine) {
1532 code1 = lookBits(13);
1533 } while ((code1 >> 1) != 0x001);
1537 nextLine2D = !(code1 & 1);
1542 outputBits = codingLine[1] - codingLine[0];
1543 if (outputBits == 0) {
1545 outputBits = codingLine[2] - codingLine[1];
1552 if (outputBits >= 8) {
1553 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1554 if ((outputBits -= 8) == 0) {
1556 if (codingLine[a0] < columns) {
1557 outputBits = codingLine[a0 + 1] - codingLine[a0];
1564 if (outputBits > bits) {
1567 if ((a0 & 1) == 0) {
1568 ret |= 0xff >> (8 - i);
1574 if ((a0 & 1) == 0) {
1575 ret |= (0xff >> (8 - i)) << bits;
1579 if (codingLine[a0] < columns) {
1580 outputBits = codingLine[a0 + 1] - codingLine[a0];
1583 } while (bits > 0 && codingLine[a0] < columns);
1585 buf = black ? (ret ^ 0xff) : ret;
1589 short CCITTFaxStream::getTwoDimCode() {
1594 code = 0; // make gcc happy
1597 p = &twoDimTab1[code];
1603 for (n = 1; n <= 7; ++n) {
1608 p = &twoDimTab1[code];
1615 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1619 short CCITTFaxStream::getWhiteCode() {
1624 code = 0; // make gcc happy
1626 code = lookBits(12);
1627 if ((code >> 5) == 0) {
1628 p = &whiteTab1[code];
1630 p = &whiteTab2[code >> 3];
1637 for (n = 1; n <= 9; ++n) {
1642 p = &whiteTab2[code];
1648 for (n = 11; n <= 12; ++n) {
1653 p = &whiteTab1[code];
1660 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1661 // eat a bit and return a positive number so that the caller doesn't
1662 // go into an infinite loop
1667 short CCITTFaxStream::getBlackCode() {
1672 code = 0; // make gcc happy
1674 code = lookBits(13);
1675 if ((code >> 7) == 0) {
1676 p = &blackTab1[code];
1677 } else if ((code >> 9) == 0) {
1678 p = &blackTab2[(code >> 1) - 64];
1680 p = &blackTab3[code >> 7];
1687 for (n = 2; n <= 6; ++n) {
1692 p = &blackTab3[code];
1698 for (n = 7; n <= 12; ++n) {
1704 p = &blackTab2[code - 64];
1711 for (n = 10; n <= 13; ++n) {
1716 p = &blackTab1[code];
1723 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
1724 // eat a bit and return a positive number so that the caller doesn't
1725 // go into an infinite loop
1730 short CCITTFaxStream::lookBits(int n) {
1733 while (inputBits < n) {
1734 if ((c = str->getChar()) == EOF) {
1735 if (inputBits == 0) {
1738 // near the end of the stream, the caller may ask for more bits
1739 // than are available, but there may still be a valid code in
1740 // however many bits are available -- we need to return correct
1741 // data in this case
1742 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
1744 inputBuf = (inputBuf << 8) + c;
1747 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1750 GString *CCITTFaxStream::getPSFilter(int psLevel, char *indent) {
1757 if (!(s = str->getPSFilter(psLevel, indent))) {
1760 s->append(indent)->append("<< ");
1761 if (encoding != 0) {
1762 sprintf(s1, "/K %d ", encoding);
1766 s->append("/EndOfLine true ");
1769 s->append("/EncodedByteAlign true ");
1771 sprintf(s1, "/Columns %d ", columns);
1774 sprintf(s1, "/Rows %d ", rows);
1778 s->append("/EndOfBlock false ");
1781 s->append("/BlackIs1 true ");
1783 s->append(">> /CCITTFaxDecode filter\n");
1787 GBool CCITTFaxStream::isBinary(GBool last) {
1788 return str->isBinary(gTrue);
1791 //------------------------------------------------------------------------
1793 //------------------------------------------------------------------------
1795 // IDCT constants (20.12 fixed point format)
1796 #define dctCos1 4017 // cos(pi/16)
1797 #define dctSin1 799 // sin(pi/16)
1798 #define dctCos3 3406 // cos(3*pi/16)
1799 #define dctSin3 2276 // sin(3*pi/16)
1800 #define dctCos6 1567 // cos(6*pi/16)
1801 #define dctSin6 3784 // sin(6*pi/16)
1802 #define dctSqrt2 5793 // sqrt(2)
1803 #define dctSqrt1d2 2896 // sqrt(2) / 2
1805 // color conversion parameters (16.16 fixed point format)
1806 #define dctCrToR 91881 // 1.4020
1807 #define dctCbToG -22553 // -0.3441363
1808 #define dctCrToG -46802 // -0.71413636
1809 #define dctCbToB 116130 // 1.772
1811 // clip [-256,511] --> [0,255]
1812 #define dctClipOffset 256
1813 static Guchar dctClip[768];
1814 static int dctClipInit = 0;
1816 // zig zag decode map
1817 static int dctZigZag[64] = {
1823 5, 12, 19, 26, 33, 40,
1824 48, 41, 34, 27, 20, 13, 6,
1825 7, 14, 21, 28, 35, 42, 49, 56,
1826 57, 50, 43, 36, 29, 22, 15,
1827 23, 30, 37, 44, 51, 58,
1835 DCTStream::DCTStream(Stream *strA):
1836 FilterStream(strA) {
1839 progressive = interleaved = gFalse;
1841 mcuWidth = mcuHeight = 0;
1845 for (i = 0; i < 4; ++i) {
1846 for (j = 0; j < 32; ++j) {
1847 rowBuf[i][j] = NULL;
1853 for (i = -256; i < 0; ++i)
1854 dctClip[dctClipOffset + i] = 0;
1855 for (i = 0; i < 256; ++i)
1856 dctClip[dctClipOffset + i] = i;
1857 for (i = 256; i < 512; ++i)
1858 dctClip[dctClipOffset + i] = 255;
1863 DCTStream::~DCTStream() {
1867 if (progressive || !interleaved) {
1868 for (i = 0; i < numComps; ++i) {
1872 for (i = 0; i < numComps; ++i) {
1873 for (j = 0; j < mcuHeight; ++j) {
1874 gfree(rowBuf[i][j]);
1880 void DCTStream::reset() {
1881 int minHSample, minVSample;
1886 progressive = interleaved = gFalse;
1890 numDCHuffTables = 0;
1891 numACHuffTables = 0;
1893 gotJFIFMarker = gFalse;
1894 gotAdobeMarker = gFalse;
1895 restartInterval = 0;
1897 if (!readHeader()) {
1903 mcuWidth = minHSample = compInfo[0].hSample;
1904 mcuHeight = minVSample = compInfo[0].vSample;
1905 for (i = 1; i < numComps; ++i) {
1906 if (compInfo[i].hSample < minHSample)
1907 minHSample = compInfo[i].hSample;
1908 if (compInfo[i].vSample < minVSample)
1909 minVSample = compInfo[i].vSample;
1910 if (compInfo[i].hSample > mcuWidth)
1911 mcuWidth = compInfo[i].hSample;
1912 if (compInfo[i].vSample > mcuHeight)
1913 mcuHeight = compInfo[i].vSample;
1915 for (i = 0; i < numComps; ++i) {
1916 compInfo[i].hSample /= minHSample;
1917 compInfo[i].vSample /= minVSample;
1919 mcuWidth = (mcuWidth / minHSample) * 8;
1920 mcuHeight = (mcuHeight / minVSample) * 8;
1922 // figure out color transform
1923 if (!gotAdobeMarker && numComps == 3) {
1924 if (gotJFIFMarker) {
1926 } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
1927 compInfo[2].id == 66) { // ASCII "RGB"
1934 if (progressive || !interleaved) {
1936 // allocate a buffer for the whole image
1937 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
1938 bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
1939 for (i = 0; i < numComps; ++i) {
1940 frameBuf[i] = (int *)gmalloc(bufWidth * bufHeight * sizeof(int));
1941 memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
1944 // read the image data
1946 restartMarker = 0xd0;
1949 } while (readHeader());
1954 // initialize counters
1961 // allocate a buffer for one row of MCUs
1962 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
1963 for (i = 0; i < numComps; ++i) {
1964 for (j = 0; j < mcuHeight; ++j) {
1965 rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
1969 // initialize counters
1975 restartMarker = 0xd0;
1980 int DCTStream::getChar() {
1986 if (progressive || !interleaved) {
1987 c = frameBuf[comp][y * bufWidth + x];
1988 if (++comp == numComps) {
1996 if (dy >= mcuHeight) {
1997 if (!readMCURow()) {
2005 c = rowBuf[comp][dy][x];
2006 if (++comp == numComps) {
2021 int DCTStream::lookChar() {
2025 if (progressive || !interleaved) {
2026 return frameBuf[comp][y * bufWidth + x];
2028 if (dy >= mcuHeight) {
2029 if (!readMCURow()) {
2037 return rowBuf[comp][dy][x];
2041 void DCTStream::restart() {
2045 restartCtr = restartInterval;
2046 for (i = 0; i < numComps; ++i) {
2047 compInfo[i].prevDC = 0;
2052 // Read one row of MCUs from a sequential JPEG stream.
2053 GBool DCTStream::readMCURow() {
2057 int pY, pCb, pCr, pR, pG, pB;
2058 int h, v, horiz, vert, hSub, vSub;
2059 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2062 for (x1 = 0; x1 < width; x1 += mcuWidth) {
2064 // deal with restart marker
2065 if (restartInterval > 0 && restartCtr == 0) {
2067 if (c != restartMarker) {
2068 error(getPos(), "Bad DCT data: incorrect restart marker");
2071 if (++restartMarker == 0xd8)
2072 restartMarker = 0xd0;
2077 for (cc = 0; cc < numComps; ++cc) {
2078 h = compInfo[cc].hSample;
2079 v = compInfo[cc].vSample;
2080 horiz = mcuWidth / h;
2081 vert = mcuHeight / v;
2084 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2085 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2086 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2087 &acHuffTables[scanInfo.acHuffTable[cc]],
2088 &compInfo[cc].prevDC,
2092 transformDataUnit(quantTables[compInfo[cc].quantTable],
2094 if (hSub == 1 && vSub == 1) {
2095 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2096 p1 = &rowBuf[cc][y2+y3][x1+x2];
2106 } else if (hSub == 2 && vSub == 2) {
2107 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2108 p1 = &rowBuf[cc][y2+y3][x1+x2];
2109 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
2110 p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
2111 p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
2112 p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
2113 p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
2114 p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
2115 p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
2116 p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
2117 p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
2121 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2122 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2123 for (y5 = 0; y5 < vSub; ++y5)
2124 for (x5 = 0; x5 < hSub; ++x5)
2125 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
2135 // color space conversion
2137 // convert YCbCr to RGB
2138 if (numComps == 3) {
2139 for (y2 = 0; y2 < mcuHeight; ++y2) {
2140 for (x2 = 0; x2 < mcuWidth; ++x2) {
2141 pY = rowBuf[0][y2][x1+x2];
2142 pCb = rowBuf[1][y2][x1+x2] - 128;
2143 pCr = rowBuf[2][y2][x1+x2] - 128;
2144 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2145 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
2146 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2147 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
2148 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2149 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
2152 // convert YCbCrK to CMYK (K is passed through unchanged)
2153 } else if (numComps == 4) {
2154 for (y2 = 0; y2 < mcuHeight; ++y2) {
2155 for (x2 = 0; x2 < mcuWidth; ++x2) {
2156 pY = rowBuf[0][y2][x1+x2];
2157 pCb = rowBuf[1][y2][x1+x2] - 128;
2158 pCr = rowBuf[2][y2][x1+x2] - 128;
2159 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2160 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2161 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2162 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2163 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2164 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2173 // Read one scan from a progressive or non-interleaved JPEG stream.
2174 void DCTStream::readScan() {
2176 int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
2177 int h, v, horiz, vert, vSub;
2181 if (scanInfo.numComps == 1) {
2182 for (cc = 0; cc < numComps; ++cc) {
2183 if (scanInfo.comp[cc]) {
2187 dx1 = mcuWidth / compInfo[cc].hSample;
2188 dy1 = mcuHeight / compInfo[cc].vSample;
2194 for (y1 = 0; y1 < height; y1 += dy1) {
2195 for (x1 = 0; x1 < width; x1 += dx1) {
2197 // deal with restart marker
2198 if (restartInterval > 0 && restartCtr == 0) {
2200 if (c != restartMarker) {
2201 error(getPos(), "Bad DCT data: incorrect restart marker");
2204 if (++restartMarker == 0xd8) {
2205 restartMarker = 0xd0;
2211 for (cc = 0; cc < numComps; ++cc) {
2212 if (!scanInfo.comp[cc]) {
2216 h = compInfo[cc].hSample;
2217 v = compInfo[cc].vSample;
2218 horiz = mcuWidth / h;
2219 vert = mcuHeight / v;
2221 for (y2 = 0; y2 < dy1; y2 += vert) {
2222 for (x2 = 0; x2 < dx1; x2 += horiz) {
2224 // pull out the current values
2225 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2226 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2235 p1 += bufWidth * vSub;
2238 // read one data unit
2240 if (!readProgressiveDataUnit(
2241 &dcHuffTables[scanInfo.dcHuffTable[cc]],
2242 &acHuffTables[scanInfo.acHuffTable[cc]],
2243 &compInfo[cc].prevDC,
2248 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2249 &acHuffTables[scanInfo.acHuffTable[cc]],
2250 &compInfo[cc].prevDC,
2256 // add the data unit into frameBuf
2257 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2258 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2267 p1 += bufWidth * vSub;
2277 // Read one data unit from a sequential JPEG stream.
2278 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2279 DCTHuffTable *acHuffTable,
2280 int *prevDC, int data[64]) {
2285 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2289 if ((amp = readAmp(size)) == 9999) {
2295 data[0] = *prevDC += amp;
2296 for (i = 1; i < 64; ++i) {
2302 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
2311 run += (c >> 4) & 0x0f;
2313 amp = readAmp(size);
2327 // Read one data unit from a sequential JPEG stream.
2328 GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
2329 DCTHuffTable *acHuffTable,
2330 int *prevDC, int data[64]) {
2331 int run, size, amp, bit, c;
2334 // get the DC coefficient
2335 i = scanInfo.firstCoeff;
2337 if (scanInfo.ah == 0) {
2338 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2342 if ((amp = readAmp(size)) == 9999) {
2348 data[0] += (*prevDC += amp) << scanInfo.al;
2350 if ((bit = readBit()) == 9999) {
2353 data[0] += bit << scanInfo.al;
2357 if (scanInfo.lastCoeff == 0) {
2361 // check for an EOB run
2363 while (i <= scanInfo.lastCoeff) {
2366 if ((bit = readBit()) == EOF) {
2370 data[j] += 1 << scanInfo.al;
2378 // read the AC coefficients
2379 while (i <= scanInfo.lastCoeff) {
2380 if ((c = readHuffSym(acHuffTable)) == 9999) {
2392 if ((bit = readBit()) == EOF) {
2396 data[j] += 1 << scanInfo.al;
2402 } else if ((c & 0x0f) == 0x00) {
2405 for (k = 0; k < j; ++k) {
2406 if ((bit = readBit()) == EOF) {
2409 eobRun = (eobRun << 1) | bit;
2412 while (i <= scanInfo.lastCoeff) {
2415 if ((bit = readBit()) == EOF) {
2419 data[j] += 1 << scanInfo.al;
2426 // zero run and one AC coefficient
2428 run = (c >> 4) & 0x0f;
2430 if ((amp = readAmp(size)) == 9999) {
2436 while (data[j] != 0) {
2437 if ((bit = readBit()) == EOF) {
2441 data[j] += 1 << scanInfo.al;
2447 data[j] = amp << scanInfo.al;
2454 // Decode a progressive JPEG image.
2455 void DCTStream::decodeImage() {
2459 int pY, pCb, pCr, pR, pG, pB;
2460 int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2461 int h, v, horiz, vert, hSub, vSub;
2464 for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
2465 for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
2466 for (cc = 0; cc < numComps; ++cc) {
2467 quantTable = quantTables[compInfo[cc].quantTable];
2468 h = compInfo[cc].hSample;
2469 v = compInfo[cc].vSample;
2470 horiz = mcuWidth / h;
2471 vert = mcuHeight / v;
2474 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2475 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2477 // pull out the coded data unit
2478 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2479 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2481 dataIn[i+1] = p1[1];
2482 dataIn[i+2] = p1[2];
2483 dataIn[i+3] = p1[3];
2484 dataIn[i+4] = p1[4];
2485 dataIn[i+5] = p1[5];
2486 dataIn[i+6] = p1[6];
2487 dataIn[i+7] = p1[7];
2488 p1 += bufWidth * vSub;
2492 transformDataUnit(quantTable, dataIn, dataOut);
2494 // store back into frameBuf, doing replication for
2495 // subsampled components
2496 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2497 if (hSub == 1 && vSub == 1) {
2498 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2499 p1[0] = dataOut[i] & 0xff;
2500 p1[1] = dataOut[i+1] & 0xff;
2501 p1[2] = dataOut[i+2] & 0xff;
2502 p1[3] = dataOut[i+3] & 0xff;
2503 p1[4] = dataOut[i+4] & 0xff;
2504 p1[5] = dataOut[i+5] & 0xff;
2505 p1[6] = dataOut[i+6] & 0xff;
2506 p1[7] = dataOut[i+7] & 0xff;
2509 } else if (hSub == 2 && vSub == 2) {
2511 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2512 p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
2513 p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
2514 p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
2515 p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
2516 p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
2517 p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
2518 p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
2519 p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
2525 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2526 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2528 for (y5 = 0; y5 < vSub; ++y5) {
2529 for (x5 = 0; x5 < hSub; ++x5) {
2530 p2[x5] = dataOut[i] & 0xff;
2536 p1 += bufWidth * vSub;
2543 // color space conversion
2545 // convert YCbCr to RGB
2546 if (numComps == 3) {
2547 for (y2 = 0; y2 < mcuHeight; ++y2) {
2548 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2549 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2550 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2551 for (x2 = 0; x2 < mcuWidth; ++x2) {
2555 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2556 *p0++ = dctClip[dctClipOffset + pR];
2557 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2559 *p1++ = dctClip[dctClipOffset + pG];
2560 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2561 *p2++ = dctClip[dctClipOffset + pB];
2564 // convert YCbCrK to CMYK (K is passed through unchanged)
2565 } else if (numComps == 4) {
2566 for (y2 = 0; y2 < mcuHeight; ++y2) {
2567 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2568 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2569 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2570 for (x2 = 0; x2 < mcuWidth; ++x2) {
2574 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2575 *p0++ = 255 - dctClip[dctClipOffset + pR];
2576 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2578 *p1++ = 255 - dctClip[dctClipOffset + pG];
2579 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2580 *p2++ = 255 - dctClip[dctClipOffset + pB];
2589 // Transform one data unit -- this performs the dequantization and
2590 // IDCT steps. This IDCT algorithm is taken from:
2591 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2592 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2593 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2595 // The stage numbers mentioned in the comments refer to Figure 1 in this
2597 void DCTStream::transformDataUnit(Guchar *quantTable,
2598 int dataIn[64], Guchar dataOut[64]) {
2599 int v0, v1, v2, v3, v4, v5, v6, v7, t;
2604 for (i = 0; i < 64; ++i) {
2605 dataIn[i] *= quantTable[i];
2608 // inverse DCT on rows
2609 for (i = 0; i < 64; i += 8) {
2612 // check for all-zero AC coefficients
2613 if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
2614 p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
2615 t = (dctSqrt2 * p[0] + 512) >> 10;
2628 v0 = (dctSqrt2 * p[0] + 128) >> 8;
2629 v1 = (dctSqrt2 * p[4] + 128) >> 8;
2632 v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
2633 v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
2638 t = (v0 - v1+ 1) >> 1;
2639 v0 = (v0 + v1 + 1) >> 1;
2641 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2642 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2644 t = (v4 - v6 + 1) >> 1;
2645 v4 = (v4 + v6 + 1) >> 1;
2647 t = (v7 + v5 + 1) >> 1;
2648 v5 = (v7 - v5 + 1) >> 1;
2652 t = (v0 - v3 + 1) >> 1;
2653 v0 = (v0 + v3 + 1) >> 1;
2655 t = (v1 - v2 + 1) >> 1;
2656 v1 = (v1 + v2 + 1) >> 1;
2658 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2659 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2661 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2662 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2676 // inverse DCT on columns
2677 for (i = 0; i < 8; ++i) {
2680 // check for all-zero AC coefficients
2681 if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
2682 p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
2683 t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
2696 v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
2697 v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
2700 v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
2701 v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
2706 t = (v0 - v1 + 1) >> 1;
2707 v0 = (v0 + v1 + 1) >> 1;
2709 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2710 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2712 t = (v4 - v6 + 1) >> 1;
2713 v4 = (v4 + v6 + 1) >> 1;
2715 t = (v7 + v5 + 1) >> 1;
2716 v5 = (v7 - v5 + 1) >> 1;
2720 t = (v0 - v3 + 1) >> 1;
2721 v0 = (v0 + v3 + 1) >> 1;
2723 t = (v1 - v2 + 1) >> 1;
2724 v1 = (v1 + v2 + 1) >> 1;
2726 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2727 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2729 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2730 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2744 // convert to 8-bit integers
2745 for (i = 0; i < 64; ++i) {
2746 dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
2750 int DCTStream::readHuffSym(DCTHuffTable *table) {
2758 // add a bit to the code
2759 if ((bit = readBit()) == EOF)
2761 code = (code << 1) + bit;
2765 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2766 code -= table->firstCode[codeBits];
2767 return table->sym[table->firstSym[codeBits] + code];
2769 } while (codeBits < 16);
2771 error(getPos(), "Bad Huffman code in DCT stream");
2775 int DCTStream::readAmp(int size) {
2780 for (bits = 0; bits < size; ++bits) {
2781 if ((bit = readBit()) == EOF)
2783 amp = (amp << 1) + bit;
2785 if (amp < (1 << (size - 1)))
2786 amp -= (1 << size) - 1;
2790 int DCTStream::readBit() {
2794 if (inputBits == 0) {
2795 if ((c = str->getChar()) == EOF)
2799 c2 = str->getChar();
2800 } while (c2 == 0xff);
2802 error(getPos(), "Bad DCT data: missing 00 after ff");
2809 bit = (inputBuf >> (inputBits - 1)) & 1;
2814 GBool DCTStream::readHeader() {
2826 if (!readBaselineSOF()) {
2831 if (!readProgressiveSOF()) {
2836 if (!readHuffmanTables()) {
2845 if (!readScanInfo()) {
2851 if (!readQuantTables()) {
2856 if (!readRestartInterval()) {
2861 if (!readJFIFMarker()) {
2866 if (!readAdobeMarker()) {
2871 error(getPos(), "Bad DCT header");
2874 // skip APPn / COM / etc.
2877 for (i = 0; i < n; ++i) {
2881 error(getPos(), "Unknown DCT marker <%02x>", c);
2891 GBool DCTStream::readBaselineSOF() {
2898 prec = str->getChar();
2901 numComps = str->getChar();
2903 error(getPos(), "Bad DCT precision %d", prec);
2906 for (i = 0; i < numComps; ++i) {
2907 compInfo[i].id = str->getChar();
2909 compInfo[i].hSample = (c >> 4) & 0x0f;
2910 compInfo[i].vSample = c & 0x0f;
2911 compInfo[i].quantTable = str->getChar();
2913 progressive = gFalse;
2917 GBool DCTStream::readProgressiveSOF() {
2924 prec = str->getChar();
2927 numComps = str->getChar();
2929 error(getPos(), "Bad DCT precision %d", prec);
2932 for (i = 0; i < numComps; ++i) {
2933 compInfo[i].id = str->getChar();
2935 compInfo[i].hSample = (c >> 4) & 0x0f;
2936 compInfo[i].vSample = c & 0x0f;
2937 compInfo[i].quantTable = str->getChar();
2939 progressive = gTrue;
2943 GBool DCTStream::readScanInfo() {
2948 length = read16() - 2;
2949 scanInfo.numComps = str->getChar();
2951 if (length != 2 * scanInfo.numComps + 3) {
2952 error(getPos(), "Bad DCT scan info block");
2955 interleaved = scanInfo.numComps == numComps;
2956 for (j = 0; j < numComps; ++j) {
2957 scanInfo.comp[j] = gFalse;
2959 for (i = 0; i < scanInfo.numComps; ++i) {
2960 id = str->getChar();
2961 // some (broken) DCT streams reuse ID numbers, but at least they
2962 // keep the components in order, so we check compInfo[i] first to
2963 // work around the problem
2964 if (id == compInfo[i].id) {
2967 for (j = 0; j < numComps; ++j) {
2968 if (id == compInfo[j].id) {
2972 if (j == numComps) {
2973 error(getPos(), "Bad DCT component ID in scan info block");
2977 scanInfo.comp[j] = gTrue;
2979 scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
2980 scanInfo.acHuffTable[j] = c & 0x0f;
2982 scanInfo.firstCoeff = str->getChar();
2983 scanInfo.lastCoeff = str->getChar();
2985 scanInfo.ah = (c >> 4) & 0x0f;
2986 scanInfo.al = c & 0x0f;
2990 GBool DCTStream::readQuantTables() {
2995 length = read16() - 2;
2996 while (length > 0) {
2997 index = str->getChar();
2998 if ((index & 0xf0) || index >= 4) {
2999 error(getPos(), "Bad DCT quantization table");
3002 if (index == numQuantTables)
3003 numQuantTables = index + 1;
3004 for (i = 0; i < 64; ++i)
3005 quantTables[index][dctZigZag[i]] = str->getChar();
3011 GBool DCTStream::readHuffmanTables() {
3020 length = read16() - 2;
3021 while (length > 0) {
3022 index = str->getChar();
3024 if ((index & 0x0f) >= 4) {
3025 error(getPos(), "Bad DCT Huffman table");
3030 if (index >= numACHuffTables)
3031 numACHuffTables = index+1;
3032 tbl = &acHuffTables[index];
3034 if (index >= numDCHuffTables)
3035 numDCHuffTables = index+1;
3036 tbl = &dcHuffTables[index];
3040 for (i = 1; i <= 16; ++i) {
3042 tbl->firstSym[i] = sym;
3043 tbl->firstCode[i] = code;
3044 tbl->numCodes[i] = c;
3046 code = (code + c) << 1;
3049 for (i = 0; i < sym; ++i)
3050 tbl->sym[i] = str->getChar();
3056 GBool DCTStream::readRestartInterval() {
3061 error(getPos(), "Bad DCT restart interval");
3064 restartInterval = read16();
3068 GBool DCTStream::readJFIFMarker() {
3076 for (i = 0; i < 5; ++i) {
3077 if ((c = str->getChar()) == EOF) {
3078 error(getPos(), "Bad DCT APP0 marker");
3084 if (!memcmp(buf, "JFIF\0", 5)) {
3085 gotJFIFMarker = gTrue;
3088 while (length > 0) {
3089 if (str->getChar() == EOF) {
3090 error(getPos(), "Bad DCT APP0 marker");
3098 GBool DCTStream::readAdobeMarker() {
3107 for (i = 0; i < 12; ++i) {
3108 if ((c = str->getChar()) == EOF) {
3113 if (strncmp(buf, "Adobe", 5)) {
3116 colorXform = buf[11];
3117 gotAdobeMarker = gTrue;
3118 for (i = 14; i < length; ++i) {
3119 if (str->getChar() == EOF) {
3126 error(getPos(), "Bad DCT Adobe APP14 marker");
3130 GBool DCTStream::readTrailer() {
3134 if (c != 0xd9) { // EOI
3135 error(getPos(), "Bad DCT trailer");
3141 int DCTStream::readMarker() {
3147 } while (c != 0xff);
3150 } while (c == 0xff);
3151 } while (c == 0x00);
3155 int DCTStream::read16() {
3158 if ((c1 = str->getChar()) == EOF)
3160 if ((c2 = str->getChar()) == EOF)
3162 return (c1 << 8) + c2;
3165 GString *DCTStream::getPSFilter(int psLevel, char *indent) {
3171 if (!(s = str->getPSFilter(psLevel, indent))) {
3174 s->append(indent)->append("<< >> /DCTDecode filter\n");
3178 GBool DCTStream::isBinary(GBool last) {
3179 return str->isBinary(gTrue);
3182 //------------------------------------------------------------------------
3184 //------------------------------------------------------------------------
3186 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
3187 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3190 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
3222 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
3255 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
3256 int colors, int bits):
3257 FilterStream(strA) {
3258 if (predictor != 1) {
3259 pred = new StreamPredictor(this, predictor, columns, colors, bits);
3263 litCodeTab.codes = NULL;
3264 distCodeTab.codes = NULL;
3267 FlateStream::~FlateStream() {
3268 gfree(litCodeTab.codes);
3269 gfree(distCodeTab.codes);
3276 void FlateStream::reset() {
3283 compressedBlock = gFalse;
3290 //~ need to look at window size?
3291 endOfBlock = eof = gTrue;
3292 cmf = str->getChar();
3293 flg = str->getChar();
3294 if (cmf == EOF || flg == EOF)
3296 if ((cmf & 0x0f) != 0x08) {
3297 error(getPos(), "Unknown compression method in flate stream");
3300 if ((((cmf << 8) + flg) % 31) != 0) {
3301 error(getPos(), "Bad FCHECK in flate stream");
3305 error(getPos(), "FDICT bit set in flate stream");
3312 int FlateStream::getChar() {
3316 return pred->getChar();
3318 while (remain == 0) {
3319 if (endOfBlock && eof)
3324 index = (index + 1) & flateMask;
3329 int FlateStream::lookChar() {
3333 return pred->lookChar();
3335 while (remain == 0) {
3336 if (endOfBlock && eof)
3344 int FlateStream::getRawChar() {
3347 while (remain == 0) {
3348 if (endOfBlock && eof)
3353 index = (index + 1) & flateMask;
3358 GString *FlateStream::getPSFilter(int psLevel, char *indent) {
3361 if (psLevel < 3 || pred) {
3364 if (!(s = str->getPSFilter(psLevel, indent))) {
3367 s->append(indent)->append("<< >> /FlateDecode filter\n");
3371 GBool FlateStream::isBinary(GBool last) {
3372 return str->isBinary(gTrue);
3375 void FlateStream::readSome() {
3386 if (compressedBlock) {
3387 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
3392 } else if (code1 == 256) {
3397 code2 = lengthDecode[code1].bits;
3398 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3400 len = lengthDecode[code1].first + code2;
3401 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
3403 code2 = distDecode[code1].bits;
3404 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3406 dist = distDecode[code1].first + code2;
3408 j = (index - dist) & flateMask;
3409 for (k = 0; k < len; ++k) {
3411 i = (i + 1) & flateMask;
3412 j = (j + 1) & flateMask;
3418 len = (blockLen < flateWindow) ? blockLen : flateWindow;
3419 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
3420 if ((c = str->getChar()) == EOF) {
3421 endOfBlock = eof = gTrue;
3435 error(getPos(), "Unexpected end of file in flate stream");
3436 endOfBlock = eof = gTrue;
3440 GBool FlateStream::startBlock() {
3445 // free the code tables from the previous block
3446 gfree(litCodeTab.codes);
3447 litCodeTab.codes = NULL;
3448 gfree(distCodeTab.codes);
3449 distCodeTab.codes = NULL;
3451 // read block header
3452 blockHdr = getCodeWord(3);
3457 // uncompressed block
3458 if (blockHdr == 0) {
3459 compressedBlock = gFalse;
3460 if ((c = str->getChar()) == EOF)
3462 blockLen = c & 0xff;
3463 if ((c = str->getChar()) == EOF)
3465 blockLen |= (c & 0xff) << 8;
3466 if ((c = str->getChar()) == EOF)
3469 if ((c = str->getChar()) == EOF)
3471 check |= (c & 0xff) << 8;
3472 if (check != (~blockLen & 0xffff))
3473 error(getPos(), "Bad uncompressed block length in flate stream");
3477 // compressed block with fixed codes
3478 } else if (blockHdr == 1) {
3479 compressedBlock = gTrue;
3482 // compressed block with dynamic codes
3483 } else if (blockHdr == 2) {
3484 compressedBlock = gTrue;
3485 if (!readDynamicCodes()) {
3489 // unknown block type
3494 endOfBlock = gFalse;
3498 error(getPos(), "Bad block header in flate stream");
3499 endOfBlock = eof = gTrue;
3503 void FlateStream::loadFixedCodes() {
3506 // build the literal code table
3507 for (i = 0; i <= 143; ++i) {
3510 for (i = 144; i <= 255; ++i) {
3513 for (i = 256; i <= 279; ++i) {
3516 for (i = 280; i <= 287; ++i) {
3519 compHuffmanCodes(codeLengths, flateMaxLitCodes, &litCodeTab);
3521 // build the distance code table
3522 for (i = 0; i < flateMaxDistCodes; ++i) {
3525 compHuffmanCodes(codeLengths, flateMaxDistCodes, &distCodeTab);
3528 GBool FlateStream::readDynamicCodes() {
3529 int numCodeLenCodes;
3532 int codeLenCodeLengths[flateMaxCodeLenCodes];
3533 FlateHuffmanTab codeLenCodeTab;
3534 int len, repeat, code;
3537 codeLenCodeTab.codes = NULL;
3540 if ((numLitCodes = getCodeWord(5)) == EOF) {
3544 if ((numDistCodes = getCodeWord(5)) == EOF) {
3548 if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
3551 numCodeLenCodes += 4;
3552 if (numLitCodes > flateMaxLitCodes ||
3553 numDistCodes > flateMaxDistCodes ||
3554 numCodeLenCodes > flateMaxCodeLenCodes) {
3558 // build the code length code table
3559 for (i = 0; i < flateMaxCodeLenCodes; ++i) {
3560 codeLenCodeLengths[i] = 0;
3562 for (i = 0; i < numCodeLenCodes; ++i) {
3563 if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
3567 compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
3569 // build the literal and distance code tables
3573 while (i < numLitCodes + numDistCodes) {
3574 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
3578 if ((repeat = getCodeWord(2)) == EOF) {
3582 if (i + repeat > numLitCodes + numDistCodes) {
3585 for (; repeat > 0; --repeat) {
3586 codeLengths[i++] = len;
3588 } else if (code == 17) {
3589 if ((repeat = getCodeWord(3)) == EOF) {
3593 if (i + repeat > numLitCodes + numDistCodes) {
3597 for (; repeat > 0; --repeat) {
3598 codeLengths[i++] = 0;
3600 } else if (code == 18) {
3601 if ((repeat = getCodeWord(7)) == EOF) {
3605 if (i + repeat > numLitCodes + numDistCodes) {
3609 for (; repeat > 0; --repeat) {
3610 codeLengths[i++] = 0;
3613 codeLengths[i++] = len = code;
3616 compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
3617 compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
3619 gfree(codeLenCodeTab.codes);
3623 error(getPos(), "Bad dynamic code table in flate stream");
3624 gfree(codeLenCodeTab.codes);
3628 // Convert an array <lengths> of <n> lengths, in value order, into a
3629 // Huffman code lookup table.
3630 void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
3631 int tabSize, len, code, code2, skip, val, i, t;
3633 // find max code length
3635 for (val = 0; val < n; ++val) {
3636 if (lengths[val] > tab->maxLen) {
3637 tab->maxLen = lengths[val];
3641 // allocate the table
3642 tabSize = 1 << tab->maxLen;
3643 tab->codes = (FlateCode *)gmalloc(tabSize * sizeof(FlateCode));
3646 for (i = 0; i < tabSize; ++i) {
3647 tab->codes[i].len = 0;
3648 tab->codes[i].val = 0;
3652 for (len = 1, code = 0, skip = 2;
3654 ++len, code <<= 1, skip <<= 1) {
3655 for (val = 0; val < n; ++val) {
3656 if (lengths[val] == len) {
3658 // bit-reverse the code
3661 for (i = 0; i < len; ++i) {
3662 code2 = (code2 << 1) | (t & 1);
3666 // fill in the table entries
3667 for (i = code2; i < tabSize; i += skip) {
3668 tab->codes[i].len = (Gushort)len;
3669 tab->codes[i].val = (Gushort)val;
3678 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
3682 while (codeSize < tab->maxLen) {
3683 if ((c = str->getChar()) == EOF) {
3686 codeBuf |= (c & 0xff) << codeSize;
3689 code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
3690 if (codeSize == 0 || codeSize < code->len || code->len == 0) {
3693 codeBuf >>= code->len;
3694 codeSize -= code->len;
3695 return (int)code->val;
3698 int FlateStream::getCodeWord(int bits) {
3701 while (codeSize < bits) {
3702 if ((c = str->getChar()) == EOF)
3704 codeBuf |= (c & 0xff) << codeSize;
3707 c = codeBuf & ((1 << bits) - 1);
3713 //------------------------------------------------------------------------
3715 //------------------------------------------------------------------------
3717 EOFStream::EOFStream(Stream *strA):
3718 FilterStream(strA) {
3721 EOFStream::~EOFStream() {
3725 //------------------------------------------------------------------------
3726 // FixedLengthEncoder
3727 //------------------------------------------------------------------------
3729 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
3730 FilterStream(strA) {
3735 FixedLengthEncoder::~FixedLengthEncoder() {
3736 if (str->isEncoder())
3740 void FixedLengthEncoder::reset() {
3745 int FixedLengthEncoder::getChar() {
3746 if (length >= 0 && count >= length)
3749 return str->getChar();
3752 int FixedLengthEncoder::lookChar() {
3753 if (length >= 0 && count >= length)
3755 return str->getChar();
3758 GBool FixedLengthEncoder::isBinary(GBool last) {
3759 return str->isBinary(gTrue);
3762 //------------------------------------------------------------------------
3764 //------------------------------------------------------------------------
3766 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
3767 FilterStream(strA) {
3768 bufPtr = bufEnd = buf;
3773 ASCIIHexEncoder::~ASCIIHexEncoder() {
3774 if (str->isEncoder()) {
3779 void ASCIIHexEncoder::reset() {
3781 bufPtr = bufEnd = buf;
3786 GBool ASCIIHexEncoder::fillBuf() {
3787 static char *hex = "0123456789abcdef";
3793 bufPtr = bufEnd = buf;
3794 if ((c = str->getChar()) == EOF) {
3798 if (lineLen >= 64) {
3802 *bufEnd++ = hex[(c >> 4) & 0x0f];
3803 *bufEnd++ = hex[c & 0x0f];
3809 //------------------------------------------------------------------------
3811 //------------------------------------------------------------------------
3813 ASCII85Encoder::ASCII85Encoder(Stream *strA):
3814 FilterStream(strA) {
3815 bufPtr = bufEnd = buf;
3820 ASCII85Encoder::~ASCII85Encoder() {
3821 if (str->isEncoder())
3825 void ASCII85Encoder::reset() {
3827 bufPtr = bufEnd = buf;
3832 GBool ASCII85Encoder::fillBuf() {
3841 for (n = 0; n < 4; ++n) {
3842 if ((c = str->getChar()) == EOF)
3846 bufPtr = bufEnd = buf;
3848 if (n == 4 && t == 0) {
3850 if (++lineLen == 65) {
3857 for (i = 4; i >= 0; --i) {
3858 buf1[i] = (char)(t % 85 + 0x21);
3861 for (i = 0; i <= n; ++i) {
3862 *bufEnd++ = buf1[i];
3863 if (++lineLen == 65) {
3875 return bufPtr < bufEnd;
3878 //------------------------------------------------------------------------
3880 //------------------------------------------------------------------------
3882 RunLengthEncoder::RunLengthEncoder(Stream *strA):
3883 FilterStream(strA) {
3884 bufPtr = bufEnd = nextEnd = buf;
3888 RunLengthEncoder::~RunLengthEncoder() {
3889 if (str->isEncoder())
3893 void RunLengthEncoder::reset() {
3895 bufPtr = bufEnd = nextEnd = buf;
3900 // When fillBuf finishes, buf[] looks like this:
3901 // +-----+--------------+-----------------+--
3902 // + tag | ... data ... | next 0, 1, or 2 |
3903 // +-----+--------------+-----------------+--
3905 // bufPtr bufEnd nextEnd
3907 GBool RunLengthEncoder::fillBuf() {
3916 if (nextEnd < bufEnd + 1) {
3917 if ((c1 = str->getChar()) == EOF) {
3922 c1 = bufEnd[0] & 0xff;
3924 if (nextEnd < bufEnd + 2) {
3925 if ((c2 = str->getChar()) == EOF) {
3934 c2 = bufEnd[1] & 0xff;
3938 c = 0; // make gcc happy
3941 while (n < 128 && (c = str->getChar()) == c1)
3943 buf[0] = (char)(257 - n);
3948 } else if (n < 128) {
3955 // get up to 128 chars
3961 if ((c = str->getChar()) == EOF) {
3967 if (buf[n] == buf[n-1])
3970 if (buf[n] == buf[n-1]) {
3971 buf[0] = (char)(n-2-1);
3973 nextEnd = &buf[n+1];
3975 buf[0] = (char)(n-1);
3976 bufEnd = nextEnd = &buf[n+1];