1 //========================================================================
5 // Copyright 1996-2002 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 //~ this is completely untested
510 if (predictor == 2) {
512 inBuf = predLine[pixBytes - 1];
513 for (i = pixBytes; i < rowBytes; i += 8) {
514 // 1-bit add is just xor
515 inBuf = (inBuf << 8) | predLine[i];
516 predLine[i] ^= inBuf >> nComps;
518 } else if (nBits == 8) {
519 for (i = pixBytes; i < rowBytes; ++i) {
520 predLine[i] += predLine[i - nComps];
523 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
524 bitMask = (1 << nBits) - 1;
526 inBits = outBits = 0;
528 for (i = 0; i < nVals; ++i) {
529 if (inBits < nBits) {
530 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
533 upLeftBuf[3] = upLeftBuf[2];
534 upLeftBuf[2] = upLeftBuf[1];
535 upLeftBuf[1] = upLeftBuf[0];
536 upLeftBuf[0] = (upLeftBuf[nComps] +
537 (inBuf >> (inBits - nBits))) & bitMask;
538 outBuf = (outBuf << nBits) | upLeftBuf[0];
542 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
546 predLine[k++] = (Guchar)(outBuf << (8 - outBits));
551 // reset to start of line
557 //------------------------------------------------------------------------
559 //------------------------------------------------------------------------
561 FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
562 Guint lengthA, Object *dictA):
568 bufPtr = bufEnd = buf;
574 FileStream::~FileStream() {
578 Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
579 Guint lengthA, Object *dictA) {
580 return new FileStream(f, startA, limitedA, lengthA, dictA);
583 void FileStream::reset() {
585 savePos = (Guint)ftello(f);
586 fseeko(f, start, SEEK_SET);
588 savePos = (Guint)ftell64(f);
589 fseek64(f, start, SEEK_SET);
591 savePos = (Guint)ftell(f);
592 fseek(f, start, SEEK_SET);
595 bufPtr = bufEnd = buf;
597 #ifndef NO_DECRYPTION
603 void FileStream::close() {
606 fseeko(f, savePos, SEEK_SET);
608 fseek64(f, savePos, SEEK_SET);
610 fseek(f, savePos, SEEK_SET);
616 GBool FileStream::fillBuf() {
618 #ifndef NO_DECRYPTION
622 bufPos += bufEnd - buf;
623 bufPtr = bufEnd = buf;
624 if (limited && bufPos >= start + length) {
627 if (limited && bufPos + fileStreamBufSize > start + length) {
628 n = start + length - bufPos;
630 n = fileStreamBufSize;
632 n = fread(buf, 1, n, f);
634 if (bufPtr >= bufEnd) {
637 #ifndef NO_DECRYPTION
639 for (p = buf; p < bufEnd; ++p) {
640 *p = (char)decrypt->decryptByte((Guchar)*p);
647 void FileStream::setPos(Guint pos, int dir) {
652 fseeko(f, pos, SEEK_SET);
654 fseek64(f, pos, SEEK_SET);
656 fseek(f, pos, SEEK_SET);
661 fseeko(f, 0, SEEK_END);
662 size = (Guint)ftello(f);
664 fseek64(f, 0, SEEK_END);
665 size = (Guint)ftell64(f);
667 fseek(f, 0, SEEK_END);
668 size = (Guint)ftell(f);
673 //~ work around a bug in cygwin's implementation of fseek
677 fseeko(f, -(int)pos, SEEK_END);
678 bufPos = (Guint)ftello(f);
680 fseek64(f, -(int)pos, SEEK_END);
681 bufPos = (Guint)ftell64(f);
683 fseek(f, -(int)pos, SEEK_END);
684 bufPos = (Guint)ftell(f);
687 bufPtr = bufEnd = buf;
690 void FileStream::moveStart(int delta) {
692 bufPtr = bufEnd = buf;
696 //------------------------------------------------------------------------
698 //------------------------------------------------------------------------
700 MemStream::MemStream(char *bufA, Guint lengthA, Object *dictA):
705 bufEnd = buf + length;
709 MemStream::~MemStream() {
715 Stream *MemStream::makeSubStream(Guint start, GBool limited,
716 Guint lengthA, Object *dictA) {
719 if (!limited || start + lengthA > length) {
720 newLength = length - start;
724 return new MemStream(buf + start, newLength, dictA);
727 void MemStream::reset() {
729 #ifndef NO_DECRYPTION
736 void MemStream::close() {
739 void MemStream::setPos(Guint pos, int dir) {
750 bufPtr = bufEnd - pos;
755 void MemStream::moveStart(int delta) {
760 #ifndef NO_DECRYPTION
761 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
762 int objNum, int objGen) {
766 this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
768 newBuf = (char *)gmalloc(bufEnd - buf);
769 for (p = buf, q = newBuf; p < bufEnd; ++p, ++q) {
770 *q = (char)decrypt->decryptByte((Guchar)*p);
772 bufEnd = newBuf + (bufEnd - buf);
773 bufPtr = newBuf + (bufPtr - buf);
780 //------------------------------------------------------------------------
782 //------------------------------------------------------------------------
784 EmbedStream::EmbedStream(Stream *strA, Object *dictA):
789 EmbedStream::~EmbedStream() {
792 Stream *EmbedStream::makeSubStream(Guint start, GBool limited,
793 Guint length, Object *dictA) {
794 error(-1, "Internal: called makeSubStream() on EmbedStream");
798 void EmbedStream::setPos(Guint pos, int dir) {
799 error(-1, "Internal: called setPos() on EmbedStream");
802 Guint EmbedStream::getStart() {
803 error(-1, "Internal: called getStart() on EmbedStream");
807 void EmbedStream::moveStart(int delta) {
808 error(-1, "Internal: called moveStart() on EmbedStream");
811 //------------------------------------------------------------------------
813 //------------------------------------------------------------------------
815 ASCIIHexStream::ASCIIHexStream(Stream *strA):
821 ASCIIHexStream::~ASCIIHexStream() {
825 void ASCIIHexStream::reset() {
831 int ASCIIHexStream::lookChar() {
842 } while (isspace(c1));
850 } while (isspace(c2));
855 if (c1 >= '0' && c1 <= '9') {
857 } else if (c1 >= 'A' && c1 <= 'F') {
858 x = (c1 - 'A' + 10) << 4;
859 } else if (c1 >= 'a' && c1 <= 'f') {
860 x = (c1 - 'a' + 10) << 4;
861 } else if (c1 == EOF) {
865 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
868 if (c2 >= '0' && c2 <= '9') {
870 } else if (c2 >= 'A' && c2 <= 'F') {
872 } else if (c2 >= 'a' && c2 <= 'f') {
874 } else if (c2 == EOF) {
878 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
884 GString *ASCIIHexStream::getPSFilter(char *indent) {
887 if (!(s = str->getPSFilter(indent))) {
890 s->append(indent)->append("/ASCIIHexDecode filter\n");
894 GBool ASCIIHexStream::isBinary(GBool last) {
895 return str->isBinary(gFalse);
898 //------------------------------------------------------------------------
900 //------------------------------------------------------------------------
902 ASCII85Stream::ASCII85Stream(Stream *strA):
908 ASCII85Stream::~ASCII85Stream() {
912 void ASCII85Stream::reset() {
918 int ASCII85Stream::lookChar() {
927 c[0] = str->getChar();
928 } while (c[0] == '\n' || c[0] == '\r');
929 if (c[0] == '~' || c[0] == EOF) {
933 } else if (c[0] == 'z') {
934 b[0] = b[1] = b[2] = b[3] = 0;
937 for (k = 1; k < 5; ++k) {
939 c[k] = str->getChar();
940 } while (c[k] == '\n' || c[k] == '\r');
941 if (c[k] == '~' || c[k] == EOF)
945 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
946 for (++k; k < 5; ++k)
951 for (k = 0; k < 5; ++k)
952 t = t * 85 + (c[k] - 0x21);
953 for (k = 3; k >= 0; --k) {
954 b[k] = (int)(t & 0xff);
962 GString *ASCII85Stream::getPSFilter(char *indent) {
965 if (!(s = str->getPSFilter(indent))) {
968 s->append(indent)->append("/ASCII85Decode filter\n");
972 GBool ASCII85Stream::isBinary(GBool last) {
973 return str->isBinary(gFalse);
976 //------------------------------------------------------------------------
978 //------------------------------------------------------------------------
980 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
981 int bits, int earlyA):
983 if (predictor != 1) {
984 pred = new StreamPredictor(this, predictor, columns, colors, bits);
994 LZWStream::~LZWStream() {
1001 int LZWStream::getChar() {
1003 return pred->getChar();
1008 if (seqIndex >= seqLength) {
1009 if (!processNextCode()) {
1013 return seqBuf[seqIndex++];
1016 int LZWStream::lookChar() {
1018 return pred->lookChar();
1023 if (seqIndex >= seqLength) {
1024 if (!processNextCode()) {
1028 return seqBuf[seqIndex];
1031 int LZWStream::getRawChar() {
1035 if (seqIndex >= seqLength) {
1036 if (!processNextCode()) {
1040 return seqBuf[seqIndex++];
1043 void LZWStream::reset() {
1050 GBool LZWStream::processNextCode() {
1060 // check for eod and clear-table codes
1063 if (code == EOF || code == 257) {
1071 if (nextCode >= 4097) {
1072 error(getPos(), "Bad LZW stream - expected clear-table code");
1076 // process the next code
1077 nextLength = seqLength + 1;
1081 } else if (code < nextCode) {
1082 seqLength = table[code].length;
1083 for (i = seqLength - 1, j = code; i > 0; --i) {
1084 seqBuf[i] = table[j].tail;
1088 } else if (code == nextCode) {
1089 seqBuf[seqLength] = newChar;
1092 error(getPos(), "Bad LZW stream - unexpected code");
1096 newChar = seqBuf[0];
1100 table[nextCode].length = nextLength;
1101 table[nextCode].head = prevCode;
1102 table[nextCode].tail = newChar;
1104 if (nextCode + early == 512)
1106 else if (nextCode + early == 1024)
1108 else if (nextCode + early == 2048)
1119 void LZWStream::clearTable() {
1122 seqIndex = seqLength = 0;
1126 int LZWStream::getCode() {
1130 while (inputBits < nextBits) {
1131 if ((c = str->getChar()) == EOF)
1133 inputBuf = (inputBuf << 8) | (c & 0xff);
1136 code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
1137 inputBits -= nextBits;
1141 GString *LZWStream::getPSFilter(char *indent) {
1147 if (!(s = str->getPSFilter(indent))) {
1150 s->append(indent)->append("/LZWDecode filter\n");
1154 GBool LZWStream::isBinary(GBool last) {
1155 return str->isBinary(gTrue);
1158 //------------------------------------------------------------------------
1160 //------------------------------------------------------------------------
1162 RunLengthStream::RunLengthStream(Stream *strA):
1163 FilterStream(strA) {
1164 bufPtr = bufEnd = buf;
1168 RunLengthStream::~RunLengthStream() {
1172 void RunLengthStream::reset() {
1174 bufPtr = bufEnd = buf;
1178 GString *RunLengthStream::getPSFilter(char *indent) {
1181 if (!(s = str->getPSFilter(indent))) {
1184 s->append(indent)->append("/RunLengthDecode filter\n");
1188 GBool RunLengthStream::isBinary(GBool last) {
1189 return str->isBinary(gTrue);
1192 GBool RunLengthStream::fillBuf() {
1199 if (c == 0x80 || c == EOF) {
1205 for (i = 0; i < n; ++i)
1206 buf[i] = (char)str->getChar();
1210 for (i = 0; i < n; ++i)
1218 //------------------------------------------------------------------------
1220 //------------------------------------------------------------------------
1222 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1223 GBool byteAlignA, int columnsA, int rowsA,
1224 GBool endOfBlockA, GBool blackA):
1225 FilterStream(strA) {
1226 encoding = encodingA;
1227 endOfLine = endOfLineA;
1228 byteAlign = byteAlignA;
1231 endOfBlock = endOfBlockA;
1233 refLine = (short *)gmalloc((columns + 3) * sizeof(short));
1234 codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
1238 nextLine2D = encoding < 0;
1241 codingLine[1] = refLine[2] = columns;
1247 CCITTFaxStream::~CCITTFaxStream() {
1253 void CCITTFaxStream::reset() {
1259 nextLine2D = encoding < 0;
1262 codingLine[1] = refLine[2] = columns;
1266 // get initial end-of-line marker and 2D encoding tag
1268 if (lookBits(12) == 0x001) {
1272 for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
1273 if (n == 11 && lookBits(12) == 0x001) {
1278 nextLine2D = !lookBits(1);
1283 int CCITTFaxStream::lookChar() {
1284 short code1, code2, code3;
1293 // if at eof just return EOF
1294 if (eof && codingLine[a0] >= columns) {
1298 // read the next row
1302 if (codingLine[a0] >= columns) {
1306 for (i = 0; codingLine[i] < columns; ++i)
1307 refLine[i] = codingLine[i];
1308 refLine[i] = refLine[i + 1] = columns;
1310 a0New = codingLine[a0 = 0] = 0;
1312 code1 = getTwoDimCode();
1315 if (refLine[b1] < columns) {
1316 a0New = refLine[b1 + 1];
1321 if ((a0 & 1) == 0) {
1324 code1 += code3 = getWhiteCode();
1325 } while (code3 >= 64);
1327 code2 += code3 = getBlackCode();
1328 } while (code3 >= 64);
1332 code1 += code3 = getBlackCode();
1333 } while (code3 >= 64);
1335 code2 += code3 = getWhiteCode();
1336 } while (code3 >= 64);
1338 codingLine[a0 + 1] = a0New + code1;
1340 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1342 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1346 a0New = codingLine[++a0] = refLine[b1];
1347 if (refLine[b1] < columns) {
1349 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1354 a0New = codingLine[++a0] = refLine[b1] + 1;
1355 if (refLine[b1] < columns) {
1357 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1362 a0New = codingLine[++a0] = refLine[b1] - 1;
1364 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1368 a0New = codingLine[++a0] = refLine[b1] + 2;
1369 if (refLine[b1] < columns) {
1371 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1376 a0New = codingLine[++a0] = refLine[b1] - 2;
1378 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1382 a0New = codingLine[++a0] = refLine[b1] + 3;
1383 if (refLine[b1] < columns) {
1385 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1390 a0New = codingLine[++a0] = refLine[b1] - 3;
1392 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1397 codingLine[a0 = 0] = columns;
1400 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1409 } while (codingLine[a0] < columns);
1413 codingLine[a0 = 0] = 0;
1417 code1 += code3 = getWhiteCode();
1418 } while (code3 >= 64);
1419 codingLine[a0+1] = codingLine[a0] + code1;
1421 if (codingLine[a0] >= columns)
1425 code2 += code3 = getBlackCode();
1426 } while (code3 >= 64);
1427 codingLine[a0+1] = codingLine[a0] + code2;
1429 if (codingLine[a0] >= columns)
1434 if (codingLine[a0] != columns) {
1435 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
1441 // byte-align the row
1446 // check for end-of-line marker, skipping over any extra zero bits
1448 if (!endOfBlock && row == rows - 1) {
1451 code1 = lookBits(12);
1452 while (code1 == 0) {
1454 code1 = lookBits(12);
1456 if (code1 == 0x001) {
1459 } else if (code1 == EOF) {
1464 // get 2D encoding tag
1465 if (!eof && encoding > 0) {
1466 nextLine2D = !lookBits(1);
1470 // check for end-of-block marker
1471 if (endOfBlock && gotEOL) {
1472 code1 = lookBits(12);
1473 if (code1 == 0x001) {
1479 if (encoding >= 0) {
1480 for (i = 0; i < 4; ++i) {
1481 code1 = lookBits(12);
1482 if (code1 != 0x001) {
1483 error(getPos(), "Bad RTC code in CCITTFax stream");
1497 // This looks for an end-of-line marker after an error, however
1498 // some (most?) CCITT streams in PDF files don't use end-of-line
1499 // markers, and the just-plow-on technique works better in those
1508 code1 = look13Bits();
1509 } while ((code1 >> 1) != 0x001);
1511 codingLine[++a0] = columns;
1514 nextLine2D = !(code1 & 1);
1520 outputBits = codingLine[1] - codingLine[0];
1521 if (outputBits == 0) {
1523 outputBits = codingLine[2] - codingLine[1];
1530 if (outputBits >= 8) {
1531 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1532 if ((outputBits -= 8) == 0) {
1534 if (codingLine[a0] < columns) {
1535 outputBits = codingLine[a0 + 1] - codingLine[a0];
1542 if (outputBits > bits) {
1545 if ((a0 & 1) == 0) {
1546 ret |= 0xff >> (8 - i);
1552 if ((a0 & 1) == 0) {
1553 ret |= (0xff >> (8 - i)) << bits;
1557 if (codingLine[a0] < columns) {
1558 outputBits = codingLine[a0 + 1] - codingLine[a0];
1561 } while (bits > 0 && codingLine[a0] < columns);
1563 buf = black ? (ret ^ 0xff) : ret;
1567 short CCITTFaxStream::getTwoDimCode() {
1572 code = 0; // make gcc happy
1575 p = &twoDimTab1[code];
1581 for (n = 1; n <= 7; ++n) {
1586 p = &twoDimTab1[code];
1593 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1597 short CCITTFaxStream::getWhiteCode() {
1602 code = 0; // make gcc happy
1604 code = lookBits(12);
1605 if ((code >> 5) == 0) {
1606 p = &whiteTab1[code];
1608 p = &whiteTab2[code >> 3];
1615 for (n = 1; n <= 9; ++n) {
1620 p = &whiteTab2[code];
1626 for (n = 11; n <= 12; ++n) {
1631 p = &whiteTab1[code];
1638 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1639 // eat a bit and return a positive number so that the caller doesn't
1640 // go into an infinite loop
1645 short CCITTFaxStream::getBlackCode() {
1650 code = 0; // make gcc happy
1652 code = lookBits(13);
1653 if ((code >> 7) == 0) {
1654 p = &blackTab1[code];
1655 } else if ((code >> 9) == 0) {
1656 p = &blackTab2[(code >> 1) - 64];
1658 p = &blackTab3[code >> 7];
1665 for (n = 2; n <= 6; ++n) {
1670 p = &blackTab3[code];
1676 for (n = 7; n <= 12; ++n) {
1682 p = &blackTab2[code - 64];
1689 for (n = 10; n <= 13; ++n) {
1694 p = &blackTab1[code];
1701 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
1702 // eat a bit and return a positive number so that the caller doesn't
1703 // go into an infinite loop
1708 short CCITTFaxStream::lookBits(int n) {
1711 while (inputBits < n) {
1712 if ((c = str->getChar()) == EOF) {
1713 if (inputBits == 0) {
1716 // near the end of the stream, the caller may ask for more bits
1717 // than are available, but there may still be a valid code in
1718 // however many bits are available -- we need to return correct
1719 // data in this case
1720 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
1722 inputBuf = (inputBuf << 8) + c;
1725 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1728 GString *CCITTFaxStream::getPSFilter(char *indent) {
1732 if (!(s = str->getPSFilter(indent))) {
1735 s->append(indent)->append("<< ");
1736 if (encoding != 0) {
1737 sprintf(s1, "/K %d ", encoding);
1741 s->append("/EndOfLine true ");
1744 s->append("/EncodedByteAlign true ");
1746 sprintf(s1, "/Columns %d ", columns);
1749 sprintf(s1, "/Rows %d ", rows);
1753 s->append("/EndOfBlock false ");
1756 s->append("/BlackIs1 true ");
1758 s->append(">> /CCITTFaxDecode filter\n");
1762 GBool CCITTFaxStream::isBinary(GBool last) {
1763 return str->isBinary(gTrue);
1766 //------------------------------------------------------------------------
1768 //------------------------------------------------------------------------
1770 // IDCT constants (20.12 fixed point format)
1771 #define dctCos1 4017 // cos(pi/16)
1772 #define dctSin1 799 // sin(pi/16)
1773 #define dctCos3 3406 // cos(3*pi/16)
1774 #define dctSin3 2276 // sin(3*pi/16)
1775 #define dctCos6 1567 // cos(6*pi/16)
1776 #define dctSin6 3784 // sin(6*pi/16)
1777 #define dctSqrt2 5793 // sqrt(2)
1778 #define dctSqrt1d2 2896 // sqrt(2) / 2
1780 // color conversion parameters (16.16 fixed point format)
1781 #define dctCrToR 91881 // 1.4020
1782 #define dctCbToG -22553 // -0.3441363
1783 #define dctCrToG -46802 // -0.71413636
1784 #define dctCbToB 116130 // 1.772
1786 // clip [-256,511] --> [0,255]
1787 #define dctClipOffset 256
1788 static Guchar dctClip[768];
1789 static int dctClipInit = 0;
1791 // zig zag decode map
1792 static int dctZigZag[64] = {
1798 5, 12, 19, 26, 33, 40,
1799 48, 41, 34, 27, 20, 13, 6,
1800 7, 14, 21, 28, 35, 42, 49, 56,
1801 57, 50, 43, 36, 29, 22, 15,
1802 23, 30, 37, 44, 51, 58,
1810 DCTStream::DCTStream(Stream *strA):
1811 FilterStream(strA) {
1814 progressive = interleaved = gFalse;
1816 mcuWidth = mcuHeight = 0;
1820 for (i = 0; i < 4; ++i) {
1821 for (j = 0; j < 32; ++j) {
1822 rowBuf[i][j] = NULL;
1828 for (i = -256; i < 0; ++i)
1829 dctClip[dctClipOffset + i] = 0;
1830 for (i = 0; i < 256; ++i)
1831 dctClip[dctClipOffset + i] = i;
1832 for (i = 256; i < 512; ++i)
1833 dctClip[dctClipOffset + i] = 255;
1838 DCTStream::~DCTStream() {
1842 if (progressive || !interleaved) {
1843 for (i = 0; i < numComps; ++i) {
1847 for (i = 0; i < numComps; ++i) {
1848 for (j = 0; j < mcuHeight; ++j) {
1849 gfree(rowBuf[i][j]);
1855 void DCTStream::reset() {
1856 int minHSample, minVSample;
1861 progressive = interleaved = gFalse;
1865 numDCHuffTables = 0;
1866 numACHuffTables = 0;
1868 gotAdobeMarker = gFalse;
1869 restartInterval = 0;
1871 if (!readHeader()) {
1877 mcuWidth = minHSample = compInfo[0].hSample;
1878 mcuHeight = minVSample = compInfo[0].vSample;
1879 for (i = 1; i < numComps; ++i) {
1880 if (compInfo[i].hSample < minHSample)
1881 minHSample = compInfo[i].hSample;
1882 if (compInfo[i].vSample < minVSample)
1883 minVSample = compInfo[i].vSample;
1884 if (compInfo[i].hSample > mcuWidth)
1885 mcuWidth = compInfo[i].hSample;
1886 if (compInfo[i].vSample > mcuHeight)
1887 mcuHeight = compInfo[i].vSample;
1889 for (i = 0; i < numComps; ++i) {
1890 compInfo[i].hSample /= minHSample;
1891 compInfo[i].vSample /= minVSample;
1893 mcuWidth = (mcuWidth / minHSample) * 8;
1894 mcuHeight = (mcuHeight / minVSample) * 8;
1896 // figure out color transform
1897 if (!gotAdobeMarker && numComps == 3) {
1898 if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
1903 if (progressive || !interleaved) {
1905 // allocate a buffer for the whole image
1906 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
1907 bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
1908 for (i = 0; i < numComps; ++i) {
1909 frameBuf[i] = (int *)gmalloc(bufWidth * bufHeight * sizeof(int));
1910 memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
1913 // read the image data
1915 restartMarker = 0xd0;
1918 } while (readHeader());
1923 // initialize counters
1930 // allocate a buffer for one row of MCUs
1931 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
1932 for (i = 0; i < numComps; ++i) {
1933 for (j = 0; j < mcuHeight; ++j) {
1934 rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
1938 // initialize counters
1944 restartMarker = 0xd0;
1949 int DCTStream::getChar() {
1955 if (progressive || !interleaved) {
1956 c = frameBuf[comp][y * bufWidth + x];
1957 if (++comp == numComps) {
1965 if (dy >= mcuHeight) {
1966 if (!readMCURow()) {
1974 c = rowBuf[comp][dy][x];
1975 if (++comp == numComps) {
1990 int DCTStream::lookChar() {
1994 if (progressive || !interleaved) {
1995 return frameBuf[comp][y * bufWidth + x];
1997 if (dy >= mcuHeight) {
1998 if (!readMCURow()) {
2006 return rowBuf[comp][dy][x];
2010 void DCTStream::restart() {
2014 restartCtr = restartInterval;
2015 for (i = 0; i < numComps; ++i) {
2016 compInfo[i].prevDC = 0;
2021 // Read one row of MCUs from a sequential JPEG stream.
2022 GBool DCTStream::readMCURow() {
2026 int pY, pCb, pCr, pR, pG, pB;
2027 int h, v, horiz, vert, hSub, vSub;
2028 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2031 for (x1 = 0; x1 < width; x1 += mcuWidth) {
2033 // deal with restart marker
2034 if (restartInterval > 0 && restartCtr == 0) {
2036 if (c != restartMarker) {
2037 error(getPos(), "Bad DCT data: incorrect restart marker");
2040 if (++restartMarker == 0xd8)
2041 restartMarker = 0xd0;
2046 for (cc = 0; cc < numComps; ++cc) {
2047 h = compInfo[cc].hSample;
2048 v = compInfo[cc].vSample;
2049 horiz = mcuWidth / h;
2050 vert = mcuHeight / v;
2053 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2054 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2055 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2056 &acHuffTables[scanInfo.acHuffTable[cc]],
2057 &compInfo[cc].prevDC,
2061 transformDataUnit(quantTables[compInfo[cc].quantTable],
2063 if (hSub == 1 && vSub == 1) {
2064 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2065 p1 = &rowBuf[cc][y2+y3][x1+x2];
2075 } else if (hSub == 2 && vSub == 2) {
2076 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2077 p1 = &rowBuf[cc][y2+y3][x1+x2];
2078 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
2079 p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
2080 p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
2081 p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
2082 p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
2083 p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
2084 p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
2085 p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
2086 p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
2090 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2091 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2092 for (y5 = 0; y5 < vSub; ++y5)
2093 for (x5 = 0; x5 < hSub; ++x5)
2094 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
2104 // color space conversion
2106 // convert YCbCr to RGB
2107 if (numComps == 3) {
2108 for (y2 = 0; y2 < mcuHeight; ++y2) {
2109 for (x2 = 0; x2 < mcuWidth; ++x2) {
2110 pY = rowBuf[0][y2][x1+x2];
2111 pCb = rowBuf[1][y2][x1+x2] - 128;
2112 pCr = rowBuf[2][y2][x1+x2] - 128;
2113 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2114 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
2115 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2116 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
2117 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2118 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
2121 // convert YCbCrK to CMYK (K is passed through unchanged)
2122 } else if (numComps == 4) {
2123 for (y2 = 0; y2 < mcuHeight; ++y2) {
2124 for (x2 = 0; x2 < mcuWidth; ++x2) {
2125 pY = rowBuf[0][y2][x1+x2];
2126 pCb = rowBuf[1][y2][x1+x2] - 128;
2127 pCr = rowBuf[2][y2][x1+x2] - 128;
2128 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2129 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2130 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2131 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2132 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2133 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2142 // Read one scan from a progressive or non-interleaved JPEG stream.
2143 void DCTStream::readScan() {
2145 int x1, y1, dy1, x2, y2, y3, cc, i;
2146 int h, v, horiz, vert, hSub, vSub;
2150 if (scanInfo.numComps == 1) {
2151 for (cc = 0; cc < numComps; ++cc) {
2152 if (scanInfo.comp[cc]) {
2156 dy1 = mcuHeight / compInfo[cc].vSample;
2161 for (y1 = 0; y1 < bufHeight; y1 += dy1) {
2162 for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
2164 // deal with restart marker
2165 if (restartInterval > 0 && restartCtr == 0) {
2167 if (c != restartMarker) {
2168 error(getPos(), "Bad DCT data: incorrect restart marker");
2171 if (++restartMarker == 0xd8) {
2172 restartMarker = 0xd0;
2178 for (cc = 0; cc < numComps; ++cc) {
2179 if (!scanInfo.comp[cc]) {
2183 h = compInfo[cc].hSample;
2184 v = compInfo[cc].vSample;
2185 horiz = mcuWidth / h;
2186 vert = mcuHeight / v;
2189 for (y2 = 0; y2 < dy1; y2 += vert) {
2190 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2192 // pull out the current values
2193 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2194 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2203 p1 += bufWidth * vSub;
2206 // read one data unit
2208 if (!readProgressiveDataUnit(
2209 &dcHuffTables[scanInfo.dcHuffTable[cc]],
2210 &acHuffTables[scanInfo.acHuffTable[cc]],
2211 &compInfo[cc].prevDC,
2216 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2217 &acHuffTables[scanInfo.acHuffTable[cc]],
2218 &compInfo[cc].prevDC,
2224 // add the data unit into frameBuf
2225 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2226 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2235 p1 += bufWidth * vSub;
2245 // Read one data unit from a sequential JPEG stream.
2246 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2247 DCTHuffTable *acHuffTable,
2248 int *prevDC, int data[64]) {
2253 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2257 if ((amp = readAmp(size)) == 9999) {
2263 data[0] = *prevDC += amp;
2264 for (i = 1; i < 64; ++i) {
2270 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
2279 run += (c >> 4) & 0x0f;
2281 amp = readAmp(size);
2293 // Read one data unit from a sequential JPEG stream.
2294 GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
2295 DCTHuffTable *acHuffTable,
2296 int *prevDC, int data[64]) {
2297 int run, size, amp, bit, c;
2300 // get the DC coefficient
2301 i = scanInfo.firstCoeff;
2303 if (scanInfo.ah == 0) {
2304 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2308 if ((amp = readAmp(size)) == 9999) {
2314 data[0] += (*prevDC += amp) << scanInfo.al;
2316 if ((bit = readBit()) == 9999) {
2319 data[0] += bit << scanInfo.al;
2323 if (scanInfo.lastCoeff == 0) {
2327 // check for an EOB run
2329 while (i <= scanInfo.lastCoeff) {
2332 if ((bit = readBit()) == EOF) {
2336 data[j] += 1 << scanInfo.al;
2344 // read the AC coefficients
2345 while (i <= scanInfo.lastCoeff) {
2346 if ((c = readHuffSym(acHuffTable)) == 9999) {
2358 if ((bit = readBit()) == EOF) {
2362 data[j] += 1 << scanInfo.al;
2368 } else if ((c & 0x0f) == 0x00) {
2371 for (k = 0; k < j; ++k) {
2372 if ((bit = readBit()) == EOF) {
2375 eobRun = (eobRun << 1) | bit;
2378 while (i <= scanInfo.lastCoeff) {
2381 if ((bit = readBit()) == EOF) {
2385 data[j] += 1 << scanInfo.al;
2392 // zero run and one AC coefficient
2394 run = (c >> 4) & 0x0f;
2396 if ((amp = readAmp(size)) == 9999) {
2402 while (data[j] != 0) {
2403 if ((bit = readBit()) == EOF) {
2407 data[j] += 1 << scanInfo.al;
2413 data[j] = amp << scanInfo.al;
2420 // Decode a progressive JPEG image.
2421 void DCTStream::decodeImage() {
2425 int pY, pCb, pCr, pR, pG, pB;
2426 int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2427 int h, v, horiz, vert, hSub, vSub;
2430 for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
2431 for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
2432 for (cc = 0; cc < numComps; ++cc) {
2433 quantTable = quantTables[compInfo[cc].quantTable];
2434 h = compInfo[cc].hSample;
2435 v = compInfo[cc].vSample;
2436 horiz = mcuWidth / h;
2437 vert = mcuHeight / v;
2440 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2441 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2443 // pull out the coded data unit
2444 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2445 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2447 dataIn[i+1] = p1[1];
2448 dataIn[i+2] = p1[2];
2449 dataIn[i+3] = p1[3];
2450 dataIn[i+4] = p1[4];
2451 dataIn[i+5] = p1[5];
2452 dataIn[i+6] = p1[6];
2453 dataIn[i+7] = p1[7];
2454 p1 += bufWidth * vSub;
2458 transformDataUnit(quantTable, dataIn, dataOut);
2460 // store back into frameBuf, doing replication for
2461 // subsampled components
2462 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2463 if (hSub == 1 && vSub == 1) {
2464 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2465 p1[0] = dataOut[i] & 0xff;
2466 p1[1] = dataOut[i+1] & 0xff;
2467 p1[2] = dataOut[i+2] & 0xff;
2468 p1[3] = dataOut[i+3] & 0xff;
2469 p1[4] = dataOut[i+4] & 0xff;
2470 p1[5] = dataOut[i+5] & 0xff;
2471 p1[6] = dataOut[i+6] & 0xff;
2472 p1[7] = dataOut[i+7] & 0xff;
2475 } else if (hSub == 2 && vSub == 2) {
2477 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2478 p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
2479 p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
2480 p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
2481 p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
2482 p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
2483 p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
2484 p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
2485 p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
2491 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2492 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2494 for (y5 = 0; y5 < vSub; ++y5) {
2495 for (x5 = 0; x5 < hSub; ++x5) {
2496 p2[x5] = dataOut[i] & 0xff;
2502 p1 += bufWidth * vSub;
2509 // color space conversion
2511 // convert YCbCr to RGB
2512 if (numComps == 3) {
2513 for (y2 = 0; y2 < mcuHeight; ++y2) {
2514 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2515 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2516 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2517 for (x2 = 0; x2 < mcuWidth; ++x2) {
2521 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2522 *p0++ = dctClip[dctClipOffset + pR];
2523 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2525 *p1++ = dctClip[dctClipOffset + pG];
2526 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2527 *p2++ = dctClip[dctClipOffset + pB];
2530 // convert YCbCrK to CMYK (K is passed through unchanged)
2531 } else if (numComps == 4) {
2532 for (y2 = 0; y2 < mcuHeight; ++y2) {
2533 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2534 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2535 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2536 for (x2 = 0; x2 < mcuWidth; ++x2) {
2540 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2541 *p0++ = 255 - dctClip[dctClipOffset + pR];
2542 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2544 *p1++ = 255 - dctClip[dctClipOffset + pG];
2545 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2546 *p2++ = 255 - dctClip[dctClipOffset + pB];
2555 // Transform one data unit -- this performs the dequantization and
2556 // IDCT steps. This IDCT algorithm is taken from:
2557 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2558 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2559 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2561 // The stage numbers mentioned in the comments refer to Figure 1 in this
2563 void DCTStream::transformDataUnit(Guchar *quantTable,
2564 int dataIn[64], Guchar dataOut[64]) {
2565 int v0, v1, v2, v3, v4, v5, v6, v7, t;
2570 for (i = 0; i < 64; ++i) {
2571 dataIn[i] *= quantTable[i];
2574 // inverse DCT on rows
2575 for (i = 0; i < 64; i += 8) {
2578 // check for all-zero AC coefficients
2579 if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
2580 p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
2581 t = (dctSqrt2 * p[0] + 512) >> 10;
2594 v0 = (dctSqrt2 * p[0] + 128) >> 8;
2595 v1 = (dctSqrt2 * p[4] + 128) >> 8;
2598 v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
2599 v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
2604 t = (v0 - v1+ 1) >> 1;
2605 v0 = (v0 + v1 + 1) >> 1;
2607 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2608 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2610 t = (v4 - v6 + 1) >> 1;
2611 v4 = (v4 + v6 + 1) >> 1;
2613 t = (v7 + v5 + 1) >> 1;
2614 v5 = (v7 - v5 + 1) >> 1;
2618 t = (v0 - v3 + 1) >> 1;
2619 v0 = (v0 + v3 + 1) >> 1;
2621 t = (v1 - v2 + 1) >> 1;
2622 v1 = (v1 + v2 + 1) >> 1;
2624 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2625 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2627 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2628 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2642 // inverse DCT on columns
2643 for (i = 0; i < 8; ++i) {
2646 // check for all-zero AC coefficients
2647 if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
2648 p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
2649 t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
2662 v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
2663 v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
2666 v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
2667 v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
2672 t = (v0 - v1 + 1) >> 1;
2673 v0 = (v0 + v1 + 1) >> 1;
2675 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2676 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2678 t = (v4 - v6 + 1) >> 1;
2679 v4 = (v4 + v6 + 1) >> 1;
2681 t = (v7 + v5 + 1) >> 1;
2682 v5 = (v7 - v5 + 1) >> 1;
2686 t = (v0 - v3 + 1) >> 1;
2687 v0 = (v0 + v3 + 1) >> 1;
2689 t = (v1 - v2 + 1) >> 1;
2690 v1 = (v1 + v2 + 1) >> 1;
2692 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2693 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2695 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2696 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2710 // convert to 8-bit integers
2711 for (i = 0; i < 64; ++i) {
2712 dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
2716 int DCTStream::readHuffSym(DCTHuffTable *table) {
2724 // add a bit to the code
2725 if ((bit = readBit()) == EOF)
2727 code = (code << 1) + bit;
2731 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2732 code -= table->firstCode[codeBits];
2733 return table->sym[table->firstSym[codeBits] + code];
2735 } while (codeBits < 16);
2737 error(getPos(), "Bad Huffman code in DCT stream");
2741 int DCTStream::readAmp(int size) {
2746 for (bits = 0; bits < size; ++bits) {
2747 if ((bit = readBit()) == EOF)
2749 amp = (amp << 1) + bit;
2751 if (amp < (1 << (size - 1)))
2752 amp -= (1 << size) - 1;
2756 int DCTStream::readBit() {
2760 if (inputBits == 0) {
2761 if ((c = str->getChar()) == EOF)
2765 c2 = str->getChar();
2766 } while (c2 == 0xff);
2768 error(getPos(), "Bad DCT data: missing 00 after ff");
2775 bit = (inputBuf >> (inputBits - 1)) & 1;
2780 GBool DCTStream::readHeader() {
2792 if (!readBaselineSOF()) {
2797 if (!readProgressiveSOF()) {
2802 if (!readHuffmanTables()) {
2812 if (!readScanInfo()) {
2818 if (!readQuantTables()) {
2823 if (!readRestartInterval()) {
2828 if (!readAdobeMarker()) {
2833 error(getPos(), "Bad DCT header");
2836 // skip APPn / COM / etc.
2839 for (i = 0; i < n; ++i) {
2843 error(getPos(), "Unknown DCT marker <%02x>", c);
2853 GBool DCTStream::readBaselineSOF() {
2860 prec = str->getChar();
2863 numComps = str->getChar();
2865 error(getPos(), "Bad DCT precision %d", prec);
2868 for (i = 0; i < numComps; ++i) {
2869 compInfo[i].id = str->getChar();
2871 compInfo[i].hSample = (c >> 4) & 0x0f;
2872 compInfo[i].vSample = c & 0x0f;
2873 compInfo[i].quantTable = str->getChar();
2875 progressive = gFalse;
2879 GBool DCTStream::readProgressiveSOF() {
2886 prec = str->getChar();
2889 numComps = str->getChar();
2891 error(getPos(), "Bad DCT precision %d", prec);
2894 for (i = 0; i < numComps; ++i) {
2895 compInfo[i].id = str->getChar();
2897 compInfo[i].hSample = (c >> 4) & 0x0f;
2898 compInfo[i].vSample = c & 0x0f;
2899 compInfo[i].quantTable = str->getChar();
2901 progressive = gTrue;
2905 GBool DCTStream::readScanInfo() {
2910 length = read16() - 2;
2911 scanInfo.numComps = str->getChar();
2913 if (length != 2 * scanInfo.numComps + 3) {
2914 error(getPos(), "Bad DCT scan info block");
2917 interleaved = scanInfo.numComps == numComps;
2918 for (j = 0; j < numComps; ++j) {
2919 scanInfo.comp[j] = gFalse;
2921 for (i = 0; i < scanInfo.numComps; ++i) {
2922 id = str->getChar();
2923 for (j = 0; j < numComps; ++j) {
2924 if (id == compInfo[j].id) {
2928 if (j == numComps) {
2929 error(getPos(), "Bad DCT component ID in scan info block");
2932 scanInfo.comp[j] = gTrue;
2934 scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
2935 scanInfo.acHuffTable[j] = c & 0x0f;
2937 scanInfo.firstCoeff = str->getChar();
2938 scanInfo.lastCoeff = str->getChar();
2940 scanInfo.ah = (c >> 4) & 0x0f;
2941 scanInfo.al = c & 0x0f;
2945 GBool DCTStream::readQuantTables() {
2950 length = read16() - 2;
2951 while (length > 0) {
2952 index = str->getChar();
2953 if ((index & 0xf0) || index >= 4) {
2954 error(getPos(), "Bad DCT quantization table");
2957 if (index == numQuantTables)
2958 numQuantTables = index + 1;
2959 for (i = 0; i < 64; ++i)
2960 quantTables[index][dctZigZag[i]] = str->getChar();
2966 GBool DCTStream::readHuffmanTables() {
2975 length = read16() - 2;
2976 while (length > 0) {
2977 index = str->getChar();
2979 if ((index & 0x0f) >= 4) {
2980 error(getPos(), "Bad DCT Huffman table");
2985 if (index >= numACHuffTables)
2986 numACHuffTables = index+1;
2987 tbl = &acHuffTables[index];
2989 if (index >= numDCHuffTables)
2990 numDCHuffTables = index+1;
2991 tbl = &dcHuffTables[index];
2995 for (i = 1; i <= 16; ++i) {
2997 tbl->firstSym[i] = sym;
2998 tbl->firstCode[i] = code;
2999 tbl->numCodes[i] = c;
3001 code = (code + c) << 1;
3004 for (i = 0; i < sym; ++i)
3005 tbl->sym[i] = str->getChar();
3011 GBool DCTStream::readRestartInterval() {
3016 error(getPos(), "Bad DCT restart interval");
3019 restartInterval = read16();
3023 GBool DCTStream::readAdobeMarker() {
3032 for (i = 0; i < 12; ++i) {
3033 if ((c = str->getChar()) == EOF) {
3038 if (strncmp(buf, "Adobe", 5)) {
3041 colorXform = buf[11];
3042 gotAdobeMarker = gTrue;
3043 for (i = 14; i < length; ++i) {
3044 if (str->getChar() == EOF) {
3051 error(getPos(), "Bad DCT Adobe APP14 marker");
3055 GBool DCTStream::readTrailer() {
3059 if (c != 0xd9) { // EOI
3060 error(getPos(), "Bad DCT trailer");
3066 int DCTStream::readMarker() {
3072 } while (c != 0xff);
3075 } while (c == 0xff);
3076 } while (c == 0x00);
3080 int DCTStream::read16() {
3083 if ((c1 = str->getChar()) == EOF)
3085 if ((c2 = str->getChar()) == EOF)
3087 return (c1 << 8) + c2;
3090 GString *DCTStream::getPSFilter(char *indent) {
3093 if (!(s = str->getPSFilter(indent))) {
3096 s->append(indent)->append("<< >> /DCTDecode filter\n");
3100 GBool DCTStream::isBinary(GBool last) {
3101 return str->isBinary(gTrue);
3104 //------------------------------------------------------------------------
3106 //------------------------------------------------------------------------
3108 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
3109 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3112 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
3144 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
3177 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
3178 int colors, int bits):
3179 FilterStream(strA) {
3180 if (predictor != 1) {
3181 pred = new StreamPredictor(this, predictor, columns, colors, bits);
3185 litCodeTab.codes = NULL;
3186 distCodeTab.codes = NULL;
3189 FlateStream::~FlateStream() {
3190 gfree(litCodeTab.codes);
3191 gfree(distCodeTab.codes);
3198 void FlateStream::reset() {
3205 compressedBlock = gFalse;
3212 //~ need to look at window size?
3213 endOfBlock = eof = gTrue;
3214 cmf = str->getChar();
3215 flg = str->getChar();
3216 if (cmf == EOF || flg == EOF)
3218 if ((cmf & 0x0f) != 0x08) {
3219 error(getPos(), "Unknown compression method in flate stream");
3222 if ((((cmf << 8) + flg) % 31) != 0) {
3223 error(getPos(), "Bad FCHECK in flate stream");
3227 error(getPos(), "FDICT bit set in flate stream");
3234 int FlateStream::getChar() {
3238 return pred->getChar();
3240 while (remain == 0) {
3241 if (endOfBlock && eof)
3246 index = (index + 1) & flateMask;
3251 int FlateStream::lookChar() {
3255 return pred->lookChar();
3257 while (remain == 0) {
3258 if (endOfBlock && eof)
3266 int FlateStream::getRawChar() {
3269 while (remain == 0) {
3270 if (endOfBlock && eof)
3275 index = (index + 1) & flateMask;
3280 GString *FlateStream::getPSFilter(char *indent) {
3284 GBool FlateStream::isBinary(GBool last) {
3285 return str->isBinary(gTrue);
3288 void FlateStream::readSome() {
3299 if (compressedBlock) {
3300 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
3305 } else if (code1 == 256) {
3310 code2 = lengthDecode[code1].bits;
3311 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3313 len = lengthDecode[code1].first + code2;
3314 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
3316 code2 = distDecode[code1].bits;
3317 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3319 dist = distDecode[code1].first + code2;
3321 j = (index - dist) & flateMask;
3322 for (k = 0; k < len; ++k) {
3324 i = (i + 1) & flateMask;
3325 j = (j + 1) & flateMask;
3331 len = (blockLen < flateWindow) ? blockLen : flateWindow;
3332 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
3333 if ((c = str->getChar()) == EOF) {
3334 endOfBlock = eof = gTrue;
3348 error(getPos(), "Unexpected end of file in flate stream");
3349 endOfBlock = eof = gTrue;
3353 GBool FlateStream::startBlock() {
3358 // free the code tables from the previous block
3359 gfree(litCodeTab.codes);
3360 litCodeTab.codes = NULL;
3361 gfree(distCodeTab.codes);
3362 distCodeTab.codes = NULL;
3364 // read block header
3365 blockHdr = getCodeWord(3);
3370 // uncompressed block
3371 if (blockHdr == 0) {
3372 compressedBlock = gFalse;
3373 if ((c = str->getChar()) == EOF)
3375 blockLen = c & 0xff;
3376 if ((c = str->getChar()) == EOF)
3378 blockLen |= (c & 0xff) << 8;
3379 if ((c = str->getChar()) == EOF)
3382 if ((c = str->getChar()) == EOF)
3384 check |= (c & 0xff) << 8;
3385 if (check != (~blockLen & 0xffff))
3386 error(getPos(), "Bad uncompressed block length in flate stream");
3390 // compressed block with fixed codes
3391 } else if (blockHdr == 1) {
3392 compressedBlock = gTrue;
3395 // compressed block with dynamic codes
3396 } else if (blockHdr == 2) {
3397 compressedBlock = gTrue;
3398 if (!readDynamicCodes()) {
3402 // unknown block type
3407 endOfBlock = gFalse;
3411 error(getPos(), "Bad block header in flate stream");
3412 endOfBlock = eof = gTrue;
3416 void FlateStream::loadFixedCodes() {
3419 // build the literal code table
3420 for (i = 0; i <= 143; ++i) {
3423 for (i = 144; i <= 255; ++i) {
3426 for (i = 256; i <= 279; ++i) {
3429 for (i = 280; i <= 287; ++i) {
3432 compHuffmanCodes(codeLengths, flateMaxLitCodes, &litCodeTab);
3434 // build the distance code table
3435 for (i = 0; i < flateMaxDistCodes; ++i) {
3438 compHuffmanCodes(codeLengths, flateMaxDistCodes, &distCodeTab);
3441 GBool FlateStream::readDynamicCodes() {
3442 int numCodeLenCodes;
3445 int codeLenCodeLengths[flateMaxCodeLenCodes];
3446 FlateHuffmanTab codeLenCodeTab;
3447 int len, repeat, code;
3451 if ((numLitCodes = getCodeWord(5)) == EOF) {
3455 if ((numDistCodes = getCodeWord(5)) == EOF) {
3459 if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
3462 numCodeLenCodes += 4;
3463 if (numLitCodes > flateMaxLitCodes ||
3464 numDistCodes > flateMaxDistCodes ||
3465 numCodeLenCodes > flateMaxCodeLenCodes) {
3469 // build the code length code table
3470 for (i = 0; i < flateMaxCodeLenCodes; ++i) {
3471 codeLenCodeLengths[i] = 0;
3473 for (i = 0; i < numCodeLenCodes; ++i) {
3474 if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
3478 compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
3480 // build the literal and distance code tables
3484 while (i < numLitCodes + numDistCodes) {
3485 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
3489 if ((repeat = getCodeWord(2)) == EOF) {
3492 for (repeat += 3; repeat > 0; --repeat) {
3493 codeLengths[i++] = len;
3495 } else if (code == 17) {
3496 if ((repeat = getCodeWord(3)) == EOF) {
3500 for (repeat += 3; repeat > 0; --repeat) {
3501 codeLengths[i++] = 0;
3503 } else if (code == 18) {
3504 if ((repeat = getCodeWord(7)) == EOF) {
3508 for (repeat += 11; repeat > 0; --repeat) {
3509 codeLengths[i++] = 0;
3512 codeLengths[i++] = len = code;
3515 compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
3516 compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
3518 gfree(codeLenCodeTab.codes);
3522 error(getPos(), "Bad dynamic code table in flate stream");
3523 gfree(codeLenCodeTab.codes);
3527 // Convert an array <lengths> of <n> lengths, in value order, into a
3528 // Huffman code lookup table.
3529 void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
3530 int tabSize, len, code, code2, skip, val, i, t;
3532 // find max code length
3534 for (val = 0; val < n; ++val) {
3535 if (lengths[val] > tab->maxLen) {
3536 tab->maxLen = lengths[val];
3540 // allocate the table
3541 tabSize = 1 << tab->maxLen;
3542 tab->codes = (FlateCode *)gmalloc(tabSize * sizeof(FlateCode));
3545 for (i = 0; i < tabSize; ++i) {
3546 tab->codes[i].len = 0;
3547 tab->codes[i].val = 0;
3551 for (len = 1, code = 0, skip = 2;
3553 ++len, code <<= 1, skip <<= 1) {
3554 for (val = 0; val < n; ++val) {
3555 if (lengths[val] == len) {
3557 // bit-reverse the code
3560 for (i = 0; i < len; ++i) {
3561 code2 = (code2 << 1) | (t & 1);
3565 // fill in the table entries
3566 for (i = code2; i < tabSize; i += skip) {
3567 tab->codes[i].len = (Gushort)len;
3568 tab->codes[i].val = (Gushort)val;
3577 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
3581 while (codeSize < tab->maxLen) {
3582 if ((c = str->getChar()) == EOF) {
3585 codeBuf |= (c & 0xff) << codeSize;
3588 code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
3589 if (codeSize == 0 || codeSize < code->len || code->len == 0) {
3592 codeBuf >>= code->len;
3593 codeSize -= code->len;
3594 return (int)code->val;
3597 int FlateStream::getCodeWord(int bits) {
3600 while (codeSize < bits) {
3601 if ((c = str->getChar()) == EOF)
3603 codeBuf |= (c & 0xff) << codeSize;
3606 c = codeBuf & ((1 << bits) - 1);
3612 //------------------------------------------------------------------------
3614 //------------------------------------------------------------------------
3616 EOFStream::EOFStream(Stream *strA):
3617 FilterStream(strA) {
3620 EOFStream::~EOFStream() {
3624 //------------------------------------------------------------------------
3625 // FixedLengthEncoder
3626 //------------------------------------------------------------------------
3628 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
3629 FilterStream(strA) {
3634 FixedLengthEncoder::~FixedLengthEncoder() {
3635 if (str->isEncoder())
3639 void FixedLengthEncoder::reset() {
3644 void FixedLengthEncoder::close() {
3647 int FixedLengthEncoder::getChar() {
3648 if (length >= 0 && count >= length)
3651 return str->getChar();
3654 int FixedLengthEncoder::lookChar() {
3655 if (length >= 0 && count >= length)
3657 return str->getChar();
3660 //------------------------------------------------------------------------
3662 //------------------------------------------------------------------------
3664 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
3665 FilterStream(strA) {
3666 bufPtr = bufEnd = buf;
3671 ASCIIHexEncoder::~ASCIIHexEncoder() {
3672 if (str->isEncoder()) {
3677 void ASCIIHexEncoder::reset() {
3679 bufPtr = bufEnd = buf;
3684 void ASCIIHexEncoder::close() {
3687 GBool ASCIIHexEncoder::fillBuf() {
3688 static char *hex = "0123456789abcdef";
3694 bufPtr = bufEnd = buf;
3695 if ((c = str->getChar()) == EOF) {
3699 if (lineLen >= 64) {
3703 *bufEnd++ = hex[(c >> 4) & 0x0f];
3704 *bufEnd++ = hex[c & 0x0f];
3710 //------------------------------------------------------------------------
3712 //------------------------------------------------------------------------
3714 ASCII85Encoder::ASCII85Encoder(Stream *strA):
3715 FilterStream(strA) {
3716 bufPtr = bufEnd = buf;
3721 ASCII85Encoder::~ASCII85Encoder() {
3722 if (str->isEncoder())
3726 void ASCII85Encoder::reset() {
3728 bufPtr = bufEnd = buf;
3733 void ASCII85Encoder::close() {
3736 GBool ASCII85Encoder::fillBuf() {
3745 for (n = 0; n < 4; ++n) {
3746 if ((c = str->getChar()) == EOF)
3750 bufPtr = bufEnd = buf;
3752 if (n == 4 && t == 0) {
3754 if (++lineLen == 65) {
3761 for (i = 4; i >= 0; --i) {
3762 buf1[i] = (char)(t % 85 + 0x21);
3765 for (i = 0; i <= n; ++i) {
3766 *bufEnd++ = buf1[i];
3767 if (++lineLen == 65) {
3779 return bufPtr < bufEnd;
3782 //------------------------------------------------------------------------
3784 //------------------------------------------------------------------------
3786 RunLengthEncoder::RunLengthEncoder(Stream *strA):
3787 FilterStream(strA) {
3788 bufPtr = bufEnd = nextEnd = buf;
3792 RunLengthEncoder::~RunLengthEncoder() {
3793 if (str->isEncoder())
3797 void RunLengthEncoder::reset() {
3799 bufPtr = bufEnd = nextEnd = buf;
3803 void RunLengthEncoder::close() {
3807 // When fillBuf finishes, buf[] looks like this:
3808 // +-----+--------------+-----------------+--
3809 // + tag | ... data ... | next 0, 1, or 2 |
3810 // +-----+--------------+-----------------+--
3812 // bufPtr bufEnd nextEnd
3814 GBool RunLengthEncoder::fillBuf() {
3823 if (nextEnd < bufEnd + 1) {
3824 if ((c1 = str->getChar()) == EOF) {
3829 c1 = bufEnd[0] & 0xff;
3831 if (nextEnd < bufEnd + 2) {
3832 if ((c2 = str->getChar()) == EOF) {
3841 c2 = bufEnd[1] & 0xff;
3845 c = 0; // make gcc happy
3848 while (n < 128 && (c = str->getChar()) == c1)
3850 buf[0] = (char)(257 - n);
3855 } else if (n < 128) {
3862 // get up to 128 chars
3868 if ((c = str->getChar()) == EOF) {
3874 if (buf[n] == buf[n-1])
3877 if (buf[n] == buf[n-1]) {
3878 buf[0] = (char)(n-2-1);
3880 nextEnd = &buf[n+1];
3882 buf[0] = (char)(n-1);
3883 bufEnd = nextEnd = &buf[n+1];