1 //========================================================================
5 // Copyright 1996 Derek B. Noonburg
7 //========================================================================
10 #pragma implementation
30 #include "Stream-CCITT.h"
33 static GBool setDJSYSFLAGS = gFalse;
37 #if (__VMS_VER < 70000000)
38 extern "C" int unlink(char *filename);
48 #include "StuffItEngineLib.h"
51 //------------------------------------------------------------------------
52 // Stream (base class)
53 //------------------------------------------------------------------------
62 void Stream::close() {
65 int Stream::getRawChar() {
66 error(-1, "Internal: called getRawChar() on non-predictor stream");
70 char *Stream::getLine(char *buf, int size) {
74 if (lookChar() == EOF)
76 for (i = 0; i < size - 1; ++i) {
78 if (c == EOF || c == '\n')
81 if ((c = lookChar()) == '\n')
91 GString *Stream::getPSFilter(char *indent) {
95 Stream *Stream::addFilters(Object *dict) {
97 Object params, params2;
102 dict->dictLookup("Filter", &obj);
105 dict->dictLookup("F", &obj);
107 dict->dictLookup("DecodeParms", ¶ms);
108 if (params.isNull()) {
110 dict->dictLookup("DP", ¶ms);
113 str = makeFilter(obj.getName(), str, ¶ms);
114 } else if (obj.isArray()) {
115 for (i = 0; i < obj.arrayGetLength(); ++i) {
116 obj.arrayGet(i, &obj2);
117 if (params.isArray())
118 params.arrayGet(i, ¶ms2);
122 str = makeFilter(obj2.getName(), str, ¶ms2);
124 error(getPos(), "Bad filter name");
125 str = new EOFStream(str);
130 } else if (!obj.isNull()) {
131 error(getPos(), "Bad 'Filter' attribute in stream");
139 Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
140 int pred; // parameters
145 GBool endOfLine, byteAlign, endOfBlock, black;
149 if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
150 str = new ASCIIHexStream(str);
151 } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
152 str = new ASCII85Stream(str);
153 } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
159 if (params->isDict()) {
160 params->dictLookup("Predictor", &obj);
164 params->dictLookup("Columns", &obj);
166 columns = obj.getInt();
168 params->dictLookup("Colors", &obj);
170 colors = obj.getInt();
172 params->dictLookup("BitsPerComponent", &obj);
176 params->dictLookup("EarlyChange", &obj);
178 early = obj.getInt();
181 str = new LZWStream(str, pred, columns, colors, bits, early);
182 } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
183 str = new RunLengthStream(str);
184 } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
192 if (params->isDict()) {
193 params->dictLookup("K", &obj);
195 encoding = obj.getInt();
198 params->dictLookup("EndOfLine", &obj);
200 endOfLine = obj.getBool();
203 params->dictLookup("EncodedByteAlign", &obj);
205 byteAlign = obj.getBool();
208 params->dictLookup("Columns", &obj);
210 columns = obj.getInt();
213 params->dictLookup("Rows", &obj);
218 params->dictLookup("EndOfBlock", &obj);
220 endOfBlock = obj.getBool();
223 params->dictLookup("BlackIs1", &obj);
225 black = obj.getBool();
229 str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
230 columns, rows, endOfBlock, black);
231 } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
232 str = new DCTStream(str);
233 } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
238 if (params->isDict()) {
239 params->dictLookup("Predictor", &obj);
243 params->dictLookup("Columns", &obj);
245 columns = obj.getInt();
247 params->dictLookup("Colors", &obj);
249 colors = obj.getInt();
251 params->dictLookup("BitsPerComponent", &obj);
256 str = new FlateStream(str, pred, columns, colors, bits);
258 error(getPos(), "Unknown filter '%s'", name);
259 str = new EOFStream(str);
264 //------------------------------------------------------------------------
266 //------------------------------------------------------------------------
268 BaseStream::BaseStream(Object *dict) {
270 #ifndef NO_DECRYPTION
275 BaseStream::~BaseStream() {
277 #ifndef NO_DECRYPTION
283 #ifndef NO_DECRYPTION
284 void BaseStream::doDecryption(Guchar *fileKey, int objNum, int objGen) {
285 decrypt = new Decrypt(fileKey, objNum, objGen);
289 //------------------------------------------------------------------------
291 //------------------------------------------------------------------------
293 FilterStream::FilterStream(Stream *str) {
297 FilterStream::~FilterStream() {
300 void FilterStream::close() {
304 void FilterStream::setPos(int pos) {
305 error(-1, "Internal: called setPos() on FilterStream");
308 //------------------------------------------------------------------------
310 //------------------------------------------------------------------------
312 ImageStream::ImageStream(Stream *str, int width, int nComps, int nBits) {
317 this->nComps = nComps;
320 nVals = width * nComps;
322 imgLineSize = (nVals + 7) & ~7;
326 imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
330 ImageStream::~ImageStream() {
334 void ImageStream::reset() {
338 GBool ImageStream::getPixel(Guchar *pix) {
344 if (imgIdx >= nVals) {
346 // read one line of image pixels
348 for (i = 0; i < nVals; i += 8) {
350 imgLine[i+0] = (Guchar)((c >> 7) & 1);
351 imgLine[i+1] = (Guchar)((c >> 6) & 1);
352 imgLine[i+2] = (Guchar)((c >> 5) & 1);
353 imgLine[i+3] = (Guchar)((c >> 4) & 1);
354 imgLine[i+4] = (Guchar)((c >> 3) & 1);
355 imgLine[i+5] = (Guchar)((c >> 2) & 1);
356 imgLine[i+6] = (Guchar)((c >> 1) & 1);
357 imgLine[i+7] = (Guchar)(c & 1);
359 } else if (nBits == 8) {
360 for (i = 0; i < nVals; ++i) {
361 imgLine[i] = str->getChar();
364 bitMask = (1 << nBits) - 1;
367 for (i = 0; i < nVals; ++i) {
369 buf = (buf << 8) | (str->getChar() & 0xff);
372 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
377 // reset to start of line
381 for (i = 0; i < nComps; ++i)
382 pix[i] = imgLine[imgIdx++];
386 void ImageStream::skipLine() {
389 n = (nVals * nBits + 7) >> 3;
390 for (i = 0; i < n; ++i) {
395 //------------------------------------------------------------------------
397 //------------------------------------------------------------------------
399 StreamPredictor::StreamPredictor(Stream *str, int predictor,
400 int width, int nComps, int nBits) {
402 this->predictor = predictor;
404 this->nComps = nComps;
407 nVals = width * nComps;
408 pixBytes = (nComps * nBits + 7) >> 3;
409 rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
410 predLine = (Guchar *)gmalloc(rowBytes);
411 memset(predLine, 0, rowBytes);
415 StreamPredictor::~StreamPredictor() {
419 int StreamPredictor::lookChar() {
420 if (predIdx >= rowBytes) {
421 if (!getNextLine()) {
425 return predLine[predIdx];
428 int StreamPredictor::getChar() {
429 if (predIdx >= rowBytes) {
430 if (!getNextLine()) {
434 return predLine[predIdx++];
437 GBool StreamPredictor::getNextLine() {
440 int left, up, upLeft, p, pa, pb, pc;
442 Gulong inBuf, outBuf, bitMask;
446 // get PNG optimum predictor number
447 if (predictor == 15) {
448 if ((curPred = str->getRawChar()) == EOF) {
456 // read the raw line, apply PNG (byte) predictor
457 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
458 for (i = pixBytes; i < rowBytes; ++i) {
459 upLeftBuf[3] = upLeftBuf[2];
460 upLeftBuf[2] = upLeftBuf[1];
461 upLeftBuf[1] = upLeftBuf[0];
462 upLeftBuf[0] = predLine[i];
463 if ((c = str->getRawChar()) == EOF) {
468 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
471 predLine[i] = predLine[i] + (Guchar)c;
473 case 13: // PNG average
474 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
477 case 14: // PNG Paeth
478 left = predLine[i - pixBytes];
480 upLeft = upLeftBuf[pixBytes];
481 p = left + up - upLeft;
482 if ((pa = p - left) < 0)
484 if ((pb = p - up) < 0)
486 if ((pc = p - upLeft) < 0)
488 if (pa <= pb && pa <= pc)
489 predLine[i] = pa + (Guchar)c;
491 predLine[i] = pb + (Guchar)c;
493 predLine[i] = pc + (Guchar)c;
496 default: // no predictor or TIFF predictor
497 predLine[i] = (Guchar)c;
502 // apply TIFF (component) predictor
503 //~ this is completely untested
504 if (predictor == 2) {
506 inBuf = predLine[pixBytes - 1];
507 for (i = pixBytes; i < rowBytes; i += 8) {
508 // 1-bit add is just xor
509 inBuf = (inBuf << 8) | predLine[i];
510 predLine[i] ^= inBuf >> nComps;
512 } else if (nBits == 8) {
513 for (i = pixBytes; i < rowBytes; ++i) {
514 predLine[i] += predLine[i - nComps];
517 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
518 bitMask = (1 << nBits) - 1;
520 inBits = outBits = 0;
522 for (i = 0; i < nVals; ++i) {
523 if (inBits < nBits) {
524 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
527 upLeftBuf[3] = upLeftBuf[2];
528 upLeftBuf[2] = upLeftBuf[1];
529 upLeftBuf[1] = upLeftBuf[0];
530 upLeftBuf[0] = (upLeftBuf[nComps] +
531 (inBuf >> (inBits - nBits))) & bitMask;
532 outBuf = (outBuf << nBits) | upLeftBuf[0];
536 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
540 predLine[k++] = (Guchar)(outBuf << (8 - outBits));
545 // reset to start of line
551 //------------------------------------------------------------------------
553 //------------------------------------------------------------------------
555 FileStream::FileStream(FILE *f, int start, int length, Object *dict):
559 this->length = length;
560 bufPtr = bufEnd = buf;
565 FileStream::~FileStream() {
569 Stream *FileStream::makeSubStream(int start, int length, Object *dict) {
570 return new FileStream(f, start, length, dict);
573 void FileStream::reset() {
574 savePos = (int)ftell(f);
575 fseek(f, start, SEEK_SET);
576 bufPtr = bufEnd = buf;
578 #ifndef NO_DECRYPTION
584 void FileStream::close() {
586 fseek(f, savePos, SEEK_SET);
591 GBool FileStream::fillBuf() {
593 #ifndef NO_DECRYPTION
597 bufPos += bufEnd - buf;
598 bufPtr = bufEnd = buf;
599 if (length >= 0 && bufPos >= start + length) {
602 if (length >= 0 && bufPos + fileStreamBufSize > start + length) {
603 n = start + length - bufPos;
605 n = fileStreamBufSize;
607 n = fread(buf, 1, n, f);
609 if (bufPtr >= bufEnd) {
612 #ifndef NO_DECRYPTION
614 for (p = buf; p < bufEnd; ++p) {
615 *p = (char)decrypt->decryptByte((Guchar)*p);
622 void FileStream::setPos(int pos1) {
626 fseek(f, pos1, SEEK_SET);
629 fseek(f, 0, SEEK_END);
633 fseek(f, pos1, SEEK_END);
634 bufPos = (int)ftell(f);
636 bufPtr = bufEnd = buf;
639 void FileStream::moveStart(int delta) {
640 this->start += delta;
641 bufPtr = bufEnd = buf;
645 //------------------------------------------------------------------------
647 //------------------------------------------------------------------------
649 EmbedStream::EmbedStream(Stream *str, Object *dict):
654 EmbedStream::~EmbedStream() {
657 Stream *EmbedStream::makeSubStream(int start, int length, Object *dict) {
658 error(-1, "Internal: called makeSubStream() on EmbedStream");
662 void EmbedStream::setPos(int pos) {
663 error(-1, "Internal: called setPos() on EmbedStream");
666 int EmbedStream::getStart() {
667 error(-1, "Internal: called getStart() on EmbedStream");
671 void EmbedStream::moveStart(int start) {
672 error(-1, "Internal: called moveStart() on EmbedStream");
675 //------------------------------------------------------------------------
677 //------------------------------------------------------------------------
679 ASCIIHexStream::ASCIIHexStream(Stream *str):
685 ASCIIHexStream::~ASCIIHexStream() {
689 void ASCIIHexStream::reset() {
695 int ASCIIHexStream::lookChar() {
706 } while (isspace(c1));
714 } while (isspace(c2));
719 if (c1 >= '0' && c1 <= '9') {
721 } else if (c1 >= 'A' && c1 <= 'F') {
722 x = (c1 - 'A' + 10) << 4;
723 } else if (c1 >= 'a' && c1 <= 'f') {
724 x = (c1 - 'a' + 10) << 4;
725 } else if (c1 == EOF) {
729 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
732 if (c2 >= '0' && c2 <= '9') {
734 } else if (c2 >= 'A' && c2 <= 'F') {
736 } else if (c2 >= 'a' && c2 <= 'f') {
738 } else if (c2 == EOF) {
742 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
748 GString *ASCIIHexStream::getPSFilter(char *indent) {
751 s = str->getPSFilter(indent);
752 s->append(indent)->append("/ASCIIHexDecode filter\n");
756 GBool ASCIIHexStream::isBinary(GBool last) {
757 return str->isBinary(gFalse);
760 //------------------------------------------------------------------------
762 //------------------------------------------------------------------------
764 ASCII85Stream::ASCII85Stream(Stream *str):
770 ASCII85Stream::~ASCII85Stream() {
774 void ASCII85Stream::reset() {
780 int ASCII85Stream::lookChar() {
789 c[0] = str->getChar();
790 } while (c[0] == '\n' || c[0] == '\r');
791 if (c[0] == '~' || c[0] == EOF) {
795 } else if (c[0] == 'z') {
796 b[0] = b[1] = b[2] = b[3] = 0;
799 for (k = 1; k < 5; ++k) {
801 c[k] = str->getChar();
802 } while (c[k] == '\n' || c[k] == '\r');
803 if (c[k] == '~' || c[k] == EOF)
807 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
808 for (++k; k < 5; ++k)
813 for (k = 0; k < 5; ++k)
814 t = t * 85 + (c[k] - 0x21);
815 for (k = 3; k >= 0; --k) {
816 b[k] = (int)(t & 0xff);
824 GString *ASCII85Stream::getPSFilter(char *indent) {
827 s = str->getPSFilter(indent);
828 s->append(indent)->append("/ASCII85Decode filter\n");
832 GBool ASCII85Stream::isBinary(GBool last) {
833 return str->isBinary(gFalse);
836 //------------------------------------------------------------------------
838 //------------------------------------------------------------------------
840 LZWStream::LZWStream(Stream *str, int predictor1, int columns1, int colors1,
841 int bits1, int early1):
843 if (predictor1 != 1) {
844 pred = new StreamPredictor(this, predictor1, columns1, colors1, bits1);
850 bufPtr = bufEnd = buf;
853 LZWStream::~LZWStream() {
861 unlink(zName->getCString());
870 int LZWStream::getChar() {
872 return pred->getChar();
874 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
877 int LZWStream::lookChar() {
879 return pred->lookChar();
881 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff);
884 int LZWStream::getRawChar() {
885 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
888 void LZWStream::reset() {
892 //----- close old LZW stream
900 unlink(zName->getCString());
904 //----- tell Delorie runtime to spawn a new instance of COMMAND.COM
907 if (!setDJSYSFLAGS) {
908 setenv("DJSYSFLAGS", "0x0002", 0);
909 setDJSYSFLAGS = gTrue;
913 //----- create the .Z file
914 if (!openTempFile(&zName, &f, "wb", ".Z")) {
915 error(getPos(), "Couldn't create temporary file for LZW stream");
921 //----- execute uncompress / gzip
922 zCmd = new GString(uncompressCmd);
927 // first we open the engine up
928 OSErr err = OpenSITEngine(kUseExternalEngine, &magicCookie);
929 // if we found it - let's use it!
930 if (!err && magicCookie) {
931 // make sure we have the correct version of the Engine
932 if (GetSITEngineVersion(magicCookie) >= kFirstSupportedEngine) {
935 strcpy((char *)pName, zName->getCString());
936 c2pstr((char *)pName);
937 FSMakeFSSpec(0, 0, pName, &myFSS);
938 short ftype = DetermineFileType(magicCookie, &myFSS);
939 OSErr expandErr = ExpandFSSpec(magicCookie, ftype, &myFSS,
940 NULL, NULL, kCreateFolderNever,
941 kDeleteOriginal, kTextConvertSmart);
944 #elif defined(HAVE_POPEN)
945 if (!(zPipe = popen(zCmd->getCString(), POPEN_READ_MODE))) {
946 error(getPos(), "Couldn't popen '%s'", zCmd->getCString());
947 unlink(zName->getCString());
953 if (!system(zCmd->getCString())) {
955 if (system(zCmd->getCString())) {
957 error(getPos(), "Couldn't execute '%s'", zCmd->getCString());
958 unlink(zName->getCString());
962 zName->del(zName->getLength() - 2, 2);
963 if (!(zPipe = fopen(zName->getCString(), "rb"))) {
964 error(getPos(), "Couldn't open uncompress file '%s'", zName->getCString());
965 unlink(zName->getCString());
974 //----- initialize buffer
975 bufPtr = bufEnd = buf;
978 void LZWStream::dumpFile(FILE *f) {
979 int outCodeBits; // size of output code
980 int outBits; // max output code
981 int outBuf[8]; // output buffer
982 int outData; // temporary output buffer
983 int inCode, outCode; // input and output codes
984 int nextCode; // next code index
985 GBool eof; // set when EOF is reached
986 GBool clear; // set if table needs to be cleared
987 GBool first; // indicates first code word after clear
996 // max code length, block mode flag
1014 for (i = 0; i < 8; ++i) {
1015 // check for table overflow
1016 if (nextCode + early > 0x1001) {
1023 if (inCode == EOF) {
1027 } while (first && inCode == 256);
1030 // compute output code
1033 } else if (inCode == 256) {
1036 } else if (inCode == 257) {
1040 outCode = inCode - 1;
1042 outBuf[i] = outCode;
1050 // check input code size
1051 if (nextCode + early == 0x200)
1053 else if (nextCode + early == 0x400) {
1055 } else if (nextCode + early == 0x800) {
1059 // check for eof/clear
1068 // write output block
1072 while (j < i || outBits > 0) {
1073 if (outBits < 8 && j < i) {
1074 outData = outData | (outBuf[j++] << outBits);
1075 outBits += outCodeBits;
1077 fputc(outData & 0xff, f);
1082 // check output code size
1083 if (nextCode - 1 == 512 ||
1084 nextCode - 1 == 1024 ||
1085 nextCode - 1 == 2048 ||
1086 nextCode - 1 == 4096) {
1087 outCodeBits = inCodeBits;
1090 // clear table if necessary
1101 int LZWStream::getCode() {
1105 while (inputBits < inCodeBits) {
1106 if ((c = str->getChar()) == EOF)
1108 inputBuf = (inputBuf << 8) | (c & 0xff);
1111 code = (inputBuf >> (inputBits - inCodeBits)) & ((1 << inCodeBits) - 1);
1112 inputBits -= inCodeBits;
1116 GBool LZWStream::fillBuf() {
1121 if ((n = fread(buf, 1, 256, zPipe)) < 256) {
1128 unlink(zName->getCString());
1136 GString *LZWStream::getPSFilter(char *indent) {
1142 s = str->getPSFilter(indent);
1143 s->append(indent)->append("/LZWDecode filter\n");
1147 GBool LZWStream::isBinary(GBool last) {
1148 return str->isBinary(gTrue);
1151 //------------------------------------------------------------------------
1153 //------------------------------------------------------------------------
1155 RunLengthStream::RunLengthStream(Stream *str):
1157 bufPtr = bufEnd = buf;
1161 RunLengthStream::~RunLengthStream() {
1165 void RunLengthStream::reset() {
1167 bufPtr = bufEnd = buf;
1171 GString *RunLengthStream::getPSFilter(char *indent) {
1174 s = str->getPSFilter(indent);
1175 s->append(indent)->append("/RunLengthDecode filter\n");
1179 GBool RunLengthStream::isBinary(GBool last) {
1180 return str->isBinary(gTrue);
1183 GBool RunLengthStream::fillBuf() {
1190 if (c == 0x80 || c == EOF) {
1196 for (i = 0; i < n; ++i)
1197 buf[i] = (char)str->getChar();
1201 for (i = 0; i < n; ++i)
1209 //------------------------------------------------------------------------
1211 //------------------------------------------------------------------------
1213 CCITTFaxStream::CCITTFaxStream(Stream *str, int encoding, GBool endOfLine,
1214 GBool byteAlign, int columns, int rows,
1215 GBool endOfBlock, GBool black):
1217 this->encoding = encoding;
1218 this->endOfLine = endOfLine;
1219 this->byteAlign = byteAlign;
1220 this->columns = columns;
1222 this->endOfBlock = endOfBlock;
1223 this->black = black;
1224 refLine = (short *)gmalloc((columns + 3) * sizeof(short));
1225 codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
1229 nextLine2D = encoding < 0;
1232 codingLine[1] = refLine[2] = columns;
1238 CCITTFaxStream::~CCITTFaxStream() {
1244 void CCITTFaxStream::reset() {
1250 nextLine2D = encoding < 0;
1253 codingLine[1] = refLine[2] = columns;
1257 // get initial end-of-line marker and 2D encoding tag
1259 if (lookBits(12) == 0x001) {
1263 for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
1264 if (n == 11 && lookBits(12) == 0x001) {
1269 nextLine2D = !lookBits(1);
1274 int CCITTFaxStream::lookChar() {
1275 short code1, code2, code3;
1284 // if at eof just return EOF
1285 if (eof && codingLine[a0] >= columns) {
1289 // read the next row
1293 if (codingLine[a0] >= columns) {
1297 for (i = 0; codingLine[i] < columns; ++i)
1298 refLine[i] = codingLine[i];
1299 refLine[i] = refLine[i + 1] = columns;
1301 a0New = codingLine[a0 = 0] = 0;
1303 code1 = getTwoDimCode();
1306 if (refLine[b1] < columns) {
1307 a0New = refLine[b1 + 1];
1312 if ((a0 & 1) == 0) {
1315 code1 += code3 = getWhiteCode();
1316 } while (code3 >= 64);
1318 code2 += code3 = getBlackCode();
1319 } while (code3 >= 64);
1323 code1 += code3 = getBlackCode();
1324 } while (code3 >= 64);
1326 code2 += code3 = getWhiteCode();
1327 } while (code3 >= 64);
1329 codingLine[a0 + 1] = a0New + code1;
1331 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1333 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1337 a0New = codingLine[++a0] = refLine[b1];
1338 if (refLine[b1] < columns) {
1340 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1345 a0New = codingLine[++a0] = refLine[b1] + 1;
1346 if (refLine[b1] < columns) {
1348 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1353 a0New = codingLine[++a0] = refLine[b1] - 1;
1355 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1359 a0New = codingLine[++a0] = refLine[b1] + 2;
1360 if (refLine[b1] < columns) {
1362 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1367 a0New = codingLine[++a0] = refLine[b1] - 2;
1369 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1373 a0New = codingLine[++a0] = refLine[b1] + 3;
1374 if (refLine[b1] < columns) {
1376 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1381 a0New = codingLine[++a0] = refLine[b1] - 3;
1383 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1388 codingLine[a0 = 0] = columns;
1391 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1400 } while (codingLine[a0] < columns);
1404 codingLine[a0 = 0] = 0;
1408 code1 += code3 = getWhiteCode();
1409 } while (code3 >= 64);
1410 codingLine[a0+1] = codingLine[a0] + code1;
1412 if (codingLine[a0] >= columns)
1416 code2 += code3 = getBlackCode();
1417 } while (code3 >= 64);
1418 codingLine[a0+1] = codingLine[a0] + code2;
1420 if (codingLine[a0] >= columns)
1425 if (codingLine[a0] != columns) {
1426 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
1432 // byte-align the row
1437 // check for end-of-line marker, skipping over any extra zero bits
1439 if (!endOfBlock && row == rows - 1) {
1442 code1 = lookBits(12);
1443 while (code1 == 0) {
1445 code1 = lookBits(12);
1447 if (code1 == 0x001) {
1450 } else if (code1 == EOF) {
1455 // get 2D encoding tag
1456 if (!eof && encoding > 0) {
1457 nextLine2D = !lookBits(1);
1461 // check for end-of-block marker
1462 if (endOfBlock && gotEOL) {
1463 code1 = lookBits(12);
1464 if (code1 == 0x001) {
1470 if (encoding >= 0) {
1471 for (i = 0; i < 4; ++i) {
1472 code1 = lookBits(12);
1473 if (code1 != 0x001) {
1474 error(getPos(), "Bad RTC code in CCITTFax stream");
1488 // This looks for an end-of-line marker after an error, however
1489 // some (most?) CCITT streams in PDF files don't use end-of-line
1490 // markers, and the just-plow-on technique works better in those
1499 code1 = look13Bits();
1500 } while ((code1 >> 1) != 0x001);
1502 codingLine[++a0] = columns;
1505 nextLine2D = !(code1 & 1);
1511 outputBits = codingLine[1] - codingLine[0];
1512 if (outputBits == 0) {
1514 outputBits = codingLine[2] - codingLine[1];
1521 if (outputBits >= 8) {
1522 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1523 if ((outputBits -= 8) == 0) {
1525 if (codingLine[a0] < columns) {
1526 outputBits = codingLine[a0 + 1] - codingLine[a0];
1533 if (outputBits > bits) {
1536 if ((a0 & 1) == 0) {
1537 ret |= 0xff >> (8 - i);
1543 if ((a0 & 1) == 0) {
1544 ret |= (0xff >> (8 - i)) << bits;
1548 if (codingLine[a0] < columns) {
1549 outputBits = codingLine[a0 + 1] - codingLine[a0];
1552 } while (bits > 0 && codingLine[a0] < columns);
1554 buf = black ? (ret ^ 0xff) : ret;
1558 short CCITTFaxStream::getTwoDimCode() {
1563 code = 0; // make gcc happy
1566 p = &twoDimTab1[code];
1572 for (n = 1; n <= 7; ++n) {
1577 p = &twoDimTab1[code];
1584 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1588 short CCITTFaxStream::getWhiteCode() {
1593 code = 0; // make gcc happy
1595 code = lookBits(12);
1596 if ((code >> 5) == 0) {
1597 p = &whiteTab1[code];
1599 p = &whiteTab2[code >> 3];
1606 for (n = 1; n <= 9; ++n) {
1611 p = &whiteTab2[code];
1617 for (n = 11; n <= 12; ++n) {
1622 p = &whiteTab1[code];
1629 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1630 // eat a bit and return a positive number so that the caller doesn't
1631 // go into an infinite loop
1636 short CCITTFaxStream::getBlackCode() {
1641 code = 0; // make gcc happy
1643 code = lookBits(13);
1644 if ((code >> 7) == 0) {
1645 p = &blackTab1[code];
1646 } else if ((code >> 9) == 0) {
1647 p = &blackTab2[(code >> 1) - 64];
1649 p = &blackTab3[code >> 7];
1656 for (n = 2; n <= 6; ++n) {
1661 p = &blackTab3[code];
1667 for (n = 7; n <= 12; ++n) {
1673 p = &blackTab2[code - 64];
1680 for (n = 10; n <= 13; ++n) {
1685 p = &blackTab1[code];
1692 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
1693 // eat a bit and return a positive number so that the caller doesn't
1694 // go into an infinite loop
1699 short CCITTFaxStream::lookBits(int n) {
1702 while (inputBits < n) {
1703 if ((c = str->getChar()) == EOF) {
1704 if (inputBits == 0) {
1707 // near the end of the stream, the caller may ask for more bits
1708 // than are available, but there may still be a valid code in
1709 // however many bits are available -- we need to return correct
1710 // data in this case
1711 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
1713 inputBuf = (inputBuf << 8) + c;
1716 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1719 GString *CCITTFaxStream::getPSFilter(char *indent) {
1723 s = str->getPSFilter(indent);
1724 s->append(indent)->append("<< ");
1725 if (encoding != 0) {
1726 sprintf(s1, "/K %d ", encoding);
1730 s->append("/EndOfLine true ");
1733 s->append("/EncodedByteAlign true ");
1735 sprintf(s1, "/Columns %d ", columns);
1738 sprintf(s1, "/Rows %d ", rows);
1742 s->append("/EndOfBlock false ");
1745 s->append("/BlackIs1 true ");
1747 s->append(">> /CCITTFaxDecode filter\n");
1751 GBool CCITTFaxStream::isBinary(GBool last) {
1752 return str->isBinary(gTrue);
1755 //------------------------------------------------------------------------
1757 //------------------------------------------------------------------------
1759 // IDCT constants (20.12 fixed point format)
1761 #define dctCos1 4017 // cos(pi/16)
1762 #define dctSin1 799 // sin(pi/16)
1763 #define dctCos3 3406 // cos(3*pi/16)
1764 #define dctSin3 2276 // sin(3*pi/16)
1765 #define dctCos6 1567 // cos(6*pi/16)
1766 #define dctSin6 3784 // sin(6*pi/16)
1767 #define dctSqrt2 5793 // sqrt(2)
1768 #define dctSqrt1d2 2896 // sqrt(2) / 2
1773 #define dctCos1 0.98078528 // cos(pi/16)
1774 #define dctSin1 0.19509032 // sin(pi/16)
1775 #define dctCos3 0.83146961 // cos(3*pi/16)
1776 #define dctSin3 0.55557023 // sin(3*pi/16)
1777 #define dctCos6 0.38268343 // cos(6*pi/16)
1778 #define dctSin6 0.92387953 // sin(6*pi/16)
1779 #define dctSqrt2 1.41421356 // sqrt(2)
1780 #define dctSqrt1d2 0.70710678 // sqrt(2) / 2
1783 // color conversion parameters (16.16 fixed point format)
1784 #define dctCrToR 91881 // 1.4020
1785 #define dctCbToG -22553 // -0.3441363
1786 #define dctCrToG -46802 // -0.71413636
1787 #define dctCbToB 116130 // 1.772
1789 // clip [-256,511] --> [0,255]
1790 #define dctClipOffset 256
1791 static Guchar dctClip[768];
1792 static int dctClipInit = 0;
1794 // zig zag decode map
1795 static int dctZigZag[64] = {
1801 5, 12, 19, 26, 33, 40,
1802 48, 41, 34, 27, 20, 13, 6,
1803 7, 14, 21, 28, 35, 42, 49, 56,
1804 57, 50, 43, 36, 29, 22, 15,
1805 23, 30, 37, 44, 51, 58,
1813 DCTStream::DCTStream(Stream *str):
1818 mcuWidth = mcuHeight = 0;
1822 for (i = 0; i < 4; ++i)
1823 for (j = 0; j < 32; ++j)
1824 rowBuf[i][j] = NULL;
1827 for (i = -256; i < 0; ++i)
1828 dctClip[dctClipOffset + i] = 0;
1829 for (i = 0; i < 256; ++i)
1830 dctClip[dctClipOffset + i] = i;
1831 for (i = 256; i < 512; ++i)
1832 dctClip[dctClipOffset + i] = 255;
1837 DCTStream::~DCTStream() {
1841 for (i = 0; i < numComps; ++i)
1842 for (j = 0; j < mcuHeight; ++j)
1843 gfree(rowBuf[i][j]);
1846 void DCTStream::reset() {
1848 if (!readHeader()) {
1852 restartMarker = 0xd0;
1856 int DCTStream::getChar() {
1862 if (++comp == numComps) {
1875 int DCTStream::lookChar() {
1878 if (dy >= mcuHeight) {
1879 if (!readMCURow()) {
1887 return rowBuf[comp][dy][x];
1890 void DCTStream::restart() {
1894 restartCtr = restartInterval;
1895 for (i = 0; i < numComps; ++i)
1896 compInfo[i].prevDC = 0;
1899 GBool DCTStream::readMCURow() {
1902 int pY, pCb, pCr, pR, pG, pB;
1903 int h, v, horiz, vert, hSub, vSub;
1904 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
1907 for (x1 = 0; x1 < width; x1 += mcuWidth) {
1909 // deal with restart marker
1910 if (restartInterval > 0 && restartCtr == 0) {
1912 if (c != restartMarker) {
1913 error(getPos(), "Bad DCT data: incorrect restart marker");
1916 if (++restartMarker == 0xd8)
1917 restartMarker = 0xd0;
1922 for (cc = 0; cc < numComps; ++cc) {
1923 h = compInfo[cc].hSample;
1924 v = compInfo[cc].vSample;
1925 horiz = mcuWidth / h;
1926 vert = mcuHeight / v;
1929 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
1930 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
1931 if (!readDataUnit(&dcHuffTables[compInfo[cc].dcHuffTable],
1932 &acHuffTables[compInfo[cc].acHuffTable],
1933 quantTables[compInfo[cc].quantTable],
1934 &compInfo[cc].prevDC,
1937 if (hSub == 1 && vSub == 1) {
1938 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
1939 p1 = &rowBuf[cc][y2+y3][x1+x2];
1949 } else if (hSub == 2 && vSub == 2) {
1950 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
1951 p1 = &rowBuf[cc][y2+y3][x1+x2];
1952 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
1953 p1[0] = p1[1] = p2[0] = p2[1] = data[i];
1954 p1[2] = p1[3] = p2[2] = p2[3] = data[i+1];
1955 p1[4] = p1[5] = p2[4] = p2[5] = data[i+2];
1956 p1[6] = p1[7] = p2[6] = p2[7] = data[i+3];
1957 p1[8] = p1[9] = p2[8] = p2[9] = data[i+4];
1958 p1[10] = p1[11] = p2[10] = p2[11] = data[i+5];
1959 p1[12] = p1[13] = p2[12] = p2[13] = data[i+6];
1960 p1[14] = p1[15] = p2[14] = p2[15] = data[i+7];
1964 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
1965 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
1966 for (y5 = 0; y5 < vSub; ++y5)
1967 for (x5 = 0; x5 < hSub; ++x5)
1968 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data[i];
1978 // color space conversion
1980 // convert YCbCr to RGB
1981 if (numComps == 3) {
1982 for (y2 = 0; y2 < mcuHeight; ++y2) {
1983 for (x2 = 0; x2 < mcuWidth; ++x2) {
1984 pY = rowBuf[0][y2][x1+x2];
1985 pCb = rowBuf[1][y2][x1+x2] - 128;
1986 pCr = rowBuf[2][y2][x1+x2] - 128;
1987 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
1988 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
1989 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
1990 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
1991 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
1992 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
1995 // convert YCbCrK to CMYK (K is passed through unchanged)
1996 } else if (numComps == 4) {
1997 for (y2 = 0; y2 < mcuHeight; ++y2) {
1998 for (x2 = 0; x2 < mcuWidth; ++x2) {
1999 pY = rowBuf[0][y2][x1+x2];
2000 pCb = rowBuf[1][y2][x1+x2] - 128;
2001 pCr = rowBuf[2][y2][x1+x2] - 128;
2002 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2003 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2004 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32678) >> 16;
2005 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2006 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2007 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2016 // This IDCT algorithm is taken from:
2017 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2018 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2019 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2021 // The stage numbers mentioned in the comments refer to Figure 1 in this
2024 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2025 DCTHuffTable *acHuffTable,
2026 Guchar quantTable[64], int *prevDC,
2029 int v0, v1, v2, v3, v4, v5, v6, v7, t;
2034 // Huffman decode and dequantize
2035 size = readHuffSym(dcHuffTable);
2039 amp = readAmp(size);
2045 tmp1[0] = (*prevDC += amp) * quantTable[0];
2046 for (i = 1; i < 64; ++i)
2051 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
2058 run += (c >> 4) & 0x0f;
2060 amp = readAmp(size);
2065 tmp1[j] = amp * quantTable[j];
2069 // inverse DCT on rows
2070 for (i = 0; i < 64; i += 8) {
2073 v0 = (dctSqrt2 * tmp1[i+0] + 128) >> 8;
2074 v1 = (dctSqrt2 * tmp1[i+4] + 128) >> 8;
2077 v4 = (dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]) + 128) >> 8;
2078 v7 = (dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]) + 128) >> 8;
2079 v5 = tmp1[i+3] << 4;
2080 v6 = tmp1[i+5] << 4;
2083 t = (v0 - v1+ 1) >> 1;
2084 v0 = (v0 + v1 + 1) >> 1;
2086 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2087 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2089 t = (v4 - v6 + 1) >> 1;
2090 v4 = (v4 + v6 + 1) >> 1;
2092 t = (v7 + v5 + 1) >> 1;
2093 v5 = (v7 - v5 + 1) >> 1;
2097 t = (v0 - v3 + 1) >> 1;
2098 v0 = (v0 + v3 + 1) >> 1;
2100 t = (v1 - v2 + 1) >> 1;
2101 v1 = (v1 + v2 + 1) >> 1;
2103 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2104 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2106 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2107 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2111 tmp1[i+0] = v0 + v7;
2112 tmp1[i+7] = v0 - v7;
2113 tmp1[i+1] = v1 + v6;
2114 tmp1[i+6] = v1 - v6;
2115 tmp1[i+2] = v2 + v5;
2116 tmp1[i+5] = v2 - v5;
2117 tmp1[i+3] = v3 + v4;
2118 tmp1[i+4] = v3 - v4;
2121 // inverse DCT on columns
2122 for (i = 0; i < 8; ++i) {
2125 v0 = (dctSqrt2 * tmp1[0*8+i] + 2048) >> 12;
2126 v1 = (dctSqrt2 * tmp1[4*8+i] + 2048) >> 12;
2129 v4 = (dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]) + 2048) >> 12;
2130 v7 = (dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]) + 2048) >> 12;
2135 t = (v0 - v1 + 1) >> 1;
2136 v0 = (v0 + v1 + 1) >> 1;
2138 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2139 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2141 t = (v4 - v6 + 1) >> 1;
2142 v4 = (v4 + v6 + 1) >> 1;
2144 t = (v7 + v5 + 1) >> 1;
2145 v5 = (v7 - v5 + 1) >> 1;
2149 t = (v0 - v3 + 1) >> 1;
2150 v0 = (v0 + v3 + 1) >> 1;
2152 t = (v1 - v2 + 1) >> 1;
2153 v1 = (v1 + v2 + 1) >> 1;
2155 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2156 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2158 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2159 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2163 tmp1[0*8+i] = v0 + v7;
2164 tmp1[7*8+i] = v0 - v7;
2165 tmp1[1*8+i] = v1 + v6;
2166 tmp1[6*8+i] = v1 - v6;
2167 tmp1[2*8+i] = v2 + v5;
2168 tmp1[5*8+i] = v2 - v5;
2169 tmp1[3*8+i] = v3 + v4;
2170 tmp1[4*8+i] = v3 - v4;
2173 // convert to 8-bit integers
2174 for (i = 0; i < 64; ++i)
2175 data[i] = dctClip[dctClipOffset + 128 + ((tmp1[i] + 8) >> 4)];
2182 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2183 DCTHuffTable *acHuffTable,
2184 Guchar quantTable[64], int *prevDC,
2187 double v0, v1, v2, v3, v4, v5, v6, v7, t;
2192 // Huffman decode and dequantize
2193 size = readHuffSym(dcHuffTable);
2197 amp = readAmp(size);
2203 tmp1[0] = (*prevDC += amp) * quantTable[0];
2204 for (i = 1; i < 64; ++i)
2209 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
2216 run += (c >> 4) & 0x0f;
2218 amp = readAmp(size);
2223 tmp1[j] = amp * quantTable[j];
2227 // inverse DCT on rows
2228 for (i = 0; i < 64; i += 8) {
2231 v0 = dctSqrt2 * tmp1[i+0];
2232 v1 = dctSqrt2 * tmp1[i+4];
2235 v4 = dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]);
2236 v7 = dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]);
2241 t = 0.5 * (v0 - v1);
2242 v0 = 0.5 * (v0 + v1);
2244 t = v2 * dctSin6 + v3 * dctCos6;
2245 v2 = v2 * dctCos6 - v3 * dctSin6;
2247 t = 0.5 * (v4 - v6);
2248 v4 = 0.5 * (v4 + v6);
2250 t = 0.5 * (v7 + v5);
2251 v5 = 0.5 * (v7 - v5);
2255 t = 0.5 * (v0 - v3);
2256 v0 = 0.5 * (v0 + v3);
2258 t = 0.5 * (v1 - v2);
2259 v1 = 0.5 * (v1 + v2);
2261 t = v4 * dctSin3 + v7 * dctCos3;
2262 v4 = v4 * dctCos3 - v7 * dctSin3;
2264 t = v5 * dctSin1 + v6 * dctCos1;
2265 v5 = v5 * dctCos1 - v6 * dctSin1;
2269 tmp1[i+0] = v0 + v7;
2270 tmp1[i+7] = v0 - v7;
2271 tmp1[i+1] = v1 + v6;
2272 tmp1[i+6] = v1 - v6;
2273 tmp1[i+2] = v2 + v5;
2274 tmp1[i+5] = v2 - v5;
2275 tmp1[i+3] = v3 + v4;
2276 tmp1[i+4] = v3 - v4;
2279 // inverse DCT on columns
2280 for (i = 0; i < 8; ++i) {
2283 v0 = dctSqrt2 * tmp1[0*8+i];
2284 v1 = dctSqrt2 * tmp1[4*8+i];
2287 v4 = dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]);
2288 v7 = dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]);
2293 t = 0.5 * (v0 - v1);
2294 v0 = 0.5 * (v0 + v1);
2296 t = v2 * dctSin6 + v3 * dctCos6;
2297 v2 = v2 * dctCos6 - v3 * dctSin6;
2299 t = 0.5 * (v4 - v6);
2300 v4 = 0.5 * (v4 + v6);
2302 t = 0.5 * (v7 + v5);
2303 v5 = 0.5 * (v7 - v5);
2307 t = 0.5 * (v0 - v3);
2308 v0 = 0.5 * (v0 + v3);
2310 t = 0.5 * (v1 - v2);
2311 v1 = 0.5 * (v1 + v2);
2313 t = v4 * dctSin3 + v7 * dctCos3;
2314 v4 = v4 * dctCos3 - v7 * dctSin3;
2316 t = v5 * dctSin1 + v6 * dctCos1;
2317 v5 = v5 * dctCos1 - v6 * dctSin1;
2321 tmp1[0*8+i] = v0 + v7;
2322 tmp1[7*8+i] = v0 - v7;
2323 tmp1[1*8+i] = v1 + v6;
2324 tmp1[6*8+i] = v1 - v6;
2325 tmp1[2*8+i] = v2 + v5;
2326 tmp1[5*8+i] = v2 - v5;
2327 tmp1[3*8+i] = v3 + v4;
2328 tmp1[4*8+i] = v3 - v4;
2331 // convert to 8-bit integers
2332 for (i = 0; i < 64; ++i)
2333 data[i] = dctClip[dctClipOffset + (int)(tmp1[i] + 128.5)];
2339 int DCTStream::readHuffSym(DCTHuffTable *table) {
2347 // add a bit to the code
2348 if ((bit = readBit()) == EOF)
2350 code = (code << 1) + bit;
2354 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2355 code -= table->firstCode[codeBits];
2356 return table->sym[table->firstSym[codeBits] + code];
2358 } while (codeBits < 16);
2360 error(getPos(), "Bad Huffman code in DCT stream");
2364 int DCTStream::readAmp(int size) {
2369 for (bits = 0; bits < size; ++bits) {
2370 if ((bit = readBit()) == EOF)
2372 amp = (amp << 1) + bit;
2374 if (amp < (1 << (size - 1)))
2375 amp -= (1 << size) - 1;
2379 int DCTStream::readBit() {
2383 if (inputBits == 0) {
2384 if ((c = str->getChar()) == EOF)
2388 c2 = str->getChar();
2389 } while (c2 == 0xff);
2391 error(getPos(), "Bad DCT data: missing 00 after ff");
2398 bit = (inputBuf >> (inputBits - 1)) & 1;
2403 GBool DCTStream::readHeader() {
2405 int minHSample, minVSample;
2414 numDCHuffTables = 0;
2415 numACHuffTables = 0;
2417 gotAdobeMarker = gFalse;
2418 restartInterval = 0;
2426 if (!readFrameInfo())
2430 if (!readHuffmanTables())
2436 if (!readScanInfo())
2441 if (!readQuantTables())
2445 if (!readRestartInterval())
2449 if (!readAdobeMarker())
2453 error(getPos(), "Bad DCT header");
2456 // skip APPn / COM / etc.
2459 for (i = 0; i < n; ++i)
2462 error(getPos(), "Unknown DCT marker <%02x>", c);
2470 mcuWidth = minHSample = compInfo[0].hSample;
2471 mcuHeight = minVSample = compInfo[0].vSample;
2472 for (i = 1; i < numComps; ++i) {
2473 if (compInfo[i].hSample < minHSample)
2474 minHSample = compInfo[i].hSample;
2475 if (compInfo[i].vSample < minVSample)
2476 minVSample = compInfo[i].vSample;
2477 if (compInfo[i].hSample > mcuWidth)
2478 mcuWidth = compInfo[i].hSample;
2479 if (compInfo[i].vSample > mcuHeight)
2480 mcuHeight = compInfo[i].vSample;
2482 for (i = 0; i < numComps; ++i) {
2483 compInfo[i].hSample /= minHSample;
2484 compInfo[i].vSample /= minVSample;
2486 mcuWidth = (mcuWidth / minHSample) * 8;
2487 mcuHeight = (mcuHeight / minVSample) * 8;
2490 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2491 for (i = 0; i < numComps; ++i)
2492 for (j = 0; j < mcuHeight; ++j)
2493 rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
2495 // figure out color transform
2496 if (!gotAdobeMarker && numComps == 3) {
2497 if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
2502 // initialize counters
2511 GBool DCTStream::readFrameInfo() {
2517 length = read16() - 2;
2518 prec = str->getChar();
2521 numComps = str->getChar();
2524 error(getPos(), "Bad DCT precision %d", prec);
2527 for (i = 0; i < numComps; ++i) {
2528 compInfo[i].id = str->getChar();
2529 compInfo[i].inScan = gFalse;
2531 compInfo[i].hSample = (c >> 4) & 0x0f;
2532 compInfo[i].vSample = c & 0x0f;
2533 compInfo[i].quantTable = str->getChar();
2534 compInfo[i].dcHuffTable = 0;
2535 compInfo[i].acHuffTable = 0;
2540 GBool DCTStream::readScanInfo() {
2542 int scanComps, id, c;
2545 length = read16() - 2;
2546 scanComps = str->getChar();
2548 if (length != 2 * scanComps + 3) {
2549 error(getPos(), "Bad DCT scan info block");
2552 for (i = 0; i < scanComps; ++i) {
2553 id = str->getChar();
2554 for (j = 0; j < numComps; ++j) {
2555 if (id == compInfo[j].id)
2558 if (j == numComps) {
2559 error(getPos(), "Bad DCT component ID in scan info block");
2562 compInfo[j].inScan = gTrue;
2564 compInfo[j].dcHuffTable = (c >> 4) & 0x0f;
2565 compInfo[j].acHuffTable = c & 0x0f;
2573 GBool DCTStream::readQuantTables() {
2578 length = read16() - 2;
2579 while (length > 0) {
2580 index = str->getChar();
2581 if ((index & 0xf0) || index >= 4) {
2582 error(getPos(), "Bad DCT quantization table");
2585 if (index == numQuantTables)
2586 numQuantTables = index + 1;
2587 for (i = 0; i < 64; ++i)
2588 quantTables[index][dctZigZag[i]] = str->getChar();
2594 GBool DCTStream::readHuffmanTables() {
2603 length = read16() - 2;
2604 while (length > 0) {
2605 index = str->getChar();
2607 if ((index & 0x0f) >= 4) {
2608 error(getPos(), "Bad DCT Huffman table");
2613 if (index >= numACHuffTables)
2614 numACHuffTables = index+1;
2615 tbl = &acHuffTables[index];
2617 if (index >= numDCHuffTables)
2618 numDCHuffTables = index+1;
2619 tbl = &dcHuffTables[index];
2623 for (i = 1; i <= 16; ++i) {
2625 tbl->firstSym[i] = sym;
2626 tbl->firstCode[i] = code;
2627 tbl->numCodes[i] = c;
2629 code = (code + c) << 1;
2632 for (i = 0; i < sym; ++i)
2633 tbl->sym[i] = str->getChar();
2639 GBool DCTStream::readRestartInterval() {
2644 error(getPos(), "Bad DCT restart interval");
2647 restartInterval = read16();
2651 GBool DCTStream::readAdobeMarker() {
2659 for (i = 0; i < 12; ++i) {
2660 if ((c = str->getChar()) == EOF)
2664 if (strncmp(buf, "Adobe", 5))
2666 colorXform = buf[11];
2667 gotAdobeMarker = gTrue;
2671 error(getPos(), "Bad DCT Adobe APP14 marker");
2675 GBool DCTStream::readTrailer() {
2679 if (c != 0xd9) { // EOI
2680 error(getPos(), "Bad DCT trailer");
2686 int DCTStream::readMarker() {
2692 } while (c != 0xff);
2695 } while (c == 0xff);
2696 } while (c == 0x00);
2700 int DCTStream::read16() {
2703 if ((c1 = str->getChar()) == EOF)
2705 if ((c2 = str->getChar()) == EOF)
2707 return (c1 << 8) + c2;
2710 GString *DCTStream::getPSFilter(char *indent) {
2713 s = str->getPSFilter(indent);
2714 s->append(indent)->append("<< >> /DCTDecode filter\n");
2718 GBool DCTStream::isBinary(GBool last) {
2719 return str->isBinary(gTrue);
2722 //------------------------------------------------------------------------
2724 //------------------------------------------------------------------------
2726 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
2727 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
2730 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
2762 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
2795 FlateStream::FlateStream(Stream *str, int predictor1, int columns1,
2796 int colors1, int bits1):
2798 if (predictor1 != 1) {
2799 pred = new StreamPredictor(this, predictor1, columns1, colors1, bits1);
2805 FlateStream::~FlateStream() {
2812 void FlateStream::reset() {
2819 compressedBlock = gFalse;
2826 //~ need to look at window size?
2827 endOfBlock = eof = gTrue;
2828 cmf = str->getChar();
2829 flg = str->getChar();
2830 if (cmf == EOF || flg == EOF)
2832 if ((cmf & 0x0f) != 0x08) {
2833 error(getPos(), "Unknown compression method in flate stream");
2836 if ((((cmf << 8) + flg) % 31) != 0) {
2837 error(getPos(), "Bad FCHECK in flate stream");
2841 error(getPos(), "FDICT bit set in flate stream");
2848 int FlateStream::getChar() {
2852 return pred->getChar();
2854 while (remain == 0) {
2855 if (endOfBlock && eof)
2860 index = (index + 1) & flateMask;
2865 int FlateStream::lookChar() {
2869 return pred->lookChar();
2871 while (remain == 0) {
2872 if (endOfBlock && eof)
2880 int FlateStream::getRawChar() {
2883 while (remain == 0) {
2884 if (endOfBlock && eof)
2889 index = (index + 1) & flateMask;
2894 GString *FlateStream::getPSFilter(char *indent) {
2898 GBool FlateStream::isBinary(GBool last) {
2899 return str->isBinary(gTrue);
2902 void FlateStream::readSome() {
2913 if (compressedBlock) {
2914 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
2919 } else if (code1 == 256) {
2924 code2 = lengthDecode[code1].bits;
2925 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
2927 len = lengthDecode[code1].first + code2;
2928 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
2930 code2 = distDecode[code1].bits;
2931 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
2933 dist = distDecode[code1].first + code2;
2935 j = (index - dist) & flateMask;
2936 for (k = 0; k < len; ++k) {
2938 i = (i + 1) & flateMask;
2939 j = (j + 1) & flateMask;
2945 len = (blockLen < flateWindow) ? blockLen : flateWindow;
2946 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
2947 if ((c = str->getChar()) == EOF) {
2948 endOfBlock = eof = gTrue;
2962 error(getPos(), "Unexpected end of file in flate stream");
2963 endOfBlock = eof = gTrue;
2967 GBool FlateStream::startBlock() {
2972 // read block header
2973 blockHdr = getCodeWord(3);
2978 // uncompressed block
2979 if (blockHdr == 0) {
2980 compressedBlock = gFalse;
2981 if ((c = str->getChar()) == EOF)
2983 blockLen = c & 0xff;
2984 if ((c = str->getChar()) == EOF)
2986 blockLen |= (c & 0xff) << 8;
2987 if ((c = str->getChar()) == EOF)
2990 if ((c = str->getChar()) == EOF)
2992 check |= (c & 0xff) << 8;
2993 if (check != (~blockLen & 0xffff))
2994 error(getPos(), "Bad uncompressed block length in flate stream");
2998 // compressed block with fixed codes
2999 } else if (blockHdr == 1) {
3000 compressedBlock = gTrue;
3003 // compressed block with dynamic codes
3004 } else if (blockHdr == 2) {
3005 compressedBlock = gTrue;
3006 if (!readDynamicCodes())
3009 // unknown block type
3014 endOfBlock = gFalse;
3018 error(getPos(), "Bad block header in flate stream");
3019 endOfBlock = eof = gTrue;
3023 void FlateStream::loadFixedCodes() {
3026 // set up code arrays
3027 litCodeTab.codes = allCodes;
3028 distCodeTab.codes = allCodes + flateMaxLitCodes;
3030 // initialize literal code table
3031 for (i = 0; i <= 143; ++i)
3032 litCodeTab.codes[i].len = 8;
3033 for (i = 144; i <= 255; ++i)
3034 litCodeTab.codes[i].len = 9;
3035 for (i = 256; i <= 279; ++i)
3036 litCodeTab.codes[i].len = 7;
3037 for (i = 280; i <= 287; ++i)
3038 litCodeTab.codes[i].len = 8;
3039 compHuffmanCodes(&litCodeTab, flateMaxLitCodes);
3041 // initialize distance code table
3042 for (i = 0; i <= 5; ++i) {
3043 distCodeTab.start[i] = 0;
3045 for (i = 6; i <= flateMaxHuffman+1; ++i) {
3046 distCodeTab.start[i] = flateMaxDistCodes;
3048 for (i = 0; i < flateMaxDistCodes; ++i) {
3049 distCodeTab.codes[i].len = 5;
3050 distCodeTab.codes[i].code = i;
3051 distCodeTab.codes[i].val = i;
3055 GBool FlateStream::readDynamicCodes() {
3056 int numCodeLenCodes;
3059 FlateCode codeLenCodes[flateMaxCodeLenCodes];
3060 FlateHuffmanTab codeLenCodeTab;
3061 int len, repeat, code;
3065 if ((numLitCodes = getCodeWord(5)) == EOF)
3068 if ((numDistCodes = getCodeWord(5)) == EOF)
3071 if ((numCodeLenCodes = getCodeWord(4)) == EOF)
3073 numCodeLenCodes += 4;
3074 if (numLitCodes > flateMaxLitCodes ||
3075 numDistCodes > flateMaxDistCodes ||
3076 numCodeLenCodes > flateMaxCodeLenCodes)
3079 // read code length code table
3080 codeLenCodeTab.codes = codeLenCodes;
3081 for (i = 0; i < flateMaxCodeLenCodes; ++i)
3082 codeLenCodes[i].len = 0;
3083 for (i = 0; i < numCodeLenCodes; ++i) {
3084 if ((codeLenCodes[codeLenCodeMap[i]].len = getCodeWord(3)) == -1)
3087 compHuffmanCodes(&codeLenCodeTab, flateMaxCodeLenCodes);
3089 // set up code arrays
3090 litCodeTab.codes = allCodes;
3091 distCodeTab.codes = allCodes + numLitCodes;
3093 // read literal and distance code tables
3097 while (i < numLitCodes + numDistCodes) {
3098 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF)
3101 if ((repeat = getCodeWord(2)) == EOF)
3103 for (repeat += 3; repeat > 0; --repeat)
3104 allCodes[i++].len = len;
3105 } else if (code == 17) {
3106 if ((repeat = getCodeWord(3)) == EOF)
3109 for (repeat += 3; repeat > 0; --repeat)
3110 allCodes[i++].len = 0;
3111 } else if (code == 18) {
3112 if ((repeat = getCodeWord(7)) == EOF)
3115 for (repeat += 11; repeat > 0; --repeat)
3116 allCodes[i++].len = 0;
3118 allCodes[i++].len = len = code;
3121 compHuffmanCodes(&litCodeTab, numLitCodes);
3122 compHuffmanCodes(&distCodeTab, numDistCodes);
3127 error(getPos(), "Bad dynamic code table in flate stream");
3131 // On entry, the <tab->codes> array contains the lengths of each code,
3132 // stored in code value order. This function computes the code words.
3133 // The result is sorted in order of (1) code length and (2) code word.
3134 // The length values are no longer valid. The <tab->start> array is
3135 // filled with the indexes of the first code of each length.
3136 void FlateStream::compHuffmanCodes(FlateHuffmanTab *tab, int n) {
3137 int numLengths[flateMaxHuffman+1];
3138 int nextCode[flateMaxHuffman+1];
3139 int nextIndex[flateMaxHuffman+2];
3143 // count number of codes for each code length
3144 for (i = 0; i <= flateMaxHuffman; ++i)
3146 for (i = 0; i < n; ++i)
3147 ++numLengths[tab->codes[i].len];
3149 // compute first index for each length
3150 tab->start[0] = nextIndex[0] = 0;
3151 for (i = 1; i <= flateMaxHuffman + 1; ++i)
3152 tab->start[i] = nextIndex[i] = tab->start[i-1] + numLengths[i-1];
3154 // compute first code for each length
3157 for (i = 1; i <= flateMaxHuffman; ++i) {
3158 code = (code + numLengths[i-1]) << 1;
3162 // compute the codes -- this permutes the codes array from value
3163 // order to length/code order
3164 for (i = 0; i < n; ++i) {
3165 j = nextIndex[tab->codes[i].len]++;
3166 if (tab->codes[i].len == 0)
3167 tab->codes[j].code = 0;
3169 tab->codes[j].code = nextCode[tab->codes[i].len]++;
3170 tab->codes[j].val = i;
3174 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
3181 for (len = 1; len <= flateMaxHuffman; ++len) {
3183 // add a bit to the code
3184 if (codeSize == 0) {
3185 if ((c = str->getChar()) == EOF)
3190 code = (code << 1) | (codeBuf & 1);
3195 i = tab->start[len];
3196 j = tab->start[len + 1];
3197 if (i < j && code >= tab->codes[i].code && code <= tab->codes[j-1].code) {
3198 i += code - tab->codes[i].code;
3199 return tab->codes[i].val;
3204 error(getPos(), "Bad code (%04x) in flate stream", code);
3208 int FlateStream::getCodeWord(int bits) {
3211 while (codeSize < bits) {
3212 if ((c = str->getChar()) == EOF)
3214 codeBuf |= (c & 0xff) << codeSize;
3217 c = codeBuf & ((1 << bits) - 1);
3223 //------------------------------------------------------------------------
3225 //------------------------------------------------------------------------
3227 EOFStream::EOFStream(Stream *str):
3231 EOFStream::~EOFStream() {
3235 //------------------------------------------------------------------------
3236 // FixedLengthEncoder
3237 //------------------------------------------------------------------------
3239 FixedLengthEncoder::FixedLengthEncoder(Stream *str, int length1):
3245 FixedLengthEncoder::~FixedLengthEncoder() {
3246 if (str->isEncoder())
3250 void FixedLengthEncoder::reset() {
3255 void FixedLengthEncoder::close() {
3258 int FixedLengthEncoder::getChar() {
3259 if (length >= 0 && count >= length)
3262 return str->getChar();
3265 int FixedLengthEncoder::lookChar() {
3266 if (length >= 0 && count >= length)
3268 return str->getChar();
3271 //------------------------------------------------------------------------
3273 //------------------------------------------------------------------------
3275 ASCII85Encoder::ASCII85Encoder(Stream *str):
3277 bufPtr = bufEnd = buf;
3282 ASCII85Encoder::~ASCII85Encoder() {
3283 if (str->isEncoder())
3287 void ASCII85Encoder::reset() {
3289 bufPtr = bufEnd = buf;
3294 void ASCII85Encoder::close() {
3297 GBool ASCII85Encoder::fillBuf() {
3306 for (n = 0; n < 4; ++n) {
3307 if ((c = str->getChar()) == EOF)
3311 bufPtr = bufEnd = buf;
3313 if (n == 4 && t == 0) {
3315 if (++lineLen == 65) {
3322 for (i = 4; i >= 0; --i) {
3323 buf1[i] = (char)(t % 85 + 0x21);
3326 for (i = 0; i <= n; ++i) {
3327 *bufEnd++ = buf1[i];
3328 if (++lineLen == 65) {
3340 return bufPtr < bufEnd;
3343 //------------------------------------------------------------------------
3345 //------------------------------------------------------------------------
3347 RunLengthEncoder::RunLengthEncoder(Stream *str):
3349 bufPtr = bufEnd = nextEnd = buf;
3353 RunLengthEncoder::~RunLengthEncoder() {
3354 if (str->isEncoder())
3358 void RunLengthEncoder::reset() {
3360 bufPtr = bufEnd = nextEnd = buf;
3364 void RunLengthEncoder::close() {
3368 // When fillBuf finishes, buf[] looks like this:
3369 // +-----+--------------+-----------------+--
3370 // + tag | ... data ... | next 0, 1, or 2 |
3371 // +-----+--------------+-----------------+--
3373 // bufPtr bufEnd nextEnd
3375 GBool RunLengthEncoder::fillBuf() {
3384 if (nextEnd < bufEnd + 1) {
3385 if ((c1 = str->getChar()) == EOF) {
3390 c1 = bufEnd[0] & 0xff;
3392 if (nextEnd < bufEnd + 2) {
3393 if ((c2 = str->getChar()) == EOF) {
3402 c2 = bufEnd[1] & 0xff;
3406 c = 0; // make gcc happy
3409 while (n < 128 && (c = str->getChar()) == c1)
3411 buf[0] = (char)(257 - n);
3416 } else if (n < 128) {
3423 // get up to 128 chars
3429 if ((c = str->getChar()) == EOF) {
3435 if (buf[n] == buf[n-1])
3438 if (buf[n] == buf[n-1]) {
3439 buf[0] = (char)(n-2-1);
3441 nextEnd = &buf[n+1];
3443 buf[0] = (char)(n-1);
3444 bufEnd = nextEnd = &buf[n+1];