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 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, 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 dy1 = mcuHeight / compInfo[cc].vSample;
2160 for (y1 = 0; y1 < bufHeight; y1 += dy1) {
2161 for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
2163 // deal with restart marker
2164 if (restartInterval > 0 && restartCtr == 0) {
2166 if (c != restartMarker) {
2167 error(getPos(), "Bad DCT data: incorrect restart marker");
2170 if (++restartMarker == 0xd8) {
2171 restartMarker = 0xd0;
2177 for (cc = 0; cc < numComps; ++cc) {
2178 if (!scanInfo.comp[cc]) {
2182 h = compInfo[cc].hSample;
2183 v = compInfo[cc].vSample;
2184 horiz = mcuWidth / h;
2185 vert = mcuHeight / v;
2188 for (y2 = 0; y2 < dy1; y2 += vert) {
2189 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2191 // pull out the current values
2192 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2193 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2202 p1 += bufWidth * vSub;
2205 // read one data unit
2207 if (!readProgressiveDataUnit(
2208 &dcHuffTables[scanInfo.dcHuffTable[cc]],
2209 &acHuffTables[scanInfo.acHuffTable[cc]],
2210 &compInfo[cc].prevDC,
2215 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2216 &acHuffTables[scanInfo.acHuffTable[cc]],
2217 &compInfo[cc].prevDC,
2223 // add the data unit into frameBuf
2224 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2225 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2234 p1 += bufWidth * vSub;
2244 // Read one data unit from a sequential JPEG stream.
2245 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2246 DCTHuffTable *acHuffTable,
2247 int *prevDC, int data[64]) {
2252 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2256 if ((amp = readAmp(size)) == 9999) {
2262 data[0] = *prevDC += amp;
2263 for (i = 1; i < 64; ++i) {
2269 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
2278 run += (c >> 4) & 0x0f;
2280 amp = readAmp(size);
2292 // Read one data unit from a sequential JPEG stream.
2293 GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
2294 DCTHuffTable *acHuffTable,
2295 int *prevDC, int data[64]) {
2296 int run, size, amp, bit, c;
2299 // get the DC coefficient
2300 i = scanInfo.firstCoeff;
2302 if (scanInfo.ah == 0) {
2303 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2307 if ((amp = readAmp(size)) == 9999) {
2313 data[0] += (*prevDC += amp) << scanInfo.al;
2315 if ((bit = readBit()) == 9999) {
2318 data[0] += bit << scanInfo.al;
2322 if (scanInfo.lastCoeff == 0) {
2326 // check for an EOB run
2328 while (i <= scanInfo.lastCoeff) {
2331 if ((bit = readBit()) == EOF) {
2335 data[j] += 1 << scanInfo.al;
2343 // read the AC coefficients
2344 while (i <= scanInfo.lastCoeff) {
2345 if ((c = readHuffSym(acHuffTable)) == 9999) {
2357 if ((bit = readBit()) == EOF) {
2361 data[j] += 1 << scanInfo.al;
2367 } else if ((c & 0x0f) == 0x00) {
2370 for (k = 0; k < j; ++k) {
2371 if ((bit = readBit()) == EOF) {
2374 eobRun = (eobRun << 1) | bit;
2377 while (i <= scanInfo.lastCoeff) {
2380 if ((bit = readBit()) == EOF) {
2384 data[j] += 1 << scanInfo.al;
2391 // zero run and one AC coefficient
2393 run = (c >> 4) & 0x0f;
2395 if ((amp = readAmp(size)) == 9999) {
2401 while (data[j] != 0) {
2402 if ((bit = readBit()) == EOF) {
2406 data[j] += 1 << scanInfo.al;
2412 data[j] = amp << scanInfo.al;
2419 // Decode a progressive JPEG image.
2420 void DCTStream::decodeImage() {
2424 int pY, pCb, pCr, pR, pG, pB;
2425 int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2426 int h, v, horiz, vert, hSub, vSub;
2429 for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
2430 for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
2431 for (cc = 0; cc < numComps; ++cc) {
2432 quantTable = quantTables[compInfo[cc].quantTable];
2433 h = compInfo[cc].hSample;
2434 v = compInfo[cc].vSample;
2435 horiz = mcuWidth / h;
2436 vert = mcuHeight / v;
2439 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2440 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2442 // pull out the coded data unit
2443 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2444 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2446 dataIn[i+1] = p1[1];
2447 dataIn[i+2] = p1[2];
2448 dataIn[i+3] = p1[3];
2449 dataIn[i+4] = p1[4];
2450 dataIn[i+5] = p1[5];
2451 dataIn[i+6] = p1[6];
2452 dataIn[i+7] = p1[7];
2453 p1 += bufWidth * vSub;
2457 transformDataUnit(quantTable, dataIn, dataOut);
2459 // store back into frameBuf, doing replication for
2460 // subsampled components
2461 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2462 if (hSub == 1 && vSub == 1) {
2463 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2464 p1[0] = dataOut[i] & 0xff;
2465 p1[1] = dataOut[i+1] & 0xff;
2466 p1[2] = dataOut[i+2] & 0xff;
2467 p1[3] = dataOut[i+3] & 0xff;
2468 p1[4] = dataOut[i+4] & 0xff;
2469 p1[5] = dataOut[i+5] & 0xff;
2470 p1[6] = dataOut[i+6] & 0xff;
2471 p1[7] = dataOut[i+7] & 0xff;
2474 } else if (hSub == 2 && vSub == 2) {
2476 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2477 p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
2478 p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
2479 p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
2480 p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
2481 p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
2482 p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
2483 p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
2484 p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
2490 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2491 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2493 for (y5 = 0; y5 < vSub; ++y5) {
2494 for (x5 = 0; x5 < hSub; ++x5) {
2495 p2[x5] = dataOut[i] & 0xff;
2501 p1 += bufWidth * vSub;
2508 // color space conversion
2510 // convert YCbCr to RGB
2511 if (numComps == 3) {
2512 for (y2 = 0; y2 < mcuHeight; ++y2) {
2513 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2514 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2515 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2516 for (x2 = 0; x2 < mcuWidth; ++x2) {
2520 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2521 *p0++ = dctClip[dctClipOffset + pR];
2522 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2524 *p1++ = dctClip[dctClipOffset + pG];
2525 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2526 *p2++ = dctClip[dctClipOffset + pB];
2529 // convert YCbCrK to CMYK (K is passed through unchanged)
2530 } else if (numComps == 4) {
2531 for (y2 = 0; y2 < mcuHeight; ++y2) {
2532 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2533 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2534 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2535 for (x2 = 0; x2 < mcuWidth; ++x2) {
2539 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2540 *p0++ = 255 - dctClip[dctClipOffset + pR];
2541 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2543 *p1++ = 255 - dctClip[dctClipOffset + pG];
2544 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2545 *p2++ = 255 - dctClip[dctClipOffset + pB];
2554 // Transform one data unit -- this performs the dequantization and
2555 // IDCT steps. This IDCT algorithm is taken from:
2556 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2557 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2558 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2560 // The stage numbers mentioned in the comments refer to Figure 1 in this
2562 void DCTStream::transformDataUnit(Guchar *quantTable,
2563 int dataIn[64], Guchar dataOut[64]) {
2564 int v0, v1, v2, v3, v4, v5, v6, v7, t;
2569 for (i = 0; i < 64; ++i) {
2570 dataIn[i] *= quantTable[i];
2573 // inverse DCT on rows
2574 for (i = 0; i < 64; i += 8) {
2577 // check for all-zero AC coefficients
2578 if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
2579 p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
2580 t = (dctSqrt2 * p[0] + 512) >> 10;
2593 v0 = (dctSqrt2 * p[0] + 128) >> 8;
2594 v1 = (dctSqrt2 * p[4] + 128) >> 8;
2597 v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
2598 v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
2603 t = (v0 - v1+ 1) >> 1;
2604 v0 = (v0 + v1 + 1) >> 1;
2606 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2607 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2609 t = (v4 - v6 + 1) >> 1;
2610 v4 = (v4 + v6 + 1) >> 1;
2612 t = (v7 + v5 + 1) >> 1;
2613 v5 = (v7 - v5 + 1) >> 1;
2617 t = (v0 - v3 + 1) >> 1;
2618 v0 = (v0 + v3 + 1) >> 1;
2620 t = (v1 - v2 + 1) >> 1;
2621 v1 = (v1 + v2 + 1) >> 1;
2623 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2624 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2626 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2627 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2641 // inverse DCT on columns
2642 for (i = 0; i < 8; ++i) {
2645 // check for all-zero AC coefficients
2646 if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
2647 p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
2648 t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
2661 v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
2662 v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
2665 v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
2666 v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
2671 t = (v0 - v1 + 1) >> 1;
2672 v0 = (v0 + v1 + 1) >> 1;
2674 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2675 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2677 t = (v4 - v6 + 1) >> 1;
2678 v4 = (v4 + v6 + 1) >> 1;
2680 t = (v7 + v5 + 1) >> 1;
2681 v5 = (v7 - v5 + 1) >> 1;
2685 t = (v0 - v3 + 1) >> 1;
2686 v0 = (v0 + v3 + 1) >> 1;
2688 t = (v1 - v2 + 1) >> 1;
2689 v1 = (v1 + v2 + 1) >> 1;
2691 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2692 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2694 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2695 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2709 // convert to 8-bit integers
2710 for (i = 0; i < 64; ++i) {
2711 dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
2715 int DCTStream::readHuffSym(DCTHuffTable *table) {
2723 // add a bit to the code
2724 if ((bit = readBit()) == EOF)
2726 code = (code << 1) + bit;
2730 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2731 code -= table->firstCode[codeBits];
2732 return table->sym[table->firstSym[codeBits] + code];
2734 } while (codeBits < 16);
2736 error(getPos(), "Bad Huffman code in DCT stream");
2740 int DCTStream::readAmp(int size) {
2745 for (bits = 0; bits < size; ++bits) {
2746 if ((bit = readBit()) == EOF)
2748 amp = (amp << 1) + bit;
2750 if (amp < (1 << (size - 1)))
2751 amp -= (1 << size) - 1;
2755 int DCTStream::readBit() {
2759 if (inputBits == 0) {
2760 if ((c = str->getChar()) == EOF)
2764 c2 = str->getChar();
2765 } while (c2 == 0xff);
2767 error(getPos(), "Bad DCT data: missing 00 after ff");
2774 bit = (inputBuf >> (inputBits - 1)) & 1;
2779 GBool DCTStream::readHeader() {
2791 if (!readBaselineSOF()) {
2796 if (!readProgressiveSOF()) {
2801 if (!readHuffmanTables()) {
2811 if (!readScanInfo()) {
2817 if (!readQuantTables()) {
2822 if (!readRestartInterval()) {
2827 if (!readAdobeMarker()) {
2832 error(getPos(), "Bad DCT header");
2835 // skip APPn / COM / etc.
2838 for (i = 0; i < n; ++i) {
2842 error(getPos(), "Unknown DCT marker <%02x>", c);
2852 GBool DCTStream::readBaselineSOF() {
2859 prec = str->getChar();
2862 numComps = str->getChar();
2864 error(getPos(), "Bad DCT precision %d", prec);
2867 for (i = 0; i < numComps; ++i) {
2868 compInfo[i].id = str->getChar();
2870 compInfo[i].hSample = (c >> 4) & 0x0f;
2871 compInfo[i].vSample = c & 0x0f;
2872 compInfo[i].quantTable = str->getChar();
2874 progressive = gFalse;
2878 GBool DCTStream::readProgressiveSOF() {
2885 prec = str->getChar();
2888 numComps = str->getChar();
2890 error(getPos(), "Bad DCT precision %d", prec);
2893 for (i = 0; i < numComps; ++i) {
2894 compInfo[i].id = str->getChar();
2896 compInfo[i].hSample = (c >> 4) & 0x0f;
2897 compInfo[i].vSample = c & 0x0f;
2898 compInfo[i].quantTable = str->getChar();
2900 progressive = gTrue;
2904 GBool DCTStream::readScanInfo() {
2909 length = read16() - 2;
2910 scanInfo.numComps = str->getChar();
2912 if (length != 2 * scanInfo.numComps + 3) {
2913 error(getPos(), "Bad DCT scan info block");
2916 interleaved = scanInfo.numComps == numComps;
2917 for (j = 0; j < numComps; ++j) {
2918 scanInfo.comp[j] = gFalse;
2920 for (i = 0; i < scanInfo.numComps; ++i) {
2921 id = str->getChar();
2922 for (j = 0; j < numComps; ++j) {
2923 if (id == compInfo[j].id) {
2927 if (j == numComps) {
2928 error(getPos(), "Bad DCT component ID in scan info block");
2931 scanInfo.comp[j] = gTrue;
2933 scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
2934 scanInfo.acHuffTable[j] = c & 0x0f;
2936 scanInfo.firstCoeff = str->getChar();
2937 scanInfo.lastCoeff = str->getChar();
2939 scanInfo.ah = (c >> 4) & 0x0f;
2940 scanInfo.al = c & 0x0f;
2944 GBool DCTStream::readQuantTables() {
2949 length = read16() - 2;
2950 while (length > 0) {
2951 index = str->getChar();
2952 if ((index & 0xf0) || index >= 4) {
2953 error(getPos(), "Bad DCT quantization table");
2956 if (index == numQuantTables)
2957 numQuantTables = index + 1;
2958 for (i = 0; i < 64; ++i)
2959 quantTables[index][dctZigZag[i]] = str->getChar();
2965 GBool DCTStream::readHuffmanTables() {
2974 length = read16() - 2;
2975 while (length > 0) {
2976 index = str->getChar();
2978 if ((index & 0x0f) >= 4) {
2979 error(getPos(), "Bad DCT Huffman table");
2984 if (index >= numACHuffTables)
2985 numACHuffTables = index+1;
2986 tbl = &acHuffTables[index];
2988 if (index >= numDCHuffTables)
2989 numDCHuffTables = index+1;
2990 tbl = &dcHuffTables[index];
2994 for (i = 1; i <= 16; ++i) {
2996 tbl->firstSym[i] = sym;
2997 tbl->firstCode[i] = code;
2998 tbl->numCodes[i] = c;
3000 code = (code + c) << 1;
3003 for (i = 0; i < sym; ++i)
3004 tbl->sym[i] = str->getChar();
3010 GBool DCTStream::readRestartInterval() {
3015 error(getPos(), "Bad DCT restart interval");
3018 restartInterval = read16();
3022 GBool DCTStream::readAdobeMarker() {
3031 for (i = 0; i < 12; ++i) {
3032 if ((c = str->getChar()) == EOF) {
3037 if (strncmp(buf, "Adobe", 5)) {
3040 colorXform = buf[11];
3041 gotAdobeMarker = gTrue;
3042 for (i = 14; i < length; ++i) {
3043 if (str->getChar() == EOF) {
3050 error(getPos(), "Bad DCT Adobe APP14 marker");
3054 GBool DCTStream::readTrailer() {
3058 if (c != 0xd9) { // EOI
3059 error(getPos(), "Bad DCT trailer");
3065 int DCTStream::readMarker() {
3071 } while (c != 0xff);
3074 } while (c == 0xff);
3075 } while (c == 0x00);
3079 int DCTStream::read16() {
3082 if ((c1 = str->getChar()) == EOF)
3084 if ((c2 = str->getChar()) == EOF)
3086 return (c1 << 8) + c2;
3089 GString *DCTStream::getPSFilter(char *indent) {
3092 if (!(s = str->getPSFilter(indent))) {
3095 s->append(indent)->append("<< >> /DCTDecode filter\n");
3099 GBool DCTStream::isBinary(GBool last) {
3100 return str->isBinary(gTrue);
3103 //------------------------------------------------------------------------
3105 //------------------------------------------------------------------------
3107 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
3108 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3111 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
3143 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
3176 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
3177 int colors, int bits):
3178 FilterStream(strA) {
3179 if (predictor != 1) {
3180 pred = new StreamPredictor(this, predictor, columns, colors, bits);
3184 litCodeTab.codes = NULL;
3185 distCodeTab.codes = NULL;
3188 FlateStream::~FlateStream() {
3189 gfree(litCodeTab.codes);
3190 gfree(distCodeTab.codes);
3197 void FlateStream::reset() {
3204 compressedBlock = gFalse;
3211 //~ need to look at window size?
3212 endOfBlock = eof = gTrue;
3213 cmf = str->getChar();
3214 flg = str->getChar();
3215 if (cmf == EOF || flg == EOF)
3217 if ((cmf & 0x0f) != 0x08) {
3218 error(getPos(), "Unknown compression method in flate stream");
3221 if ((((cmf << 8) + flg) % 31) != 0) {
3222 error(getPos(), "Bad FCHECK in flate stream");
3226 error(getPos(), "FDICT bit set in flate stream");
3233 int FlateStream::getChar() {
3237 return pred->getChar();
3239 while (remain == 0) {
3240 if (endOfBlock && eof)
3245 index = (index + 1) & flateMask;
3250 int FlateStream::lookChar() {
3254 return pred->lookChar();
3256 while (remain == 0) {
3257 if (endOfBlock && eof)
3265 int FlateStream::getRawChar() {
3268 while (remain == 0) {
3269 if (endOfBlock && eof)
3274 index = (index + 1) & flateMask;
3279 GString *FlateStream::getPSFilter(char *indent) {
3283 GBool FlateStream::isBinary(GBool last) {
3284 return str->isBinary(gTrue);
3287 void FlateStream::readSome() {
3298 if (compressedBlock) {
3299 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
3304 } else if (code1 == 256) {
3309 code2 = lengthDecode[code1].bits;
3310 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3312 len = lengthDecode[code1].first + code2;
3313 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
3315 code2 = distDecode[code1].bits;
3316 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3318 dist = distDecode[code1].first + code2;
3320 j = (index - dist) & flateMask;
3321 for (k = 0; k < len; ++k) {
3323 i = (i + 1) & flateMask;
3324 j = (j + 1) & flateMask;
3330 len = (blockLen < flateWindow) ? blockLen : flateWindow;
3331 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
3332 if ((c = str->getChar()) == EOF) {
3333 endOfBlock = eof = gTrue;
3347 error(getPos(), "Unexpected end of file in flate stream");
3348 endOfBlock = eof = gTrue;
3352 GBool FlateStream::startBlock() {
3357 // free the code tables from the previous block
3358 gfree(litCodeTab.codes);
3359 litCodeTab.codes = NULL;
3360 gfree(distCodeTab.codes);
3361 distCodeTab.codes = NULL;
3363 // read block header
3364 blockHdr = getCodeWord(3);
3369 // uncompressed block
3370 if (blockHdr == 0) {
3371 compressedBlock = gFalse;
3372 if ((c = str->getChar()) == EOF)
3374 blockLen = c & 0xff;
3375 if ((c = str->getChar()) == EOF)
3377 blockLen |= (c & 0xff) << 8;
3378 if ((c = str->getChar()) == EOF)
3381 if ((c = str->getChar()) == EOF)
3383 check |= (c & 0xff) << 8;
3384 if (check != (~blockLen & 0xffff))
3385 error(getPos(), "Bad uncompressed block length in flate stream");
3389 // compressed block with fixed codes
3390 } else if (blockHdr == 1) {
3391 compressedBlock = gTrue;
3394 // compressed block with dynamic codes
3395 } else if (blockHdr == 2) {
3396 compressedBlock = gTrue;
3397 if (!readDynamicCodes()) {
3401 // unknown block type
3406 endOfBlock = gFalse;
3410 error(getPos(), "Bad block header in flate stream");
3411 endOfBlock = eof = gTrue;
3415 void FlateStream::loadFixedCodes() {
3418 // build the literal code table
3419 for (i = 0; i <= 143; ++i) {
3422 for (i = 144; i <= 255; ++i) {
3425 for (i = 256; i <= 279; ++i) {
3428 for (i = 280; i <= 287; ++i) {
3431 compHuffmanCodes(codeLengths, flateMaxLitCodes, &litCodeTab);
3433 // build the distance code table
3434 for (i = 0; i < flateMaxDistCodes; ++i) {
3437 compHuffmanCodes(codeLengths, flateMaxDistCodes, &distCodeTab);
3440 GBool FlateStream::readDynamicCodes() {
3441 int numCodeLenCodes;
3444 int codeLenCodeLengths[flateMaxCodeLenCodes];
3445 FlateHuffmanTab codeLenCodeTab;
3446 int len, repeat, code;
3450 if ((numLitCodes = getCodeWord(5)) == EOF) {
3454 if ((numDistCodes = getCodeWord(5)) == EOF) {
3458 if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
3461 numCodeLenCodes += 4;
3462 if (numLitCodes > flateMaxLitCodes ||
3463 numDistCodes > flateMaxDistCodes ||
3464 numCodeLenCodes > flateMaxCodeLenCodes) {
3468 // build the code length code table
3469 for (i = 0; i < flateMaxCodeLenCodes; ++i) {
3470 codeLenCodeLengths[i] = 0;
3472 for (i = 0; i < numCodeLenCodes; ++i) {
3473 if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
3477 compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
3479 // build the literal and distance code tables
3483 while (i < numLitCodes + numDistCodes) {
3484 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
3488 if ((repeat = getCodeWord(2)) == EOF) {
3491 for (repeat += 3; repeat > 0; --repeat) {
3492 codeLengths[i++] = len;
3494 } else if (code == 17) {
3495 if ((repeat = getCodeWord(3)) == EOF) {
3499 for (repeat += 3; repeat > 0; --repeat) {
3500 codeLengths[i++] = 0;
3502 } else if (code == 18) {
3503 if ((repeat = getCodeWord(7)) == EOF) {
3507 for (repeat += 11; repeat > 0; --repeat) {
3508 codeLengths[i++] = 0;
3511 codeLengths[i++] = len = code;
3514 compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
3515 compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
3517 gfree(codeLenCodeTab.codes);
3521 error(getPos(), "Bad dynamic code table in flate stream");
3522 gfree(codeLenCodeTab.codes);
3526 // Convert an array <lengths> of <n> lengths, in value order, into a
3527 // Huffman code lookup table.
3528 void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
3529 int tabSize, len, code, code2, skip, val, i, t;
3531 // find max code length
3533 for (val = 0; val < n; ++val) {
3534 if (lengths[val] > tab->maxLen) {
3535 tab->maxLen = lengths[val];
3539 // allocate the table
3540 tabSize = 1 << tab->maxLen;
3541 tab->codes = (FlateCode *)gmalloc(tabSize * sizeof(FlateCode));
3544 for (i = 0; i < tabSize; ++i) {
3545 tab->codes[i].len = 0;
3546 tab->codes[i].val = 0;
3550 for (len = 1, code = 0, skip = 2;
3552 ++len, code <<= 1, skip <<= 1) {
3553 for (val = 0; val < n; ++val) {
3554 if (lengths[val] == len) {
3556 // bit-reverse the code
3559 for (i = 0; i < len; ++i) {
3560 code2 = (code2 << 1) | (t & 1);
3564 // fill in the table entries
3565 for (i = code2; i < tabSize; i += skip) {
3566 tab->codes[i].len = (Gushort)len;
3567 tab->codes[i].val = (Gushort)val;
3576 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
3580 while (codeSize < tab->maxLen) {
3581 if ((c = str->getChar()) == EOF) {
3584 codeBuf |= (c & 0xff) << codeSize;
3587 code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
3588 if (codeSize == 0 || codeSize < code->len || code->len == 0) {
3591 codeBuf >>= code->len;
3592 codeSize -= code->len;
3593 return (int)code->val;
3596 int FlateStream::getCodeWord(int bits) {
3599 while (codeSize < bits) {
3600 if ((c = str->getChar()) == EOF)
3602 codeBuf |= (c & 0xff) << codeSize;
3605 c = codeBuf & ((1 << bits) - 1);
3611 //------------------------------------------------------------------------
3613 //------------------------------------------------------------------------
3615 EOFStream::EOFStream(Stream *strA):
3616 FilterStream(strA) {
3619 EOFStream::~EOFStream() {
3623 //------------------------------------------------------------------------
3624 // FixedLengthEncoder
3625 //------------------------------------------------------------------------
3627 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
3628 FilterStream(strA) {
3633 FixedLengthEncoder::~FixedLengthEncoder() {
3634 if (str->isEncoder())
3638 void FixedLengthEncoder::reset() {
3643 void FixedLengthEncoder::close() {
3646 int FixedLengthEncoder::getChar() {
3647 if (length >= 0 && count >= length)
3650 return str->getChar();
3653 int FixedLengthEncoder::lookChar() {
3654 if (length >= 0 && count >= length)
3656 return str->getChar();
3659 //------------------------------------------------------------------------
3661 //------------------------------------------------------------------------
3663 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
3664 FilterStream(strA) {
3665 bufPtr = bufEnd = buf;
3670 ASCIIHexEncoder::~ASCIIHexEncoder() {
3671 if (str->isEncoder()) {
3676 void ASCIIHexEncoder::reset() {
3678 bufPtr = bufEnd = buf;
3683 void ASCIIHexEncoder::close() {
3686 GBool ASCIIHexEncoder::fillBuf() {
3687 static char *hex = "0123456789abcdef";
3693 bufPtr = bufEnd = buf;
3694 if ((c = str->getChar()) == EOF) {
3698 if (lineLen >= 64) {
3702 *bufEnd++ = hex[(c >> 4) & 0x0f];
3703 *bufEnd++ = hex[c & 0x0f];
3709 //------------------------------------------------------------------------
3711 //------------------------------------------------------------------------
3713 ASCII85Encoder::ASCII85Encoder(Stream *strA):
3714 FilterStream(strA) {
3715 bufPtr = bufEnd = buf;
3720 ASCII85Encoder::~ASCII85Encoder() {
3721 if (str->isEncoder())
3725 void ASCII85Encoder::reset() {
3727 bufPtr = bufEnd = buf;
3732 void ASCII85Encoder::close() {
3735 GBool ASCII85Encoder::fillBuf() {
3744 for (n = 0; n < 4; ++n) {
3745 if ((c = str->getChar()) == EOF)
3749 bufPtr = bufEnd = buf;
3751 if (n == 4 && t == 0) {
3753 if (++lineLen == 65) {
3760 for (i = 4; i >= 0; --i) {
3761 buf1[i] = (char)(t % 85 + 0x21);
3764 for (i = 0; i <= n; ++i) {
3765 *bufEnd++ = buf1[i];
3766 if (++lineLen == 65) {
3778 return bufPtr < bufEnd;
3781 //------------------------------------------------------------------------
3783 //------------------------------------------------------------------------
3785 RunLengthEncoder::RunLengthEncoder(Stream *strA):
3786 FilterStream(strA) {
3787 bufPtr = bufEnd = nextEnd = buf;
3791 RunLengthEncoder::~RunLengthEncoder() {
3792 if (str->isEncoder())
3796 void RunLengthEncoder::reset() {
3798 bufPtr = bufEnd = nextEnd = buf;
3802 void RunLengthEncoder::close() {
3806 // When fillBuf finishes, buf[] looks like this:
3807 // +-----+--------------+-----------------+--
3808 // + tag | ... data ... | next 0, 1, or 2 |
3809 // +-----+--------------+-----------------+--
3811 // bufPtr bufEnd nextEnd
3813 GBool RunLengthEncoder::fillBuf() {
3822 if (nextEnd < bufEnd + 1) {
3823 if ((c1 = str->getChar()) == EOF) {
3828 c1 = bufEnd[0] & 0xff;
3830 if (nextEnd < bufEnd + 2) {
3831 if ((c2 = str->getChar()) == EOF) {
3840 c2 = bufEnd[1] & 0xff;
3844 c = 0; // make gcc happy
3847 while (n < 128 && (c = str->getChar()) == c1)
3849 buf[0] = (char)(257 - n);
3854 } else if (n < 128) {
3861 // get up to 128 chars
3867 if ((c = str->getChar()) == EOF) {
3873 if (buf[n] == buf[n-1])
3876 if (buf[n] == buf[n-1]) {
3877 buf[0] = (char)(n-2-1);
3879 nextEnd = &buf[n+1];
3881 buf[0] = (char)(n-1);
3882 bufEnd = nextEnd = &buf[n+1];