1 //========================================================================
5 // Copyright 1996 Derek B. Noonburg
7 //========================================================================
10 #pragma implementation
26 #include "Stream-CCITT.h"
30 #define pclose _pclose
34 static GBool setDJSYSFLAGS = gFalse;
38 #if (__VMS_VER < 70000000)
39 extern "C" int unlink(char *filename);
48 //------------------------------------------------------------------------
49 // Stream (base class)
50 //------------------------------------------------------------------------
59 int Stream::getRawChar() {
60 error(-1, "Internal: called getRawChar() on non-predictor stream");
64 char *Stream::getLine(char *buf, int size) {
68 if (lookChar() == EOF)
70 for (i = 0; i < size - 1; ++i) {
72 if (c == EOF || c == '\n')
75 if ((c = lookChar()) == '\n')
85 GString *Stream::getPSFilter(char *indent) {
89 Stream *Stream::addFilters(Object *dict) {
91 Object params, params2;
96 dict->dictLookup("Filter", &obj);
99 dict->dictLookup("F", &obj);
101 dict->dictLookup("DecodeParms", ¶ms);
102 if (params.isNull()) {
104 dict->dictLookup("DP", ¶ms);
107 str = makeFilter(obj.getName(), str, ¶ms);
108 } else if (obj.isArray()) {
109 for (i = 0; i < obj.arrayGetLength(); ++i) {
110 obj.arrayGet(i, &obj2);
111 if (params.isArray())
112 params.arrayGet(i, ¶ms2);
116 str = makeFilter(obj2.getName(), str, ¶ms2);
118 error(getPos(), "Bad filter name");
119 str = new EOFStream(str);
124 } else if (!obj.isNull()) {
125 error(getPos(), "Bad 'Filter' attribute in stream");
133 Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
134 int pred; // parameters
139 GBool endOfLine, byteAlign, endOfBlock, black;
143 if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
144 str = new ASCIIHexStream(str);
145 } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
146 str = new ASCII85Stream(str);
147 } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
153 if (params->isDict()) {
154 params->dictLookup("Predictor", &obj);
158 params->dictLookup("Columns", &obj);
160 columns = obj.getInt();
162 params->dictLookup("Colors", &obj);
164 colors = obj.getInt();
166 params->dictLookup("BitsPerComponent", &obj);
170 params->dictLookup("EarlyChange", &obj);
172 early = obj.getInt();
175 str = new LZWStream(str, pred, columns, colors, bits, early);
176 } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
177 str = new RunLengthStream(str);
178 } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
186 if (params->isDict()) {
187 params->dictLookup("K", &obj);
189 encoding = obj.getInt();
192 params->dictLookup("EndOfLine", &obj);
194 endOfLine = obj.getBool();
197 params->dictLookup("EncodedByteAlign", &obj);
199 byteAlign = obj.getBool();
202 params->dictLookup("Columns", &obj);
204 columns = obj.getInt();
207 params->dictLookup("Rows", &obj);
212 params->dictLookup("EndOfBlock", &obj);
214 endOfBlock = obj.getBool();
217 params->dictLookup("BlackIs1", &obj);
219 black = obj.getBool();
223 str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
224 columns, rows, endOfBlock, black);
225 } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
226 str = new DCTStream(str);
227 } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
232 if (params->isDict()) {
233 params->dictLookup("Predictor", &obj);
237 params->dictLookup("Columns", &obj);
239 columns = obj.getInt();
241 params->dictLookup("Colors", &obj);
243 colors = obj.getInt();
245 params->dictLookup("BitsPerComponent", &obj);
250 str = new FlateStream(str, pred, columns, colors, bits);
252 error(getPos(), "Unknown filter '%s'", name);
253 str = new EOFStream(str);
258 //------------------------------------------------------------------------
260 //------------------------------------------------------------------------
262 BaseStream::BaseStream(Object *dict) {
266 BaseStream::~BaseStream() {
270 //------------------------------------------------------------------------
272 //------------------------------------------------------------------------
274 FilterStream::FilterStream(Stream *str) {
278 FilterStream::~FilterStream() {
281 void FilterStream::setPos(int pos) {
282 error(-1, "Internal: called setPos() on FilterStream");
285 //------------------------------------------------------------------------
287 //------------------------------------------------------------------------
289 ImageStream::ImageStream(Stream *str, int width, int nComps, int nBits) {
294 this->nComps = nComps;
297 nVals = width * nComps;
299 imgLineSize = (nVals + 7) & ~7;
303 imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
307 ImageStream::~ImageStream() {
311 void ImageStream::reset() {
315 GBool ImageStream::getPixel(Guchar *pix) {
321 if (imgIdx >= nVals) {
323 // read one line of image pixels
325 for (i = 0; i < nVals; i += 8) {
327 imgLine[i+0] = (Guchar)((c >> 7) & 1);
328 imgLine[i+1] = (Guchar)((c >> 6) & 1);
329 imgLine[i+2] = (Guchar)((c >> 5) & 1);
330 imgLine[i+3] = (Guchar)((c >> 4) & 1);
331 imgLine[i+4] = (Guchar)((c >> 3) & 1);
332 imgLine[i+5] = (Guchar)((c >> 2) & 1);
333 imgLine[i+6] = (Guchar)((c >> 1) & 1);
334 imgLine[i+7] = (Guchar)(c & 1);
336 } else if (nBits == 8) {
337 for (i = 0; i < nVals; ++i) {
338 imgLine[i] = str->getChar();
341 bitMask = (1 << nBits) - 1;
344 for (i = 0; i < nVals; ++i) {
346 buf = (buf << 8) | (str->getChar() & 0xff);
349 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
354 // reset to start of line
358 for (i = 0; i < nComps; ++i)
359 pix[i] = imgLine[imgIdx++];
363 void ImageStream::skipLine() {
366 n = (nVals * nBits + 7) >> 3;
367 for (i = 0; i < n; ++i) {
372 //------------------------------------------------------------------------
374 //------------------------------------------------------------------------
376 StreamPredictor::StreamPredictor(Stream *str, int predictor,
377 int width, int nComps, int nBits) {
379 this->predictor = predictor;
381 this->nComps = nComps;
384 nVals = width * nComps;
385 pixBytes = (nComps * nBits + 7) >> 3;
386 rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
387 predLine = (Guchar *)gmalloc(rowBytes);
388 memset(predLine, 0, rowBytes);
392 StreamPredictor::~StreamPredictor() {
396 int StreamPredictor::lookChar() {
397 if (predIdx >= rowBytes) {
398 if (!getNextLine()) {
402 return predLine[predIdx];
405 int StreamPredictor::getChar() {
406 if (predIdx >= rowBytes) {
407 if (!getNextLine()) {
411 return predLine[predIdx++];
414 GBool StreamPredictor::getNextLine() {
417 int left, up, upLeft, p, pa, pb, pc;
419 Gulong inBuf, outBuf, bitMask;
423 // get PNG optimum predictor number
424 if (predictor == 15) {
425 if ((curPred = str->getRawChar()) == EOF) {
433 // read the raw line, apply PNG (byte) predictor
434 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
435 for (i = pixBytes; i < rowBytes; ++i) {
436 upLeftBuf[3] = upLeftBuf[2];
437 upLeftBuf[2] = upLeftBuf[1];
438 upLeftBuf[1] = upLeftBuf[0];
439 upLeftBuf[0] = predLine[i];
440 if ((c = str->getRawChar()) == EOF) {
445 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
448 predLine[i] = predLine[i] + (Guchar)c;
450 case 13: // PNG average
451 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
454 case 14: // PNG Paeth
455 left = predLine[i - pixBytes];
457 upLeft = upLeftBuf[pixBytes];
458 p = left + up - upLeft;
459 if ((pa = p - left) < 0)
461 if ((pb = p - up) < 0)
463 if ((pc = p - upLeft) < 0)
465 if (pa <= pb && pa <= pc)
466 predLine[i] = pa + (Guchar)c;
468 predLine[i] = pb + (Guchar)c;
470 predLine[i] = pc + (Guchar)c;
473 default: // no predictor or TIFF predictor
474 predLine[i] = (Guchar)c;
479 // apply TIFF (component) predictor
480 //~ this is completely untested
481 if (predictor == 2) {
483 inBuf = predLine[pixBytes - 1];
484 for (i = pixBytes; i < rowBytes; i += 8) {
485 // 1-bit add is just xor
486 inBuf = (inBuf << 8) | predLine[i];
487 predLine[i] ^= inBuf >> nComps;
489 } else if (nBits == 8) {
490 for (i = pixBytes; i < rowBytes; ++i) {
491 predLine[i] += predLine[i - nComps];
494 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
495 bitMask = (1 << nBits) - 1;
497 inBits = outBits = 0;
499 for (i = 0; i < nVals; ++i) {
500 if (inBits < nBits) {
501 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
504 upLeftBuf[3] = upLeftBuf[2];
505 upLeftBuf[2] = upLeftBuf[1];
506 upLeftBuf[1] = upLeftBuf[0];
507 upLeftBuf[0] = (upLeftBuf[nComps] +
508 (inBuf >> (inBits - nBits))) & bitMask;
509 outBuf = (outBuf << nBits) | upLeftBuf[0];
513 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
517 predLine[k++] = (Guchar)(outBuf << (8 - outBits));
522 // reset to start of line
528 //------------------------------------------------------------------------
530 //------------------------------------------------------------------------
532 FileStream::FileStream(FILE *f, int start, int length, Object *dict):
536 this->length = length;
537 bufPtr = bufEnd = buf;
542 FileStream::~FileStream() {
544 fseek(f, savePos, SEEK_SET);
548 Stream *FileStream::makeSubStream(int start, int length, Object *dict) {
549 return new FileStream(f, start, length, dict);
552 void FileStream::reset() {
553 savePos = (int)ftell(f);
554 fseek(f, start, SEEK_SET);
555 bufPtr = bufEnd = buf;
559 GBool FileStream::fillBuf() {
562 bufPos += bufEnd - buf;
563 bufPtr = bufEnd = buf;
564 if (length >= 0 && bufPos >= start + length)
566 if (length >= 0 && bufPos + 256 > start + length)
567 n = start + length - bufPos;
570 n = fread(buf, 1, n, f);
572 if (bufPtr >= bufEnd)
577 void FileStream::setPos(int pos1) {
581 fseek(f, pos1, SEEK_SET);
584 fseek(f, 0, SEEK_END);
588 fseek(f, pos1, SEEK_END);
589 bufPos = (int)ftell(f);
591 bufPtr = bufEnd = buf;
594 void FileStream::moveStart(int delta) {
595 this->start += delta;
596 bufPtr = bufEnd = buf;
600 //------------------------------------------------------------------------
602 //------------------------------------------------------------------------
604 EmbedStream::EmbedStream(Stream *str, Object *dict):
609 EmbedStream::~EmbedStream() {
612 Stream *EmbedStream::makeSubStream(int start, int length, Object *dict) {
613 error(-1, "Internal: called makeSubStream() on EmbedStream");
617 void EmbedStream::setPos(int pos) {
618 error(-1, "Internal: called setPos() on EmbedStream");
621 int EmbedStream::getStart() {
622 error(-1, "Internal: called getStart() on EmbedStream");
626 void EmbedStream::moveStart(int start) {
627 error(-1, "Internal: called moveStart() on EmbedStream");
630 //------------------------------------------------------------------------
632 //------------------------------------------------------------------------
634 ASCIIHexStream::ASCIIHexStream(Stream *str):
640 ASCIIHexStream::~ASCIIHexStream() {
644 void ASCIIHexStream::reset() {
650 int ASCIIHexStream::lookChar() {
661 } while (isspace(c1));
669 } while (isspace(c2));
674 if (c1 >= '0' && c1 <= '9') {
676 } else if (c1 >= 'A' && c1 <= 'F') {
677 x = (c1 - 'A' + 10) << 4;
678 } else if (c1 >= 'a' && c1 <= 'f') {
679 x = (c1 - 'a' + 10) << 4;
680 } else if (c1 == EOF) {
684 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
687 if (c2 >= '0' && c2 <= '9') {
689 } else if (c2 >= 'A' && c2 <= 'F') {
691 } else if (c2 >= 'a' && c2 <= 'f') {
693 } else if (c2 == EOF) {
697 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
703 GString *ASCIIHexStream::getPSFilter(char *indent) {
706 s = str->getPSFilter(indent);
707 s->append(indent)->append("/ASCIIHexDecode filter\n");
711 GBool ASCIIHexStream::isBinary(GBool last) {
712 return str->isBinary(gFalse);
715 //------------------------------------------------------------------------
717 //------------------------------------------------------------------------
719 ASCII85Stream::ASCII85Stream(Stream *str):
725 ASCII85Stream::~ASCII85Stream() {
729 void ASCII85Stream::reset() {
735 int ASCII85Stream::lookChar() {
744 c[0] = str->getChar();
745 } while (c[0] == '\n' || c[0] == '\r');
746 if (c[0] == '~' || c[0] == EOF) {
750 } else if (c[0] == 'z') {
751 b[0] = b[1] = b[2] = b[3] = 0;
754 for (k = 1; k < 5; ++k) {
756 c[k] = str->getChar();
757 } while (c[k] == '\n' || c[k] == '\r');
758 if (c[k] == '~' || c[k] == EOF)
762 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
763 for (++k; k < 5; ++k)
768 for (k = 0; k < 5; ++k)
769 t = t * 85 + (c[k] - 0x21);
770 for (k = 3; k >= 0; --k) {
771 b[k] = (int)(t & 0xff);
779 GString *ASCII85Stream::getPSFilter(char *indent) {
782 s = str->getPSFilter(indent);
783 s->append(indent)->append("/ASCII85Decode filter\n");
787 GBool ASCII85Stream::isBinary(GBool last) {
788 return str->isBinary(gFalse);
791 //------------------------------------------------------------------------
793 //------------------------------------------------------------------------
795 LZWStream::LZWStream(Stream *str, int predictor1, int columns1, int colors1,
796 int bits1, int early1):
798 if (predictor1 != 1) {
799 pred = new StreamPredictor(this, predictor1, columns1, colors1, bits1);
805 bufPtr = bufEnd = buf;
808 LZWStream::~LZWStream() {
824 int LZWStream::getChar() {
826 return pred->getChar();
828 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
831 int LZWStream::lookChar() {
833 return pred->lookChar();
835 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff);
838 int LZWStream::getRawChar() {
839 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
842 void LZWStream::reset() {
846 bufPtr = bufEnd = buf;
857 if (!setDJSYSFLAGS) {
858 setenv("DJSYSFLAGS", "0x0002", 0);
859 setDJSYSFLAGS = gTrue;
862 strcpy(zCmd, uncompressCmd);
864 zName = zCmd + strlen(zCmd);
867 zName[strlen(zName) - 2] = '\0';
870 if (!(f = fopen(zName, "wb"))) {
871 error(getPos(), "Couldn't open temporary file '%s'", zName);
877 if (!(zPipe = popen(zCmd, "r"))) {
878 error(getPos(), "Couldn't popen '%s'", zCmd);
888 error(getPos(), "Couldn't execute '%s'", zCmd);
892 zName[strlen(zName) - 2] = '\0';
893 if (!(zPipe = fopen(zName, "rb"))) {
894 error(getPos(), "Couldn't open uncompress file '%s'", zName);
901 void LZWStream::dumpFile(FILE *f) {
902 int outCodeBits; // size of output code
903 int outBits; // max output code
904 int outBuf[8]; // output buffer
905 int outData; // temporary output buffer
906 int inCode, outCode; // input and output codes
907 int nextCode; // next code index
908 GBool eof; // set when EOF is reached
909 GBool clear; // set if table needs to be cleared
910 GBool first; // indicates first code word after clear
917 // max code length, block mode flag
935 for (i = 0; i < 8; ++i) {
936 // check for table overflow
937 if (nextCode + early > 0x1001) {
948 } while (first && inCode == 256);
951 // compute output code
954 } else if (inCode == 256) {
957 } else if (inCode == 257) {
961 outCode = inCode - 1;
971 // check input code size
972 if (nextCode + early == 0x200)
974 else if (nextCode + early == 0x400) {
976 } else if (nextCode + early == 0x800) {
980 // check for eof/clear
989 // write output block
993 while (j < i || outBits > 0) {
994 if (outBits < 8 && j < i) {
995 outData = outData | (outBuf[j++] << outBits);
996 outBits += outCodeBits;
998 fputc(outData & 0xff, f);
1003 // check output code size
1004 if (nextCode - 1 == 512 ||
1005 nextCode - 1 == 1024 ||
1006 nextCode - 1 == 2048 ||
1007 nextCode - 1 == 4096) {
1008 outCodeBits = inCodeBits;
1011 // clear table if necessary
1022 int LZWStream::getCode() {
1026 while (inputBits < inCodeBits) {
1027 if ((c = str->getChar()) == EOF)
1029 inputBuf = (inputBuf << 8) | (c & 0xff);
1032 code = (inputBuf >> (inputBits - inCodeBits)) & ((1 << inCodeBits) - 1);
1033 inputBits -= inCodeBits;
1037 GBool LZWStream::fillBuf() {
1042 if ((n = fread(buf, 1, 256, zPipe)) < 256) {
1056 GString *LZWStream::getPSFilter(char *indent) {
1062 s = str->getPSFilter(indent);
1063 s->append(indent)->append("/LZWDecode filter\n");
1067 GBool LZWStream::isBinary(GBool last) {
1068 return str->isBinary(gTrue);
1071 //------------------------------------------------------------------------
1073 //------------------------------------------------------------------------
1075 RunLengthStream::RunLengthStream(Stream *str):
1077 bufPtr = bufEnd = buf;
1081 RunLengthStream::~RunLengthStream() {
1085 void RunLengthStream::reset() {
1087 bufPtr = bufEnd = buf;
1091 GString *RunLengthStream::getPSFilter(char *indent) {
1094 s = str->getPSFilter(indent);
1095 s->append(indent)->append("/RunLengthDecode filter\n");
1099 GBool RunLengthStream::isBinary(GBool last) {
1100 return str->isBinary(gTrue);
1103 GBool RunLengthStream::fillBuf() {
1110 if (c == 0x80 || c == EOF) {
1116 for (i = 0; i < n; ++i)
1117 buf[i] = (char)str->getChar();
1121 for (i = 0; i < n; ++i)
1129 //------------------------------------------------------------------------
1131 //------------------------------------------------------------------------
1133 CCITTFaxStream::CCITTFaxStream(Stream *str, int encoding, GBool endOfLine,
1134 GBool byteAlign, int columns, int rows,
1135 GBool endOfBlock, GBool black):
1137 this->encoding = encoding;
1138 this->endOfLine = endOfLine;
1139 this->byteAlign = byteAlign;
1140 this->columns = columns;
1142 this->endOfBlock = endOfBlock;
1143 this->black = black;
1144 refLine = (short *)gmalloc((columns + 2) * sizeof(short));
1145 codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
1149 nextLine2D = encoding < 0;
1152 codingLine[1] = refLine[2] = columns;
1158 CCITTFaxStream::~CCITTFaxStream() {
1164 void CCITTFaxStream::reset() {
1170 nextLine2D = encoding < 0;
1173 codingLine[1] = refLine[2] = columns;
1177 // get initial end-of-line marker and 2D encoding tag
1179 if (lookBits(12) == 0x001) {
1183 for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
1184 if (n == 11 && lookBits(12) == 0x001) {
1189 nextLine2D = !lookBits(1);
1194 int CCITTFaxStream::lookChar() {
1195 short code1, code2, code3;
1203 // if at eof just return EOF
1204 if (eof && codingLine[a0] >= columns) {
1208 // read the next row
1212 if (codingLine[a0] >= columns) {
1216 for (i = 0; codingLine[i] < columns; ++i)
1217 refLine[i] = codingLine[i];
1218 refLine[i] = refLine[i + 1] = columns;
1220 a0New = codingLine[a0 = 0] = 0;
1222 code1 = getTwoDimCode();
1225 if (refLine[b1] < columns) {
1226 a0New = refLine[b1 + 1];
1231 if ((a0 & 1) == 0) {
1234 code1 += code3 = getWhiteCode();
1235 } while (code3 >= 64);
1237 code2 += code3 = getBlackCode();
1238 } while (code3 >= 64);
1242 code1 += code3 = getBlackCode();
1243 } while (code3 >= 64);
1245 code2 += code3 = getWhiteCode();
1246 } while (code3 >= 64);
1248 codingLine[a0 + 1] = a0New + code1;
1250 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1252 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1256 a0New = codingLine[++a0] = refLine[b1];
1257 if (refLine[b1] < columns) {
1259 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1264 a0New = codingLine[++a0] = refLine[b1] + 1;
1265 if (refLine[b1] < columns) {
1267 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1272 a0New = codingLine[++a0] = refLine[b1] - 1;
1274 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1278 a0New = codingLine[++a0] = refLine[b1] + 2;
1279 if (refLine[b1] < columns) {
1281 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1286 a0New = codingLine[++a0] = refLine[b1] - 2;
1288 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1292 a0New = codingLine[++a0] = refLine[b1] + 3;
1293 if (refLine[b1] < columns) {
1295 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1300 a0New = codingLine[++a0] = refLine[b1] - 3;
1302 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1307 codingLine[a0 = 0] = columns;
1310 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1319 } while (codingLine[a0] < columns);
1323 codingLine[a0 = 0] = 0;
1327 code1 += code3 = getWhiteCode();
1328 } while (code3 >= 64);
1329 codingLine[a0+1] = codingLine[a0] + code1;
1331 if (codingLine[a0] >= columns)
1335 code2 += code3 = getBlackCode();
1336 } while (code3 >= 64);
1337 codingLine[a0+1] = codingLine[a0] + code2;
1339 if (codingLine[a0] >= columns)
1344 if (codingLine[a0] != columns) {
1345 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
1351 // byte-align the row
1356 // check for end-of-line marker, end-of-block marker, and
1359 code1 = lookBits(12);
1362 } else if (code1 == 0x001) {
1365 nextLine2D = !lookBits(1);
1368 code1 = lookBits(12);
1369 if (code1 == 0x001) {
1375 if (encoding >= 0) {
1376 for (i = 0; i < 4; ++i) {
1377 code1 = lookBits(12);
1378 if (code1 != 0x001) {
1379 error(getPos(), "Bad RTC code in CCITTFax stream");
1392 nextLine2D = !lookBits(1);
1397 if (row == rows - 1) {
1400 for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
1401 if (n == 11 && lookBits(12) == 0x001) {
1405 nextLine2D = !lookBits(1);
1412 // This looks for an end-of-line marker after an error, however
1413 // some (most?) CCITT streams in PDF files don't use end-of-line
1414 // markers, and the just-plow-on technique works better in those
1423 code1 = look13Bits();
1424 } while ((code1 >> 1) != 0x001);
1426 codingLine[++a0] = columns;
1429 nextLine2D = !(code1 & 1);
1435 outputBits = codingLine[1] - codingLine[0];
1436 if (outputBits == 0) {
1438 outputBits = codingLine[2] - codingLine[1];
1445 if (outputBits >= 8) {
1446 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1447 if ((outputBits -= 8) == 0) {
1449 if (codingLine[a0] < columns) {
1450 outputBits = codingLine[a0 + 1] - codingLine[a0];
1457 if (outputBits > bits) {
1460 if ((a0 & 1) == 0) {
1461 ret |= 0xff >> (8 - i);
1467 if ((a0 & 1) == 0) {
1468 ret |= (0xff >> (8 - i)) << bits;
1472 if (codingLine[a0] < columns) {
1473 outputBits = codingLine[a0 + 1] - codingLine[a0];
1476 } while (bits > 0 && codingLine[a0] < columns);
1478 buf = black ? (ret ^ 0xff) : ret;
1482 short CCITTFaxStream::getTwoDimCode() {
1487 code = 0; // make gcc happy
1490 p = &twoDimTab1[code];
1496 for (n = 1; n <= 7; ++n) {
1501 p = &twoDimTab1[code];
1508 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1512 short CCITTFaxStream::getWhiteCode() {
1517 code = 0; // make gcc happy
1519 code = lookBits(12);
1520 if ((code >> 5) == 0)
1521 p = &whiteTab1[code];
1523 p = &whiteTab2[code >> 3];
1529 for (n = 1; n <= 9; ++n) {
1534 p = &whiteTab2[code];
1540 for (n = 11; n <= 12; ++n) {
1545 p = &whiteTab1[code];
1552 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1556 short CCITTFaxStream::getBlackCode() {
1561 code = 0; // make gcc happy
1563 code = lookBits(13);
1564 if ((code >> 7) == 0)
1565 p = &blackTab1[code];
1566 else if ((code >> 9) == 0)
1567 p = &blackTab2[(code >> 1) - 64];
1569 p = &blackTab3[code >> 7];
1575 for (n = 2; n <= 6; ++n) {
1580 p = &blackTab3[code];
1586 for (n = 7; n <= 12; ++n) {
1592 p = &blackTab2[code - 64];
1599 for (n = 10; n <= 13; ++n) {
1604 p = &blackTab1[code];
1611 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
1615 short CCITTFaxStream::lookBits(int n) {
1618 while (inputBits < n) {
1619 if ((c = str->getChar()) == EOF) {
1624 inputBuf = (inputBuf << 8) + c;
1627 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1630 GString *CCITTFaxStream::getPSFilter(char *indent) {
1634 s = str->getPSFilter(indent);
1635 s->append(indent)->append("<< ");
1636 if (encoding != 0) {
1637 sprintf(s1, "/K %d ", encoding);
1641 s->append("/EndOfLine true ");
1644 s->append("/EncodedByteAlign true ");
1646 sprintf(s1, "/Columns %d ", columns);
1649 sprintf(s1, "/Rows %d ", rows);
1653 s->append("/EndOfBlock false ");
1656 s->append("/BlackIs1 true ");
1658 s->append(">> /CCITTFaxDecode filter\n");
1662 GBool CCITTFaxStream::isBinary(GBool last) {
1663 return str->isBinary(gTrue);
1666 //------------------------------------------------------------------------
1668 //------------------------------------------------------------------------
1670 // IDCT constants (20.12 fixed point format)
1672 #define dctCos1 4017 // cos(pi/16)
1673 #define dctSin1 799 // sin(pi/16)
1674 #define dctCos3 3406 // cos(3*pi/16)
1675 #define dctSin3 2276 // sin(3*pi/16)
1676 #define dctCos6 1567 // cos(6*pi/16)
1677 #define dctSin6 3784 // sin(6*pi/16)
1678 #define dctSqrt2 5793 // sqrt(2)
1679 #define dctSqrt1d2 2896 // sqrt(2) / 2
1684 #define dctCos1 0.98078528 // cos(pi/16)
1685 #define dctSin1 0.19509032 // sin(pi/16)
1686 #define dctCos3 0.83146961 // cos(3*pi/16)
1687 #define dctSin3 0.55557023 // sin(3*pi/16)
1688 #define dctCos6 0.38268343 // cos(6*pi/16)
1689 #define dctSin6 0.92387953 // sin(6*pi/16)
1690 #define dctSqrt2 1.41421356 // sqrt(2)
1691 #define dctSqrt1d2 0.70710678 // sqrt(2) / 2
1694 // color conversion parameters (16.16 fixed point format)
1695 #define dctCrToR 91881 // 1.4020
1696 #define dctCbToG -22553 // -0.3441363
1697 #define dctCrToG -46802 // -0.71413636
1698 #define dctCbToB 116130 // 1.772
1700 // clip [-256,511] --> [0,255]
1701 #define dctClipOffset 256
1702 static Guchar dctClip[768];
1703 static int dctClipInit = 0;
1705 // zig zag decode map
1706 static int dctZigZag[64] = {
1712 5, 12, 19, 26, 33, 40,
1713 48, 41, 34, 27, 20, 13, 6,
1714 7, 14, 21, 28, 35, 42, 49, 56,
1715 57, 50, 43, 36, 29, 22, 15,
1716 23, 30, 37, 44, 51, 58,
1724 DCTStream::DCTStream(Stream *str):
1729 mcuWidth = mcuHeight = 0;
1733 for (i = 0; i < 4; ++i)
1734 for (j = 0; j < 32; ++j)
1735 rowBuf[i][j] = NULL;
1738 for (i = -256; i < 0; ++i)
1739 dctClip[dctClipOffset + i] = 0;
1740 for (i = 0; i < 256; ++i)
1741 dctClip[dctClipOffset + i] = i;
1742 for (i = 256; i < 512; ++i)
1743 dctClip[dctClipOffset + i] = 255;
1748 DCTStream::~DCTStream() {
1752 for (i = 0; i < numComps; ++i)
1753 for (j = 0; j < mcuHeight; ++j)
1754 gfree(rowBuf[i][j]);
1757 void DCTStream::reset() {
1759 if (!readHeader()) {
1763 restartMarker = 0xd0;
1767 int DCTStream::getChar() {
1773 if (++comp == numComps) {
1786 int DCTStream::lookChar() {
1789 if (dy >= mcuHeight) {
1790 if (!readMCURow()) {
1798 return rowBuf[comp][dy][x];
1801 void DCTStream::restart() {
1805 restartCtr = restartInterval;
1806 for (i = 0; i < numComps; ++i)
1807 compInfo[i].prevDC = 0;
1810 GBool DCTStream::readMCURow() {
1813 int pY, pCb, pCr, pR, pG, pB;
1814 int h, v, horiz, vert, hSub, vSub;
1815 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
1818 for (x1 = 0; x1 < width; x1 += mcuWidth) {
1820 // deal with restart marker
1821 if (restartInterval > 0 && restartCtr == 0) {
1823 if (c != restartMarker) {
1824 error(getPos(), "Bad DCT data: incorrect restart marker");
1827 if (++restartMarker == 0xd8)
1828 restartMarker = 0xd0;
1833 for (cc = 0; cc < numComps; ++cc) {
1834 h = compInfo[cc].hSample;
1835 v = compInfo[cc].vSample;
1836 horiz = mcuWidth / h;
1837 vert = mcuHeight / v;
1840 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
1841 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
1842 if (!readDataUnit(&dcHuffTables[compInfo[cc].dcHuffTable],
1843 &acHuffTables[compInfo[cc].acHuffTable],
1844 quantTables[compInfo[cc].quantTable],
1845 &compInfo[cc].prevDC,
1848 if (hSub == 1 && vSub == 1) {
1849 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
1850 p1 = &rowBuf[cc][y2+y3][x1+x2];
1860 } else if (hSub == 2 && vSub == 2) {
1861 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
1862 p1 = &rowBuf[cc][y2+y3][x1+x2];
1863 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
1864 p1[0] = p1[1] = p2[0] = p2[1] = data[i];
1865 p1[2] = p1[3] = p2[2] = p2[3] = data[i+1];
1866 p1[4] = p1[5] = p2[4] = p2[5] = data[i+2];
1867 p1[6] = p1[7] = p2[6] = p2[7] = data[i+3];
1868 p1[8] = p1[9] = p2[8] = p2[9] = data[i+4];
1869 p1[10] = p1[11] = p2[10] = p2[11] = data[i+5];
1870 p1[12] = p1[13] = p2[12] = p2[13] = data[i+6];
1871 p1[14] = p1[15] = p2[14] = p2[15] = data[i+7];
1875 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
1876 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
1877 for (y5 = 0; y5 < vSub; ++y5)
1878 for (x5 = 0; x5 < hSub; ++x5)
1879 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data[i];
1889 // color space conversion
1891 // convert YCbCr to RGB
1892 if (numComps == 3) {
1893 for (y2 = 0; y2 < mcuHeight; ++y2) {
1894 for (x2 = 0; x2 < mcuWidth; ++x2) {
1895 pY = rowBuf[0][y2][x1+x2];
1896 pCb = rowBuf[1][y2][x1+x2] - 128;
1897 pCr = rowBuf[2][y2][x1+x2] - 128;
1898 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
1899 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
1900 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
1901 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
1902 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
1903 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
1906 // convert YCbCrK to CMYK (K is passed through unchanged)
1907 } else if (numComps == 4) {
1908 for (y2 = 0; y2 < mcuHeight; ++y2) {
1909 for (x2 = 0; x2 < mcuWidth; ++x2) {
1910 pY = rowBuf[0][y2][x1+x2];
1911 pCb = rowBuf[1][y2][x1+x2] - 128;
1912 pCr = rowBuf[2][y2][x1+x2] - 128;
1913 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
1914 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
1915 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32678) >> 16;
1916 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
1917 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
1918 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
1927 // This IDCT algorithm is taken from:
1928 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
1929 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
1930 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
1932 // The stage numbers mentioned in the comments refer to Figure 1 in this
1935 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
1936 DCTHuffTable *acHuffTable,
1937 Guchar quantTable[64], int *prevDC,
1940 int v0, v1, v2, v3, v4, v5, v6, v7, t;
1945 // Huffman decode and dequantize
1946 size = readHuffSym(dcHuffTable);
1950 amp = readAmp(size);
1956 tmp1[0] = (*prevDC += amp) * quantTable[0];
1957 for (i = 1; i < 64; ++i)
1962 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
1969 run += (c >> 4) & 0x0f;
1971 amp = readAmp(size);
1976 tmp1[j] = amp * quantTable[j];
1980 // inverse DCT on rows
1981 for (i = 0; i < 64; i += 8) {
1984 v0 = (dctSqrt2 * tmp1[i+0] + 128) >> 8;
1985 v1 = (dctSqrt2 * tmp1[i+4] + 128) >> 8;
1988 v4 = (dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]) + 128) >> 8;
1989 v7 = (dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]) + 128) >> 8;
1990 v5 = tmp1[i+3] << 4;
1991 v6 = tmp1[i+5] << 4;
1994 t = (v0 - v1+ 1) >> 1;
1995 v0 = (v0 + v1 + 1) >> 1;
1997 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
1998 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2000 t = (v4 - v6 + 1) >> 1;
2001 v4 = (v4 + v6 + 1) >> 1;
2003 t = (v7 + v5 + 1) >> 1;
2004 v5 = (v7 - v5 + 1) >> 1;
2008 t = (v0 - v3 + 1) >> 1;
2009 v0 = (v0 + v3 + 1) >> 1;
2011 t = (v1 - v2 + 1) >> 1;
2012 v1 = (v1 + v2 + 1) >> 1;
2014 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2015 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2017 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2018 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2022 tmp1[i+0] = v0 + v7;
2023 tmp1[i+7] = v0 - v7;
2024 tmp1[i+1] = v1 + v6;
2025 tmp1[i+6] = v1 - v6;
2026 tmp1[i+2] = v2 + v5;
2027 tmp1[i+5] = v2 - v5;
2028 tmp1[i+3] = v3 + v4;
2029 tmp1[i+4] = v3 - v4;
2032 // inverse DCT on columns
2033 for (i = 0; i < 8; ++i) {
2036 v0 = (dctSqrt2 * tmp1[0*8+i] + 2048) >> 12;
2037 v1 = (dctSqrt2 * tmp1[4*8+i] + 2048) >> 12;
2040 v4 = (dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]) + 2048) >> 12;
2041 v7 = (dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]) + 2048) >> 12;
2046 t = (v0 - v1 + 1) >> 1;
2047 v0 = (v0 + v1 + 1) >> 1;
2049 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2050 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2052 t = (v4 - v6 + 1) >> 1;
2053 v4 = (v4 + v6 + 1) >> 1;
2055 t = (v7 + v5 + 1) >> 1;
2056 v5 = (v7 - v5 + 1) >> 1;
2060 t = (v0 - v3 + 1) >> 1;
2061 v0 = (v0 + v3 + 1) >> 1;
2063 t = (v1 - v2 + 1) >> 1;
2064 v1 = (v1 + v2 + 1) >> 1;
2066 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2067 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2069 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2070 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2074 tmp1[0*8+i] = v0 + v7;
2075 tmp1[7*8+i] = v0 - v7;
2076 tmp1[1*8+i] = v1 + v6;
2077 tmp1[6*8+i] = v1 - v6;
2078 tmp1[2*8+i] = v2 + v5;
2079 tmp1[5*8+i] = v2 - v5;
2080 tmp1[3*8+i] = v3 + v4;
2081 tmp1[4*8+i] = v3 - v4;
2084 // convert to 8-bit integers
2085 for (i = 0; i < 64; ++i)
2086 data[i] = dctClip[dctClipOffset + 128 + ((tmp1[i] + 8) >> 4)];
2093 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2094 DCTHuffTable *acHuffTable,
2095 Guchar quantTable[64], int *prevDC,
2098 double v0, v1, v2, v3, v4, v5, v6, v7, t;
2103 // Huffman decode and dequantize
2104 size = readHuffSym(dcHuffTable);
2108 amp = readAmp(size);
2114 tmp1[0] = (*prevDC += amp) * quantTable[0];
2115 for (i = 1; i < 64; ++i)
2120 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
2127 run += (c >> 4) & 0x0f;
2129 amp = readAmp(size);
2134 tmp1[j] = amp * quantTable[j];
2138 // inverse DCT on rows
2139 for (i = 0; i < 64; i += 8) {
2142 v0 = dctSqrt2 * tmp1[i+0];
2143 v1 = dctSqrt2 * tmp1[i+4];
2146 v4 = dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]);
2147 v7 = dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]);
2152 t = 0.5 * (v0 - v1);
2153 v0 = 0.5 * (v0 + v1);
2155 t = v2 * dctSin6 + v3 * dctCos6;
2156 v2 = v2 * dctCos6 - v3 * dctSin6;
2158 t = 0.5 * (v4 - v6);
2159 v4 = 0.5 * (v4 + v6);
2161 t = 0.5 * (v7 + v5);
2162 v5 = 0.5 * (v7 - v5);
2166 t = 0.5 * (v0 - v3);
2167 v0 = 0.5 * (v0 + v3);
2169 t = 0.5 * (v1 - v2);
2170 v1 = 0.5 * (v1 + v2);
2172 t = v4 * dctSin3 + v7 * dctCos3;
2173 v4 = v4 * dctCos3 - v7 * dctSin3;
2175 t = v5 * dctSin1 + v6 * dctCos1;
2176 v5 = v5 * dctCos1 - v6 * dctSin1;
2180 tmp1[i+0] = v0 + v7;
2181 tmp1[i+7] = v0 - v7;
2182 tmp1[i+1] = v1 + v6;
2183 tmp1[i+6] = v1 - v6;
2184 tmp1[i+2] = v2 + v5;
2185 tmp1[i+5] = v2 - v5;
2186 tmp1[i+3] = v3 + v4;
2187 tmp1[i+4] = v3 - v4;
2190 // inverse DCT on columns
2191 for (i = 0; i < 8; ++i) {
2194 v0 = dctSqrt2 * tmp1[0*8+i];
2195 v1 = dctSqrt2 * tmp1[4*8+i];
2198 v4 = dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]);
2199 v7 = dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]);
2204 t = 0.5 * (v0 - v1);
2205 v0 = 0.5 * (v0 + v1);
2207 t = v2 * dctSin6 + v3 * dctCos6;
2208 v2 = v2 * dctCos6 - v3 * dctSin6;
2210 t = 0.5 * (v4 - v6);
2211 v4 = 0.5 * (v4 + v6);
2213 t = 0.5 * (v7 + v5);
2214 v5 = 0.5 * (v7 - v5);
2218 t = 0.5 * (v0 - v3);
2219 v0 = 0.5 * (v0 + v3);
2221 t = 0.5 * (v1 - v2);
2222 v1 = 0.5 * (v1 + v2);
2224 t = v4 * dctSin3 + v7 * dctCos3;
2225 v4 = v4 * dctCos3 - v7 * dctSin3;
2227 t = v5 * dctSin1 + v6 * dctCos1;
2228 v5 = v5 * dctCos1 - v6 * dctSin1;
2232 tmp1[0*8+i] = v0 + v7;
2233 tmp1[7*8+i] = v0 - v7;
2234 tmp1[1*8+i] = v1 + v6;
2235 tmp1[6*8+i] = v1 - v6;
2236 tmp1[2*8+i] = v2 + v5;
2237 tmp1[5*8+i] = v2 - v5;
2238 tmp1[3*8+i] = v3 + v4;
2239 tmp1[4*8+i] = v3 - v4;
2242 // convert to 8-bit integers
2243 for (i = 0; i < 64; ++i)
2244 data[i] = dctClip[dctClipOffset + (int)(tmp1[i] + 128.5)];
2250 int DCTStream::readHuffSym(DCTHuffTable *table) {
2258 // add a bit to the code
2259 if ((bit = readBit()) == EOF)
2261 code = (code << 1) + bit;
2265 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2266 code -= table->firstCode[codeBits];
2267 return table->sym[table->firstSym[codeBits] + code];
2269 } while (codeBits < 16);
2271 error(getPos(), "Bad Huffman code in DCT stream");
2275 int DCTStream::readAmp(int size) {
2280 for (bits = 0; bits < size; ++bits) {
2281 if ((bit = readBit()) == EOF)
2283 amp = (amp << 1) + bit;
2285 if (amp < (1 << (size - 1)))
2286 amp -= (1 << size) - 1;
2290 int DCTStream::readBit() {
2294 if (inputBits == 0) {
2295 if ((c = str->getChar()) == EOF)
2299 c2 = str->getChar();
2300 } while (c2 == 0xff);
2302 error(getPos(), "Bad DCT data: missing 00 after ff");
2309 bit = (inputBuf >> (inputBits - 1)) & 1;
2314 GBool DCTStream::readHeader() {
2316 int minHSample, minVSample;
2325 numDCHuffTables = 0;
2326 numACHuffTables = 0;
2328 gotAdobeMarker = gFalse;
2329 restartInterval = 0;
2337 if (!readFrameInfo())
2341 if (!readHuffmanTables())
2347 if (!readScanInfo())
2352 if (!readQuantTables())
2356 if (!readRestartInterval())
2360 if (!readAdobeMarker())
2364 error(getPos(), "Bad DCT header");
2367 // skip APPn / COM / etc.
2370 for (i = 0; i < n; ++i)
2373 error(getPos(), "Unknown DCT marker <%02x>", c);
2381 mcuWidth = minHSample = compInfo[0].hSample;
2382 mcuHeight = minVSample = compInfo[0].vSample;
2383 for (i = 1; i < numComps; ++i) {
2384 if (compInfo[i].hSample < minHSample)
2385 minHSample = compInfo[i].hSample;
2386 if (compInfo[i].vSample < minVSample)
2387 minVSample = compInfo[i].vSample;
2388 if (compInfo[i].hSample > mcuWidth)
2389 mcuWidth = compInfo[i].hSample;
2390 if (compInfo[i].vSample > mcuHeight)
2391 mcuHeight = compInfo[i].vSample;
2393 for (i = 0; i < numComps; ++i) {
2394 compInfo[i].hSample /= minHSample;
2395 compInfo[i].vSample /= minVSample;
2397 mcuWidth = (mcuWidth / minHSample) * 8;
2398 mcuHeight = (mcuHeight / minVSample) * 8;
2401 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2402 for (i = 0; i < numComps; ++i)
2403 for (j = 0; j < mcuHeight; ++j)
2404 rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
2406 // figure out color transform
2407 if (!gotAdobeMarker && numComps == 3) {
2408 if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
2413 // initialize counters
2422 GBool DCTStream::readFrameInfo() {
2428 length = read16() - 2;
2429 prec = str->getChar();
2432 numComps = str->getChar();
2435 error(getPos(), "Bad DCT precision %d", prec);
2438 for (i = 0; i < numComps; ++i) {
2439 compInfo[i].id = str->getChar();
2440 compInfo[i].inScan = gFalse;
2442 compInfo[i].hSample = (c >> 4) & 0x0f;
2443 compInfo[i].vSample = c & 0x0f;
2444 compInfo[i].quantTable = str->getChar();
2445 compInfo[i].dcHuffTable = 0;
2446 compInfo[i].acHuffTable = 0;
2451 GBool DCTStream::readScanInfo() {
2453 int scanComps, id, c;
2456 length = read16() - 2;
2457 scanComps = str->getChar();
2459 if (length != 2 * scanComps + 3) {
2460 error(getPos(), "Bad DCT scan info block");
2463 for (i = 0; i < scanComps; ++i) {
2464 id = str->getChar();
2465 for (j = 0; j < numComps; ++j) {
2466 if (id == compInfo[j].id)
2469 if (j == numComps) {
2470 error(getPos(), "Bad DCT component ID in scan info block");
2473 compInfo[j].inScan = gTrue;
2475 compInfo[j].dcHuffTable = (c >> 4) & 0x0f;
2476 compInfo[j].acHuffTable = c & 0x0f;
2484 GBool DCTStream::readQuantTables() {
2489 length = read16() - 2;
2490 while (length > 0) {
2491 index = str->getChar();
2492 if ((index & 0xf0) || index >= 4) {
2493 error(getPos(), "Bad DCT quantization table");
2496 if (index == numQuantTables)
2497 numQuantTables = index + 1;
2498 for (i = 0; i < 64; ++i)
2499 quantTables[index][dctZigZag[i]] = str->getChar();
2505 GBool DCTStream::readHuffmanTables() {
2514 length = read16() - 2;
2515 while (length > 0) {
2516 index = str->getChar();
2518 if ((index & 0x0f) >= 4) {
2519 error(getPos(), "Bad DCT Huffman table");
2524 if (index >= numACHuffTables)
2525 numACHuffTables = index+1;
2526 tbl = &acHuffTables[index];
2528 if (index >= numDCHuffTables)
2529 numDCHuffTables = index+1;
2530 tbl = &dcHuffTables[index];
2534 for (i = 1; i <= 16; ++i) {
2536 tbl->firstSym[i] = sym;
2537 tbl->firstCode[i] = code;
2538 tbl->numCodes[i] = c;
2540 code = (code + c) << 1;
2543 for (i = 0; i < sym; ++i)
2544 tbl->sym[i] = str->getChar();
2550 GBool DCTStream::readRestartInterval() {
2555 error(getPos(), "Bad DCT restart interval");
2558 restartInterval = read16();
2562 GBool DCTStream::readAdobeMarker() {
2570 for (i = 0; i < 12; ++i) {
2571 if ((c = str->getChar()) == EOF)
2575 if (strncmp(buf, "Adobe", 5))
2577 colorXform = buf[11];
2578 gotAdobeMarker = gTrue;
2582 error(getPos(), "Bad DCT Adobe APP14 marker");
2586 GBool DCTStream::readTrailer() {
2590 if (c != 0xd9) { // EOI
2591 error(getPos(), "Bad DCT trailer");
2597 int DCTStream::readMarker() {
2603 } while (c != 0xff);
2606 } while (c == 0xff);
2607 } while (c == 0x00);
2611 int DCTStream::read16() {
2614 if ((c1 = str->getChar()) == EOF)
2616 if ((c2 = str->getChar()) == EOF)
2618 return (c1 << 8) + c2;
2621 GString *DCTStream::getPSFilter(char *indent) {
2624 s = str->getPSFilter(indent);
2625 s->append(indent)->append("<< >> /DCTDecode filter\n");
2629 GBool DCTStream::isBinary(GBool last) {
2630 return str->isBinary(gTrue);
2633 //------------------------------------------------------------------------
2635 //------------------------------------------------------------------------
2637 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
2638 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
2641 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
2673 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
2706 FlateStream::FlateStream(Stream *str, int predictor1, int columns1,
2707 int colors1, int bits1):
2709 if (predictor1 != 1) {
2710 pred = new StreamPredictor(this, predictor1, columns1, colors1, bits1);
2716 FlateStream::~FlateStream() {
2723 void FlateStream::reset() {
2729 //~ need to look at window size?
2730 endOfBlock = eof = gTrue;
2731 cmf = str->getChar();
2732 flg = str->getChar();
2733 if (cmf == EOF || flg == EOF)
2735 if ((cmf & 0x0f) != 0x08) {
2736 error(getPos(), "Unknown compression method in flate stream");
2739 if ((((cmf << 8) + flg) % 31) != 0) {
2740 error(getPos(), "Bad FCHECK in flate stream");
2744 error(getPos(), "FDICT bit set in flate stream");
2753 compressedBlock = gFalse;
2758 int FlateStream::getChar() {
2762 return pred->getChar();
2764 while (remain == 0) {
2765 if (endOfBlock && eof)
2770 index = (index + 1) & flateMask;
2775 int FlateStream::lookChar() {
2779 return pred->lookChar();
2781 while (remain == 0) {
2782 if (endOfBlock && eof)
2790 int FlateStream::getRawChar() {
2793 while (remain == 0) {
2794 if (endOfBlock && eof)
2799 index = (index + 1) & flateMask;
2804 GString *FlateStream::getPSFilter(char *indent) {
2808 GBool FlateStream::isBinary(GBool last) {
2809 return str->isBinary(gTrue);
2812 void FlateStream::readSome() {
2823 if (compressedBlock) {
2824 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
2829 } else if (code1 == 256) {
2834 code2 = lengthDecode[code1].bits;
2835 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
2837 len = lengthDecode[code1].first + code2;
2838 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
2840 code2 = distDecode[code1].bits;
2841 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
2843 dist = distDecode[code1].first + code2;
2845 j = (index - dist) & flateMask;
2846 for (k = 0; k < len; ++k) {
2848 i = (i + 1) & flateMask;
2849 j = (j + 1) & flateMask;
2855 len = (blockLen < flateWindow) ? blockLen : flateWindow;
2856 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
2857 if ((c = str->getChar()) == EOF) {
2858 endOfBlock = eof = gTrue;
2872 error(getPos(), "Unexpected end of file in flate stream");
2873 endOfBlock = eof = gTrue;
2877 GBool FlateStream::startBlock() {
2882 // read block header
2883 blockHdr = getCodeWord(3);
2888 // uncompressed block
2889 if (blockHdr == 0) {
2890 compressedBlock = gFalse;
2891 if ((c = str->getChar()) == EOF)
2893 blockLen = c & 0xff;
2894 if ((c = str->getChar()) == EOF)
2896 blockLen |= (c & 0xff) << 8;
2897 if ((c = str->getChar()) == EOF)
2900 if ((c = str->getChar()) == EOF)
2902 check |= (c & 0xff) << 8;
2903 if (check != (~blockLen & 0xffff))
2904 error(getPos(), "Bad uncompressed block length in flate stream");
2908 // compressed block with fixed codes
2909 } else if (blockHdr == 1) {
2910 compressedBlock = gTrue;
2913 // compressed block with dynamic codes
2914 } else if (blockHdr == 2) {
2915 compressedBlock = gTrue;
2916 if (!readDynamicCodes())
2919 // unknown block type
2924 endOfBlock = gFalse;
2928 error(getPos(), "Bad block header in flate stream");
2929 endOfBlock = eof = gTrue;
2933 void FlateStream::loadFixedCodes() {
2936 // set up code arrays
2937 litCodeTab.codes = allCodes;
2938 distCodeTab.codes = allCodes + flateMaxLitCodes;
2940 // initialize literal code table
2941 for (i = 0; i <= 143; ++i)
2942 litCodeTab.codes[i].len = 8;
2943 for (i = 144; i <= 255; ++i)
2944 litCodeTab.codes[i].len = 9;
2945 for (i = 256; i <= 279; ++i)
2946 litCodeTab.codes[i].len = 7;
2947 for (i = 280; i <= 287; ++i)
2948 litCodeTab.codes[i].len = 8;
2949 compHuffmanCodes(&litCodeTab, flateMaxLitCodes);
2951 // initialize distance code table
2952 for (i = 0; i < 5; ++i)
2953 distCodeTab.start[i] = 0;
2954 distCodeTab.start[5] = 0;
2955 for (i = 6; i <= flateMaxHuffman+1; ++i)
2956 distCodeTab.start[6] = flateMaxDistCodes;
2957 for (i = 0; i < flateMaxDistCodes; ++i) {
2958 distCodeTab.codes[i].len = 5;
2959 distCodeTab.codes[i].code = i;
2960 distCodeTab.codes[i].val = i;
2964 GBool FlateStream::readDynamicCodes() {
2965 int numCodeLenCodes;
2968 FlateCode codeLenCodes[flateMaxCodeLenCodes];
2969 FlateHuffmanTab codeLenCodeTab;
2970 int len, repeat, code;
2974 if ((numLitCodes = getCodeWord(5)) == EOF)
2977 if ((numDistCodes = getCodeWord(5)) == EOF)
2980 if ((numCodeLenCodes = getCodeWord(4)) == EOF)
2982 numCodeLenCodes += 4;
2983 if (numLitCodes > flateMaxLitCodes ||
2984 numDistCodes > flateMaxDistCodes ||
2985 numCodeLenCodes > flateMaxCodeLenCodes)
2988 // read code length code table
2989 codeLenCodeTab.codes = codeLenCodes;
2990 for (i = 0; i < flateMaxCodeLenCodes; ++i)
2991 codeLenCodes[i].len = 0;
2992 for (i = 0; i < numCodeLenCodes; ++i) {
2993 if ((codeLenCodes[codeLenCodeMap[i]].len = getCodeWord(3)) == -1)
2996 compHuffmanCodes(&codeLenCodeTab, flateMaxCodeLenCodes);
2998 // set up code arrays
2999 litCodeTab.codes = allCodes;
3000 distCodeTab.codes = allCodes + numLitCodes;
3002 // read literal and distance code tables
3006 while (i < numLitCodes + numDistCodes) {
3007 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF)
3010 if ((repeat = getCodeWord(2)) == EOF)
3012 for (repeat += 3; repeat > 0; --repeat)
3013 allCodes[i++].len = len;
3014 } else if (code == 17) {
3015 if ((repeat = getCodeWord(3)) == EOF)
3018 for (repeat += 3; repeat > 0; --repeat)
3019 allCodes[i++].len = 0;
3020 } else if (code == 18) {
3021 if ((repeat = getCodeWord(7)) == EOF)
3024 for (repeat += 11; repeat > 0; --repeat)
3025 allCodes[i++].len = 0;
3027 allCodes[i++].len = len = code;
3030 compHuffmanCodes(&litCodeTab, numLitCodes);
3031 compHuffmanCodes(&distCodeTab, numDistCodes);
3036 error(getPos(), "Bad dynamic code table in flate stream");
3040 // On entry, the <tab->codes> array contains the lengths of each code,
3041 // stored in code value order. This function computes the code words.
3042 // The result is sorted in order of (1) code length and (2) code word.
3043 // The length values are no longer valid. The <tab->start> array is
3044 // filled with the indexes of the first code of each length.
3045 void FlateStream::compHuffmanCodes(FlateHuffmanTab *tab, int n) {
3046 int numLengths[flateMaxHuffman+1];
3047 int nextCode[flateMaxHuffman+1];
3048 int nextIndex[flateMaxHuffman+2];
3052 // count number of codes for each code length
3053 for (i = 0; i <= flateMaxHuffman; ++i)
3055 for (i = 0; i < n; ++i)
3056 ++numLengths[tab->codes[i].len];
3058 // compute first index for each length
3059 tab->start[0] = nextIndex[0] = 0;
3060 for (i = 1; i <= flateMaxHuffman + 1; ++i)
3061 tab->start[i] = nextIndex[i] = tab->start[i-1] + numLengths[i-1];
3063 // compute first code for each length
3066 for (i = 1; i <= flateMaxHuffman; ++i) {
3067 code = (code + numLengths[i-1]) << 1;
3071 // compute the codes -- this permutes the codes array from value
3072 // order to length/code order
3073 for (i = 0; i < n; ++i) {
3074 j = nextIndex[tab->codes[i].len]++;
3075 if (tab->codes[i].len == 0)
3076 tab->codes[j].code = 0;
3078 tab->codes[j].code = nextCode[tab->codes[i].len]++;
3079 tab->codes[j].val = i;
3083 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
3090 for (len = 1; len <= flateMaxHuffman; ++len) {
3092 // add a bit to the code
3093 if (codeSize == 0) {
3094 if ((c = str->getChar()) == EOF)
3099 code = (code << 1) | (codeBuf & 1);
3104 i = tab->start[len];
3105 j = tab->start[len + 1];
3106 if (i < j && code >= tab->codes[i].code && code <= tab->codes[j-1].code) {
3107 i += code - tab->codes[i].code;
3108 return tab->codes[i].val;
3113 error(getPos(), "Bad code (%04x) in flate stream", code);
3117 int FlateStream::getCodeWord(int bits) {
3120 while (codeSize < bits) {
3121 if ((c = str->getChar()) == EOF)
3123 codeBuf |= (c & 0xff) << codeSize;
3126 c = codeBuf & ((1 << bits) - 1);
3132 //------------------------------------------------------------------------
3134 //------------------------------------------------------------------------
3136 EOFStream::EOFStream(Stream *str):
3140 EOFStream::~EOFStream() {
3144 //------------------------------------------------------------------------
3145 // FixedLengthEncoder
3146 //------------------------------------------------------------------------
3148 FixedLengthEncoder::FixedLengthEncoder(Stream *str, int length1):
3154 FixedLengthEncoder::~FixedLengthEncoder() {
3155 if (str->isEncoder())
3159 void FixedLengthEncoder::reset() {
3164 int FixedLengthEncoder::getChar() {
3165 if (length >= 0 && count >= length)
3168 return str->getChar();
3171 int FixedLengthEncoder::lookChar() {
3172 if (length >= 0 && count >= length)
3174 return str->getChar();
3177 //------------------------------------------------------------------------
3179 //------------------------------------------------------------------------
3181 ASCII85Encoder::ASCII85Encoder(Stream *str):
3183 bufPtr = bufEnd = buf;
3188 ASCII85Encoder::~ASCII85Encoder() {
3189 if (str->isEncoder())
3193 void ASCII85Encoder::reset() {
3195 bufPtr = bufEnd = buf;
3200 GBool ASCII85Encoder::fillBuf() {
3209 for (n = 0; n < 4; ++n) {
3210 if ((c = str->getChar()) == EOF)
3214 bufPtr = bufEnd = buf;
3216 if (n == 4 && t == 0) {
3218 if (++lineLen == 65) {
3225 for (i = 4; i >= 0; --i) {
3226 buf1[i] = (char)(t % 85 + 0x21);
3229 for (i = 0; i <= n; ++i) {
3230 *bufEnd++ = buf1[i];
3231 if (++lineLen == 65) {
3243 return bufPtr < bufEnd;
3246 //------------------------------------------------------------------------
3248 //------------------------------------------------------------------------
3250 RunLengthEncoder::RunLengthEncoder(Stream *str):
3252 bufPtr = bufEnd = nextEnd = buf;
3256 RunLengthEncoder::~RunLengthEncoder() {
3257 if (str->isEncoder())
3261 void RunLengthEncoder::reset() {
3263 bufPtr = bufEnd = nextEnd = buf;
3268 // When fillBuf finishes, buf[] looks like this:
3269 // +-----+--------------+-----------------+--
3270 // + tag | ... data ... | next 0, 1, or 2 |
3271 // +-----+--------------+-----------------+--
3273 // bufPtr bufEnd nextEnd
3275 GBool RunLengthEncoder::fillBuf() {
3284 if (nextEnd < bufEnd + 1) {
3285 if ((c1 = str->getChar()) == EOF) {
3290 c1 = bufEnd[0] & 0xff;
3292 if (nextEnd < bufEnd + 2) {
3293 if ((c2 = str->getChar()) == EOF) {
3302 c2 = bufEnd[1] & 0xff;
3308 while (n < 128 && (c = str->getChar()) == c1)
3310 buf[0] = (char)(257 - n);
3315 } else if (n < 128) {
3322 // get up to 128 chars
3328 if ((c = str->getChar()) == EOF) {
3334 if (buf[n] == buf[n-1])
3337 if (buf[n] == buf[n-1]) {
3338 buf[0] = (char)(n-2-1);
3340 nextEnd = &buf[n+1];
3342 buf[0] = (char)(n-1);
3343 bufEnd = nextEnd = &buf[n+1];