1 //========================================================================
5 // Copyright 1996-2002 Glyph & Cog, LLC
7 //========================================================================
10 #pragma implementation
31 #include "Stream-CCITT.h"
34 static GBool setDJSYSFLAGS = gFalse;
38 #if (__VMS_VER < 70000000)
39 extern "C" int unlink(char *filename);
49 #include "StuffItEngineLib.h"
52 //------------------------------------------------------------------------
53 // Stream (base class)
54 //------------------------------------------------------------------------
63 void Stream::close() {
66 int Stream::getRawChar() {
67 error(-1, "Internal: called getRawChar() on non-predictor stream");
71 char *Stream::getLine(char *buf, int size) {
75 if (lookChar() == EOF)
77 for (i = 0; i < size - 1; ++i) {
79 if (c == EOF || c == '\n')
82 if ((c = lookChar()) == '\n')
92 GString *Stream::getPSFilter(char *indent) {
96 Stream *Stream::addFilters(Object *dict) {
98 Object params, params2;
103 dict->dictLookup("Filter", &obj);
106 dict->dictLookup("F", &obj);
108 dict->dictLookup("DecodeParms", ¶ms);
109 if (params.isNull()) {
111 dict->dictLookup("DP", ¶ms);
114 str = makeFilter(obj.getName(), str, ¶ms);
115 } else if (obj.isArray()) {
116 for (i = 0; i < obj.arrayGetLength(); ++i) {
117 obj.arrayGet(i, &obj2);
118 if (params.isArray())
119 params.arrayGet(i, ¶ms2);
123 str = makeFilter(obj2.getName(), str, ¶ms2);
125 error(getPos(), "Bad filter name");
126 str = new EOFStream(str);
131 } else if (!obj.isNull()) {
132 error(getPos(), "Bad 'Filter' attribute in stream");
140 Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
141 int pred; // parameters
146 GBool endOfLine, byteAlign, endOfBlock, black;
150 if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
151 str = new ASCIIHexStream(str);
152 } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
153 str = new ASCII85Stream(str);
154 } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
160 if (params->isDict()) {
161 params->dictLookup("Predictor", &obj);
165 params->dictLookup("Columns", &obj);
167 columns = obj.getInt();
169 params->dictLookup("Colors", &obj);
171 colors = obj.getInt();
173 params->dictLookup("BitsPerComponent", &obj);
177 params->dictLookup("EarlyChange", &obj);
179 early = obj.getInt();
182 str = new LZWStream(str, pred, columns, colors, bits, early);
183 } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
184 str = new RunLengthStream(str);
185 } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
193 if (params->isDict()) {
194 params->dictLookup("K", &obj);
196 encoding = obj.getInt();
199 params->dictLookup("EndOfLine", &obj);
201 endOfLine = obj.getBool();
204 params->dictLookup("EncodedByteAlign", &obj);
206 byteAlign = obj.getBool();
209 params->dictLookup("Columns", &obj);
211 columns = obj.getInt();
214 params->dictLookup("Rows", &obj);
219 params->dictLookup("EndOfBlock", &obj);
221 endOfBlock = obj.getBool();
224 params->dictLookup("BlackIs1", &obj);
226 black = obj.getBool();
230 str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
231 columns, rows, endOfBlock, black);
232 } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
233 str = new DCTStream(str);
234 } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
239 if (params->isDict()) {
240 params->dictLookup("Predictor", &obj);
244 params->dictLookup("Columns", &obj);
246 columns = obj.getInt();
248 params->dictLookup("Colors", &obj);
250 colors = obj.getInt();
252 params->dictLookup("BitsPerComponent", &obj);
257 str = new FlateStream(str, pred, columns, colors, bits);
259 error(getPos(), "Unknown filter '%s'", name);
260 str = new EOFStream(str);
265 //------------------------------------------------------------------------
267 //------------------------------------------------------------------------
269 BaseStream::BaseStream(Object *dictA) {
271 #ifndef NO_DECRYPTION
276 BaseStream::~BaseStream() {
278 #ifndef NO_DECRYPTION
284 #ifndef NO_DECRYPTION
285 void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
286 int objNum, int objGen) {
287 decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
291 //------------------------------------------------------------------------
293 //------------------------------------------------------------------------
295 FilterStream::FilterStream(Stream *strA) {
299 FilterStream::~FilterStream() {
302 void FilterStream::close() {
306 void FilterStream::setPos(Guint pos, int dir) {
307 error(-1, "Internal: called setPos() on FilterStream");
310 //------------------------------------------------------------------------
312 //------------------------------------------------------------------------
314 ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
322 nVals = width * nComps;
324 imgLineSize = (nVals + 7) & ~7;
328 imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
332 ImageStream::~ImageStream() {
336 void ImageStream::reset() {
340 GBool ImageStream::getPixel(Guchar *pix) {
346 if (imgIdx >= nVals) {
348 // read one line of image pixels
350 for (i = 0; i < nVals; i += 8) {
352 imgLine[i+0] = (Guchar)((c >> 7) & 1);
353 imgLine[i+1] = (Guchar)((c >> 6) & 1);
354 imgLine[i+2] = (Guchar)((c >> 5) & 1);
355 imgLine[i+3] = (Guchar)((c >> 4) & 1);
356 imgLine[i+4] = (Guchar)((c >> 3) & 1);
357 imgLine[i+5] = (Guchar)((c >> 2) & 1);
358 imgLine[i+6] = (Guchar)((c >> 1) & 1);
359 imgLine[i+7] = (Guchar)(c & 1);
361 } else if (nBits == 8) {
362 for (i = 0; i < nVals; ++i) {
363 imgLine[i] = str->getChar();
366 bitMask = (1 << nBits) - 1;
369 for (i = 0; i < nVals; ++i) {
371 buf = (buf << 8) | (str->getChar() & 0xff);
374 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
379 // reset to start of line
383 for (i = 0; i < nComps; ++i)
384 pix[i] = imgLine[imgIdx++];
388 void ImageStream::skipLine() {
391 n = (nVals * nBits + 7) >> 3;
392 for (i = 0; i < n; ++i) {
397 //------------------------------------------------------------------------
399 //------------------------------------------------------------------------
401 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
402 int widthA, int nCompsA, int nBitsA) {
404 predictor = predictorA;
409 nVals = width * nComps;
410 pixBytes = (nComps * nBits + 7) >> 3;
411 rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
412 predLine = (Guchar *)gmalloc(rowBytes);
413 memset(predLine, 0, rowBytes);
417 StreamPredictor::~StreamPredictor() {
421 int StreamPredictor::lookChar() {
422 if (predIdx >= rowBytes) {
423 if (!getNextLine()) {
427 return predLine[predIdx];
430 int StreamPredictor::getChar() {
431 if (predIdx >= rowBytes) {
432 if (!getNextLine()) {
436 return predLine[predIdx++];
439 GBool StreamPredictor::getNextLine() {
442 int left, up, upLeft, p, pa, pb, pc;
444 Gulong inBuf, outBuf, bitMask;
448 // get PNG optimum predictor number
449 if (predictor == 15) {
450 if ((curPred = str->getRawChar()) == EOF) {
458 // read the raw line, apply PNG (byte) predictor
459 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
460 for (i = pixBytes; i < rowBytes; ++i) {
461 upLeftBuf[3] = upLeftBuf[2];
462 upLeftBuf[2] = upLeftBuf[1];
463 upLeftBuf[1] = upLeftBuf[0];
464 upLeftBuf[0] = predLine[i];
465 if ((c = str->getRawChar()) == EOF) {
470 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
473 predLine[i] = predLine[i] + (Guchar)c;
475 case 13: // PNG average
476 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
479 case 14: // PNG Paeth
480 left = predLine[i - pixBytes];
482 upLeft = upLeftBuf[pixBytes];
483 p = left + up - upLeft;
484 if ((pa = p - left) < 0)
486 if ((pb = p - up) < 0)
488 if ((pc = p - upLeft) < 0)
490 if (pa <= pb && pa <= pc)
491 predLine[i] = left + (Guchar)c;
493 predLine[i] = up + (Guchar)c;
495 predLine[i] = upLeft + (Guchar)c;
498 default: // no predictor or TIFF predictor
499 predLine[i] = (Guchar)c;
504 // apply TIFF (component) predictor
505 //~ this is completely untested
506 if (predictor == 2) {
508 inBuf = predLine[pixBytes - 1];
509 for (i = pixBytes; i < rowBytes; i += 8) {
510 // 1-bit add is just xor
511 inBuf = (inBuf << 8) | predLine[i];
512 predLine[i] ^= inBuf >> nComps;
514 } else if (nBits == 8) {
515 for (i = pixBytes; i < rowBytes; ++i) {
516 predLine[i] += predLine[i - nComps];
519 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
520 bitMask = (1 << nBits) - 1;
522 inBits = outBits = 0;
524 for (i = 0; i < nVals; ++i) {
525 if (inBits < nBits) {
526 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
529 upLeftBuf[3] = upLeftBuf[2];
530 upLeftBuf[2] = upLeftBuf[1];
531 upLeftBuf[1] = upLeftBuf[0];
532 upLeftBuf[0] = (upLeftBuf[nComps] +
533 (inBuf >> (inBits - nBits))) & bitMask;
534 outBuf = (outBuf << nBits) | upLeftBuf[0];
538 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
542 predLine[k++] = (Guchar)(outBuf << (8 - outBits));
547 // reset to start of line
553 //------------------------------------------------------------------------
555 //------------------------------------------------------------------------
557 FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
558 Guint lengthA, Object *dictA):
564 bufPtr = bufEnd = buf;
570 FileStream::~FileStream() {
574 Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
575 Guint lengthA, Object *dictA) {
576 return new FileStream(f, startA, limitedA, lengthA, dictA);
579 void FileStream::reset() {
581 savePos = (Guint)ftell64(f);
582 fseek64(f, start, SEEK_SET);
584 savePos = (Guint)ftell(f);
585 fseek(f, start, SEEK_SET);
588 bufPtr = bufEnd = buf;
590 #ifndef NO_DECRYPTION
596 void FileStream::close() {
599 fseek64(f, savePos, SEEK_SET);
601 fseek(f, savePos, SEEK_SET);
607 GBool FileStream::fillBuf() {
609 #ifndef NO_DECRYPTION
613 bufPos += bufEnd - buf;
614 bufPtr = bufEnd = buf;
615 if (limited && bufPos >= start + length) {
618 if (limited && bufPos + fileStreamBufSize > start + length) {
619 n = start + length - bufPos;
621 n = fileStreamBufSize;
623 n = fread(buf, 1, n, f);
625 if (bufPtr >= bufEnd) {
628 #ifndef NO_DECRYPTION
630 for (p = buf; p < bufEnd; ++p) {
631 *p = (char)decrypt->decryptByte((Guchar)*p);
638 void FileStream::setPos(Guint pos, int dir) {
643 fseek64(f, pos, SEEK_SET);
645 fseek(f, pos, SEEK_SET);
650 fseek64(f, 0, SEEK_END);
651 size = (Guint)ftell64(f);
653 fseek(f, 0, SEEK_END);
654 size = (Guint)ftell(f);
659 //~ work around a bug in cygwin's implementation of fseek
663 fseek64(f, -(int)pos, SEEK_END);
664 bufPos = (Guint)ftell64(f);
666 fseek(f, -(int)pos, SEEK_END);
667 bufPos = (Guint)ftell(f);
670 bufPtr = bufEnd = buf;
673 void FileStream::moveStart(int delta) {
675 bufPtr = bufEnd = buf;
679 //------------------------------------------------------------------------
681 //------------------------------------------------------------------------
683 MemStream::MemStream(char *bufA, Guint lengthA, Object *dictA):
688 bufEnd = buf + length;
692 MemStream::~MemStream() {
698 Stream *MemStream::makeSubStream(Guint start, GBool limited,
699 Guint lengthA, Object *dictA) {
702 if (!limited || start + lengthA > length) {
703 newLength = length - start;
707 return new MemStream(buf + start, newLength, dictA);
710 void MemStream::reset() {
712 #ifndef NO_DECRYPTION
719 void MemStream::close() {
722 void MemStream::setPos(Guint pos, int dir) {
733 bufPtr = bufEnd - pos;
738 void MemStream::moveStart(int delta) {
743 #ifndef NO_DECRYPTION
744 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
745 int objNum, int objGen) {
749 this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
751 newBuf = (char *)gmalloc(bufEnd - buf);
752 for (p = buf, q = newBuf; p < bufEnd; ++p, ++q) {
753 *q = (char)decrypt->decryptByte((Guchar)*p);
755 bufEnd = newBuf + (bufEnd - buf);
756 bufPtr = newBuf + (bufPtr - buf);
763 //------------------------------------------------------------------------
765 //------------------------------------------------------------------------
767 EmbedStream::EmbedStream(Stream *strA, Object *dictA):
772 EmbedStream::~EmbedStream() {
775 Stream *EmbedStream::makeSubStream(Guint start, GBool limited,
776 Guint length, Object *dictA) {
777 error(-1, "Internal: called makeSubStream() on EmbedStream");
781 void EmbedStream::setPos(Guint pos, int dir) {
782 error(-1, "Internal: called setPos() on EmbedStream");
785 Guint EmbedStream::getStart() {
786 error(-1, "Internal: called getStart() on EmbedStream");
790 void EmbedStream::moveStart(int delta) {
791 error(-1, "Internal: called moveStart() on EmbedStream");
794 //------------------------------------------------------------------------
796 //------------------------------------------------------------------------
798 ASCIIHexStream::ASCIIHexStream(Stream *strA):
804 ASCIIHexStream::~ASCIIHexStream() {
808 void ASCIIHexStream::reset() {
814 int ASCIIHexStream::lookChar() {
825 } while (isspace(c1));
833 } while (isspace(c2));
838 if (c1 >= '0' && c1 <= '9') {
840 } else if (c1 >= 'A' && c1 <= 'F') {
841 x = (c1 - 'A' + 10) << 4;
842 } else if (c1 >= 'a' && c1 <= 'f') {
843 x = (c1 - 'a' + 10) << 4;
844 } else if (c1 == EOF) {
848 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
851 if (c2 >= '0' && c2 <= '9') {
853 } else if (c2 >= 'A' && c2 <= 'F') {
855 } else if (c2 >= 'a' && c2 <= 'f') {
857 } else if (c2 == EOF) {
861 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
867 GString *ASCIIHexStream::getPSFilter(char *indent) {
870 if (!(s = str->getPSFilter(indent))) {
873 s->append(indent)->append("/ASCIIHexDecode filter\n");
877 GBool ASCIIHexStream::isBinary(GBool last) {
878 return str->isBinary(gFalse);
881 //------------------------------------------------------------------------
883 //------------------------------------------------------------------------
885 ASCII85Stream::ASCII85Stream(Stream *strA):
891 ASCII85Stream::~ASCII85Stream() {
895 void ASCII85Stream::reset() {
901 int ASCII85Stream::lookChar() {
910 c[0] = str->getChar();
911 } while (c[0] == '\n' || c[0] == '\r');
912 if (c[0] == '~' || c[0] == EOF) {
916 } else if (c[0] == 'z') {
917 b[0] = b[1] = b[2] = b[3] = 0;
920 for (k = 1; k < 5; ++k) {
922 c[k] = str->getChar();
923 } while (c[k] == '\n' || c[k] == '\r');
924 if (c[k] == '~' || c[k] == EOF)
928 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
929 for (++k; k < 5; ++k)
934 for (k = 0; k < 5; ++k)
935 t = t * 85 + (c[k] - 0x21);
936 for (k = 3; k >= 0; --k) {
937 b[k] = (int)(t & 0xff);
945 GString *ASCII85Stream::getPSFilter(char *indent) {
948 if (!(s = str->getPSFilter(indent))) {
951 s->append(indent)->append("/ASCII85Decode filter\n");
955 GBool ASCII85Stream::isBinary(GBool last) {
956 return str->isBinary(gFalse);
959 //------------------------------------------------------------------------
961 //------------------------------------------------------------------------
963 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
964 int bits, int earlyA):
966 if (predictor != 1) {
967 pred = new StreamPredictor(this, predictor, columns, colors, bits);
973 bufPtr = bufEnd = buf;
976 LZWStream::~LZWStream() {
984 unlink(zName->getCString());
993 int LZWStream::getChar() {
995 return pred->getChar();
997 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
1000 int LZWStream::lookChar() {
1002 return pred->lookChar();
1004 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff);
1007 int LZWStream::getRawChar() {
1008 return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
1011 void LZWStream::reset() {
1015 //----- close old LZW stream
1023 unlink(zName->getCString());
1027 //----- tell Delorie runtime to spawn a new instance of COMMAND.COM
1030 if (!setDJSYSFLAGS) {
1031 setenv("DJSYSFLAGS", "0x0002", 0);
1032 setDJSYSFLAGS = gTrue;
1036 //----- create the .Z file
1037 if (!openTempFile(&zName, &f, "wb", ".Z")) {
1038 error(getPos(), "Couldn't create temporary file for LZW stream");
1044 //----- execute uncompress / gzip
1045 zCmd = new GString(uncompressCmd);
1047 zCmd->append(zName);
1050 // first we open the engine up
1051 OSErr err = OpenSITEngine(kUseExternalEngine, &magicCookie);
1052 // if we found it - let's use it!
1053 if (!err && magicCookie) {
1054 // make sure we have the correct version of the Engine
1055 if (GetSITEngineVersion(magicCookie) >= kFirstSupportedEngine) {
1058 strcpy((char *)pName, zName->getCString());
1059 c2pstr((char *)pName);
1060 FSMakeFSSpec(0, 0, pName, &myFSS);
1061 short ftype = DetermineFileType(magicCookie, &myFSS);
1062 OSErr expandErr = ExpandFSSpec(magicCookie, ftype, &myFSS,
1063 NULL, NULL, kCreateFolderNever,
1064 kDeleteOriginal, kTextConvertSmart);
1067 #elif defined(HAVE_POPEN)
1068 if (!(zPipe = popen(zCmd->getCString(), POPEN_READ_MODE))) {
1069 error(getPos(), "Couldn't popen '%s'", zCmd->getCString());
1070 unlink(zName->getCString());
1075 if (!executeCommand(zCmd->getCString())) {
1076 error(getPos(), "Couldn't execute '%s'", zCmd->getCString());
1077 unlink(zName->getCString());
1081 zName->del(zName->getLength() - 2, 2);
1082 if (!(zPipe = fopen(zName->getCString(), "rb"))) {
1083 error(getPos(), "Couldn't open uncompress file '%s'", zName->getCString());
1084 unlink(zName->getCString());
1088 #endif // HAVE_POPEN
1093 //----- initialize buffer
1094 bufPtr = bufEnd = buf;
1097 void LZWStream::dumpFile(FILE *f) {
1098 int outCodeBits; // size of output code
1099 int outBits; // max output code
1100 int outBuf[8]; // output buffer
1101 int outData; // temporary output buffer
1102 int inCode, outCode; // input and output codes
1103 int nextCode; // next code index
1104 GBool eof; // set when EOF is reached
1105 GBool clear; // set if table needs to be cleared
1106 GBool first; // indicates first code word after clear
1115 // max code length, block mode flag
1133 for (i = 0; i < 8; ++i) {
1134 // check for table overflow
1135 if (nextCode + early > 0x1001) {
1142 if (inCode == EOF) {
1146 } while (first && inCode == 256);
1149 // compute output code
1152 } else if (inCode == 256) {
1155 } else if (inCode == 257) {
1159 outCode = inCode - 1;
1161 outBuf[i] = outCode;
1169 // check input code size
1170 if (nextCode + early == 0x200)
1172 else if (nextCode + early == 0x400) {
1174 } else if (nextCode + early == 0x800) {
1178 // check for eof/clear
1187 // write output block
1191 while (j < i || outBits > 0) {
1192 if (outBits < 8 && j < i) {
1193 outData = outData | (outBuf[j++] << outBits);
1194 outBits += outCodeBits;
1196 fputc(outData & 0xff, f);
1201 // check output code size
1202 if (nextCode - 1 == 512 ||
1203 nextCode - 1 == 1024 ||
1204 nextCode - 1 == 2048 ||
1205 nextCode - 1 == 4096) {
1206 outCodeBits = inCodeBits;
1209 // clear table if necessary
1220 int LZWStream::getCode() {
1224 while (inputBits < inCodeBits) {
1225 if ((c = str->getChar()) == EOF)
1227 inputBuf = (inputBuf << 8) | (c & 0xff);
1230 code = (inputBuf >> (inputBits - inCodeBits)) & ((1 << inCodeBits) - 1);
1231 inputBits -= inCodeBits;
1235 GBool LZWStream::fillBuf() {
1240 if ((n = fread(buf, 1, 256, zPipe)) < 256) {
1247 unlink(zName->getCString());
1255 GString *LZWStream::getPSFilter(char *indent) {
1261 if (!(s = str->getPSFilter(indent))) {
1264 s->append(indent)->append("/LZWDecode filter\n");
1268 GBool LZWStream::isBinary(GBool last) {
1269 return str->isBinary(gTrue);
1272 //------------------------------------------------------------------------
1274 //------------------------------------------------------------------------
1276 RunLengthStream::RunLengthStream(Stream *strA):
1277 FilterStream(strA) {
1278 bufPtr = bufEnd = buf;
1282 RunLengthStream::~RunLengthStream() {
1286 void RunLengthStream::reset() {
1288 bufPtr = bufEnd = buf;
1292 GString *RunLengthStream::getPSFilter(char *indent) {
1295 if (!(s = str->getPSFilter(indent))) {
1298 s->append(indent)->append("/RunLengthDecode filter\n");
1302 GBool RunLengthStream::isBinary(GBool last) {
1303 return str->isBinary(gTrue);
1306 GBool RunLengthStream::fillBuf() {
1313 if (c == 0x80 || c == EOF) {
1319 for (i = 0; i < n; ++i)
1320 buf[i] = (char)str->getChar();
1324 for (i = 0; i < n; ++i)
1332 //------------------------------------------------------------------------
1334 //------------------------------------------------------------------------
1336 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1337 GBool byteAlignA, int columnsA, int rowsA,
1338 GBool endOfBlockA, GBool blackA):
1339 FilterStream(strA) {
1340 encoding = encodingA;
1341 endOfLine = endOfLineA;
1342 byteAlign = byteAlignA;
1345 endOfBlock = endOfBlockA;
1347 refLine = (short *)gmalloc((columns + 3) * sizeof(short));
1348 codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
1352 nextLine2D = encoding < 0;
1355 codingLine[1] = refLine[2] = columns;
1361 CCITTFaxStream::~CCITTFaxStream() {
1367 void CCITTFaxStream::reset() {
1373 nextLine2D = encoding < 0;
1376 codingLine[1] = refLine[2] = columns;
1380 // get initial end-of-line marker and 2D encoding tag
1382 if (lookBits(12) == 0x001) {
1386 for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
1387 if (n == 11 && lookBits(12) == 0x001) {
1392 nextLine2D = !lookBits(1);
1397 int CCITTFaxStream::lookChar() {
1398 short code1, code2, code3;
1407 // if at eof just return EOF
1408 if (eof && codingLine[a0] >= columns) {
1412 // read the next row
1416 if (codingLine[a0] >= columns) {
1420 for (i = 0; codingLine[i] < columns; ++i)
1421 refLine[i] = codingLine[i];
1422 refLine[i] = refLine[i + 1] = columns;
1424 a0New = codingLine[a0 = 0] = 0;
1426 code1 = getTwoDimCode();
1429 if (refLine[b1] < columns) {
1430 a0New = refLine[b1 + 1];
1435 if ((a0 & 1) == 0) {
1438 code1 += code3 = getWhiteCode();
1439 } while (code3 >= 64);
1441 code2 += code3 = getBlackCode();
1442 } while (code3 >= 64);
1446 code1 += code3 = getBlackCode();
1447 } while (code3 >= 64);
1449 code2 += code3 = getWhiteCode();
1450 } while (code3 >= 64);
1452 codingLine[a0 + 1] = a0New + code1;
1454 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1456 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1460 a0New = codingLine[++a0] = refLine[b1];
1461 if (refLine[b1] < columns) {
1463 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1468 a0New = codingLine[++a0] = refLine[b1] + 1;
1469 if (refLine[b1] < columns) {
1471 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1476 a0New = codingLine[++a0] = refLine[b1] - 1;
1478 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1482 a0New = codingLine[++a0] = refLine[b1] + 2;
1483 if (refLine[b1] < columns) {
1485 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1490 a0New = codingLine[++a0] = refLine[b1] - 2;
1492 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1496 a0New = codingLine[++a0] = refLine[b1] + 3;
1497 if (refLine[b1] < columns) {
1499 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1504 a0New = codingLine[++a0] = refLine[b1] - 3;
1506 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1511 codingLine[a0 = 0] = columns;
1514 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1523 } while (codingLine[a0] < columns);
1527 codingLine[a0 = 0] = 0;
1531 code1 += code3 = getWhiteCode();
1532 } while (code3 >= 64);
1533 codingLine[a0+1] = codingLine[a0] + code1;
1535 if (codingLine[a0] >= columns)
1539 code2 += code3 = getBlackCode();
1540 } while (code3 >= 64);
1541 codingLine[a0+1] = codingLine[a0] + code2;
1543 if (codingLine[a0] >= columns)
1548 if (codingLine[a0] != columns) {
1549 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
1555 // byte-align the row
1560 // check for end-of-line marker, skipping over any extra zero bits
1562 if (!endOfBlock && row == rows - 1) {
1565 code1 = lookBits(12);
1566 while (code1 == 0) {
1568 code1 = lookBits(12);
1570 if (code1 == 0x001) {
1573 } else if (code1 == EOF) {
1578 // get 2D encoding tag
1579 if (!eof && encoding > 0) {
1580 nextLine2D = !lookBits(1);
1584 // check for end-of-block marker
1585 if (endOfBlock && gotEOL) {
1586 code1 = lookBits(12);
1587 if (code1 == 0x001) {
1593 if (encoding >= 0) {
1594 for (i = 0; i < 4; ++i) {
1595 code1 = lookBits(12);
1596 if (code1 != 0x001) {
1597 error(getPos(), "Bad RTC code in CCITTFax stream");
1611 // This looks for an end-of-line marker after an error, however
1612 // some (most?) CCITT streams in PDF files don't use end-of-line
1613 // markers, and the just-plow-on technique works better in those
1622 code1 = look13Bits();
1623 } while ((code1 >> 1) != 0x001);
1625 codingLine[++a0] = columns;
1628 nextLine2D = !(code1 & 1);
1634 outputBits = codingLine[1] - codingLine[0];
1635 if (outputBits == 0) {
1637 outputBits = codingLine[2] - codingLine[1];
1644 if (outputBits >= 8) {
1645 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1646 if ((outputBits -= 8) == 0) {
1648 if (codingLine[a0] < columns) {
1649 outputBits = codingLine[a0 + 1] - codingLine[a0];
1656 if (outputBits > bits) {
1659 if ((a0 & 1) == 0) {
1660 ret |= 0xff >> (8 - i);
1666 if ((a0 & 1) == 0) {
1667 ret |= (0xff >> (8 - i)) << bits;
1671 if (codingLine[a0] < columns) {
1672 outputBits = codingLine[a0 + 1] - codingLine[a0];
1675 } while (bits > 0 && codingLine[a0] < columns);
1677 buf = black ? (ret ^ 0xff) : ret;
1681 short CCITTFaxStream::getTwoDimCode() {
1686 code = 0; // make gcc happy
1689 p = &twoDimTab1[code];
1695 for (n = 1; n <= 7; ++n) {
1700 p = &twoDimTab1[code];
1707 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1711 short CCITTFaxStream::getWhiteCode() {
1716 code = 0; // make gcc happy
1718 code = lookBits(12);
1719 if ((code >> 5) == 0) {
1720 p = &whiteTab1[code];
1722 p = &whiteTab2[code >> 3];
1729 for (n = 1; n <= 9; ++n) {
1734 p = &whiteTab2[code];
1740 for (n = 11; n <= 12; ++n) {
1745 p = &whiteTab1[code];
1752 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1753 // eat a bit and return a positive number so that the caller doesn't
1754 // go into an infinite loop
1759 short CCITTFaxStream::getBlackCode() {
1764 code = 0; // make gcc happy
1766 code = lookBits(13);
1767 if ((code >> 7) == 0) {
1768 p = &blackTab1[code];
1769 } else if ((code >> 9) == 0) {
1770 p = &blackTab2[(code >> 1) - 64];
1772 p = &blackTab3[code >> 7];
1779 for (n = 2; n <= 6; ++n) {
1784 p = &blackTab3[code];
1790 for (n = 7; n <= 12; ++n) {
1796 p = &blackTab2[code - 64];
1803 for (n = 10; n <= 13; ++n) {
1808 p = &blackTab1[code];
1815 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
1816 // eat a bit and return a positive number so that the caller doesn't
1817 // go into an infinite loop
1822 short CCITTFaxStream::lookBits(int n) {
1825 while (inputBits < n) {
1826 if ((c = str->getChar()) == EOF) {
1827 if (inputBits == 0) {
1830 // near the end of the stream, the caller may ask for more bits
1831 // than are available, but there may still be a valid code in
1832 // however many bits are available -- we need to return correct
1833 // data in this case
1834 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
1836 inputBuf = (inputBuf << 8) + c;
1839 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1842 GString *CCITTFaxStream::getPSFilter(char *indent) {
1846 if (!(s = str->getPSFilter(indent))) {
1849 s->append(indent)->append("<< ");
1850 if (encoding != 0) {
1851 sprintf(s1, "/K %d ", encoding);
1855 s->append("/EndOfLine true ");
1858 s->append("/EncodedByteAlign true ");
1860 sprintf(s1, "/Columns %d ", columns);
1863 sprintf(s1, "/Rows %d ", rows);
1867 s->append("/EndOfBlock false ");
1870 s->append("/BlackIs1 true ");
1872 s->append(">> /CCITTFaxDecode filter\n");
1876 GBool CCITTFaxStream::isBinary(GBool last) {
1877 return str->isBinary(gTrue);
1880 //------------------------------------------------------------------------
1882 //------------------------------------------------------------------------
1884 // IDCT constants (20.12 fixed point format)
1886 #define dctCos1 4017 // cos(pi/16)
1887 #define dctSin1 799 // sin(pi/16)
1888 #define dctCos3 3406 // cos(3*pi/16)
1889 #define dctSin3 2276 // sin(3*pi/16)
1890 #define dctCos6 1567 // cos(6*pi/16)
1891 #define dctSin6 3784 // sin(6*pi/16)
1892 #define dctSqrt2 5793 // sqrt(2)
1893 #define dctSqrt1d2 2896 // sqrt(2) / 2
1898 #define dctCos1 0.98078528 // cos(pi/16)
1899 #define dctSin1 0.19509032 // sin(pi/16)
1900 #define dctCos3 0.83146961 // cos(3*pi/16)
1901 #define dctSin3 0.55557023 // sin(3*pi/16)
1902 #define dctCos6 0.38268343 // cos(6*pi/16)
1903 #define dctSin6 0.92387953 // sin(6*pi/16)
1904 #define dctSqrt2 1.41421356 // sqrt(2)
1905 #define dctSqrt1d2 0.70710678 // sqrt(2) / 2
1908 // color conversion parameters (16.16 fixed point format)
1909 #define dctCrToR 91881 // 1.4020
1910 #define dctCbToG -22553 // -0.3441363
1911 #define dctCrToG -46802 // -0.71413636
1912 #define dctCbToB 116130 // 1.772
1914 // clip [-256,511] --> [0,255]
1915 #define dctClipOffset 256
1916 static Guchar dctClip[768];
1917 static int dctClipInit = 0;
1919 // zig zag decode map
1920 static int dctZigZag[64] = {
1926 5, 12, 19, 26, 33, 40,
1927 48, 41, 34, 27, 20, 13, 6,
1928 7, 14, 21, 28, 35, 42, 49, 56,
1929 57, 50, 43, 36, 29, 22, 15,
1930 23, 30, 37, 44, 51, 58,
1938 DCTStream::DCTStream(Stream *strA):
1939 FilterStream(strA) {
1943 mcuWidth = mcuHeight = 0;
1947 for (i = 0; i < 4; ++i)
1948 for (j = 0; j < 32; ++j)
1949 rowBuf[i][j] = NULL;
1952 for (i = -256; i < 0; ++i)
1953 dctClip[dctClipOffset + i] = 0;
1954 for (i = 0; i < 256; ++i)
1955 dctClip[dctClipOffset + i] = i;
1956 for (i = 256; i < 512; ++i)
1957 dctClip[dctClipOffset + i] = 255;
1962 DCTStream::~DCTStream() {
1966 for (i = 0; i < numComps; ++i)
1967 for (j = 0; j < mcuHeight; ++j)
1968 gfree(rowBuf[i][j]);
1971 void DCTStream::reset() {
1973 if (!readHeader()) {
1977 restartMarker = 0xd0;
1981 int DCTStream::getChar() {
1987 if (++comp == numComps) {
2000 int DCTStream::lookChar() {
2003 if (dy >= mcuHeight) {
2004 if (!readMCURow()) {
2012 return rowBuf[comp][dy][x];
2015 void DCTStream::restart() {
2019 restartCtr = restartInterval;
2020 for (i = 0; i < numComps; ++i)
2021 compInfo[i].prevDC = 0;
2024 GBool DCTStream::readMCURow() {
2027 int pY, pCb, pCr, pR, pG, pB;
2028 int h, v, horiz, vert, hSub, vSub;
2029 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2032 for (x1 = 0; x1 < width; x1 += mcuWidth) {
2034 // deal with restart marker
2035 if (restartInterval > 0 && restartCtr == 0) {
2037 if (c != restartMarker) {
2038 error(getPos(), "Bad DCT data: incorrect restart marker");
2041 if (++restartMarker == 0xd8)
2042 restartMarker = 0xd0;
2047 for (cc = 0; cc < numComps; ++cc) {
2048 h = compInfo[cc].hSample;
2049 v = compInfo[cc].vSample;
2050 horiz = mcuWidth / h;
2051 vert = mcuHeight / v;
2054 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2055 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2056 if (!readDataUnit(&dcHuffTables[compInfo[cc].dcHuffTable],
2057 &acHuffTables[compInfo[cc].acHuffTable],
2058 quantTables[compInfo[cc].quantTable],
2059 &compInfo[cc].prevDC,
2062 if (hSub == 1 && vSub == 1) {
2063 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2064 p1 = &rowBuf[cc][y2+y3][x1+x2];
2074 } else if (hSub == 2 && vSub == 2) {
2075 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2076 p1 = &rowBuf[cc][y2+y3][x1+x2];
2077 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
2078 p1[0] = p1[1] = p2[0] = p2[1] = data[i];
2079 p1[2] = p1[3] = p2[2] = p2[3] = data[i+1];
2080 p1[4] = p1[5] = p2[4] = p2[5] = data[i+2];
2081 p1[6] = p1[7] = p2[6] = p2[7] = data[i+3];
2082 p1[8] = p1[9] = p2[8] = p2[9] = data[i+4];
2083 p1[10] = p1[11] = p2[10] = p2[11] = data[i+5];
2084 p1[12] = p1[13] = p2[12] = p2[13] = data[i+6];
2085 p1[14] = p1[15] = p2[14] = p2[15] = data[i+7];
2089 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2090 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2091 for (y5 = 0; y5 < vSub; ++y5)
2092 for (x5 = 0; x5 < hSub; ++x5)
2093 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data[i];
2103 // color space conversion
2105 // convert YCbCr to RGB
2106 if (numComps == 3) {
2107 for (y2 = 0; y2 < mcuHeight; ++y2) {
2108 for (x2 = 0; x2 < mcuWidth; ++x2) {
2109 pY = rowBuf[0][y2][x1+x2];
2110 pCb = rowBuf[1][y2][x1+x2] - 128;
2111 pCr = rowBuf[2][y2][x1+x2] - 128;
2112 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2113 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
2114 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2115 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
2116 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2117 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
2120 // convert YCbCrK to CMYK (K is passed through unchanged)
2121 } else if (numComps == 4) {
2122 for (y2 = 0; y2 < mcuHeight; ++y2) {
2123 for (x2 = 0; x2 < mcuWidth; ++x2) {
2124 pY = rowBuf[0][y2][x1+x2];
2125 pCb = rowBuf[1][y2][x1+x2] - 128;
2126 pCr = rowBuf[2][y2][x1+x2] - 128;
2127 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2128 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2129 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2130 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2131 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2132 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2141 // This IDCT algorithm is taken from:
2142 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2143 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2144 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2146 // The stage numbers mentioned in the comments refer to Figure 1 in this
2149 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2150 DCTHuffTable *acHuffTable,
2151 Guchar quantTable[64], int *prevDC,
2154 int v0, v1, v2, v3, v4, v5, v6, v7, t;
2159 // Huffman decode and dequantize
2160 size = readHuffSym(dcHuffTable);
2164 amp = readAmp(size);
2170 tmp1[0] = (*prevDC += amp) * quantTable[0];
2171 for (i = 1; i < 64; ++i)
2176 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
2183 run += (c >> 4) & 0x0f;
2185 amp = readAmp(size);
2190 tmp1[j] = amp * quantTable[j];
2194 // inverse DCT on rows
2195 for (i = 0; i < 64; i += 8) {
2198 v0 = (dctSqrt2 * tmp1[i+0] + 128) >> 8;
2199 v1 = (dctSqrt2 * tmp1[i+4] + 128) >> 8;
2202 v4 = (dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]) + 128) >> 8;
2203 v7 = (dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]) + 128) >> 8;
2204 v5 = tmp1[i+3] << 4;
2205 v6 = tmp1[i+5] << 4;
2208 t = (v0 - v1+ 1) >> 1;
2209 v0 = (v0 + v1 + 1) >> 1;
2211 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2212 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2214 t = (v4 - v6 + 1) >> 1;
2215 v4 = (v4 + v6 + 1) >> 1;
2217 t = (v7 + v5 + 1) >> 1;
2218 v5 = (v7 - v5 + 1) >> 1;
2222 t = (v0 - v3 + 1) >> 1;
2223 v0 = (v0 + v3 + 1) >> 1;
2225 t = (v1 - v2 + 1) >> 1;
2226 v1 = (v1 + v2 + 1) >> 1;
2228 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2229 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2231 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2232 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2236 tmp1[i+0] = v0 + v7;
2237 tmp1[i+7] = v0 - v7;
2238 tmp1[i+1] = v1 + v6;
2239 tmp1[i+6] = v1 - v6;
2240 tmp1[i+2] = v2 + v5;
2241 tmp1[i+5] = v2 - v5;
2242 tmp1[i+3] = v3 + v4;
2243 tmp1[i+4] = v3 - v4;
2246 // inverse DCT on columns
2247 for (i = 0; i < 8; ++i) {
2250 v0 = (dctSqrt2 * tmp1[0*8+i] + 2048) >> 12;
2251 v1 = (dctSqrt2 * tmp1[4*8+i] + 2048) >> 12;
2254 v4 = (dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]) + 2048) >> 12;
2255 v7 = (dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]) + 2048) >> 12;
2260 t = (v0 - v1 + 1) >> 1;
2261 v0 = (v0 + v1 + 1) >> 1;
2263 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2264 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2266 t = (v4 - v6 + 1) >> 1;
2267 v4 = (v4 + v6 + 1) >> 1;
2269 t = (v7 + v5 + 1) >> 1;
2270 v5 = (v7 - v5 + 1) >> 1;
2274 t = (v0 - v3 + 1) >> 1;
2275 v0 = (v0 + v3 + 1) >> 1;
2277 t = (v1 - v2 + 1) >> 1;
2278 v1 = (v1 + v2 + 1) >> 1;
2280 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2281 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2283 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2284 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2288 tmp1[0*8+i] = v0 + v7;
2289 tmp1[7*8+i] = v0 - v7;
2290 tmp1[1*8+i] = v1 + v6;
2291 tmp1[6*8+i] = v1 - v6;
2292 tmp1[2*8+i] = v2 + v5;
2293 tmp1[5*8+i] = v2 - v5;
2294 tmp1[3*8+i] = v3 + v4;
2295 tmp1[4*8+i] = v3 - v4;
2298 // convert to 8-bit integers
2299 for (i = 0; i < 64; ++i)
2300 data[i] = dctClip[dctClipOffset + 128 + ((tmp1[i] + 8) >> 4)];
2307 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2308 DCTHuffTable *acHuffTable,
2309 Guchar quantTable[64], int *prevDC,
2312 double v0, v1, v2, v3, v4, v5, v6, v7, t;
2317 // Huffman decode and dequantize
2318 size = readHuffSym(dcHuffTable);
2322 amp = readAmp(size);
2328 tmp1[0] = (*prevDC += amp) * quantTable[0];
2329 for (i = 1; i < 64; ++i)
2334 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
2341 run += (c >> 4) & 0x0f;
2343 amp = readAmp(size);
2348 tmp1[j] = amp * quantTable[j];
2352 // inverse DCT on rows
2353 for (i = 0; i < 64; i += 8) {
2356 v0 = dctSqrt2 * tmp1[i+0];
2357 v1 = dctSqrt2 * tmp1[i+4];
2360 v4 = dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]);
2361 v7 = dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]);
2366 t = 0.5 * (v0 - v1);
2367 v0 = 0.5 * (v0 + v1);
2369 t = v2 * dctSin6 + v3 * dctCos6;
2370 v2 = v2 * dctCos6 - v3 * dctSin6;
2372 t = 0.5 * (v4 - v6);
2373 v4 = 0.5 * (v4 + v6);
2375 t = 0.5 * (v7 + v5);
2376 v5 = 0.5 * (v7 - v5);
2380 t = 0.5 * (v0 - v3);
2381 v0 = 0.5 * (v0 + v3);
2383 t = 0.5 * (v1 - v2);
2384 v1 = 0.5 * (v1 + v2);
2386 t = v4 * dctSin3 + v7 * dctCos3;
2387 v4 = v4 * dctCos3 - v7 * dctSin3;
2389 t = v5 * dctSin1 + v6 * dctCos1;
2390 v5 = v5 * dctCos1 - v6 * dctSin1;
2394 tmp1[i+0] = v0 + v7;
2395 tmp1[i+7] = v0 - v7;
2396 tmp1[i+1] = v1 + v6;
2397 tmp1[i+6] = v1 - v6;
2398 tmp1[i+2] = v2 + v5;
2399 tmp1[i+5] = v2 - v5;
2400 tmp1[i+3] = v3 + v4;
2401 tmp1[i+4] = v3 - v4;
2404 // inverse DCT on columns
2405 for (i = 0; i < 8; ++i) {
2408 v0 = dctSqrt2 * tmp1[0*8+i];
2409 v1 = dctSqrt2 * tmp1[4*8+i];
2412 v4 = dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]);
2413 v7 = dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]);
2418 t = 0.5 * (v0 - v1);
2419 v0 = 0.5 * (v0 + v1);
2421 t = v2 * dctSin6 + v3 * dctCos6;
2422 v2 = v2 * dctCos6 - v3 * dctSin6;
2424 t = 0.5 * (v4 - v6);
2425 v4 = 0.5 * (v4 + v6);
2427 t = 0.5 * (v7 + v5);
2428 v5 = 0.5 * (v7 - v5);
2432 t = 0.5 * (v0 - v3);
2433 v0 = 0.5 * (v0 + v3);
2435 t = 0.5 * (v1 - v2);
2436 v1 = 0.5 * (v1 + v2);
2438 t = v4 * dctSin3 + v7 * dctCos3;
2439 v4 = v4 * dctCos3 - v7 * dctSin3;
2441 t = v5 * dctSin1 + v6 * dctCos1;
2442 v5 = v5 * dctCos1 - v6 * dctSin1;
2446 tmp1[0*8+i] = v0 + v7;
2447 tmp1[7*8+i] = v0 - v7;
2448 tmp1[1*8+i] = v1 + v6;
2449 tmp1[6*8+i] = v1 - v6;
2450 tmp1[2*8+i] = v2 + v5;
2451 tmp1[5*8+i] = v2 - v5;
2452 tmp1[3*8+i] = v3 + v4;
2453 tmp1[4*8+i] = v3 - v4;
2456 // convert to 8-bit integers
2457 for (i = 0; i < 64; ++i)
2458 data[i] = dctClip[dctClipOffset + (int)(tmp1[i] + 128.5)];
2464 int DCTStream::readHuffSym(DCTHuffTable *table) {
2472 // add a bit to the code
2473 if ((bit = readBit()) == EOF)
2475 code = (code << 1) + bit;
2479 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2480 code -= table->firstCode[codeBits];
2481 return table->sym[table->firstSym[codeBits] + code];
2483 } while (codeBits < 16);
2485 error(getPos(), "Bad Huffman code in DCT stream");
2489 int DCTStream::readAmp(int size) {
2494 for (bits = 0; bits < size; ++bits) {
2495 if ((bit = readBit()) == EOF)
2497 amp = (amp << 1) + bit;
2499 if (amp < (1 << (size - 1)))
2500 amp -= (1 << size) - 1;
2504 int DCTStream::readBit() {
2508 if (inputBits == 0) {
2509 if ((c = str->getChar()) == EOF)
2513 c2 = str->getChar();
2514 } while (c2 == 0xff);
2516 error(getPos(), "Bad DCT data: missing 00 after ff");
2523 bit = (inputBuf >> (inputBits - 1)) & 1;
2528 GBool DCTStream::readHeader() {
2530 int minHSample, minVSample;
2539 numDCHuffTables = 0;
2540 numACHuffTables = 0;
2542 gotAdobeMarker = gFalse;
2543 restartInterval = 0;
2551 if (!readFrameInfo())
2555 if (!readHuffmanTables())
2561 if (!readScanInfo())
2566 if (!readQuantTables())
2570 if (!readRestartInterval())
2574 if (!readAdobeMarker())
2578 error(getPos(), "Bad DCT header");
2581 // skip APPn / COM / etc.
2584 for (i = 0; i < n; ++i)
2587 error(getPos(), "Unknown DCT marker <%02x>", c);
2595 mcuWidth = minHSample = compInfo[0].hSample;
2596 mcuHeight = minVSample = compInfo[0].vSample;
2597 for (i = 1; i < numComps; ++i) {
2598 if (compInfo[i].hSample < minHSample)
2599 minHSample = compInfo[i].hSample;
2600 if (compInfo[i].vSample < minVSample)
2601 minVSample = compInfo[i].vSample;
2602 if (compInfo[i].hSample > mcuWidth)
2603 mcuWidth = compInfo[i].hSample;
2604 if (compInfo[i].vSample > mcuHeight)
2605 mcuHeight = compInfo[i].vSample;
2607 for (i = 0; i < numComps; ++i) {
2608 compInfo[i].hSample /= minHSample;
2609 compInfo[i].vSample /= minVSample;
2611 mcuWidth = (mcuWidth / minHSample) * 8;
2612 mcuHeight = (mcuHeight / minVSample) * 8;
2615 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
2616 for (i = 0; i < numComps; ++i)
2617 for (j = 0; j < mcuHeight; ++j)
2618 rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
2620 // figure out color transform
2621 if (!gotAdobeMarker && numComps == 3) {
2622 if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
2627 // initialize counters
2636 GBool DCTStream::readFrameInfo() {
2642 length = read16() - 2;
2643 prec = str->getChar();
2646 numComps = str->getChar();
2649 error(getPos(), "Bad DCT precision %d", prec);
2652 for (i = 0; i < numComps; ++i) {
2653 compInfo[i].id = str->getChar();
2654 compInfo[i].inScan = gFalse;
2656 compInfo[i].hSample = (c >> 4) & 0x0f;
2657 compInfo[i].vSample = c & 0x0f;
2658 compInfo[i].quantTable = str->getChar();
2659 compInfo[i].dcHuffTable = 0;
2660 compInfo[i].acHuffTable = 0;
2665 GBool DCTStream::readScanInfo() {
2667 int scanComps, id, c;
2670 length = read16() - 2;
2671 scanComps = str->getChar();
2673 if (length != 2 * scanComps + 3) {
2674 error(getPos(), "Bad DCT scan info block");
2677 for (i = 0; i < scanComps; ++i) {
2678 id = str->getChar();
2679 for (j = 0; j < numComps; ++j) {
2680 if (id == compInfo[j].id)
2683 if (j == numComps) {
2684 error(getPos(), "Bad DCT component ID in scan info block");
2687 compInfo[j].inScan = gTrue;
2689 compInfo[j].dcHuffTable = (c >> 4) & 0x0f;
2690 compInfo[j].acHuffTable = c & 0x0f;
2698 GBool DCTStream::readQuantTables() {
2703 length = read16() - 2;
2704 while (length > 0) {
2705 index = str->getChar();
2706 if ((index & 0xf0) || index >= 4) {
2707 error(getPos(), "Bad DCT quantization table");
2710 if (index == numQuantTables)
2711 numQuantTables = index + 1;
2712 for (i = 0; i < 64; ++i)
2713 quantTables[index][dctZigZag[i]] = str->getChar();
2719 GBool DCTStream::readHuffmanTables() {
2728 length = read16() - 2;
2729 while (length > 0) {
2730 index = str->getChar();
2732 if ((index & 0x0f) >= 4) {
2733 error(getPos(), "Bad DCT Huffman table");
2738 if (index >= numACHuffTables)
2739 numACHuffTables = index+1;
2740 tbl = &acHuffTables[index];
2742 if (index >= numDCHuffTables)
2743 numDCHuffTables = index+1;
2744 tbl = &dcHuffTables[index];
2748 for (i = 1; i <= 16; ++i) {
2750 tbl->firstSym[i] = sym;
2751 tbl->firstCode[i] = code;
2752 tbl->numCodes[i] = c;
2754 code = (code + c) << 1;
2757 for (i = 0; i < sym; ++i)
2758 tbl->sym[i] = str->getChar();
2764 GBool DCTStream::readRestartInterval() {
2769 error(getPos(), "Bad DCT restart interval");
2772 restartInterval = read16();
2776 GBool DCTStream::readAdobeMarker() {
2784 for (i = 0; i < 12; ++i) {
2785 if ((c = str->getChar()) == EOF)
2789 if (strncmp(buf, "Adobe", 5))
2791 colorXform = buf[11];
2792 gotAdobeMarker = gTrue;
2796 error(getPos(), "Bad DCT Adobe APP14 marker");
2800 GBool DCTStream::readTrailer() {
2804 if (c != 0xd9) { // EOI
2805 error(getPos(), "Bad DCT trailer");
2811 int DCTStream::readMarker() {
2817 } while (c != 0xff);
2820 } while (c == 0xff);
2821 } while (c == 0x00);
2825 int DCTStream::read16() {
2828 if ((c1 = str->getChar()) == EOF)
2830 if ((c2 = str->getChar()) == EOF)
2832 return (c1 << 8) + c2;
2835 GString *DCTStream::getPSFilter(char *indent) {
2838 if (!(s = str->getPSFilter(indent))) {
2841 s->append(indent)->append("<< >> /DCTDecode filter\n");
2845 GBool DCTStream::isBinary(GBool last) {
2846 return str->isBinary(gTrue);
2849 //------------------------------------------------------------------------
2851 //------------------------------------------------------------------------
2853 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
2854 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
2857 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
2889 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
2922 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
2923 int colors, int bits):
2924 FilterStream(strA) {
2925 if (predictor != 1) {
2926 pred = new StreamPredictor(this, predictor, columns, colors, bits);
2932 FlateStream::~FlateStream() {
2939 void FlateStream::reset() {
2946 compressedBlock = gFalse;
2953 //~ need to look at window size?
2954 endOfBlock = eof = gTrue;
2955 cmf = str->getChar();
2956 flg = str->getChar();
2957 if (cmf == EOF || flg == EOF)
2959 if ((cmf & 0x0f) != 0x08) {
2960 error(getPos(), "Unknown compression method in flate stream");
2963 if ((((cmf << 8) + flg) % 31) != 0) {
2964 error(getPos(), "Bad FCHECK in flate stream");
2968 error(getPos(), "FDICT bit set in flate stream");
2975 int FlateStream::getChar() {
2979 return pred->getChar();
2981 while (remain == 0) {
2982 if (endOfBlock && eof)
2987 index = (index + 1) & flateMask;
2992 int FlateStream::lookChar() {
2996 return pred->lookChar();
2998 while (remain == 0) {
2999 if (endOfBlock && eof)
3007 int FlateStream::getRawChar() {
3010 while (remain == 0) {
3011 if (endOfBlock && eof)
3016 index = (index + 1) & flateMask;
3021 GString *FlateStream::getPSFilter(char *indent) {
3025 GBool FlateStream::isBinary(GBool last) {
3026 return str->isBinary(gTrue);
3029 void FlateStream::readSome() {
3040 if (compressedBlock) {
3041 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
3046 } else if (code1 == 256) {
3051 code2 = lengthDecode[code1].bits;
3052 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3054 len = lengthDecode[code1].first + code2;
3055 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
3057 code2 = distDecode[code1].bits;
3058 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3060 dist = distDecode[code1].first + code2;
3062 j = (index - dist) & flateMask;
3063 for (k = 0; k < len; ++k) {
3065 i = (i + 1) & flateMask;
3066 j = (j + 1) & flateMask;
3072 len = (blockLen < flateWindow) ? blockLen : flateWindow;
3073 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
3074 if ((c = str->getChar()) == EOF) {
3075 endOfBlock = eof = gTrue;
3089 error(getPos(), "Unexpected end of file in flate stream");
3090 endOfBlock = eof = gTrue;
3094 GBool FlateStream::startBlock() {
3099 // read block header
3100 blockHdr = getCodeWord(3);
3105 // uncompressed block
3106 if (blockHdr == 0) {
3107 compressedBlock = gFalse;
3108 if ((c = str->getChar()) == EOF)
3110 blockLen = c & 0xff;
3111 if ((c = str->getChar()) == EOF)
3113 blockLen |= (c & 0xff) << 8;
3114 if ((c = str->getChar()) == EOF)
3117 if ((c = str->getChar()) == EOF)
3119 check |= (c & 0xff) << 8;
3120 if (check != (~blockLen & 0xffff))
3121 error(getPos(), "Bad uncompressed block length in flate stream");
3125 // compressed block with fixed codes
3126 } else if (blockHdr == 1) {
3127 compressedBlock = gTrue;
3130 // compressed block with dynamic codes
3131 } else if (blockHdr == 2) {
3132 compressedBlock = gTrue;
3133 if (!readDynamicCodes())
3136 // unknown block type
3141 endOfBlock = gFalse;
3145 error(getPos(), "Bad block header in flate stream");
3146 endOfBlock = eof = gTrue;
3150 void FlateStream::loadFixedCodes() {
3153 // set up code arrays
3154 litCodeTab.codes = allCodes;
3155 distCodeTab.codes = allCodes + flateMaxLitCodes;
3157 // initialize literal code table
3158 for (i = 0; i <= 143; ++i)
3159 litCodeTab.codes[i].len = 8;
3160 for (i = 144; i <= 255; ++i)
3161 litCodeTab.codes[i].len = 9;
3162 for (i = 256; i <= 279; ++i)
3163 litCodeTab.codes[i].len = 7;
3164 for (i = 280; i <= 287; ++i)
3165 litCodeTab.codes[i].len = 8;
3166 compHuffmanCodes(&litCodeTab, flateMaxLitCodes);
3168 // initialize distance code table
3169 for (i = 0; i <= 5; ++i) {
3170 distCodeTab.start[i] = 0;
3172 for (i = 6; i <= flateMaxHuffman+1; ++i) {
3173 distCodeTab.start[i] = flateMaxDistCodes;
3175 for (i = 0; i < flateMaxDistCodes; ++i) {
3176 distCodeTab.codes[i].len = 5;
3177 distCodeTab.codes[i].code = i;
3178 distCodeTab.codes[i].val = i;
3182 GBool FlateStream::readDynamicCodes() {
3183 int numCodeLenCodes;
3186 FlateCode codeLenCodes[flateMaxCodeLenCodes];
3187 FlateHuffmanTab codeLenCodeTab;
3188 int len, repeat, code;
3192 if ((numLitCodes = getCodeWord(5)) == EOF)
3195 if ((numDistCodes = getCodeWord(5)) == EOF)
3198 if ((numCodeLenCodes = getCodeWord(4)) == EOF)
3200 numCodeLenCodes += 4;
3201 if (numLitCodes > flateMaxLitCodes ||
3202 numDistCodes > flateMaxDistCodes ||
3203 numCodeLenCodes > flateMaxCodeLenCodes)
3206 // read code length code table
3207 codeLenCodeTab.codes = codeLenCodes;
3208 for (i = 0; i < flateMaxCodeLenCodes; ++i)
3209 codeLenCodes[i].len = 0;
3210 for (i = 0; i < numCodeLenCodes; ++i) {
3211 if ((codeLenCodes[codeLenCodeMap[i]].len = getCodeWord(3)) == -1)
3214 compHuffmanCodes(&codeLenCodeTab, flateMaxCodeLenCodes);
3216 // set up code arrays
3217 litCodeTab.codes = allCodes;
3218 distCodeTab.codes = allCodes + numLitCodes;
3220 // read literal and distance code tables
3224 while (i < numLitCodes + numDistCodes) {
3225 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF)
3228 if ((repeat = getCodeWord(2)) == EOF)
3230 for (repeat += 3; repeat > 0; --repeat)
3231 allCodes[i++].len = len;
3232 } else if (code == 17) {
3233 if ((repeat = getCodeWord(3)) == EOF)
3236 for (repeat += 3; repeat > 0; --repeat)
3237 allCodes[i++].len = 0;
3238 } else if (code == 18) {
3239 if ((repeat = getCodeWord(7)) == EOF)
3242 for (repeat += 11; repeat > 0; --repeat)
3243 allCodes[i++].len = 0;
3245 allCodes[i++].len = len = code;
3248 compHuffmanCodes(&litCodeTab, numLitCodes);
3249 compHuffmanCodes(&distCodeTab, numDistCodes);
3254 error(getPos(), "Bad dynamic code table in flate stream");
3258 // On entry, the <tab->codes> array contains the lengths of each code,
3259 // stored in code value order. This function computes the code words.
3260 // The result is sorted in order of (1) code length and (2) code word.
3261 // The length values are no longer valid. The <tab->start> array is
3262 // filled with the indexes of the first code of each length.
3263 void FlateStream::compHuffmanCodes(FlateHuffmanTab *tab, int n) {
3264 int numLengths[flateMaxHuffman+1];
3265 int nextCode[flateMaxHuffman+1];
3266 int nextIndex[flateMaxHuffman+2];
3270 // count number of codes for each code length
3271 for (i = 0; i <= flateMaxHuffman; ++i)
3273 for (i = 0; i < n; ++i)
3274 ++numLengths[tab->codes[i].len];
3276 // compute first index for each length
3277 tab->start[0] = nextIndex[0] = 0;
3278 for (i = 1; i <= flateMaxHuffman + 1; ++i)
3279 tab->start[i] = nextIndex[i] = tab->start[i-1] + numLengths[i-1];
3281 // compute first code for each length
3284 for (i = 1; i <= flateMaxHuffman; ++i) {
3285 code = (code + numLengths[i-1]) << 1;
3289 // compute the codes -- this permutes the codes array from value
3290 // order to length/code order
3291 for (i = 0; i < n; ++i) {
3292 j = nextIndex[tab->codes[i].len]++;
3293 if (tab->codes[i].len == 0)
3294 tab->codes[j].code = 0;
3296 tab->codes[j].code = nextCode[tab->codes[i].len]++;
3297 tab->codes[j].val = i;
3301 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
3308 for (len = 1; len <= flateMaxHuffman; ++len) {
3310 // add a bit to the code
3311 if (codeSize == 0) {
3312 if ((c = str->getChar()) == EOF)
3317 code = (code << 1) | (codeBuf & 1);
3322 i = tab->start[len];
3323 j = tab->start[len + 1];
3324 if (i < j && code >= tab->codes[i].code && code <= tab->codes[j-1].code) {
3325 i += code - tab->codes[i].code;
3326 return tab->codes[i].val;
3331 error(getPos(), "Bad code (%04x) in flate stream", code);
3335 int FlateStream::getCodeWord(int bits) {
3338 while (codeSize < bits) {
3339 if ((c = str->getChar()) == EOF)
3341 codeBuf |= (c & 0xff) << codeSize;
3344 c = codeBuf & ((1 << bits) - 1);
3350 //------------------------------------------------------------------------
3352 //------------------------------------------------------------------------
3354 EOFStream::EOFStream(Stream *strA):
3355 FilterStream(strA) {
3358 EOFStream::~EOFStream() {
3362 //------------------------------------------------------------------------
3363 // FixedLengthEncoder
3364 //------------------------------------------------------------------------
3366 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
3367 FilterStream(strA) {
3372 FixedLengthEncoder::~FixedLengthEncoder() {
3373 if (str->isEncoder())
3377 void FixedLengthEncoder::reset() {
3382 void FixedLengthEncoder::close() {
3385 int FixedLengthEncoder::getChar() {
3386 if (length >= 0 && count >= length)
3389 return str->getChar();
3392 int FixedLengthEncoder::lookChar() {
3393 if (length >= 0 && count >= length)
3395 return str->getChar();
3398 //------------------------------------------------------------------------
3400 //------------------------------------------------------------------------
3402 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
3403 FilterStream(strA) {
3404 bufPtr = bufEnd = buf;
3409 ASCIIHexEncoder::~ASCIIHexEncoder() {
3410 if (str->isEncoder()) {
3415 void ASCIIHexEncoder::reset() {
3417 bufPtr = bufEnd = buf;
3422 void ASCIIHexEncoder::close() {
3425 GBool ASCIIHexEncoder::fillBuf() {
3426 static char *hex = "0123456789abcdef";
3432 bufPtr = bufEnd = buf;
3433 if ((c = str->getChar()) == EOF) {
3437 if (lineLen >= 64) {
3441 *bufEnd++ = hex[(c >> 4) & 0x0f];
3442 *bufEnd++ = hex[c & 0x0f];
3448 //------------------------------------------------------------------------
3450 //------------------------------------------------------------------------
3452 ASCII85Encoder::ASCII85Encoder(Stream *strA):
3453 FilterStream(strA) {
3454 bufPtr = bufEnd = buf;
3459 ASCII85Encoder::~ASCII85Encoder() {
3460 if (str->isEncoder())
3464 void ASCII85Encoder::reset() {
3466 bufPtr = bufEnd = buf;
3471 void ASCII85Encoder::close() {
3474 GBool ASCII85Encoder::fillBuf() {
3483 for (n = 0; n < 4; ++n) {
3484 if ((c = str->getChar()) == EOF)
3488 bufPtr = bufEnd = buf;
3490 if (n == 4 && t == 0) {
3492 if (++lineLen == 65) {
3499 for (i = 4; i >= 0; --i) {
3500 buf1[i] = (char)(t % 85 + 0x21);
3503 for (i = 0; i <= n; ++i) {
3504 *bufEnd++ = buf1[i];
3505 if (++lineLen == 65) {
3517 return bufPtr < bufEnd;
3520 //------------------------------------------------------------------------
3522 //------------------------------------------------------------------------
3524 RunLengthEncoder::RunLengthEncoder(Stream *strA):
3525 FilterStream(strA) {
3526 bufPtr = bufEnd = nextEnd = buf;
3530 RunLengthEncoder::~RunLengthEncoder() {
3531 if (str->isEncoder())
3535 void RunLengthEncoder::reset() {
3537 bufPtr = bufEnd = nextEnd = buf;
3541 void RunLengthEncoder::close() {
3545 // When fillBuf finishes, buf[] looks like this:
3546 // +-----+--------------+-----------------+--
3547 // + tag | ... data ... | next 0, 1, or 2 |
3548 // +-----+--------------+-----------------+--
3550 // bufPtr bufEnd nextEnd
3552 GBool RunLengthEncoder::fillBuf() {
3561 if (nextEnd < bufEnd + 1) {
3562 if ((c1 = str->getChar()) == EOF) {
3567 c1 = bufEnd[0] & 0xff;
3569 if (nextEnd < bufEnd + 2) {
3570 if ((c2 = str->getChar()) == EOF) {
3579 c2 = bufEnd[1] & 0xff;
3583 c = 0; // make gcc happy
3586 while (n < 128 && (c = str->getChar()) == c1)
3588 buf[0] = (char)(257 - n);
3593 } else if (n < 128) {
3600 // get up to 128 chars
3606 if ((c = str->getChar()) == EOF) {
3612 if (buf[n] == buf[n-1])
3615 if (buf[n] == buf[n-1]) {
3616 buf[0] = (char)(n-2-1);
3618 nextEnd = &buf[n+1];
3620 buf[0] = (char)(n-1);
3621 bufEnd = nextEnd = &buf[n+1];