1 //========================================================================
5 // Copyright 1996-2002 Glyph & Cog, LLC
7 //========================================================================
10 #pragma implementation
20 extern "C" int unlink(char *filename);
33 #include "Stream-CCITT.h"
36 static GBool setDJSYSFLAGS = gFalse;
40 #if (__VMS_VER < 70000000)
41 extern "C" int unlink(char *filename);
51 #include "StuffItEngineLib.h"
54 //------------------------------------------------------------------------
55 // Stream (base class)
56 //------------------------------------------------------------------------
65 void Stream::close() {
68 int Stream::getRawChar() {
69 error(-1, "Internal: called getRawChar() on non-predictor stream");
73 char *Stream::getLine(char *buf, int size) {
77 if (lookChar() == EOF)
79 for (i = 0; i < size - 1; ++i) {
81 if (c == EOF || c == '\n')
84 if ((c = lookChar()) == '\n')
94 GString *Stream::getPSFilter(char *indent) {
98 Stream *Stream::addFilters(Object *dict) {
100 Object params, params2;
105 dict->dictLookup("Filter", &obj);
108 dict->dictLookup("F", &obj);
110 dict->dictLookup("DecodeParms", ¶ms);
111 if (params.isNull()) {
113 dict->dictLookup("DP", ¶ms);
116 str = makeFilter(obj.getName(), str, ¶ms);
117 } else if (obj.isArray()) {
118 for (i = 0; i < obj.arrayGetLength(); ++i) {
119 obj.arrayGet(i, &obj2);
120 if (params.isArray())
121 params.arrayGet(i, ¶ms2);
125 str = makeFilter(obj2.getName(), str, ¶ms2);
127 error(getPos(), "Bad filter name");
128 str = new EOFStream(str);
133 } else if (!obj.isNull()) {
134 error(getPos(), "Bad 'Filter' attribute in stream");
142 Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
143 int pred; // parameters
148 GBool endOfLine, byteAlign, endOfBlock, black;
152 if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
153 str = new ASCIIHexStream(str);
154 } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
155 str = new ASCII85Stream(str);
156 } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
162 if (params->isDict()) {
163 params->dictLookup("Predictor", &obj);
167 params->dictLookup("Columns", &obj);
169 columns = obj.getInt();
171 params->dictLookup("Colors", &obj);
173 colors = obj.getInt();
175 params->dictLookup("BitsPerComponent", &obj);
179 params->dictLookup("EarlyChange", &obj);
181 early = obj.getInt();
184 str = new LZWStream(str, pred, columns, colors, bits, early);
185 } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
186 str = new RunLengthStream(str);
187 } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
195 if (params->isDict()) {
196 params->dictLookup("K", &obj);
198 encoding = obj.getInt();
201 params->dictLookup("EndOfLine", &obj);
203 endOfLine = obj.getBool();
206 params->dictLookup("EncodedByteAlign", &obj);
208 byteAlign = obj.getBool();
211 params->dictLookup("Columns", &obj);
213 columns = obj.getInt();
216 params->dictLookup("Rows", &obj);
221 params->dictLookup("EndOfBlock", &obj);
223 endOfBlock = obj.getBool();
226 params->dictLookup("BlackIs1", &obj);
228 black = obj.getBool();
232 str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
233 columns, rows, endOfBlock, black);
234 } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
235 str = new DCTStream(str);
236 } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
241 if (params->isDict()) {
242 params->dictLookup("Predictor", &obj);
246 params->dictLookup("Columns", &obj);
248 columns = obj.getInt();
250 params->dictLookup("Colors", &obj);
252 colors = obj.getInt();
254 params->dictLookup("BitsPerComponent", &obj);
259 str = new FlateStream(str, pred, columns, colors, bits);
261 error(getPos(), "Unknown filter '%s'", name);
262 str = new EOFStream(str);
267 //------------------------------------------------------------------------
269 //------------------------------------------------------------------------
271 BaseStream::BaseStream(Object *dictA) {
273 #ifndef NO_DECRYPTION
278 BaseStream::~BaseStream() {
280 #ifndef NO_DECRYPTION
286 #ifndef NO_DECRYPTION
287 void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
288 int objNum, int objGen) {
289 decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
293 //------------------------------------------------------------------------
295 //------------------------------------------------------------------------
297 FilterStream::FilterStream(Stream *strA) {
301 FilterStream::~FilterStream() {
304 void FilterStream::close() {
308 void FilterStream::setPos(Guint pos, int dir) {
309 error(-1, "Internal: called setPos() on FilterStream");
312 //------------------------------------------------------------------------
314 //------------------------------------------------------------------------
316 ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
324 nVals = width * nComps;
326 imgLineSize = (nVals + 7) & ~7;
330 imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
334 ImageStream::~ImageStream() {
338 void ImageStream::reset() {
342 GBool ImageStream::getPixel(Guchar *pix) {
348 if (imgIdx >= nVals) {
350 // read one line of image pixels
352 for (i = 0; i < nVals; i += 8) {
354 imgLine[i+0] = (Guchar)((c >> 7) & 1);
355 imgLine[i+1] = (Guchar)((c >> 6) & 1);
356 imgLine[i+2] = (Guchar)((c >> 5) & 1);
357 imgLine[i+3] = (Guchar)((c >> 4) & 1);
358 imgLine[i+4] = (Guchar)((c >> 3) & 1);
359 imgLine[i+5] = (Guchar)((c >> 2) & 1);
360 imgLine[i+6] = (Guchar)((c >> 1) & 1);
361 imgLine[i+7] = (Guchar)(c & 1);
363 } else if (nBits == 8) {
364 for (i = 0; i < nVals; ++i) {
365 imgLine[i] = str->getChar();
368 bitMask = (1 << nBits) - 1;
371 for (i = 0; i < nVals; ++i) {
373 buf = (buf << 8) | (str->getChar() & 0xff);
376 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
381 // reset to start of line
385 for (i = 0; i < nComps; ++i)
386 pix[i] = imgLine[imgIdx++];
390 void ImageStream::skipLine() {
393 n = (nVals * nBits + 7) >> 3;
394 for (i = 0; i < n; ++i) {
399 //------------------------------------------------------------------------
401 //------------------------------------------------------------------------
403 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
404 int widthA, int nCompsA, int nBitsA) {
406 predictor = predictorA;
411 nVals = width * nComps;
412 pixBytes = (nComps * nBits + 7) >> 3;
413 rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
414 predLine = (Guchar *)gmalloc(rowBytes);
415 memset(predLine, 0, rowBytes);
419 StreamPredictor::~StreamPredictor() {
423 int StreamPredictor::lookChar() {
424 if (predIdx >= rowBytes) {
425 if (!getNextLine()) {
429 return predLine[predIdx];
432 int StreamPredictor::getChar() {
433 if (predIdx >= rowBytes) {
434 if (!getNextLine()) {
438 return predLine[predIdx++];
441 GBool StreamPredictor::getNextLine() {
444 int left, up, upLeft, p, pa, pb, pc;
446 Gulong inBuf, outBuf, bitMask;
450 // get PNG optimum predictor number
451 if (predictor == 15) {
452 if ((curPred = str->getRawChar()) == EOF) {
460 // read the raw line, apply PNG (byte) predictor
461 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
462 for (i = pixBytes; i < rowBytes; ++i) {
463 upLeftBuf[3] = upLeftBuf[2];
464 upLeftBuf[2] = upLeftBuf[1];
465 upLeftBuf[1] = upLeftBuf[0];
466 upLeftBuf[0] = predLine[i];
467 if ((c = str->getRawChar()) == EOF) {
472 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
475 predLine[i] = predLine[i] + (Guchar)c;
477 case 13: // PNG average
478 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
481 case 14: // PNG Paeth
482 left = predLine[i - pixBytes];
484 upLeft = upLeftBuf[pixBytes];
485 p = left + up - upLeft;
486 if ((pa = p - left) < 0)
488 if ((pb = p - up) < 0)
490 if ((pc = p - upLeft) < 0)
492 if (pa <= pb && pa <= pc)
493 predLine[i] = left + (Guchar)c;
495 predLine[i] = up + (Guchar)c;
497 predLine[i] = upLeft + (Guchar)c;
500 default: // no predictor or TIFF predictor
501 predLine[i] = (Guchar)c;
506 // apply TIFF (component) predictor
507 //~ this is completely untested
508 if (predictor == 2) {
510 inBuf = predLine[pixBytes - 1];
511 for (i = pixBytes; i < rowBytes; i += 8) {
512 // 1-bit add is just xor
513 inBuf = (inBuf << 8) | predLine[i];
514 predLine[i] ^= inBuf >> nComps;
516 } else if (nBits == 8) {
517 for (i = pixBytes; i < rowBytes; ++i) {
518 predLine[i] += predLine[i - nComps];
521 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
522 bitMask = (1 << nBits) - 1;
524 inBits = outBits = 0;
526 for (i = 0; i < nVals; ++i) {
527 if (inBits < nBits) {
528 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
531 upLeftBuf[3] = upLeftBuf[2];
532 upLeftBuf[2] = upLeftBuf[1];
533 upLeftBuf[1] = upLeftBuf[0];
534 upLeftBuf[0] = (upLeftBuf[nComps] +
535 (inBuf >> (inBits - nBits))) & bitMask;
536 outBuf = (outBuf << nBits) | upLeftBuf[0];
540 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
544 predLine[k++] = (Guchar)(outBuf << (8 - outBits));
549 // reset to start of line
555 //------------------------------------------------------------------------
557 //------------------------------------------------------------------------
559 FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
560 Guint lengthA, Object *dictA):
566 bufPtr = bufEnd = buf;
572 FileStream::~FileStream() {
576 Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
577 Guint lengthA, Object *dictA) {
578 return new FileStream(f, startA, limitedA, lengthA, dictA);
581 void FileStream::reset() {
583 savePos = (Guint)ftell64(f);
584 fseek64(f, start, SEEK_SET);
586 savePos = (Guint)ftell(f);
587 fseek(f, start, SEEK_SET);
590 bufPtr = bufEnd = buf;
592 #ifndef NO_DECRYPTION
598 void FileStream::close() {
601 fseek64(f, savePos, SEEK_SET);
603 fseek(f, savePos, SEEK_SET);
609 GBool FileStream::fillBuf() {
611 #ifndef NO_DECRYPTION
615 bufPos += bufEnd - buf;
616 bufPtr = bufEnd = buf;
617 if (limited && bufPos >= start + length) {
620 if (limited && bufPos + fileStreamBufSize > start + length) {
621 n = start + length - bufPos;
623 n = fileStreamBufSize;
625 n = fread(buf, 1, n, f);
627 if (bufPtr >= bufEnd) {
630 #ifndef NO_DECRYPTION
632 for (p = buf; p < bufEnd; ++p) {
633 *p = (char)decrypt->decryptByte((Guchar)*p);
640 void FileStream::setPos(Guint pos, int dir) {
645 fseek64(f, pos, SEEK_SET);
647 fseek(f, pos, SEEK_SET);
652 fseek64(f, 0, SEEK_END);
653 size = (Guint)ftell64(f);
655 fseek(f, 0, SEEK_END);
656 size = (Guint)ftell(f);
661 //~ work around a bug in cygwin's implementation of fseek
665 fseek64(f, -(int)pos, SEEK_END);
666 bufPos = (Guint)ftell64(f);
668 fseek(f, -(int)pos, SEEK_END);
669 bufPos = (Guint)ftell(f);
672 bufPtr = bufEnd = buf;
675 void FileStream::moveStart(int delta) {
677 bufPtr = bufEnd = buf;
681 //------------------------------------------------------------------------
683 //------------------------------------------------------------------------
685 MemStream::MemStream(char *bufA, Guint lengthA, Object *dictA):
690 bufEnd = buf + length;
694 MemStream::~MemStream() {
700 Stream *MemStream::makeSubStream(Guint start, GBool limited,
701 Guint lengthA, Object *dictA) {
704 if (!limited || start + lengthA > length) {
705 newLength = length - start;
709 return new MemStream(buf + start, newLength, dictA);
712 void MemStream::reset() {
714 #ifndef NO_DECRYPTION
721 void MemStream::close() {
724 void MemStream::setPos(Guint pos, int dir) {
735 bufPtr = bufEnd - pos;
740 void MemStream::moveStart(int delta) {
745 #ifndef NO_DECRYPTION
746 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
747 int objNum, int objGen) {
751 this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
753 newBuf = (char *)gmalloc(bufEnd - buf);
754 for (p = buf, q = newBuf; p < bufEnd; ++p, ++q) {
755 *q = (char)decrypt->decryptByte((Guchar)*p);
757 bufEnd = newBuf + (bufEnd - buf);
758 bufPtr = newBuf + (bufPtr - buf);
765 //------------------------------------------------------------------------
767 //------------------------------------------------------------------------
769 EmbedStream::EmbedStream(Stream *strA, Object *dictA):
774 EmbedStream::~EmbedStream() {
777 Stream *EmbedStream::makeSubStream(Guint start, GBool limited,
778 Guint length, Object *dictA) {
779 error(-1, "Internal: called makeSubStream() on EmbedStream");
783 void EmbedStream::setPos(Guint pos, int dir) {
784 error(-1, "Internal: called setPos() on EmbedStream");
787 Guint EmbedStream::getStart() {
788 error(-1, "Internal: called getStart() on EmbedStream");
792 void EmbedStream::moveStart(int delta) {
793 error(-1, "Internal: called moveStart() on EmbedStream");
796 //------------------------------------------------------------------------
798 //------------------------------------------------------------------------
800 ASCIIHexStream::ASCIIHexStream(Stream *strA):
806 ASCIIHexStream::~ASCIIHexStream() {
810 void ASCIIHexStream::reset() {
816 int ASCIIHexStream::lookChar() {
827 } while (isspace(c1));
835 } while (isspace(c2));
840 if (c1 >= '0' && c1 <= '9') {
842 } else if (c1 >= 'A' && c1 <= 'F') {
843 x = (c1 - 'A' + 10) << 4;
844 } else if (c1 >= 'a' && c1 <= 'f') {
845 x = (c1 - 'a' + 10) << 4;
846 } else if (c1 == EOF) {
850 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
853 if (c2 >= '0' && c2 <= '9') {
855 } else if (c2 >= 'A' && c2 <= 'F') {
857 } else if (c2 >= 'a' && c2 <= 'f') {
859 } else if (c2 == EOF) {
863 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
869 GString *ASCIIHexStream::getPSFilter(char *indent) {
872 if (!(s = str->getPSFilter(indent))) {
875 s->append(indent)->append("/ASCIIHexDecode filter\n");
879 GBool ASCIIHexStream::isBinary(GBool last) {
880 return str->isBinary(gFalse);
883 //------------------------------------------------------------------------
885 //------------------------------------------------------------------------
887 ASCII85Stream::ASCII85Stream(Stream *strA):
893 ASCII85Stream::~ASCII85Stream() {
897 void ASCII85Stream::reset() {
903 int ASCII85Stream::lookChar() {
912 c[0] = str->getChar();
913 } while (c[0] == '\n' || c[0] == '\r');
914 if (c[0] == '~' || c[0] == EOF) {
918 } else if (c[0] == 'z') {
919 b[0] = b[1] = b[2] = b[3] = 0;
922 for (k = 1; k < 5; ++k) {
924 c[k] = str->getChar();
925 } while (c[k] == '\n' || c[k] == '\r');
926 if (c[k] == '~' || c[k] == EOF)
930 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
931 for (++k; k < 5; ++k)
936 for (k = 0; k < 5; ++k)
937 t = t * 85 + (c[k] - 0x21);
938 for (k = 3; k >= 0; --k) {
939 b[k] = (int)(t & 0xff);
947 GString *ASCII85Stream::getPSFilter(char *indent) {
950 if (!(s = str->getPSFilter(indent))) {
953 s->append(indent)->append("/ASCII85Decode filter\n");
957 GBool ASCII85Stream::isBinary(GBool last) {
958 return str->isBinary(gFalse);
961 //------------------------------------------------------------------------
963 //------------------------------------------------------------------------
965 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
966 int bits, int earlyA):
968 if (predictor != 1) {
969 pred = new StreamPredictor(this, predictor, columns, colors, bits);
975 bufPtr = bufEnd = buf;
978 LZWStream::~LZWStream() {
986 unlink(zName->getCString());
995 int LZWStream::getChar() {
997 return pred->getChar();
999 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
1002 int LZWStream::lookChar() {
1004 return pred->lookChar();
1006 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff);
1009 int LZWStream::getRawChar() {
1010 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
1013 void LZWStream::reset() {
1017 //----- close old LZW stream
1025 unlink(zName->getCString());
1029 //----- tell Delorie runtime to spawn a new instance of COMMAND.COM
1032 if (!setDJSYSFLAGS) {
1033 setenv("DJSYSFLAGS", "0x0002", 0);
1034 setDJSYSFLAGS = gTrue;
1038 //----- create the .Z file
1039 if (!openTempFile(&zName, &f, "wb", ".Z")) {
1040 error(getPos(), "Couldn't create temporary file for LZW stream");
1046 //----- execute uncompress / gzip
1047 zCmd = new GString(uncompressCmd);
1049 zCmd->append(zName);
1052 // first we open the engine up
1053 OSErr err = OpenSITEngine(kUseExternalEngine, &magicCookie);
1054 // if we found it - let's use it!
1055 if (!err && magicCookie) {
1056 // make sure we have the correct version of the Engine
1057 if (GetSITEngineVersion(magicCookie) >= kFirstSupportedEngine) {
1060 strcpy((char *)pName, zName->getCString());
1061 c2pstr((char *)pName);
1062 FSMakeFSSpec(0, 0, pName, &myFSS);
1063 short ftype = DetermineFileType(magicCookie, &myFSS);
1064 OSErr expandErr = ExpandFSSpec(magicCookie, ftype, &myFSS,
1065 NULL, NULL, kCreateFolderNever,
1066 kDeleteOriginal, kTextConvertSmart);
1069 #elif defined(HAVE_POPEN)
1070 if (!(zPipe = popen(zCmd->getCString(), POPEN_READ_MODE))) {
1071 error(getPos(), "Couldn't popen '%s'", zCmd->getCString());
1072 unlink(zName->getCString());
1077 if (!executeCommand(zCmd->getCString())) {
1078 error(getPos(), "Couldn't execute '%s'", zCmd->getCString());
1079 unlink(zName->getCString());
1083 zName->del(zName->getLength() - 2, 2);
1084 if (!(zPipe = fopen(zName->getCString(), "rb"))) {
1085 error(getPos(), "Couldn't open uncompress file '%s'", zName->getCString());
1086 unlink(zName->getCString());
1090 #endif // HAVE_POPEN
1095 //----- initialize buffer
1096 bufPtr = bufEnd = buf;
1099 void LZWStream::dumpFile(FILE *f) {
1100 int outCodeBits; // size of output code
1101 int outBits; // max output code
1102 int outBuf[8]; // output buffer
1103 int outData; // temporary output buffer
1104 int inCode, outCode; // input and output codes
1105 int nextCode; // next code index
1106 GBool eof; // set when EOF is reached
1107 GBool clear; // set if table needs to be cleared
1108 GBool first; // indicates first code word after clear
1117 // max code length, block mode flag
1135 for (i = 0; i < 8; ++i) {
1136 // check for table overflow
1137 if (nextCode + early > 0x1001) {
1144 if (inCode == EOF) {
1148 } while (first && inCode == 256);
1151 // compute output code
1154 } else if (inCode == 256) {
1157 } else if (inCode == 257) {
1161 outCode = inCode - 1;
1163 outBuf[i] = outCode;
1171 // check input code size
1172 if (nextCode + early == 0x200)
1174 else if (nextCode + early == 0x400) {
1176 } else if (nextCode + early == 0x800) {
1180 // check for eof/clear
1189 // write output block
1193 while (j < i || outBits > 0) {
1194 if (outBits < 8 && j < i) {
1195 outData = outData | (outBuf[j++] << outBits);
1196 outBits += outCodeBits;
1198 fputc(outData & 0xff, f);
1203 // check output code size
1204 if (nextCode - 1 == 512 ||
1205 nextCode - 1 == 1024 ||
1206 nextCode - 1 == 2048 ||
1207 nextCode - 1 == 4096) {
1208 outCodeBits = inCodeBits;
1211 // clear table if necessary
1222 int LZWStream::getCode() {
1226 while (inputBits < inCodeBits) {
1227 if ((c = str->getChar()) == EOF)
1229 inputBuf = (inputBuf << 8) | (c & 0xff);
1232 code = (inputBuf >> (inputBits - inCodeBits)) & ((1 << inCodeBits) - 1);
1233 inputBits -= inCodeBits;
1237 GBool LZWStream::fillBuf() {
1242 if ((n = fread(buf, 1, 256, zPipe)) < 256) {
1249 unlink(zName->getCString());
1257 GString *LZWStream::getPSFilter(char *indent) {
1263 if (!(s = str->getPSFilter(indent))) {
1266 s->append(indent)->append("/LZWDecode filter\n");
1270 GBool LZWStream::isBinary(GBool last) {
1271 return str->isBinary(gTrue);
1274 //------------------------------------------------------------------------
1276 //------------------------------------------------------------------------
1278 RunLengthStream::RunLengthStream(Stream *strA):
1279 FilterStream(strA) {
1280 bufPtr = bufEnd = buf;
1284 RunLengthStream::~RunLengthStream() {
1288 void RunLengthStream::reset() {
1290 bufPtr = bufEnd = buf;
1294 GString *RunLengthStream::getPSFilter(char *indent) {
1297 if (!(s = str->getPSFilter(indent))) {
1300 s->append(indent)->append("/RunLengthDecode filter\n");
1304 GBool RunLengthStream::isBinary(GBool last) {
1305 return str->isBinary(gTrue);
1308 GBool RunLengthStream::fillBuf() {
1315 if (c == 0x80 || c == EOF) {
1321 for (i = 0; i < n; ++i)
1322 buf[i] = (char)str->getChar();
1326 for (i = 0; i < n; ++i)
1334 //------------------------------------------------------------------------
1336 //------------------------------------------------------------------------
1338 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1339 GBool byteAlignA, int columnsA, int rowsA,
1340 GBool endOfBlockA, GBool blackA):
1341 FilterStream(strA) {
1342 encoding = encodingA;
1343 endOfLine = endOfLineA;
1344 byteAlign = byteAlignA;
1347 endOfBlock = endOfBlockA;
1349 refLine = (short *)gmalloc((columns + 3) * sizeof(short));
1350 codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
1354 nextLine2D = encoding < 0;
1357 codingLine[1] = refLine[2] = columns;
1363 CCITTFaxStream::~CCITTFaxStream() {
1369 void CCITTFaxStream::reset() {
1375 nextLine2D = encoding < 0;
1378 codingLine[1] = refLine[2] = columns;
1382 // get initial end-of-line marker and 2D encoding tag
1384 if (lookBits(12) == 0x001) {
1388 for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
1389 if (n == 11 && lookBits(12) == 0x001) {
1394 nextLine2D = !lookBits(1);
1399 int CCITTFaxStream::lookChar() {
1400 short code1, code2, code3;
1409 // if at eof just return EOF
1410 if (eof && codingLine[a0] >= columns) {
1414 // read the next row
1418 if (codingLine[a0] >= columns) {
1422 for (i = 0; codingLine[i] < columns; ++i)
1423 refLine[i] = codingLine[i];
1424 refLine[i] = refLine[i + 1] = columns;
1426 a0New = codingLine[a0 = 0] = 0;
1428 code1 = getTwoDimCode();
1431 if (refLine[b1] < columns) {
1432 a0New = refLine[b1 + 1];
1437 if ((a0 & 1) == 0) {
1440 code1 += code3 = getWhiteCode();
1441 } while (code3 >= 64);
1443 code2 += code3 = getBlackCode();
1444 } while (code3 >= 64);
1448 code1 += code3 = getBlackCode();
1449 } while (code3 >= 64);
1451 code2 += code3 = getWhiteCode();
1452 } while (code3 >= 64);
1454 codingLine[a0 + 1] = a0New + code1;
1456 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1458 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1462 a0New = codingLine[++a0] = refLine[b1];
1463 if (refLine[b1] < columns) {
1465 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1470 a0New = codingLine[++a0] = refLine[b1] + 1;
1471 if (refLine[b1] < columns) {
1473 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1478 a0New = codingLine[++a0] = refLine[b1] - 1;
1480 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1484 a0New = codingLine[++a0] = refLine[b1] + 2;
1485 if (refLine[b1] < columns) {
1487 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1492 a0New = codingLine[++a0] = refLine[b1] - 2;
1494 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1498 a0New = codingLine[++a0] = refLine[b1] + 3;
1499 if (refLine[b1] < columns) {
1501 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1506 a0New = codingLine[++a0] = refLine[b1] - 3;
1508 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1513 codingLine[a0 = 0] = columns;
1516 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1525 } while (codingLine[a0] < columns);
1529 codingLine[a0 = 0] = 0;
1533 code1 += code3 = getWhiteCode();
1534 } while (code3 >= 64);
1535 codingLine[a0+1] = codingLine[a0] + code1;
1537 if (codingLine[a0] >= columns)
1541 code2 += code3 = getBlackCode();
1542 } while (code3 >= 64);
1543 codingLine[a0+1] = codingLine[a0] + code2;
1545 if (codingLine[a0] >= columns)
1550 if (codingLine[a0] != columns) {
1551 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
1557 // byte-align the row
1562 // check for end-of-line marker, skipping over any extra zero bits
1564 if (!endOfBlock && row == rows - 1) {
1567 code1 = lookBits(12);
1568 while (code1 == 0) {
1570 code1 = lookBits(12);
1572 if (code1 == 0x001) {
1575 } else if (code1 == EOF) {
1580 // get 2D encoding tag
1581 if (!eof && encoding > 0) {
1582 nextLine2D = !lookBits(1);
1586 // check for end-of-block marker
1587 if (endOfBlock && gotEOL) {
1588 code1 = lookBits(12);
1589 if (code1 == 0x001) {
1595 if (encoding >= 0) {
1596 for (i = 0; i < 4; ++i) {
1597 code1 = lookBits(12);
1598 if (code1 != 0x001) {
1599 error(getPos(), "Bad RTC code in CCITTFax stream");
1613 // This looks for an end-of-line marker after an error, however
1614 // some (most?) CCITT streams in PDF files don't use end-of-line
1615 // markers, and the just-plow-on technique works better in those
1624 code1 = look13Bits();
1625 } while ((code1 >> 1) != 0x001);
1627 codingLine[++a0] = columns;
1630 nextLine2D = !(code1 & 1);
1636 outputBits = codingLine[1] - codingLine[0];
1637 if (outputBits == 0) {
1639 outputBits = codingLine[2] - codingLine[1];
1646 if (outputBits >= 8) {
1647 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1648 if ((outputBits -= 8) == 0) {
1650 if (codingLine[a0] < columns) {
1651 outputBits = codingLine[a0 + 1] - codingLine[a0];
1658 if (outputBits > bits) {
1661 if ((a0 & 1) == 0) {
1662 ret |= 0xff >> (8 - i);
1668 if ((a0 & 1) == 0) {
1669 ret |= (0xff >> (8 - i)) << bits;
1673 if (codingLine[a0] < columns) {
1674 outputBits = codingLine[a0 + 1] - codingLine[a0];
1677 } while (bits > 0 && codingLine[a0] < columns);
1679 buf = black ? (ret ^ 0xff) : ret;
1683 short CCITTFaxStream::getTwoDimCode() {
1688 code = 0; // make gcc happy
1691 p = &twoDimTab1[code];
1697 for (n = 1; n <= 7; ++n) {
1702 p = &twoDimTab1[code];
1709 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1713 short CCITTFaxStream::getWhiteCode() {
1718 code = 0; // make gcc happy
1720 code = lookBits(12);
1721 if ((code >> 5) == 0) {
1722 p = &whiteTab1[code];
1724 p = &whiteTab2[code >> 3];
1731 for (n = 1; n <= 9; ++n) {
1736 p = &whiteTab2[code];
1742 for (n = 11; n <= 12; ++n) {
1747 p = &whiteTab1[code];
1754 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1755 // eat a bit and return a positive number so that the caller doesn't
1756 // go into an infinite loop
1761 short CCITTFaxStream::getBlackCode() {
1766 code = 0; // make gcc happy
1768 code = lookBits(13);
1769 if ((code >> 7) == 0) {
1770 p = &blackTab1[code];
1771 } else if ((code >> 9) == 0) {
1772 p = &blackTab2[(code >> 1) - 64];
1774 p = &blackTab3[code >> 7];
1781 for (n = 2; n <= 6; ++n) {
1786 p = &blackTab3[code];
1792 for (n = 7; n <= 12; ++n) {
1798 p = &blackTab2[code - 64];
1805 for (n = 10; n <= 13; ++n) {
1810 p = &blackTab1[code];
1817 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
1818 // eat a bit and return a positive number so that the caller doesn't
1819 // go into an infinite loop
1824 short CCITTFaxStream::lookBits(int n) {
1827 while (inputBits < n) {
1828 if ((c = str->getChar()) == EOF) {
1829 if (inputBits == 0) {
1832 // near the end of the stream, the caller may ask for more bits
1833 // than are available, but there may still be a valid code in
1834 // however many bits are available -- we need to return correct
1835 // data in this case
1836 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
1838 inputBuf = (inputBuf << 8) + c;
1841 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1844 GString *CCITTFaxStream::getPSFilter(char *indent) {
1848 if (!(s = str->getPSFilter(indent))) {
1851 s->append(indent)->append("<< ");
1852 if (encoding != 0) {
1853 sprintf(s1, "/K %d ", encoding);
1857 s->append("/EndOfLine true ");
1860 s->append("/EncodedByteAlign true ");
1862 sprintf(s1, "/Columns %d ", columns);
1865 sprintf(s1, "/Rows %d ", rows);
1869 s->append("/EndOfBlock false ");
1872 s->append("/BlackIs1 true ");
1874 s->append(">> /CCITTFaxDecode filter\n");
1878 GBool CCITTFaxStream::isBinary(GBool last) {
1879 return str->isBinary(gTrue);
1882 //------------------------------------------------------------------------
1884 //------------------------------------------------------------------------
1886 // IDCT constants (20.12 fixed point format)
1888 #define dctCos1 4017 // cos(pi/16)
1889 #define dctSin1 799 // sin(pi/16)
1890 #define dctCos3 3406 // cos(3*pi/16)
1891 #define dctSin3 2276 // sin(3*pi/16)
1892 #define dctCos6 1567 // cos(6*pi/16)
1893 #define dctSin6 3784 // sin(6*pi/16)
1894 #define dctSqrt2 5793 // sqrt(2)
1895 #define dctSqrt1d2 2896 // sqrt(2) / 2
1900 #define dctCos1 0.98078528 // cos(pi/16)
1901 #define dctSin1 0.19509032 // sin(pi/16)
1902 #define dctCos3 0.83146961 // cos(3*pi/16)
1903 #define dctSin3 0.55557023 // sin(3*pi/16)
1904 #define dctCos6 0.38268343 // cos(6*pi/16)
1905 #define dctSin6 0.92387953 // sin(6*pi/16)
1906 #define dctSqrt2 1.41421356 // sqrt(2)
1907 #define dctSqrt1d2 0.70710678 // sqrt(2) / 2
1910 // color conversion parameters (16.16 fixed point format)
1911 #define dctCrToR 91881 // 1.4020
1912 #define dctCbToG -22553 // -0.3441363
1913 #define dctCrToG -46802 // -0.71413636
1914 #define dctCbToB 116130 // 1.772
1916 // clip [-256,511] --> [0,255]
1917 #define dctClipOffset 256
1918 static Guchar dctClip[768];
1919 static int dctClipInit = 0;
1921 // zig zag decode map
1922 static int dctZigZag[64] = {
1928 5, 12, 19, 26, 33, 40,
1929 48, 41, 34, 27, 20, 13, 6,
1930 7, 14, 21, 28, 35, 42, 49, 56,
1931 57, 50, 43, 36, 29, 22, 15,
1932 23, 30, 37, 44, 51, 58,
1940 DCTStream::DCTStream(Stream *strA):
1941 FilterStream(strA) {
1945 mcuWidth = mcuHeight = 0;
1949 for (i = 0; i < 4; ++i)
1950 for (j = 0; j < 32; ++j)
1951 rowBuf[i][j] = NULL;
1954 for (i = -256; i < 0; ++i)
1955 dctClip[dctClipOffset + i] = 0;
1956 for (i = 0; i < 256; ++i)
1957 dctClip[dctClipOffset + i] = i;
1958 for (i = 256; i < 512; ++i)
1959 dctClip[dctClipOffset + i] = 255;
1964 DCTStream::~DCTStream() {
1968 for (i = 0; i < numComps; ++i)
1969 for (j = 0; j < mcuHeight; ++j)
1970 gfree(rowBuf[i][j]);
1973 void DCTStream::reset() {
1975 if (!readHeader()) {
1979 restartMarker = 0xd0;
1983 int DCTStream::getChar() {
1989 if (++comp == numComps) {
2002 int DCTStream::lookChar() {
2005 if (dy >= mcuHeight) {
2006 if (!readMCURow()) {
2014 return rowBuf[comp][dy][x];
2017 void DCTStream::restart() {
2021 restartCtr = restartInterval;
2022 for (i = 0; i < numComps; ++i)
2023 compInfo[i].prevDC = 0;
2026 GBool DCTStream::readMCURow() {
2029 int pY, pCb, pCr, pR, pG, pB;
2030 int h, v, horiz, vert, hSub, vSub;
2031 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2034 for (x1 = 0; x1 < width; x1 += mcuWidth) {
2036 // deal with restart marker
2037 if (restartInterval > 0 && restartCtr == 0) {
2039 if (c != restartMarker) {
2040 error(getPos(), "Bad DCT data: incorrect restart marker");
2043 if (++restartMarker == 0xd8)
2044 restartMarker = 0xd0;
2049 for (cc = 0; cc < numComps; ++cc) {
2050 h = compInfo[cc].hSample;
2051 v = compInfo[cc].vSample;
2052 horiz = mcuWidth / h;
2053 vert = mcuHeight / v;
2056 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2057 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2058 if (!readDataUnit(&dcHuffTables[compInfo[cc].dcHuffTable],
2059 &acHuffTables[compInfo[cc].acHuffTable],
2060 quantTables[compInfo[cc].quantTable],
2061 &compInfo[cc].prevDC,
2064 if (hSub == 1 && vSub == 1) {
2065 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2066 p1 = &rowBuf[cc][y2+y3][x1+x2];
2076 } else if (hSub == 2 && vSub == 2) {
2077 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2078 p1 = &rowBuf[cc][y2+y3][x1+x2];
2079 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
2080 p1[0] = p1[1] = p2[0] = p2[1] = data[i];
2081 p1[2] = p1[3] = p2[2] = p2[3] = data[i+1];
2082 p1[4] = p1[5] = p2[4] = p2[5] = data[i+2];
2083 p1[6] = p1[7] = p2[6] = p2[7] = data[i+3];
2084 p1[8] = p1[9] = p2[8] = p2[9] = data[i+4];
2085 p1[10] = p1[11] = p2[10] = p2[11] = data[i+5];
2086 p1[12] = p1[13] = p2[12] = p2[13] = data[i+6];
2087 p1[14] = p1[15] = p2[14] = p2[15] = data[i+7];
2091 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2092 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2093 for (y5 = 0; y5 < vSub; ++y5)
2094 for (x5 = 0; x5 < hSub; ++x5)
2095 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data[i];
2105 // color space conversion
2107 // convert YCbCr to RGB
2108 if (numComps == 3) {
2109 for (y2 = 0; y2 < mcuHeight; ++y2) {
2110 for (x2 = 0; x2 < mcuWidth; ++x2) {
2111 pY = rowBuf[0][y2][x1+x2];
2112 pCb = rowBuf[1][y2][x1+x2] - 128;
2113 pCr = rowBuf[2][y2][x1+x2] - 128;
2114 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2115 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
2116 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2117 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
2118 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2119 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
2122 // convert YCbCrK to CMYK (K is passed through unchanged)
2123 } else if (numComps == 4) {
2124 for (y2 = 0; y2 < mcuHeight; ++y2) {
2125 for (x2 = 0; x2 < mcuWidth; ++x2) {
2126 pY = rowBuf[0][y2][x1+x2];
2127 pCb = rowBuf[1][y2][x1+x2] - 128;
2128 pCr = rowBuf[2][y2][x1+x2] - 128;
2129 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2130 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2131 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2132 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2133 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2134 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2143 // This IDCT algorithm is taken from:
2144 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2145 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2146 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2148 // The stage numbers mentioned in the comments refer to Figure 1 in this
2151 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2152 DCTHuffTable *acHuffTable,
2153 Guchar quantTable[64], int *prevDC,
2156 int v0, v1, v2, v3, v4, v5, v6, v7, t;
2161 // Huffman decode and dequantize
2162 size = readHuffSym(dcHuffTable);
2166 amp = readAmp(size);
2172 tmp1[0] = (*prevDC += amp) * quantTable[0];
2173 for (i = 1; i < 64; ++i)
2178 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
2185 run += (c >> 4) & 0x0f;
2187 amp = readAmp(size);
2192 tmp1[j] = amp * quantTable[j];
2196 // inverse DCT on rows
2197 for (i = 0; i < 64; i += 8) {
2200 v0 = (dctSqrt2 * tmp1[i+0] + 128) >> 8;
2201 v1 = (dctSqrt2 * tmp1[i+4] + 128) >> 8;
2204 v4 = (dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]) + 128) >> 8;
2205 v7 = (dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]) + 128) >> 8;
2206 v5 = tmp1[i+3] << 4;
2207 v6 = tmp1[i+5] << 4;
2210 t = (v0 - v1+ 1) >> 1;
2211 v0 = (v0 + v1 + 1) >> 1;
2213 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2214 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2216 t = (v4 - v6 + 1) >> 1;
2217 v4 = (v4 + v6 + 1) >> 1;
2219 t = (v7 + v5 + 1) >> 1;
2220 v5 = (v7 - v5 + 1) >> 1;
2224 t = (v0 - v3 + 1) >> 1;
2225 v0 = (v0 + v3 + 1) >> 1;
2227 t = (v1 - v2 + 1) >> 1;
2228 v1 = (v1 + v2 + 1) >> 1;
2230 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2231 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2233 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2234 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2238 tmp1[i+0] = v0 + v7;
2239 tmp1[i+7] = v0 - v7;
2240 tmp1[i+1] = v1 + v6;
2241 tmp1[i+6] = v1 - v6;
2242 tmp1[i+2] = v2 + v5;
2243 tmp1[i+5] = v2 - v5;
2244 tmp1[i+3] = v3 + v4;
2245 tmp1[i+4] = v3 - v4;
2248 // inverse DCT on columns
2249 for (i = 0; i < 8; ++i) {
2252 v0 = (dctSqrt2 * tmp1[0*8+i] + 2048) >> 12;
2253 v1 = (dctSqrt2 * tmp1[4*8+i] + 2048) >> 12;
2256 v4 = (dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]) + 2048) >> 12;
2257 v7 = (dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]) + 2048) >> 12;
2262 t = (v0 - v1 + 1) >> 1;
2263 v0 = (v0 + v1 + 1) >> 1;
2265 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2266 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2268 t = (v4 - v6 + 1) >> 1;
2269 v4 = (v4 + v6 + 1) >> 1;
2271 t = (v7 + v5 + 1) >> 1;
2272 v5 = (v7 - v5 + 1) >> 1;
2276 t = (v0 - v3 + 1) >> 1;
2277 v0 = (v0 + v3 + 1) >> 1;
2279 t = (v1 - v2 + 1) >> 1;
2280 v1 = (v1 + v2 + 1) >> 1;
2282 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2283 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2285 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2286 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2290 tmp1[0*8+i] = v0 + v7;
2291 tmp1[7*8+i] = v0 - v7;
2292 tmp1[1*8+i] = v1 + v6;
2293 tmp1[6*8+i] = v1 - v6;
2294 tmp1[2*8+i] = v2 + v5;
2295 tmp1[5*8+i] = v2 - v5;
2296 tmp1[3*8+i] = v3 + v4;
2297 tmp1[4*8+i] = v3 - v4;
2300 // convert to 8-bit integers
2301 for (i = 0; i < 64; ++i)
2302 data[i] = dctClip[dctClipOffset + 128 + ((tmp1[i] + 8) >> 4)];
2309 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2310 DCTHuffTable *acHuffTable,
2311 Guchar quantTable[64], int *prevDC,
2314 double v0, v1, v2, v3, v4, v5, v6, v7, t;
2319 // Huffman decode and dequantize
2320 size = readHuffSym(dcHuffTable);
2324 amp = readAmp(size);
2330 tmp1[0] = (*prevDC += amp) * quantTable[0];
2331 for (i = 1; i < 64; ++i)
2336 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
2343 run += (c >> 4) & 0x0f;
2345 amp = readAmp(size);
2350 tmp1[j] = amp * quantTable[j];
2354 // inverse DCT on rows
2355 for (i = 0; i < 64; i += 8) {
2358 v0 = dctSqrt2 * tmp1[i+0];
2359 v1 = dctSqrt2 * tmp1[i+4];
2362 v4 = dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]);
2363 v7 = dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]);
2368 t = 0.5 * (v0 - v1);
2369 v0 = 0.5 * (v0 + v1);
2371 t = v2 * dctSin6 + v3 * dctCos6;
2372 v2 = v2 * dctCos6 - v3 * dctSin6;
2374 t = 0.5 * (v4 - v6);
2375 v4 = 0.5 * (v4 + v6);
2377 t = 0.5 * (v7 + v5);
2378 v5 = 0.5 * (v7 - v5);
2382 t = 0.5 * (v0 - v3);
2383 v0 = 0.5 * (v0 + v3);
2385 t = 0.5 * (v1 - v2);
2386 v1 = 0.5 * (v1 + v2);
2388 t = v4 * dctSin3 + v7 * dctCos3;
2389 v4 = v4 * dctCos3 - v7 * dctSin3;
2391 t = v5 * dctSin1 + v6 * dctCos1;
2392 v5 = v5 * dctCos1 - v6 * dctSin1;
2396 tmp1[i+0] = v0 + v7;
2397 tmp1[i+7] = v0 - v7;
2398 tmp1[i+1] = v1 + v6;
2399 tmp1[i+6] = v1 - v6;
2400 tmp1[i+2] = v2 + v5;
2401 tmp1[i+5] = v2 - v5;
2402 tmp1[i+3] = v3 + v4;
2403 tmp1[i+4] = v3 - v4;
2406 // inverse DCT on columns
2407 for (i = 0; i < 8; ++i) {
2410 v0 = dctSqrt2 * tmp1[0*8+i];
2411 v1 = dctSqrt2 * tmp1[4*8+i];
2414 v4 = dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]);
2415 v7 = dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]);
2420 t = 0.5 * (v0 - v1);
2421 v0 = 0.5 * (v0 + v1);
2423 t = v2 * dctSin6 + v3 * dctCos6;
2424 v2 = v2 * dctCos6 - v3 * dctSin6;
2426 t = 0.5 * (v4 - v6);
2427 v4 = 0.5 * (v4 + v6);
2429 t = 0.5 * (v7 + v5);
2430 v5 = 0.5 * (v7 - v5);
2434 t = 0.5 * (v0 - v3);
2435 v0 = 0.5 * (v0 + v3);
2437 t = 0.5 * (v1 - v2);
2438 v1 = 0.5 * (v1 + v2);
2440 t = v4 * dctSin3 + v7 * dctCos3;
2441 v4 = v4 * dctCos3 - v7 * dctSin3;
2443 t = v5 * dctSin1 + v6 * dctCos1;
2444 v5 = v5 * dctCos1 - v6 * dctSin1;
2448 tmp1[0*8+i] = v0 + v7;
2449 tmp1[7*8+i] = v0 - v7;
2450 tmp1[1*8+i] = v1 + v6;
2451 tmp1[6*8+i] = v1 - v6;
2452 tmp1[2*8+i] = v2 + v5;
2453 tmp1[5*8+i] = v2 - v5;
2454 tmp1[3*8+i] = v3 + v4;
2455 tmp1[4*8+i] = v3 - v4;
2458 // convert to 8-bit integers
2459 for (i = 0; i < 64; ++i)
2460 data[i] = dctClip[dctClipOffset + (int)(tmp1[i] + 128.5)];
2466 int DCTStream::readHuffSym(DCTHuffTable *table) {
2474 // add a bit to the code
2475 if ((bit = readBit()) == EOF)
2477 code = (code << 1) + bit;
2481 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2482 code -= table->firstCode[codeBits];
2483 return table->sym[table->firstSym[codeBits] + code];
2485 } while (codeBits < 16);
2487 error(getPos(), "Bad Huffman code in DCT stream");
2491 int DCTStream::readAmp(int size) {
2496 for (bits = 0; bits < size; ++bits) {
2497 if ((bit = readBit()) == EOF)
2499 amp = (amp << 1) + bit;
2501 if (amp < (1 << (size - 1)))
2502 amp -= (1 << size) - 1;
2506 int DCTStream::readBit() {
2510 if (inputBits == 0) {
2511 if ((c = str->getChar()) == EOF)
2515 c2 = str->getChar();
2516 } while (c2 == 0xff);
2518 error(getPos(), "Bad DCT data: missing 00 after ff");
2525 bit = (inputBuf >> (inputBits - 1)) & 1;
2530 GBool DCTStream::readHeader() {
2532 int minHSample, minVSample;
2541 numDCHuffTables = 0;
2542 numACHuffTables = 0;
2544 gotAdobeMarker = gFalse;
2545 restartInterval = 0;
2553 if (!readFrameInfo())
2557 if (!readHuffmanTables())
2563 if (!readScanInfo())
2568 if (!readQuantTables())
2572 if (!readRestartInterval())
2576 if (!readAdobeMarker())
2580 error(getPos(), "Bad DCT header");
2583 // skip APPn / COM / etc.
2586 for (i = 0; i < n; ++i)
2589 error(getPos(), "Unknown DCT marker <%02x>", c);
2597 mcuWidth = minHSample = compInfo[0].hSample;
2598 mcuHeight = minVSample = compInfo[0].vSample;
2599 for (i = 1; i < numComps; ++i) {
2600 if (compInfo[i].hSample < minHSample)
2601 minHSample = compInfo[i].hSample;
2602 if (compInfo[i].vSample < minVSample)
2603 minVSample = compInfo[i].vSample;
2604 if (compInfo[i].hSample > mcuWidth)
2605 mcuWidth = compInfo[i].hSample;
2606 if (compInfo[i].vSample > mcuHeight)
2607 mcuHeight = compInfo[i].vSample;
2609 for (i = 0; i < numComps; ++i) {
2610 compInfo[i].hSample /= minHSample;
2611 compInfo[i].vSample /= minVSample;
2613 mcuWidth = (mcuWidth / minHSample) * 8;
2614 mcuHeight = (mcuHeight / minVSample) * 8;
2617 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2618 for (i = 0; i < numComps; ++i)
2619 for (j = 0; j < mcuHeight; ++j)
2620 rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
2622 // figure out color transform
2623 if (!gotAdobeMarker && numComps == 3) {
2624 if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
2629 // initialize counters
2638 GBool DCTStream::readFrameInfo() {
2644 length = read16() - 2;
2645 prec = str->getChar();
2648 numComps = str->getChar();
2651 error(getPos(), "Bad DCT precision %d", prec);
2654 for (i = 0; i < numComps; ++i) {
2655 compInfo[i].id = str->getChar();
2656 compInfo[i].inScan = gFalse;
2658 compInfo[i].hSample = (c >> 4) & 0x0f;
2659 compInfo[i].vSample = c & 0x0f;
2660 compInfo[i].quantTable = str->getChar();
2661 compInfo[i].dcHuffTable = 0;
2662 compInfo[i].acHuffTable = 0;
2667 GBool DCTStream::readScanInfo() {
2669 int scanComps, id, c;
2672 length = read16() - 2;
2673 scanComps = str->getChar();
2675 if (length != 2 * scanComps + 3) {
2676 error(getPos(), "Bad DCT scan info block");
2679 for (i = 0; i < scanComps; ++i) {
2680 id = str->getChar();
2681 for (j = 0; j < numComps; ++j) {
2682 if (id == compInfo[j].id)
2685 if (j == numComps) {
2686 error(getPos(), "Bad DCT component ID in scan info block");
2689 compInfo[j].inScan = gTrue;
2691 compInfo[j].dcHuffTable = (c >> 4) & 0x0f;
2692 compInfo[j].acHuffTable = c & 0x0f;
2700 GBool DCTStream::readQuantTables() {
2705 length = read16() - 2;
2706 while (length > 0) {
2707 index = str->getChar();
2708 if ((index & 0xf0) || index >= 4) {
2709 error(getPos(), "Bad DCT quantization table");
2712 if (index == numQuantTables)
2713 numQuantTables = index + 1;
2714 for (i = 0; i < 64; ++i)
2715 quantTables[index][dctZigZag[i]] = str->getChar();
2721 GBool DCTStream::readHuffmanTables() {
2730 length = read16() - 2;
2731 while (length > 0) {
2732 index = str->getChar();
2734 if ((index & 0x0f) >= 4) {
2735 error(getPos(), "Bad DCT Huffman table");
2740 if (index >= numACHuffTables)
2741 numACHuffTables = index+1;
2742 tbl = &acHuffTables[index];
2744 if (index >= numDCHuffTables)
2745 numDCHuffTables = index+1;
2746 tbl = &dcHuffTables[index];
2750 for (i = 1; i <= 16; ++i) {
2752 tbl->firstSym[i] = sym;
2753 tbl->firstCode[i] = code;
2754 tbl->numCodes[i] = c;
2756 code = (code + c) << 1;
2759 for (i = 0; i < sym; ++i)
2760 tbl->sym[i] = str->getChar();
2766 GBool DCTStream::readRestartInterval() {
2771 error(getPos(), "Bad DCT restart interval");
2774 restartInterval = read16();
2778 GBool DCTStream::readAdobeMarker() {
2786 for (i = 0; i < 12; ++i) {
2787 if ((c = str->getChar()) == EOF)
2791 if (strncmp(buf, "Adobe", 5))
2793 colorXform = buf[11];
2794 gotAdobeMarker = gTrue;
2798 error(getPos(), "Bad DCT Adobe APP14 marker");
2802 GBool DCTStream::readTrailer() {
2806 if (c != 0xd9) { // EOI
2807 error(getPos(), "Bad DCT trailer");
2813 int DCTStream::readMarker() {
2819 } while (c != 0xff);
2822 } while (c == 0xff);
2823 } while (c == 0x00);
2827 int DCTStream::read16() {
2830 if ((c1 = str->getChar()) == EOF)
2832 if ((c2 = str->getChar()) == EOF)
2834 return (c1 << 8) + c2;
2837 GString *DCTStream::getPSFilter(char *indent) {
2840 if (!(s = str->getPSFilter(indent))) {
2843 s->append(indent)->append("<< >> /DCTDecode filter\n");
2847 GBool DCTStream::isBinary(GBool last) {
2848 return str->isBinary(gTrue);
2851 //------------------------------------------------------------------------
2853 //------------------------------------------------------------------------
2855 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
2856 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
2859 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
2891 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
2924 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
2925 int colors, int bits):
2926 FilterStream(strA) {
2927 if (predictor != 1) {
2928 pred = new StreamPredictor(this, predictor, columns, colors, bits);
2934 FlateStream::~FlateStream() {
2941 void FlateStream::reset() {
2948 compressedBlock = gFalse;
2955 //~ need to look at window size?
2956 endOfBlock = eof = gTrue;
2957 cmf = str->getChar();
2958 flg = str->getChar();
2959 if (cmf == EOF || flg == EOF)
2961 if ((cmf & 0x0f) != 0x08) {
2962 error(getPos(), "Unknown compression method in flate stream");
2965 if ((((cmf << 8) + flg) % 31) != 0) {
2966 error(getPos(), "Bad FCHECK in flate stream");
2970 error(getPos(), "FDICT bit set in flate stream");
2977 int FlateStream::getChar() {
2981 return pred->getChar();
2983 while (remain == 0) {
2984 if (endOfBlock && eof)
2989 index = (index + 1) & flateMask;
2994 int FlateStream::lookChar() {
2998 return pred->lookChar();
3000 while (remain == 0) {
3001 if (endOfBlock && eof)
3009 int FlateStream::getRawChar() {
3012 while (remain == 0) {
3013 if (endOfBlock && eof)
3018 index = (index + 1) & flateMask;
3023 GString *FlateStream::getPSFilter(char *indent) {
3027 GBool FlateStream::isBinary(GBool last) {
3028 return str->isBinary(gTrue);
3031 void FlateStream::readSome() {
3042 if (compressedBlock) {
3043 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
3048 } else if (code1 == 256) {
3053 code2 = lengthDecode[code1].bits;
3054 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3056 len = lengthDecode[code1].first + code2;
3057 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
3059 code2 = distDecode[code1].bits;
3060 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3062 dist = distDecode[code1].first + code2;
3064 j = (index - dist) & flateMask;
3065 for (k = 0; k < len; ++k) {
3067 i = (i + 1) & flateMask;
3068 j = (j + 1) & flateMask;
3074 len = (blockLen < flateWindow) ? blockLen : flateWindow;
3075 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
3076 if ((c = str->getChar()) == EOF) {
3077 endOfBlock = eof = gTrue;
3091 error(getPos(), "Unexpected end of file in flate stream");
3092 endOfBlock = eof = gTrue;
3096 GBool FlateStream::startBlock() {
3101 // read block header
3102 blockHdr = getCodeWord(3);
3107 // uncompressed block
3108 if (blockHdr == 0) {
3109 compressedBlock = gFalse;
3110 if ((c = str->getChar()) == EOF)
3112 blockLen = c & 0xff;
3113 if ((c = str->getChar()) == EOF)
3115 blockLen |= (c & 0xff) << 8;
3116 if ((c = str->getChar()) == EOF)
3119 if ((c = str->getChar()) == EOF)
3121 check |= (c & 0xff) << 8;
3122 if (check != (~blockLen & 0xffff))
3123 error(getPos(), "Bad uncompressed block length in flate stream");
3127 // compressed block with fixed codes
3128 } else if (blockHdr == 1) {
3129 compressedBlock = gTrue;
3132 // compressed block with dynamic codes
3133 } else if (blockHdr == 2) {
3134 compressedBlock = gTrue;
3135 if (!readDynamicCodes())
3138 // unknown block type
3143 endOfBlock = gFalse;
3147 error(getPos(), "Bad block header in flate stream");
3148 endOfBlock = eof = gTrue;
3152 void FlateStream::loadFixedCodes() {
3155 // set up code arrays
3156 litCodeTab.codes = allCodes;
3157 distCodeTab.codes = allCodes + flateMaxLitCodes;
3159 // initialize literal code table
3160 for (i = 0; i <= 143; ++i)
3161 litCodeTab.codes[i].len = 8;
3162 for (i = 144; i <= 255; ++i)
3163 litCodeTab.codes[i].len = 9;
3164 for (i = 256; i <= 279; ++i)
3165 litCodeTab.codes[i].len = 7;
3166 for (i = 280; i <= 287; ++i)
3167 litCodeTab.codes[i].len = 8;
3168 compHuffmanCodes(&litCodeTab, flateMaxLitCodes);
3170 // initialize distance code table
3171 for (i = 0; i <= 5; ++i) {
3172 distCodeTab.start[i] = 0;
3174 for (i = 6; i <= flateMaxHuffman+1; ++i) {
3175 distCodeTab.start[i] = flateMaxDistCodes;
3177 for (i = 0; i < flateMaxDistCodes; ++i) {
3178 distCodeTab.codes[i].len = 5;
3179 distCodeTab.codes[i].code = i;
3180 distCodeTab.codes[i].val = i;
3184 GBool FlateStream::readDynamicCodes() {
3185 int numCodeLenCodes;
3188 FlateCode codeLenCodes[flateMaxCodeLenCodes];
3189 FlateHuffmanTab codeLenCodeTab;
3190 int len, repeat, code;
3194 if ((numLitCodes = getCodeWord(5)) == EOF)
3197 if ((numDistCodes = getCodeWord(5)) == EOF)
3200 if ((numCodeLenCodes = getCodeWord(4)) == EOF)
3202 numCodeLenCodes += 4;
3203 if (numLitCodes > flateMaxLitCodes ||
3204 numDistCodes > flateMaxDistCodes ||
3205 numCodeLenCodes > flateMaxCodeLenCodes)
3208 // read code length code table
3209 codeLenCodeTab.codes = codeLenCodes;
3210 for (i = 0; i < flateMaxCodeLenCodes; ++i)
3211 codeLenCodes[i].len = 0;
3212 for (i = 0; i < numCodeLenCodes; ++i) {
3213 if ((codeLenCodes[codeLenCodeMap[i]].len = getCodeWord(3)) == -1)
3216 compHuffmanCodes(&codeLenCodeTab, flateMaxCodeLenCodes);
3218 // set up code arrays
3219 litCodeTab.codes = allCodes;
3220 distCodeTab.codes = allCodes + numLitCodes;
3222 // read literal and distance code tables
3226 while (i < numLitCodes + numDistCodes) {
3227 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF)
3230 if ((repeat = getCodeWord(2)) == EOF)
3232 for (repeat += 3; repeat > 0; --repeat)
3233 allCodes[i++].len = len;
3234 } else if (code == 17) {
3235 if ((repeat = getCodeWord(3)) == EOF)
3238 for (repeat += 3; repeat > 0; --repeat)
3239 allCodes[i++].len = 0;
3240 } else if (code == 18) {
3241 if ((repeat = getCodeWord(7)) == EOF)
3244 for (repeat += 11; repeat > 0; --repeat)
3245 allCodes[i++].len = 0;
3247 allCodes[i++].len = len = code;
3250 compHuffmanCodes(&litCodeTab, numLitCodes);
3251 compHuffmanCodes(&distCodeTab, numDistCodes);
3256 error(getPos(), "Bad dynamic code table in flate stream");
3260 // On entry, the <tab->codes> array contains the lengths of each code,
3261 // stored in code value order. This function computes the code words.
3262 // The result is sorted in order of (1) code length and (2) code word.
3263 // The length values are no longer valid. The <tab->start> array is
3264 // filled with the indexes of the first code of each length.
3265 void FlateStream::compHuffmanCodes(FlateHuffmanTab *tab, int n) {
3266 int numLengths[flateMaxHuffman+1];
3267 int nextCode[flateMaxHuffman+1];
3268 int nextIndex[flateMaxHuffman+2];
3272 // count number of codes for each code length
3273 for (i = 0; i <= flateMaxHuffman; ++i)
3275 for (i = 0; i < n; ++i)
3276 ++numLengths[tab->codes[i].len];
3278 // compute first index for each length
3279 tab->start[0] = nextIndex[0] = 0;
3280 for (i = 1; i <= flateMaxHuffman + 1; ++i)
3281 tab->start[i] = nextIndex[i] = tab->start[i-1] + numLengths[i-1];
3283 // compute first code for each length
3286 for (i = 1; i <= flateMaxHuffman; ++i) {
3287 code = (code + numLengths[i-1]) << 1;
3291 // compute the codes -- this permutes the codes array from value
3292 // order to length/code order
3293 for (i = 0; i < n; ++i) {
3294 j = nextIndex[tab->codes[i].len]++;
3295 if (tab->codes[i].len == 0)
3296 tab->codes[j].code = 0;
3298 tab->codes[j].code = nextCode[tab->codes[i].len]++;
3299 tab->codes[j].val = i;
3303 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
3310 for (len = 1; len <= flateMaxHuffman; ++len) {
3312 // add a bit to the code
3313 if (codeSize == 0) {
3314 if ((c = str->getChar()) == EOF)
3319 code = (code << 1) | (codeBuf & 1);
3324 i = tab->start[len];
3325 j = tab->start[len + 1];
3326 if (i < j && code >= tab->codes[i].code && code <= tab->codes[j-1].code) {
3327 i += code - tab->codes[i].code;
3328 return tab->codes[i].val;
3333 error(getPos(), "Bad code (%04x) in flate stream", code);
3337 int FlateStream::getCodeWord(int bits) {
3340 while (codeSize < bits) {
3341 if ((c = str->getChar()) == EOF)
3343 codeBuf |= (c & 0xff) << codeSize;
3346 c = codeBuf & ((1 << bits) - 1);
3352 //------------------------------------------------------------------------
3354 //------------------------------------------------------------------------
3356 EOFStream::EOFStream(Stream *strA):
3357 FilterStream(strA) {
3360 EOFStream::~EOFStream() {
3364 //------------------------------------------------------------------------
3365 // FixedLengthEncoder
3366 //------------------------------------------------------------------------
3368 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
3369 FilterStream(strA) {
3374 FixedLengthEncoder::~FixedLengthEncoder() {
3375 if (str->isEncoder())
3379 void FixedLengthEncoder::reset() {
3384 void FixedLengthEncoder::close() {
3387 int FixedLengthEncoder::getChar() {
3388 if (length >= 0 && count >= length)
3391 return str->getChar();
3394 int FixedLengthEncoder::lookChar() {
3395 if (length >= 0 && count >= length)
3397 return str->getChar();
3400 //------------------------------------------------------------------------
3402 //------------------------------------------------------------------------
3404 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
3405 FilterStream(strA) {
3406 bufPtr = bufEnd = buf;
3411 ASCIIHexEncoder::~ASCIIHexEncoder() {
3412 if (str->isEncoder()) {
3417 void ASCIIHexEncoder::reset() {
3419 bufPtr = bufEnd = buf;
3424 void ASCIIHexEncoder::close() {
3427 GBool ASCIIHexEncoder::fillBuf() {
3428 static char *hex = "0123456789abcdef";
3434 bufPtr = bufEnd = buf;
3435 if ((c = str->getChar()) == EOF) {
3439 if (lineLen >= 64) {
3443 *bufEnd++ = hex[(c >> 4) & 0x0f];
3444 *bufEnd++ = hex[c & 0x0f];
3450 //------------------------------------------------------------------------
3452 //------------------------------------------------------------------------
3454 ASCII85Encoder::ASCII85Encoder(Stream *strA):
3455 FilterStream(strA) {
3456 bufPtr = bufEnd = buf;
3461 ASCII85Encoder::~ASCII85Encoder() {
3462 if (str->isEncoder())
3466 void ASCII85Encoder::reset() {
3468 bufPtr = bufEnd = buf;
3473 void ASCII85Encoder::close() {
3476 GBool ASCII85Encoder::fillBuf() {
3485 for (n = 0; n < 4; ++n) {
3486 if ((c = str->getChar()) == EOF)
3490 bufPtr = bufEnd = buf;
3492 if (n == 4 && t == 0) {
3494 if (++lineLen == 65) {
3501 for (i = 4; i >= 0; --i) {
3502 buf1[i] = (char)(t % 85 + 0x21);
3505 for (i = 0; i <= n; ++i) {
3506 *bufEnd++ = buf1[i];
3507 if (++lineLen == 65) {
3519 return bufPtr < bufEnd;
3522 //------------------------------------------------------------------------
3524 //------------------------------------------------------------------------
3526 RunLengthEncoder::RunLengthEncoder(Stream *strA):
3527 FilterStream(strA) {
3528 bufPtr = bufEnd = nextEnd = buf;
3532 RunLengthEncoder::~RunLengthEncoder() {
3533 if (str->isEncoder())
3537 void RunLengthEncoder::reset() {
3539 bufPtr = bufEnd = nextEnd = buf;
3543 void RunLengthEncoder::close() {
3547 // When fillBuf finishes, buf[] looks like this:
3548 // +-----+--------------+-----------------+--
3549 // + tag | ... data ... | next 0, 1, or 2 |
3550 // +-----+--------------+-----------------+--
3552 // bufPtr bufEnd nextEnd
3554 GBool RunLengthEncoder::fillBuf() {
3563 if (nextEnd < bufEnd + 1) {
3564 if ((c1 = str->getChar()) == EOF) {
3569 c1 = bufEnd[0] & 0xff;
3571 if (nextEnd < bufEnd + 2) {
3572 if ((c2 = str->getChar()) == EOF) {
3581 c2 = bufEnd[1] & 0xff;
3585 c = 0; // make gcc happy
3588 while (n < 128 && (c = str->getChar()) == c1)
3590 buf[0] = (char)(257 - n);
3595 } else if (n < 128) {
3602 // get up to 128 chars
3608 if ((c = str->getChar()) == EOF) {
3614 if (buf[n] == buf[n-1])
3617 if (buf[n] == buf[n-1]) {
3618 buf[0] = (char)(n-2-1);
3620 nextEnd = &buf[n+1];
3622 buf[0] = (char)(n-1);
3623 bufEnd = nextEnd = &buf[n+1];