1 //========================================================================
5 // Copyright 1996-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
32 #include "JBIG2Stream.h"
33 #include "Stream-CCITT.h"
36 static GBool setDJSYSFLAGS = gFalse;
47 //------------------------------------------------------------------------
48 // Stream (base class)
49 //------------------------------------------------------------------------
58 void Stream::close() {
61 int Stream::getRawChar() {
62 error(-1, "Internal: called getRawChar() on non-predictor stream");
66 char *Stream::getLine(char *buf, int size) {
70 if (lookChar() == EOF)
72 for (i = 0; i < size - 1; ++i) {
74 if (c == EOF || c == '\n')
77 if ((c = lookChar()) == '\n')
87 GString *Stream::getPSFilter(char *indent) {
91 Stream *Stream::addFilters(Object *dict) {
93 Object params, params2;
98 dict->dictLookup("Filter", &obj);
101 dict->dictLookup("F", &obj);
103 dict->dictLookup("DecodeParms", ¶ms);
104 if (params.isNull()) {
106 dict->dictLookup("DP", ¶ms);
109 str = makeFilter(obj.getName(), str, ¶ms);
110 } else if (obj.isArray()) {
111 for (i = 0; i < obj.arrayGetLength(); ++i) {
112 obj.arrayGet(i, &obj2);
113 if (params.isArray())
114 params.arrayGet(i, ¶ms2);
118 str = makeFilter(obj2.getName(), str, ¶ms2);
120 error(getPos(), "Bad filter name");
121 str = new EOFStream(str);
126 } else if (!obj.isNull()) {
127 error(getPos(), "Bad 'Filter' attribute in stream");
135 Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
136 int pred; // parameters
141 GBool endOfLine, byteAlign, endOfBlock, black;
145 if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
146 str = new ASCIIHexStream(str);
147 } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
148 str = new ASCII85Stream(str);
149 } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
155 if (params->isDict()) {
156 params->dictLookup("Predictor", &obj);
160 params->dictLookup("Columns", &obj);
162 columns = obj.getInt();
164 params->dictLookup("Colors", &obj);
166 colors = obj.getInt();
168 params->dictLookup("BitsPerComponent", &obj);
172 params->dictLookup("EarlyChange", &obj);
174 early = obj.getInt();
177 str = new LZWStream(str, pred, columns, colors, bits, early);
178 } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
179 str = new RunLengthStream(str);
180 } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
188 if (params->isDict()) {
189 params->dictLookup("K", &obj);
191 encoding = obj.getInt();
194 params->dictLookup("EndOfLine", &obj);
196 endOfLine = obj.getBool();
199 params->dictLookup("EncodedByteAlign", &obj);
201 byteAlign = obj.getBool();
204 params->dictLookup("Columns", &obj);
206 columns = obj.getInt();
209 params->dictLookup("Rows", &obj);
214 params->dictLookup("EndOfBlock", &obj);
216 endOfBlock = obj.getBool();
219 params->dictLookup("BlackIs1", &obj);
221 black = obj.getBool();
225 str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
226 columns, rows, endOfBlock, black);
227 } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
228 str = new DCTStream(str);
229 } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
234 if (params->isDict()) {
235 params->dictLookup("Predictor", &obj);
239 params->dictLookup("Columns", &obj);
241 columns = obj.getInt();
243 params->dictLookup("Colors", &obj);
245 colors = obj.getInt();
247 params->dictLookup("BitsPerComponent", &obj);
252 str = new FlateStream(str, pred, columns, colors, bits);
253 } else if (!strcmp(name, "JBIG2Decode")) {
254 if (params->isDict()) {
255 params->dictLookup("JBIG2Globals", &globals);
257 str = new JBIG2Stream(str, &globals);
260 error(getPos(), "Unknown filter '%s'", name);
261 str = new EOFStream(str);
266 //------------------------------------------------------------------------
268 //------------------------------------------------------------------------
270 BaseStream::BaseStream(Object *dictA) {
272 #ifndef NO_DECRYPTION
277 BaseStream::~BaseStream() {
279 #ifndef NO_DECRYPTION
285 #ifndef NO_DECRYPTION
286 void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
287 int objNum, int objGen) {
288 decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
292 //------------------------------------------------------------------------
294 //------------------------------------------------------------------------
296 FilterStream::FilterStream(Stream *strA) {
300 FilterStream::~FilterStream() {
303 void FilterStream::close() {
307 void FilterStream::setPos(Guint pos, int dir) {
308 error(-1, "Internal: called setPos() on FilterStream");
311 //------------------------------------------------------------------------
313 //------------------------------------------------------------------------
315 ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
323 nVals = width * nComps;
325 imgLineSize = (nVals + 7) & ~7;
329 imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
333 ImageStream::~ImageStream() {
337 void ImageStream::reset() {
341 GBool ImageStream::getPixel(Guchar *pix) {
344 if (imgIdx >= nVals) {
348 for (i = 0; i < nComps; ++i) {
349 pix[i] = imgLine[imgIdx++];
354 Guchar *ImageStream::getLine() {
361 for (i = 0; i < nVals; i += 8) {
363 imgLine[i+0] = (Guchar)((c >> 7) & 1);
364 imgLine[i+1] = (Guchar)((c >> 6) & 1);
365 imgLine[i+2] = (Guchar)((c >> 5) & 1);
366 imgLine[i+3] = (Guchar)((c >> 4) & 1);
367 imgLine[i+4] = (Guchar)((c >> 3) & 1);
368 imgLine[i+5] = (Guchar)((c >> 2) & 1);
369 imgLine[i+6] = (Guchar)((c >> 1) & 1);
370 imgLine[i+7] = (Guchar)(c & 1);
372 } else if (nBits == 8) {
373 for (i = 0; i < nVals; ++i) {
374 imgLine[i] = str->getChar();
377 bitMask = (1 << nBits) - 1;
380 for (i = 0; i < nVals; ++i) {
382 buf = (buf << 8) | (str->getChar() & 0xff);
385 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
392 void ImageStream::skipLine() {
395 n = (nVals * nBits + 7) >> 3;
396 for (i = 0; i < n; ++i) {
401 //------------------------------------------------------------------------
403 //------------------------------------------------------------------------
405 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
406 int widthA, int nCompsA, int nBitsA) {
408 predictor = predictorA;
413 nVals = width * nComps;
414 pixBytes = (nComps * nBits + 7) >> 3;
415 rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
416 predLine = (Guchar *)gmalloc(rowBytes);
417 memset(predLine, 0, rowBytes);
421 StreamPredictor::~StreamPredictor() {
425 int StreamPredictor::lookChar() {
426 if (predIdx >= rowBytes) {
427 if (!getNextLine()) {
431 return predLine[predIdx];
434 int StreamPredictor::getChar() {
435 if (predIdx >= rowBytes) {
436 if (!getNextLine()) {
440 return predLine[predIdx++];
443 GBool StreamPredictor::getNextLine() {
446 int left, up, upLeft, p, pa, pb, pc;
448 Gulong inBuf, outBuf, bitMask;
452 // get PNG optimum predictor number
453 if (predictor == 15) {
454 if ((curPred = str->getRawChar()) == EOF) {
462 // read the raw line, apply PNG (byte) predictor
463 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
464 for (i = pixBytes; i < rowBytes; ++i) {
465 upLeftBuf[3] = upLeftBuf[2];
466 upLeftBuf[2] = upLeftBuf[1];
467 upLeftBuf[1] = upLeftBuf[0];
468 upLeftBuf[0] = predLine[i];
469 if ((c = str->getRawChar()) == EOF) {
474 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
477 predLine[i] = predLine[i] + (Guchar)c;
479 case 13: // PNG average
480 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
483 case 14: // PNG Paeth
484 left = predLine[i - pixBytes];
486 upLeft = upLeftBuf[pixBytes];
487 p = left + up - upLeft;
488 if ((pa = p - left) < 0)
490 if ((pb = p - up) < 0)
492 if ((pc = p - upLeft) < 0)
494 if (pa <= pb && pa <= pc)
495 predLine[i] = left + (Guchar)c;
497 predLine[i] = up + (Guchar)c;
499 predLine[i] = upLeft + (Guchar)c;
502 default: // no predictor or TIFF predictor
503 predLine[i] = (Guchar)c;
508 // apply TIFF (component) predictor
509 if (predictor == 2) {
511 inBuf = predLine[pixBytes - 1];
512 for (i = pixBytes; i < rowBytes; i += 8) {
513 // 1-bit add is just xor
514 inBuf = (inBuf << 8) | predLine[i];
515 predLine[i] ^= inBuf >> nComps;
517 } else if (nBits == 8) {
518 for (i = pixBytes; i < rowBytes; ++i) {
519 predLine[i] += predLine[i - nComps];
522 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
523 bitMask = (1 << nBits) - 1;
525 inBits = outBits = 0;
527 for (i = 0; i < nVals; ++i) {
528 if (inBits < nBits) {
529 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
532 upLeftBuf[3] = upLeftBuf[2];
533 upLeftBuf[2] = upLeftBuf[1];
534 upLeftBuf[1] = upLeftBuf[0];
535 upLeftBuf[0] = (upLeftBuf[nComps] +
536 (inBuf >> (inBits - nBits))) & bitMask;
537 outBuf = (outBuf << nBits) | upLeftBuf[0];
541 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
545 predLine[k++] = (Guchar)(outBuf << (8 - outBits));
550 // reset to start of line
556 //------------------------------------------------------------------------
558 //------------------------------------------------------------------------
560 FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
561 Guint lengthA, Object *dictA):
567 bufPtr = bufEnd = buf;
573 FileStream::~FileStream() {
577 Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
578 Guint lengthA, Object *dictA) {
579 return new FileStream(f, startA, limitedA, lengthA, dictA);
582 void FileStream::reset() {
584 savePos = (Guint)ftello(f);
585 fseeko(f, start, SEEK_SET);
587 savePos = (Guint)ftell64(f);
588 fseek64(f, start, SEEK_SET);
590 savePos = (Guint)ftell(f);
591 fseek(f, start, SEEK_SET);
594 bufPtr = bufEnd = buf;
596 #ifndef NO_DECRYPTION
602 void FileStream::close() {
605 fseeko(f, savePos, SEEK_SET);
607 fseek64(f, savePos, SEEK_SET);
609 fseek(f, savePos, SEEK_SET);
615 GBool FileStream::fillBuf() {
617 #ifndef NO_DECRYPTION
621 bufPos += bufEnd - buf;
622 bufPtr = bufEnd = buf;
623 if (limited && bufPos >= start + length) {
626 if (limited && bufPos + fileStreamBufSize > start + length) {
627 n = start + length - bufPos;
629 n = fileStreamBufSize;
631 n = fread(buf, 1, n, f);
633 if (bufPtr >= bufEnd) {
636 #ifndef NO_DECRYPTION
638 for (p = buf; p < bufEnd; ++p) {
639 *p = (char)decrypt->decryptByte((Guchar)*p);
646 void FileStream::setPos(Guint pos, int dir) {
651 fseeko(f, pos, SEEK_SET);
653 fseek64(f, pos, SEEK_SET);
655 fseek(f, pos, SEEK_SET);
660 fseeko(f, 0, SEEK_END);
661 size = (Guint)ftello(f);
663 fseek64(f, 0, SEEK_END);
664 size = (Guint)ftell64(f);
666 fseek(f, 0, SEEK_END);
667 size = (Guint)ftell(f);
672 //~ work around a bug in cygwin's implementation of fseek
676 fseeko(f, -(int)pos, SEEK_END);
677 bufPos = (Guint)ftello(f);
679 fseek64(f, -(int)pos, SEEK_END);
680 bufPos = (Guint)ftell64(f);
682 fseek(f, -(int)pos, SEEK_END);
683 bufPos = (Guint)ftell(f);
686 bufPtr = bufEnd = buf;
689 void FileStream::moveStart(int delta) {
691 bufPtr = bufEnd = buf;
695 //------------------------------------------------------------------------
697 //------------------------------------------------------------------------
699 MemStream::MemStream(char *bufA, Guint lengthA, Object *dictA):
704 bufEnd = buf + length;
708 MemStream::~MemStream() {
714 Stream *MemStream::makeSubStream(Guint start, GBool limited,
715 Guint lengthA, Object *dictA) {
718 if (!limited || start + lengthA > length) {
719 newLength = length - start;
723 return new MemStream(buf + start, newLength, dictA);
726 void MemStream::reset() {
728 #ifndef NO_DECRYPTION
735 void MemStream::close() {
738 void MemStream::setPos(Guint pos, int dir) {
749 bufPtr = bufEnd - pos;
754 void MemStream::moveStart(int delta) {
759 #ifndef NO_DECRYPTION
760 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
761 int objNum, int objGen) {
765 this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
767 newBuf = (char *)gmalloc(bufEnd - buf);
768 for (p = buf, q = newBuf; p < bufEnd; ++p, ++q) {
769 *q = (char)decrypt->decryptByte((Guchar)*p);
771 bufEnd = newBuf + (bufEnd - buf);
772 bufPtr = newBuf + (bufPtr - buf);
779 //------------------------------------------------------------------------
781 //------------------------------------------------------------------------
783 EmbedStream::EmbedStream(Stream *strA, Object *dictA):
788 EmbedStream::~EmbedStream() {
791 Stream *EmbedStream::makeSubStream(Guint start, GBool limited,
792 Guint length, Object *dictA) {
793 error(-1, "Internal: called makeSubStream() on EmbedStream");
797 void EmbedStream::setPos(Guint pos, int dir) {
798 error(-1, "Internal: called setPos() on EmbedStream");
801 Guint EmbedStream::getStart() {
802 error(-1, "Internal: called getStart() on EmbedStream");
806 void EmbedStream::moveStart(int delta) {
807 error(-1, "Internal: called moveStart() on EmbedStream");
810 //------------------------------------------------------------------------
812 //------------------------------------------------------------------------
814 ASCIIHexStream::ASCIIHexStream(Stream *strA):
820 ASCIIHexStream::~ASCIIHexStream() {
824 void ASCIIHexStream::reset() {
830 int ASCIIHexStream::lookChar() {
841 } while (isspace(c1));
849 } while (isspace(c2));
854 if (c1 >= '0' && c1 <= '9') {
856 } else if (c1 >= 'A' && c1 <= 'F') {
857 x = (c1 - 'A' + 10) << 4;
858 } else if (c1 >= 'a' && c1 <= 'f') {
859 x = (c1 - 'a' + 10) << 4;
860 } else if (c1 == EOF) {
864 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
867 if (c2 >= '0' && c2 <= '9') {
869 } else if (c2 >= 'A' && c2 <= 'F') {
871 } else if (c2 >= 'a' && c2 <= 'f') {
873 } else if (c2 == EOF) {
877 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
883 GString *ASCIIHexStream::getPSFilter(char *indent) {
886 if (!(s = str->getPSFilter(indent))) {
889 s->append(indent)->append("/ASCIIHexDecode filter\n");
893 GBool ASCIIHexStream::isBinary(GBool last) {
894 return str->isBinary(gFalse);
897 //------------------------------------------------------------------------
899 //------------------------------------------------------------------------
901 ASCII85Stream::ASCII85Stream(Stream *strA):
907 ASCII85Stream::~ASCII85Stream() {
911 void ASCII85Stream::reset() {
917 int ASCII85Stream::lookChar() {
926 c[0] = str->getChar();
927 } while (c[0] == '\n' || c[0] == '\r');
928 if (c[0] == '~' || c[0] == EOF) {
932 } else if (c[0] == 'z') {
933 b[0] = b[1] = b[2] = b[3] = 0;
936 for (k = 1; k < 5; ++k) {
938 c[k] = str->getChar();
939 } while (c[k] == '\n' || c[k] == '\r');
940 if (c[k] == '~' || c[k] == EOF)
944 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
945 for (++k; k < 5; ++k)
950 for (k = 0; k < 5; ++k)
951 t = t * 85 + (c[k] - 0x21);
952 for (k = 3; k >= 0; --k) {
953 b[k] = (int)(t & 0xff);
961 GString *ASCII85Stream::getPSFilter(char *indent) {
964 if (!(s = str->getPSFilter(indent))) {
967 s->append(indent)->append("/ASCII85Decode filter\n");
971 GBool ASCII85Stream::isBinary(GBool last) {
972 return str->isBinary(gFalse);
975 //------------------------------------------------------------------------
977 //------------------------------------------------------------------------
979 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
980 int bits, int earlyA):
982 if (predictor != 1) {
983 pred = new StreamPredictor(this, predictor, columns, colors, bits);
993 LZWStream::~LZWStream() {
1000 int LZWStream::getChar() {
1002 return pred->getChar();
1007 if (seqIndex >= seqLength) {
1008 if (!processNextCode()) {
1012 return seqBuf[seqIndex++];
1015 int LZWStream::lookChar() {
1017 return pred->lookChar();
1022 if (seqIndex >= seqLength) {
1023 if (!processNextCode()) {
1027 return seqBuf[seqIndex];
1030 int LZWStream::getRawChar() {
1034 if (seqIndex >= seqLength) {
1035 if (!processNextCode()) {
1039 return seqBuf[seqIndex++];
1042 void LZWStream::reset() {
1049 GBool LZWStream::processNextCode() {
1059 // check for eod and clear-table codes
1062 if (code == EOF || code == 257) {
1070 if (nextCode >= 4097) {
1071 error(getPos(), "Bad LZW stream - expected clear-table code");
1075 // process the next code
1076 nextLength = seqLength + 1;
1080 } else if (code < nextCode) {
1081 seqLength = table[code].length;
1082 for (i = seqLength - 1, j = code; i > 0; --i) {
1083 seqBuf[i] = table[j].tail;
1087 } else if (code == nextCode) {
1088 seqBuf[seqLength] = newChar;
1091 error(getPos(), "Bad LZW stream - unexpected code");
1095 newChar = seqBuf[0];
1099 table[nextCode].length = nextLength;
1100 table[nextCode].head = prevCode;
1101 table[nextCode].tail = newChar;
1103 if (nextCode + early == 512)
1105 else if (nextCode + early == 1024)
1107 else if (nextCode + early == 2048)
1118 void LZWStream::clearTable() {
1121 seqIndex = seqLength = 0;
1125 int LZWStream::getCode() {
1129 while (inputBits < nextBits) {
1130 if ((c = str->getChar()) == EOF)
1132 inputBuf = (inputBuf << 8) | (c & 0xff);
1135 code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
1136 inputBits -= nextBits;
1140 GString *LZWStream::getPSFilter(char *indent) {
1146 if (!(s = str->getPSFilter(indent))) {
1149 s->append(indent)->append("/LZWDecode filter\n");
1153 GBool LZWStream::isBinary(GBool last) {
1154 return str->isBinary(gTrue);
1157 //------------------------------------------------------------------------
1159 //------------------------------------------------------------------------
1161 RunLengthStream::RunLengthStream(Stream *strA):
1162 FilterStream(strA) {
1163 bufPtr = bufEnd = buf;
1167 RunLengthStream::~RunLengthStream() {
1171 void RunLengthStream::reset() {
1173 bufPtr = bufEnd = buf;
1177 GString *RunLengthStream::getPSFilter(char *indent) {
1180 if (!(s = str->getPSFilter(indent))) {
1183 s->append(indent)->append("/RunLengthDecode filter\n");
1187 GBool RunLengthStream::isBinary(GBool last) {
1188 return str->isBinary(gTrue);
1191 GBool RunLengthStream::fillBuf() {
1198 if (c == 0x80 || c == EOF) {
1204 for (i = 0; i < n; ++i)
1205 buf[i] = (char)str->getChar();
1209 for (i = 0; i < n; ++i)
1217 //------------------------------------------------------------------------
1219 //------------------------------------------------------------------------
1221 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1222 GBool byteAlignA, int columnsA, int rowsA,
1223 GBool endOfBlockA, GBool blackA):
1224 FilterStream(strA) {
1225 encoding = encodingA;
1226 endOfLine = endOfLineA;
1227 byteAlign = byteAlignA;
1230 endOfBlock = endOfBlockA;
1232 refLine = (short *)gmalloc((columns + 3) * sizeof(short));
1233 codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
1237 nextLine2D = encoding < 0;
1240 codingLine[1] = refLine[2] = columns;
1246 CCITTFaxStream::~CCITTFaxStream() {
1252 void CCITTFaxStream::reset() {
1258 nextLine2D = encoding < 0;
1261 codingLine[1] = refLine[2] = columns;
1265 // get initial end-of-line marker and 2D encoding tag
1267 if (lookBits(12) == 0x001) {
1271 for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
1272 if (n == 11 && lookBits(12) == 0x001) {
1277 nextLine2D = !lookBits(1);
1282 int CCITTFaxStream::lookChar() {
1283 short code1, code2, code3;
1292 // if at eof just return EOF
1293 if (eof && codingLine[a0] >= columns) {
1297 // read the next row
1301 if (codingLine[a0] >= columns) {
1305 for (i = 0; codingLine[i] < columns; ++i)
1306 refLine[i] = codingLine[i];
1307 refLine[i] = refLine[i + 1] = columns;
1309 a0New = codingLine[a0 = 0] = 0;
1311 code1 = getTwoDimCode();
1314 if (refLine[b1] < columns) {
1315 a0New = refLine[b1 + 1];
1320 if ((a0 & 1) == 0) {
1323 code1 += code3 = getWhiteCode();
1324 } while (code3 >= 64);
1326 code2 += code3 = getBlackCode();
1327 } while (code3 >= 64);
1331 code1 += code3 = getBlackCode();
1332 } while (code3 >= 64);
1334 code2 += code3 = getWhiteCode();
1335 } while (code3 >= 64);
1337 codingLine[a0 + 1] = a0New + code1;
1339 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1341 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1345 a0New = codingLine[++a0] = refLine[b1];
1346 if (refLine[b1] < columns) {
1348 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1353 a0New = codingLine[++a0] = refLine[b1] + 1;
1354 if (refLine[b1] < columns) {
1356 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1361 a0New = codingLine[++a0] = refLine[b1] - 1;
1363 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1367 a0New = codingLine[++a0] = refLine[b1] + 2;
1368 if (refLine[b1] < columns) {
1370 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1375 a0New = codingLine[++a0] = refLine[b1] - 2;
1377 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1381 a0New = codingLine[++a0] = refLine[b1] + 3;
1382 if (refLine[b1] < columns) {
1384 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1389 a0New = codingLine[++a0] = refLine[b1] - 3;
1391 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1396 codingLine[a0 = 0] = columns;
1399 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1408 } while (codingLine[a0] < columns);
1412 codingLine[a0 = 0] = 0;
1416 code1 += code3 = getWhiteCode();
1417 } while (code3 >= 64);
1418 codingLine[a0+1] = codingLine[a0] + code1;
1420 if (codingLine[a0] >= columns)
1424 code2 += code3 = getBlackCode();
1425 } while (code3 >= 64);
1426 codingLine[a0+1] = codingLine[a0] + code2;
1428 if (codingLine[a0] >= columns)
1433 if (codingLine[a0] != columns) {
1434 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
1440 // byte-align the row
1445 // check for end-of-line marker, skipping over any extra zero bits
1447 if (!endOfBlock && row == rows - 1) {
1450 code1 = lookBits(12);
1451 while (code1 == 0) {
1453 code1 = lookBits(12);
1455 if (code1 == 0x001) {
1458 } else if (code1 == EOF) {
1463 // get 2D encoding tag
1464 if (!eof && encoding > 0) {
1465 nextLine2D = !lookBits(1);
1469 // check for end-of-block marker
1470 if (endOfBlock && gotEOL) {
1471 code1 = lookBits(12);
1472 if (code1 == 0x001) {
1478 if (encoding >= 0) {
1479 for (i = 0; i < 4; ++i) {
1480 code1 = lookBits(12);
1481 if (code1 != 0x001) {
1482 error(getPos(), "Bad RTC code in CCITTFax stream");
1496 // This looks for an end-of-line marker after an error, however
1497 // some (most?) CCITT streams in PDF files don't use end-of-line
1498 // markers, and the just-plow-on technique works better in those
1507 code1 = look13Bits();
1508 } while ((code1 >> 1) != 0x001);
1510 codingLine[++a0] = columns;
1513 nextLine2D = !(code1 & 1);
1519 outputBits = codingLine[1] - codingLine[0];
1520 if (outputBits == 0) {
1522 outputBits = codingLine[2] - codingLine[1];
1529 if (outputBits >= 8) {
1530 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1531 if ((outputBits -= 8) == 0) {
1533 if (codingLine[a0] < columns) {
1534 outputBits = codingLine[a0 + 1] - codingLine[a0];
1541 if (outputBits > bits) {
1544 if ((a0 & 1) == 0) {
1545 ret |= 0xff >> (8 - i);
1551 if ((a0 & 1) == 0) {
1552 ret |= (0xff >> (8 - i)) << bits;
1556 if (codingLine[a0] < columns) {
1557 outputBits = codingLine[a0 + 1] - codingLine[a0];
1560 } while (bits > 0 && codingLine[a0] < columns);
1562 buf = black ? (ret ^ 0xff) : ret;
1566 short CCITTFaxStream::getTwoDimCode() {
1571 code = 0; // make gcc happy
1574 p = &twoDimTab1[code];
1580 for (n = 1; n <= 7; ++n) {
1585 p = &twoDimTab1[code];
1592 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1596 short CCITTFaxStream::getWhiteCode() {
1601 code = 0; // make gcc happy
1603 code = lookBits(12);
1604 if ((code >> 5) == 0) {
1605 p = &whiteTab1[code];
1607 p = &whiteTab2[code >> 3];
1614 for (n = 1; n <= 9; ++n) {
1619 p = &whiteTab2[code];
1625 for (n = 11; n <= 12; ++n) {
1630 p = &whiteTab1[code];
1637 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1638 // eat a bit and return a positive number so that the caller doesn't
1639 // go into an infinite loop
1644 short CCITTFaxStream::getBlackCode() {
1649 code = 0; // make gcc happy
1651 code = lookBits(13);
1652 if ((code >> 7) == 0) {
1653 p = &blackTab1[code];
1654 } else if ((code >> 9) == 0) {
1655 p = &blackTab2[(code >> 1) - 64];
1657 p = &blackTab3[code >> 7];
1664 for (n = 2; n <= 6; ++n) {
1669 p = &blackTab3[code];
1675 for (n = 7; n <= 12; ++n) {
1681 p = &blackTab2[code - 64];
1688 for (n = 10; n <= 13; ++n) {
1693 p = &blackTab1[code];
1700 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
1701 // eat a bit and return a positive number so that the caller doesn't
1702 // go into an infinite loop
1707 short CCITTFaxStream::lookBits(int n) {
1710 while (inputBits < n) {
1711 if ((c = str->getChar()) == EOF) {
1712 if (inputBits == 0) {
1715 // near the end of the stream, the caller may ask for more bits
1716 // than are available, but there may still be a valid code in
1717 // however many bits are available -- we need to return correct
1718 // data in this case
1719 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
1721 inputBuf = (inputBuf << 8) + c;
1724 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1727 GString *CCITTFaxStream::getPSFilter(char *indent) {
1731 if (!(s = str->getPSFilter(indent))) {
1734 s->append(indent)->append("<< ");
1735 if (encoding != 0) {
1736 sprintf(s1, "/K %d ", encoding);
1740 s->append("/EndOfLine true ");
1743 s->append("/EncodedByteAlign true ");
1745 sprintf(s1, "/Columns %d ", columns);
1748 sprintf(s1, "/Rows %d ", rows);
1752 s->append("/EndOfBlock false ");
1755 s->append("/BlackIs1 true ");
1757 s->append(">> /CCITTFaxDecode filter\n");
1761 GBool CCITTFaxStream::isBinary(GBool last) {
1762 return str->isBinary(gTrue);
1765 //------------------------------------------------------------------------
1767 //------------------------------------------------------------------------
1769 // IDCT constants (20.12 fixed point format)
1770 #define dctCos1 4017 // cos(pi/16)
1771 #define dctSin1 799 // sin(pi/16)
1772 #define dctCos3 3406 // cos(3*pi/16)
1773 #define dctSin3 2276 // sin(3*pi/16)
1774 #define dctCos6 1567 // cos(6*pi/16)
1775 #define dctSin6 3784 // sin(6*pi/16)
1776 #define dctSqrt2 5793 // sqrt(2)
1777 #define dctSqrt1d2 2896 // sqrt(2) / 2
1779 // color conversion parameters (16.16 fixed point format)
1780 #define dctCrToR 91881 // 1.4020
1781 #define dctCbToG -22553 // -0.3441363
1782 #define dctCrToG -46802 // -0.71413636
1783 #define dctCbToB 116130 // 1.772
1785 // clip [-256,511] --> [0,255]
1786 #define dctClipOffset 256
1787 static Guchar dctClip[768];
1788 static int dctClipInit = 0;
1790 // zig zag decode map
1791 static int dctZigZag[64] = {
1797 5, 12, 19, 26, 33, 40,
1798 48, 41, 34, 27, 20, 13, 6,
1799 7, 14, 21, 28, 35, 42, 49, 56,
1800 57, 50, 43, 36, 29, 22, 15,
1801 23, 30, 37, 44, 51, 58,
1809 DCTStream::DCTStream(Stream *strA):
1810 FilterStream(strA) {
1813 progressive = interleaved = gFalse;
1815 mcuWidth = mcuHeight = 0;
1819 for (i = 0; i < 4; ++i) {
1820 for (j = 0; j < 32; ++j) {
1821 rowBuf[i][j] = NULL;
1827 for (i = -256; i < 0; ++i)
1828 dctClip[dctClipOffset + i] = 0;
1829 for (i = 0; i < 256; ++i)
1830 dctClip[dctClipOffset + i] = i;
1831 for (i = 256; i < 512; ++i)
1832 dctClip[dctClipOffset + i] = 255;
1837 DCTStream::~DCTStream() {
1841 if (progressive || !interleaved) {
1842 for (i = 0; i < numComps; ++i) {
1846 for (i = 0; i < numComps; ++i) {
1847 for (j = 0; j < mcuHeight; ++j) {
1848 gfree(rowBuf[i][j]);
1854 void DCTStream::reset() {
1855 int minHSample, minVSample;
1860 progressive = interleaved = gFalse;
1864 numDCHuffTables = 0;
1865 numACHuffTables = 0;
1867 gotAdobeMarker = gFalse;
1868 restartInterval = 0;
1870 if (!readHeader()) {
1876 mcuWidth = minHSample = compInfo[0].hSample;
1877 mcuHeight = minVSample = compInfo[0].vSample;
1878 for (i = 1; i < numComps; ++i) {
1879 if (compInfo[i].hSample < minHSample)
1880 minHSample = compInfo[i].hSample;
1881 if (compInfo[i].vSample < minVSample)
1882 minVSample = compInfo[i].vSample;
1883 if (compInfo[i].hSample > mcuWidth)
1884 mcuWidth = compInfo[i].hSample;
1885 if (compInfo[i].vSample > mcuHeight)
1886 mcuHeight = compInfo[i].vSample;
1888 for (i = 0; i < numComps; ++i) {
1889 compInfo[i].hSample /= minHSample;
1890 compInfo[i].vSample /= minVSample;
1892 mcuWidth = (mcuWidth / minHSample) * 8;
1893 mcuHeight = (mcuHeight / minVSample) * 8;
1895 // figure out color transform
1896 if (!gotAdobeMarker && numComps == 3) {
1897 if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
1902 if (progressive || !interleaved) {
1904 // allocate a buffer for the whole image
1905 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
1906 bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
1907 for (i = 0; i < numComps; ++i) {
1908 frameBuf[i] = (int *)gmalloc(bufWidth * bufHeight * sizeof(int));
1909 memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
1912 // read the image data
1914 restartMarker = 0xd0;
1917 } while (readHeader());
1922 // initialize counters
1929 // allocate a buffer for one row of MCUs
1930 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
1931 for (i = 0; i < numComps; ++i) {
1932 for (j = 0; j < mcuHeight; ++j) {
1933 rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
1937 // initialize counters
1943 restartMarker = 0xd0;
1948 int DCTStream::getChar() {
1954 if (progressive || !interleaved) {
1955 c = frameBuf[comp][y * bufWidth + x];
1956 if (++comp == numComps) {
1964 if (dy >= mcuHeight) {
1965 if (!readMCURow()) {
1973 c = rowBuf[comp][dy][x];
1974 if (++comp == numComps) {
1989 int DCTStream::lookChar() {
1993 if (progressive || !interleaved) {
1994 return frameBuf[comp][y * bufWidth + x];
1996 if (dy >= mcuHeight) {
1997 if (!readMCURow()) {
2005 return rowBuf[comp][dy][x];
2009 void DCTStream::restart() {
2013 restartCtr = restartInterval;
2014 for (i = 0; i < numComps; ++i) {
2015 compInfo[i].prevDC = 0;
2020 // Read one row of MCUs from a sequential JPEG stream.
2021 GBool DCTStream::readMCURow() {
2025 int pY, pCb, pCr, pR, pG, pB;
2026 int h, v, horiz, vert, hSub, vSub;
2027 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2030 for (x1 = 0; x1 < width; x1 += mcuWidth) {
2032 // deal with restart marker
2033 if (restartInterval > 0 && restartCtr == 0) {
2035 if (c != restartMarker) {
2036 error(getPos(), "Bad DCT data: incorrect restart marker");
2039 if (++restartMarker == 0xd8)
2040 restartMarker = 0xd0;
2045 for (cc = 0; cc < numComps; ++cc) {
2046 h = compInfo[cc].hSample;
2047 v = compInfo[cc].vSample;
2048 horiz = mcuWidth / h;
2049 vert = mcuHeight / v;
2052 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2053 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2054 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2055 &acHuffTables[scanInfo.acHuffTable[cc]],
2056 &compInfo[cc].prevDC,
2060 transformDataUnit(quantTables[compInfo[cc].quantTable],
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] = data2[i];
2079 p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
2080 p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
2081 p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
2082 p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
2083 p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
2084 p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
2085 p1[14] = p1[15] = p2[14] = p2[15] = data2[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] = data2[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 // Read one scan from a progressive or non-interleaved JPEG stream.
2142 void DCTStream::readScan() {
2144 int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
2145 int h, v, horiz, vert, hSub, vSub;
2149 if (scanInfo.numComps == 1) {
2150 for (cc = 0; cc < numComps; ++cc) {
2151 if (scanInfo.comp[cc]) {
2155 dx1 = mcuWidth / compInfo[cc].hSample;
2156 dy1 = mcuHeight / compInfo[cc].vSample;
2162 for (y1 = 0; y1 < height; y1 += dy1) {
2163 for (x1 = 0; x1 < width; x1 += dx1) {
2165 // deal with restart marker
2166 if (restartInterval > 0 && restartCtr == 0) {
2168 if (c != restartMarker) {
2169 error(getPos(), "Bad DCT data: incorrect restart marker");
2172 if (++restartMarker == 0xd8) {
2173 restartMarker = 0xd0;
2179 for (cc = 0; cc < numComps; ++cc) {
2180 if (!scanInfo.comp[cc]) {
2184 h = compInfo[cc].hSample;
2185 v = compInfo[cc].vSample;
2186 horiz = mcuWidth / h;
2187 vert = mcuHeight / v;
2190 for (y2 = 0; y2 < dy1; y2 += vert) {
2191 for (x2 = 0; x2 < dx1; x2 += horiz) {
2193 // pull out the current values
2194 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2195 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2204 p1 += bufWidth * vSub;
2207 // read one data unit
2209 if (!readProgressiveDataUnit(
2210 &dcHuffTables[scanInfo.dcHuffTable[cc]],
2211 &acHuffTables[scanInfo.acHuffTable[cc]],
2212 &compInfo[cc].prevDC,
2217 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2218 &acHuffTables[scanInfo.acHuffTable[cc]],
2219 &compInfo[cc].prevDC,
2225 // add the data unit into frameBuf
2226 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2227 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2236 p1 += bufWidth * vSub;
2246 // Read one data unit from a sequential JPEG stream.
2247 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2248 DCTHuffTable *acHuffTable,
2249 int *prevDC, int data[64]) {
2254 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2258 if ((amp = readAmp(size)) == 9999) {
2264 data[0] = *prevDC += amp;
2265 for (i = 1; i < 64; ++i) {
2271 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
2280 run += (c >> 4) & 0x0f;
2282 amp = readAmp(size);
2296 // Read one data unit from a sequential JPEG stream.
2297 GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
2298 DCTHuffTable *acHuffTable,
2299 int *prevDC, int data[64]) {
2300 int run, size, amp, bit, c;
2303 // get the DC coefficient
2304 i = scanInfo.firstCoeff;
2306 if (scanInfo.ah == 0) {
2307 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2311 if ((amp = readAmp(size)) == 9999) {
2317 data[0] += (*prevDC += amp) << scanInfo.al;
2319 if ((bit = readBit()) == 9999) {
2322 data[0] += bit << scanInfo.al;
2326 if (scanInfo.lastCoeff == 0) {
2330 // check for an EOB run
2332 while (i <= scanInfo.lastCoeff) {
2335 if ((bit = readBit()) == EOF) {
2339 data[j] += 1 << scanInfo.al;
2347 // read the AC coefficients
2348 while (i <= scanInfo.lastCoeff) {
2349 if ((c = readHuffSym(acHuffTable)) == 9999) {
2361 if ((bit = readBit()) == EOF) {
2365 data[j] += 1 << scanInfo.al;
2371 } else if ((c & 0x0f) == 0x00) {
2374 for (k = 0; k < j; ++k) {
2375 if ((bit = readBit()) == EOF) {
2378 eobRun = (eobRun << 1) | bit;
2381 while (i <= scanInfo.lastCoeff) {
2384 if ((bit = readBit()) == EOF) {
2388 data[j] += 1 << scanInfo.al;
2395 // zero run and one AC coefficient
2397 run = (c >> 4) & 0x0f;
2399 if ((amp = readAmp(size)) == 9999) {
2405 while (data[j] != 0) {
2406 if ((bit = readBit()) == EOF) {
2410 data[j] += 1 << scanInfo.al;
2416 data[j] = amp << scanInfo.al;
2423 // Decode a progressive JPEG image.
2424 void DCTStream::decodeImage() {
2428 int pY, pCb, pCr, pR, pG, pB;
2429 int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2430 int h, v, horiz, vert, hSub, vSub;
2433 for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
2434 for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
2435 for (cc = 0; cc < numComps; ++cc) {
2436 quantTable = quantTables[compInfo[cc].quantTable];
2437 h = compInfo[cc].hSample;
2438 v = compInfo[cc].vSample;
2439 horiz = mcuWidth / h;
2440 vert = mcuHeight / v;
2443 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2444 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2446 // pull out the coded data unit
2447 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2448 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2450 dataIn[i+1] = p1[1];
2451 dataIn[i+2] = p1[2];
2452 dataIn[i+3] = p1[3];
2453 dataIn[i+4] = p1[4];
2454 dataIn[i+5] = p1[5];
2455 dataIn[i+6] = p1[6];
2456 dataIn[i+7] = p1[7];
2457 p1 += bufWidth * vSub;
2461 transformDataUnit(quantTable, dataIn, dataOut);
2463 // store back into frameBuf, doing replication for
2464 // subsampled components
2465 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2466 if (hSub == 1 && vSub == 1) {
2467 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2468 p1[0] = dataOut[i] & 0xff;
2469 p1[1] = dataOut[i+1] & 0xff;
2470 p1[2] = dataOut[i+2] & 0xff;
2471 p1[3] = dataOut[i+3] & 0xff;
2472 p1[4] = dataOut[i+4] & 0xff;
2473 p1[5] = dataOut[i+5] & 0xff;
2474 p1[6] = dataOut[i+6] & 0xff;
2475 p1[7] = dataOut[i+7] & 0xff;
2478 } else if (hSub == 2 && vSub == 2) {
2480 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2481 p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
2482 p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
2483 p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
2484 p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
2485 p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
2486 p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
2487 p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
2488 p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
2494 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2495 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2497 for (y5 = 0; y5 < vSub; ++y5) {
2498 for (x5 = 0; x5 < hSub; ++x5) {
2499 p2[x5] = dataOut[i] & 0xff;
2505 p1 += bufWidth * vSub;
2512 // color space conversion
2514 // convert YCbCr to RGB
2515 if (numComps == 3) {
2516 for (y2 = 0; y2 < mcuHeight; ++y2) {
2517 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2518 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2519 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2520 for (x2 = 0; x2 < mcuWidth; ++x2) {
2524 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2525 *p0++ = dctClip[dctClipOffset + pR];
2526 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2528 *p1++ = dctClip[dctClipOffset + pG];
2529 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2530 *p2++ = dctClip[dctClipOffset + pB];
2533 // convert YCbCrK to CMYK (K is passed through unchanged)
2534 } else if (numComps == 4) {
2535 for (y2 = 0; y2 < mcuHeight; ++y2) {
2536 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2537 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2538 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2539 for (x2 = 0; x2 < mcuWidth; ++x2) {
2543 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2544 *p0++ = 255 - dctClip[dctClipOffset + pR];
2545 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2547 *p1++ = 255 - dctClip[dctClipOffset + pG];
2548 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2549 *p2++ = 255 - dctClip[dctClipOffset + pB];
2558 // Transform one data unit -- this performs the dequantization and
2559 // IDCT steps. This IDCT algorithm is taken from:
2560 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2561 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2562 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2564 // The stage numbers mentioned in the comments refer to Figure 1 in this
2566 void DCTStream::transformDataUnit(Guchar *quantTable,
2567 int dataIn[64], Guchar dataOut[64]) {
2568 int v0, v1, v2, v3, v4, v5, v6, v7, t;
2573 for (i = 0; i < 64; ++i) {
2574 dataIn[i] *= quantTable[i];
2577 // inverse DCT on rows
2578 for (i = 0; i < 64; i += 8) {
2581 // check for all-zero AC coefficients
2582 if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
2583 p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
2584 t = (dctSqrt2 * p[0] + 512) >> 10;
2597 v0 = (dctSqrt2 * p[0] + 128) >> 8;
2598 v1 = (dctSqrt2 * p[4] + 128) >> 8;
2601 v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
2602 v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
2607 t = (v0 - v1+ 1) >> 1;
2608 v0 = (v0 + v1 + 1) >> 1;
2610 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2611 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2613 t = (v4 - v6 + 1) >> 1;
2614 v4 = (v4 + v6 + 1) >> 1;
2616 t = (v7 + v5 + 1) >> 1;
2617 v5 = (v7 - v5 + 1) >> 1;
2621 t = (v0 - v3 + 1) >> 1;
2622 v0 = (v0 + v3 + 1) >> 1;
2624 t = (v1 - v2 + 1) >> 1;
2625 v1 = (v1 + v2 + 1) >> 1;
2627 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2628 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2630 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2631 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2645 // inverse DCT on columns
2646 for (i = 0; i < 8; ++i) {
2649 // check for all-zero AC coefficients
2650 if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
2651 p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
2652 t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
2665 v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
2666 v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
2669 v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
2670 v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
2675 t = (v0 - v1 + 1) >> 1;
2676 v0 = (v0 + v1 + 1) >> 1;
2678 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2679 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2681 t = (v4 - v6 + 1) >> 1;
2682 v4 = (v4 + v6 + 1) >> 1;
2684 t = (v7 + v5 + 1) >> 1;
2685 v5 = (v7 - v5 + 1) >> 1;
2689 t = (v0 - v3 + 1) >> 1;
2690 v0 = (v0 + v3 + 1) >> 1;
2692 t = (v1 - v2 + 1) >> 1;
2693 v1 = (v1 + v2 + 1) >> 1;
2695 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2696 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2698 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2699 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2713 // convert to 8-bit integers
2714 for (i = 0; i < 64; ++i) {
2715 dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
2719 int DCTStream::readHuffSym(DCTHuffTable *table) {
2727 // add a bit to the code
2728 if ((bit = readBit()) == EOF)
2730 code = (code << 1) + bit;
2734 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2735 code -= table->firstCode[codeBits];
2736 return table->sym[table->firstSym[codeBits] + code];
2738 } while (codeBits < 16);
2740 error(getPos(), "Bad Huffman code in DCT stream");
2744 int DCTStream::readAmp(int size) {
2749 for (bits = 0; bits < size; ++bits) {
2750 if ((bit = readBit()) == EOF)
2752 amp = (amp << 1) + bit;
2754 if (amp < (1 << (size - 1)))
2755 amp -= (1 << size) - 1;
2759 int DCTStream::readBit() {
2763 if (inputBits == 0) {
2764 if ((c = str->getChar()) == EOF)
2768 c2 = str->getChar();
2769 } while (c2 == 0xff);
2771 error(getPos(), "Bad DCT data: missing 00 after ff");
2778 bit = (inputBuf >> (inputBits - 1)) & 1;
2783 GBool DCTStream::readHeader() {
2795 if (!readBaselineSOF()) {
2800 if (!readProgressiveSOF()) {
2805 if (!readHuffmanTables()) {
2815 if (!readScanInfo()) {
2821 if (!readQuantTables()) {
2826 if (!readRestartInterval()) {
2831 if (!readAdobeMarker()) {
2836 error(getPos(), "Bad DCT header");
2839 // skip APPn / COM / etc.
2842 for (i = 0; i < n; ++i) {
2846 error(getPos(), "Unknown DCT marker <%02x>", c);
2856 GBool DCTStream::readBaselineSOF() {
2863 prec = str->getChar();
2866 numComps = str->getChar();
2868 error(getPos(), "Bad DCT precision %d", prec);
2871 for (i = 0; i < numComps; ++i) {
2872 compInfo[i].id = str->getChar();
2874 compInfo[i].hSample = (c >> 4) & 0x0f;
2875 compInfo[i].vSample = c & 0x0f;
2876 compInfo[i].quantTable = str->getChar();
2878 progressive = gFalse;
2882 GBool DCTStream::readProgressiveSOF() {
2889 prec = str->getChar();
2892 numComps = str->getChar();
2894 error(getPos(), "Bad DCT precision %d", prec);
2897 for (i = 0; i < numComps; ++i) {
2898 compInfo[i].id = str->getChar();
2900 compInfo[i].hSample = (c >> 4) & 0x0f;
2901 compInfo[i].vSample = c & 0x0f;
2902 compInfo[i].quantTable = str->getChar();
2904 progressive = gTrue;
2908 GBool DCTStream::readScanInfo() {
2913 length = read16() - 2;
2914 scanInfo.numComps = str->getChar();
2916 if (length != 2 * scanInfo.numComps + 3) {
2917 error(getPos(), "Bad DCT scan info block");
2920 interleaved = scanInfo.numComps == numComps;
2921 for (j = 0; j < numComps; ++j) {
2922 scanInfo.comp[j] = gFalse;
2924 for (i = 0; i < scanInfo.numComps; ++i) {
2925 id = str->getChar();
2926 for (j = 0; j < numComps; ++j) {
2927 if (id == compInfo[j].id) {
2931 if (j == numComps) {
2932 error(getPos(), "Bad DCT component ID in scan info block");
2935 scanInfo.comp[j] = gTrue;
2937 scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
2938 scanInfo.acHuffTable[j] = c & 0x0f;
2940 scanInfo.firstCoeff = str->getChar();
2941 scanInfo.lastCoeff = str->getChar();
2943 scanInfo.ah = (c >> 4) & 0x0f;
2944 scanInfo.al = c & 0x0f;
2948 GBool DCTStream::readQuantTables() {
2953 length = read16() - 2;
2954 while (length > 0) {
2955 index = str->getChar();
2956 if ((index & 0xf0) || index >= 4) {
2957 error(getPos(), "Bad DCT quantization table");
2960 if (index == numQuantTables)
2961 numQuantTables = index + 1;
2962 for (i = 0; i < 64; ++i)
2963 quantTables[index][dctZigZag[i]] = str->getChar();
2969 GBool DCTStream::readHuffmanTables() {
2978 length = read16() - 2;
2979 while (length > 0) {
2980 index = str->getChar();
2982 if ((index & 0x0f) >= 4) {
2983 error(getPos(), "Bad DCT Huffman table");
2988 if (index >= numACHuffTables)
2989 numACHuffTables = index+1;
2990 tbl = &acHuffTables[index];
2992 if (index >= numDCHuffTables)
2993 numDCHuffTables = index+1;
2994 tbl = &dcHuffTables[index];
2998 for (i = 1; i <= 16; ++i) {
3000 tbl->firstSym[i] = sym;
3001 tbl->firstCode[i] = code;
3002 tbl->numCodes[i] = c;
3004 code = (code + c) << 1;
3007 for (i = 0; i < sym; ++i)
3008 tbl->sym[i] = str->getChar();
3014 GBool DCTStream::readRestartInterval() {
3019 error(getPos(), "Bad DCT restart interval");
3022 restartInterval = read16();
3026 GBool DCTStream::readAdobeMarker() {
3035 for (i = 0; i < 12; ++i) {
3036 if ((c = str->getChar()) == EOF) {
3041 if (strncmp(buf, "Adobe", 5)) {
3044 colorXform = buf[11];
3045 gotAdobeMarker = gTrue;
3046 for (i = 14; i < length; ++i) {
3047 if (str->getChar() == EOF) {
3054 error(getPos(), "Bad DCT Adobe APP14 marker");
3058 GBool DCTStream::readTrailer() {
3062 if (c != 0xd9) { // EOI
3063 error(getPos(), "Bad DCT trailer");
3069 int DCTStream::readMarker() {
3075 } while (c != 0xff);
3078 } while (c == 0xff);
3079 } while (c == 0x00);
3083 int DCTStream::read16() {
3086 if ((c1 = str->getChar()) == EOF)
3088 if ((c2 = str->getChar()) == EOF)
3090 return (c1 << 8) + c2;
3093 GString *DCTStream::getPSFilter(char *indent) {
3096 if (!(s = str->getPSFilter(indent))) {
3099 s->append(indent)->append("<< >> /DCTDecode filter\n");
3103 GBool DCTStream::isBinary(GBool last) {
3104 return str->isBinary(gTrue);
3107 //------------------------------------------------------------------------
3109 //------------------------------------------------------------------------
3111 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
3112 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3115 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
3147 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
3180 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
3181 int colors, int bits):
3182 FilterStream(strA) {
3183 if (predictor != 1) {
3184 pred = new StreamPredictor(this, predictor, columns, colors, bits);
3188 litCodeTab.codes = NULL;
3189 distCodeTab.codes = NULL;
3192 FlateStream::~FlateStream() {
3193 gfree(litCodeTab.codes);
3194 gfree(distCodeTab.codes);
3201 void FlateStream::reset() {
3208 compressedBlock = gFalse;
3215 //~ need to look at window size?
3216 endOfBlock = eof = gTrue;
3217 cmf = str->getChar();
3218 flg = str->getChar();
3219 if (cmf == EOF || flg == EOF)
3221 if ((cmf & 0x0f) != 0x08) {
3222 error(getPos(), "Unknown compression method in flate stream");
3225 if ((((cmf << 8) + flg) % 31) != 0) {
3226 error(getPos(), "Bad FCHECK in flate stream");
3230 error(getPos(), "FDICT bit set in flate stream");
3237 int FlateStream::getChar() {
3241 return pred->getChar();
3243 while (remain == 0) {
3244 if (endOfBlock && eof)
3249 index = (index + 1) & flateMask;
3254 int FlateStream::lookChar() {
3258 return pred->lookChar();
3260 while (remain == 0) {
3261 if (endOfBlock && eof)
3269 int FlateStream::getRawChar() {
3272 while (remain == 0) {
3273 if (endOfBlock && eof)
3278 index = (index + 1) & flateMask;
3283 GString *FlateStream::getPSFilter(char *indent) {
3287 GBool FlateStream::isBinary(GBool last) {
3288 return str->isBinary(gTrue);
3291 void FlateStream::readSome() {
3302 if (compressedBlock) {
3303 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
3308 } else if (code1 == 256) {
3313 code2 = lengthDecode[code1].bits;
3314 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3316 len = lengthDecode[code1].first + code2;
3317 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
3319 code2 = distDecode[code1].bits;
3320 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3322 dist = distDecode[code1].first + code2;
3324 j = (index - dist) & flateMask;
3325 for (k = 0; k < len; ++k) {
3327 i = (i + 1) & flateMask;
3328 j = (j + 1) & flateMask;
3334 len = (blockLen < flateWindow) ? blockLen : flateWindow;
3335 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
3336 if ((c = str->getChar()) == EOF) {
3337 endOfBlock = eof = gTrue;
3351 error(getPos(), "Unexpected end of file in flate stream");
3352 endOfBlock = eof = gTrue;
3356 GBool FlateStream::startBlock() {
3361 // free the code tables from the previous block
3362 gfree(litCodeTab.codes);
3363 litCodeTab.codes = NULL;
3364 gfree(distCodeTab.codes);
3365 distCodeTab.codes = NULL;
3367 // read block header
3368 blockHdr = getCodeWord(3);
3373 // uncompressed block
3374 if (blockHdr == 0) {
3375 compressedBlock = gFalse;
3376 if ((c = str->getChar()) == EOF)
3378 blockLen = c & 0xff;
3379 if ((c = str->getChar()) == EOF)
3381 blockLen |= (c & 0xff) << 8;
3382 if ((c = str->getChar()) == EOF)
3385 if ((c = str->getChar()) == EOF)
3387 check |= (c & 0xff) << 8;
3388 if (check != (~blockLen & 0xffff))
3389 error(getPos(), "Bad uncompressed block length in flate stream");
3393 // compressed block with fixed codes
3394 } else if (blockHdr == 1) {
3395 compressedBlock = gTrue;
3398 // compressed block with dynamic codes
3399 } else if (blockHdr == 2) {
3400 compressedBlock = gTrue;
3401 if (!readDynamicCodes()) {
3405 // unknown block type
3410 endOfBlock = gFalse;
3414 error(getPos(), "Bad block header in flate stream");
3415 endOfBlock = eof = gTrue;
3419 void FlateStream::loadFixedCodes() {
3422 // build the literal code table
3423 for (i = 0; i <= 143; ++i) {
3426 for (i = 144; i <= 255; ++i) {
3429 for (i = 256; i <= 279; ++i) {
3432 for (i = 280; i <= 287; ++i) {
3435 compHuffmanCodes(codeLengths, flateMaxLitCodes, &litCodeTab);
3437 // build the distance code table
3438 for (i = 0; i < flateMaxDistCodes; ++i) {
3441 compHuffmanCodes(codeLengths, flateMaxDistCodes, &distCodeTab);
3444 GBool FlateStream::readDynamicCodes() {
3445 int numCodeLenCodes;
3448 int codeLenCodeLengths[flateMaxCodeLenCodes];
3449 FlateHuffmanTab codeLenCodeTab;
3450 int len, repeat, code;
3453 codeLenCodeTab.codes = NULL;
3456 if ((numLitCodes = getCodeWord(5)) == EOF) {
3460 if ((numDistCodes = getCodeWord(5)) == EOF) {
3464 if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
3467 numCodeLenCodes += 4;
3468 if (numLitCodes > flateMaxLitCodes ||
3469 numDistCodes > flateMaxDistCodes ||
3470 numCodeLenCodes > flateMaxCodeLenCodes) {
3474 // build the code length code table
3475 for (i = 0; i < flateMaxCodeLenCodes; ++i) {
3476 codeLenCodeLengths[i] = 0;
3478 for (i = 0; i < numCodeLenCodes; ++i) {
3479 if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
3483 compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
3485 // build the literal and distance code tables
3489 while (i < numLitCodes + numDistCodes) {
3490 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
3494 if ((repeat = getCodeWord(2)) == EOF) {
3498 if (i + repeat > numLitCodes + numDistCodes) {
3501 for (; repeat > 0; --repeat) {
3502 codeLengths[i++] = len;
3504 } else if (code == 17) {
3505 if ((repeat = getCodeWord(3)) == EOF) {
3509 if (i + repeat > numLitCodes + numDistCodes) {
3513 for (; repeat > 0; --repeat) {
3514 codeLengths[i++] = 0;
3516 } else if (code == 18) {
3517 if ((repeat = getCodeWord(7)) == EOF) {
3521 if (i + repeat > numLitCodes + numDistCodes) {
3525 for (; repeat > 0; --repeat) {
3526 codeLengths[i++] = 0;
3529 codeLengths[i++] = len = code;
3532 compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
3533 compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
3535 gfree(codeLenCodeTab.codes);
3539 error(getPos(), "Bad dynamic code table in flate stream");
3540 gfree(codeLenCodeTab.codes);
3544 // Convert an array <lengths> of <n> lengths, in value order, into a
3545 // Huffman code lookup table.
3546 void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
3547 int tabSize, len, code, code2, skip, val, i, t;
3549 // find max code length
3551 for (val = 0; val < n; ++val) {
3552 if (lengths[val] > tab->maxLen) {
3553 tab->maxLen = lengths[val];
3557 // allocate the table
3558 tabSize = 1 << tab->maxLen;
3559 tab->codes = (FlateCode *)gmalloc(tabSize * sizeof(FlateCode));
3562 for (i = 0; i < tabSize; ++i) {
3563 tab->codes[i].len = 0;
3564 tab->codes[i].val = 0;
3568 for (len = 1, code = 0, skip = 2;
3570 ++len, code <<= 1, skip <<= 1) {
3571 for (val = 0; val < n; ++val) {
3572 if (lengths[val] == len) {
3574 // bit-reverse the code
3577 for (i = 0; i < len; ++i) {
3578 code2 = (code2 << 1) | (t & 1);
3582 // fill in the table entries
3583 for (i = code2; i < tabSize; i += skip) {
3584 tab->codes[i].len = (Gushort)len;
3585 tab->codes[i].val = (Gushort)val;
3594 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
3598 while (codeSize < tab->maxLen) {
3599 if ((c = str->getChar()) == EOF) {
3602 codeBuf |= (c & 0xff) << codeSize;
3605 code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
3606 if (codeSize == 0 || codeSize < code->len || code->len == 0) {
3609 codeBuf >>= code->len;
3610 codeSize -= code->len;
3611 return (int)code->val;
3614 int FlateStream::getCodeWord(int bits) {
3617 while (codeSize < bits) {
3618 if ((c = str->getChar()) == EOF)
3620 codeBuf |= (c & 0xff) << codeSize;
3623 c = codeBuf & ((1 << bits) - 1);
3629 //------------------------------------------------------------------------
3631 //------------------------------------------------------------------------
3633 EOFStream::EOFStream(Stream *strA):
3634 FilterStream(strA) {
3637 EOFStream::~EOFStream() {
3641 //------------------------------------------------------------------------
3642 // FixedLengthEncoder
3643 //------------------------------------------------------------------------
3645 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
3646 FilterStream(strA) {
3651 FixedLengthEncoder::~FixedLengthEncoder() {
3652 if (str->isEncoder())
3656 void FixedLengthEncoder::reset() {
3661 void FixedLengthEncoder::close() {
3664 int FixedLengthEncoder::getChar() {
3665 if (length >= 0 && count >= length)
3668 return str->getChar();
3671 int FixedLengthEncoder::lookChar() {
3672 if (length >= 0 && count >= length)
3674 return str->getChar();
3677 //------------------------------------------------------------------------
3679 //------------------------------------------------------------------------
3681 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
3682 FilterStream(strA) {
3683 bufPtr = bufEnd = buf;
3688 ASCIIHexEncoder::~ASCIIHexEncoder() {
3689 if (str->isEncoder()) {
3694 void ASCIIHexEncoder::reset() {
3696 bufPtr = bufEnd = buf;
3701 void ASCIIHexEncoder::close() {
3704 GBool ASCIIHexEncoder::fillBuf() {
3705 static char *hex = "0123456789abcdef";
3711 bufPtr = bufEnd = buf;
3712 if ((c = str->getChar()) == EOF) {
3716 if (lineLen >= 64) {
3720 *bufEnd++ = hex[(c >> 4) & 0x0f];
3721 *bufEnd++ = hex[c & 0x0f];
3727 //------------------------------------------------------------------------
3729 //------------------------------------------------------------------------
3731 ASCII85Encoder::ASCII85Encoder(Stream *strA):
3732 FilterStream(strA) {
3733 bufPtr = bufEnd = buf;
3738 ASCII85Encoder::~ASCII85Encoder() {
3739 if (str->isEncoder())
3743 void ASCII85Encoder::reset() {
3745 bufPtr = bufEnd = buf;
3750 void ASCII85Encoder::close() {
3753 GBool ASCII85Encoder::fillBuf() {
3762 for (n = 0; n < 4; ++n) {
3763 if ((c = str->getChar()) == EOF)
3767 bufPtr = bufEnd = buf;
3769 if (n == 4 && t == 0) {
3771 if (++lineLen == 65) {
3778 for (i = 4; i >= 0; --i) {
3779 buf1[i] = (char)(t % 85 + 0x21);
3782 for (i = 0; i <= n; ++i) {
3783 *bufEnd++ = buf1[i];
3784 if (++lineLen == 65) {
3796 return bufPtr < bufEnd;
3799 //------------------------------------------------------------------------
3801 //------------------------------------------------------------------------
3803 RunLengthEncoder::RunLengthEncoder(Stream *strA):
3804 FilterStream(strA) {
3805 bufPtr = bufEnd = nextEnd = buf;
3809 RunLengthEncoder::~RunLengthEncoder() {
3810 if (str->isEncoder())
3814 void RunLengthEncoder::reset() {
3816 bufPtr = bufEnd = nextEnd = buf;
3820 void RunLengthEncoder::close() {
3824 // When fillBuf finishes, buf[] looks like this:
3825 // +-----+--------------+-----------------+--
3826 // + tag | ... data ... | next 0, 1, or 2 |
3827 // +-----+--------------+-----------------+--
3829 // bufPtr bufEnd nextEnd
3831 GBool RunLengthEncoder::fillBuf() {
3840 if (nextEnd < bufEnd + 1) {
3841 if ((c1 = str->getChar()) == EOF) {
3846 c1 = bufEnd[0] & 0xff;
3848 if (nextEnd < bufEnd + 2) {
3849 if ((c2 = str->getChar()) == EOF) {
3858 c2 = bufEnd[1] & 0xff;
3862 c = 0; // make gcc happy
3865 while (n < 128 && (c = str->getChar()) == c1)
3867 buf[0] = (char)(257 - n);
3872 } else if (n < 128) {
3879 // get up to 128 chars
3885 if ((c = str->getChar()) == EOF) {
3891 if (buf[n] == buf[n-1])
3894 if (buf[n] == buf[n-1]) {
3895 buf[0] = (char)(n-2-1);
3897 nextEnd = &buf[n+1];
3899 buf[0] = (char)(n-1);
3900 bufEnd = nextEnd = &buf[n+1];