1 //========================================================================
5 // Copyright 1996-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
32 #include "JBIG2Stream.h"
33 #include "JPXStream.h"
34 #include "Stream-CCITT.h"
37 static GBool setDJSYSFLAGS = gFalse;
48 //------------------------------------------------------------------------
49 // Stream (base class)
50 //------------------------------------------------------------------------
59 void Stream::close() {
62 int Stream::getRawChar() {
63 error(-1, "Internal: called getRawChar() on non-predictor stream");
67 char *Stream::getLine(char *buf, int size) {
71 if (lookChar() == EOF)
73 for (i = 0; i < size - 1; ++i) {
75 if (c == EOF || c == '\n')
78 if ((c = lookChar()) == '\n')
88 GString *Stream::getPSFilter(int psLevel, char *indent) {
92 Stream *Stream::addFilters(Object *dict) {
94 Object params, params2;
99 dict->dictLookup("Filter", &obj);
102 dict->dictLookup("F", &obj);
104 dict->dictLookup("DecodeParms", ¶ms);
105 if (params.isNull()) {
107 dict->dictLookup("DP", ¶ms);
110 str = makeFilter(obj.getName(), str, ¶ms);
111 } else if (obj.isArray()) {
112 for (i = 0; i < obj.arrayGetLength(); ++i) {
113 obj.arrayGet(i, &obj2);
114 if (params.isArray())
115 params.arrayGet(i, ¶ms2);
119 str = makeFilter(obj2.getName(), str, ¶ms2);
121 error(getPos(), "Bad filter name");
122 str = new EOFStream(str);
127 } else if (!obj.isNull()) {
128 error(getPos(), "Bad 'Filter' attribute in stream");
136 Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
137 int pred; // parameters
142 GBool endOfLine, byteAlign, endOfBlock, black;
146 if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
147 str = new ASCIIHexStream(str);
148 } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
149 str = new ASCII85Stream(str);
150 } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
156 if (params->isDict()) {
157 params->dictLookup("Predictor", &obj);
161 params->dictLookup("Columns", &obj);
163 columns = obj.getInt();
165 params->dictLookup("Colors", &obj);
167 colors = obj.getInt();
169 params->dictLookup("BitsPerComponent", &obj);
173 params->dictLookup("EarlyChange", &obj);
175 early = obj.getInt();
178 str = new LZWStream(str, pred, columns, colors, bits, early);
179 } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
180 str = new RunLengthStream(str);
181 } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
189 if (params->isDict()) {
190 params->dictLookup("K", &obj);
192 encoding = obj.getInt();
195 params->dictLookup("EndOfLine", &obj);
197 endOfLine = obj.getBool();
200 params->dictLookup("EncodedByteAlign", &obj);
202 byteAlign = obj.getBool();
205 params->dictLookup("Columns", &obj);
207 columns = obj.getInt();
210 params->dictLookup("Rows", &obj);
215 params->dictLookup("EndOfBlock", &obj);
217 endOfBlock = obj.getBool();
220 params->dictLookup("BlackIs1", &obj);
222 black = obj.getBool();
226 str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
227 columns, rows, endOfBlock, black);
228 } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
229 str = new DCTStream(str);
230 } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
235 if (params->isDict()) {
236 params->dictLookup("Predictor", &obj);
240 params->dictLookup("Columns", &obj);
242 columns = obj.getInt();
244 params->dictLookup("Colors", &obj);
246 colors = obj.getInt();
248 params->dictLookup("BitsPerComponent", &obj);
253 str = new FlateStream(str, pred, columns, colors, bits);
254 } else if (!strcmp(name, "JBIG2Decode")) {
255 if (params->isDict()) {
256 params->dictLookup("JBIG2Globals", &globals);
258 str = new JBIG2Stream(str, &globals);
260 } else if (!strcmp(name, "JPXDecode")) {
261 str = new JPXStream(str);
263 error(getPos(), "Unknown filter '%s'", name);
264 str = new EOFStream(str);
269 //------------------------------------------------------------------------
271 //------------------------------------------------------------------------
273 BaseStream::BaseStream(Object *dictA) {
275 #ifndef NO_DECRYPTION
280 BaseStream::~BaseStream() {
282 #ifndef NO_DECRYPTION
288 #ifndef NO_DECRYPTION
289 void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
290 int objNum, int objGen) {
291 decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
295 //------------------------------------------------------------------------
297 //------------------------------------------------------------------------
299 FilterStream::FilterStream(Stream *strA) {
303 FilterStream::~FilterStream() {
306 void FilterStream::close() {
310 void FilterStream::setPos(Guint pos, int dir) {
311 error(-1, "Internal: called setPos() on FilterStream");
314 //------------------------------------------------------------------------
316 //------------------------------------------------------------------------
318 ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
326 nVals = width * nComps;
328 imgLineSize = (nVals + 7) & ~7;
332 imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
336 ImageStream::~ImageStream() {
340 void ImageStream::reset() {
344 GBool ImageStream::getPixel(Guchar *pix) {
347 if (imgIdx >= nVals) {
351 for (i = 0; i < nComps; ++i) {
352 pix[i] = imgLine[imgIdx++];
357 Guchar *ImageStream::getLine() {
364 for (i = 0; i < nVals; i += 8) {
366 imgLine[i+0] = (Guchar)((c >> 7) & 1);
367 imgLine[i+1] = (Guchar)((c >> 6) & 1);
368 imgLine[i+2] = (Guchar)((c >> 5) & 1);
369 imgLine[i+3] = (Guchar)((c >> 4) & 1);
370 imgLine[i+4] = (Guchar)((c >> 3) & 1);
371 imgLine[i+5] = (Guchar)((c >> 2) & 1);
372 imgLine[i+6] = (Guchar)((c >> 1) & 1);
373 imgLine[i+7] = (Guchar)(c & 1);
375 } else if (nBits == 8) {
376 for (i = 0; i < nVals; ++i) {
377 imgLine[i] = str->getChar();
380 bitMask = (1 << nBits) - 1;
383 for (i = 0; i < nVals; ++i) {
385 buf = (buf << 8) | (str->getChar() & 0xff);
388 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
395 void ImageStream::skipLine() {
398 n = (nVals * nBits + 7) >> 3;
399 for (i = 0; i < n; ++i) {
404 //------------------------------------------------------------------------
406 //------------------------------------------------------------------------
408 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
409 int widthA, int nCompsA, int nBitsA) {
411 predictor = predictorA;
416 nVals = width * nComps;
417 pixBytes = (nComps * nBits + 7) >> 3;
418 rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
419 predLine = (Guchar *)gmalloc(rowBytes);
420 memset(predLine, 0, rowBytes);
424 StreamPredictor::~StreamPredictor() {
428 int StreamPredictor::lookChar() {
429 if (predIdx >= rowBytes) {
430 if (!getNextLine()) {
434 return predLine[predIdx];
437 int StreamPredictor::getChar() {
438 if (predIdx >= rowBytes) {
439 if (!getNextLine()) {
443 return predLine[predIdx++];
446 GBool StreamPredictor::getNextLine() {
449 int left, up, upLeft, p, pa, pb, pc;
451 Gulong inBuf, outBuf, bitMask;
455 // get PNG optimum predictor number
456 if (predictor >= 10) {
457 if ((curPred = str->getRawChar()) == EOF) {
465 // read the raw line, apply PNG (byte) predictor
466 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
467 for (i = pixBytes; i < rowBytes; ++i) {
468 upLeftBuf[3] = upLeftBuf[2];
469 upLeftBuf[2] = upLeftBuf[1];
470 upLeftBuf[1] = upLeftBuf[0];
471 upLeftBuf[0] = predLine[i];
472 if ((c = str->getRawChar()) == EOF) {
477 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
480 predLine[i] = predLine[i] + (Guchar)c;
482 case 13: // PNG average
483 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
486 case 14: // PNG Paeth
487 left = predLine[i - pixBytes];
489 upLeft = upLeftBuf[pixBytes];
490 p = left + up - upLeft;
491 if ((pa = p - left) < 0)
493 if ((pb = p - up) < 0)
495 if ((pc = p - upLeft) < 0)
497 if (pa <= pb && pa <= pc)
498 predLine[i] = left + (Guchar)c;
500 predLine[i] = up + (Guchar)c;
502 predLine[i] = upLeft + (Guchar)c;
505 default: // no predictor or TIFF predictor
506 predLine[i] = (Guchar)c;
511 // apply TIFF (component) predictor
512 if (predictor == 2) {
514 inBuf = predLine[pixBytes - 1];
515 for (i = pixBytes; i < rowBytes; i += 8) {
516 // 1-bit add is just xor
517 inBuf = (inBuf << 8) | predLine[i];
518 predLine[i] ^= inBuf >> nComps;
520 } else if (nBits == 8) {
521 for (i = pixBytes; i < rowBytes; ++i) {
522 predLine[i] += predLine[i - nComps];
525 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
526 bitMask = (1 << nBits) - 1;
528 inBits = outBits = 0;
530 for (i = 0; i < nVals; ++i) {
531 if (inBits < nBits) {
532 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
535 upLeftBuf[3] = upLeftBuf[2];
536 upLeftBuf[2] = upLeftBuf[1];
537 upLeftBuf[1] = upLeftBuf[0];
538 upLeftBuf[0] = (upLeftBuf[nComps] +
539 (inBuf >> (inBits - nBits))) & bitMask;
540 outBuf = (outBuf << nBits) | upLeftBuf[0];
544 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
548 predLine[k++] = (Guchar)(outBuf << (8 - outBits));
553 // reset to start of line
559 //------------------------------------------------------------------------
561 //------------------------------------------------------------------------
563 FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
564 Guint lengthA, Object *dictA):
570 bufPtr = bufEnd = buf;
576 FileStream::~FileStream() {
580 Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
581 Guint lengthA, Object *dictA) {
582 return new FileStream(f, startA, limitedA, lengthA, dictA);
585 void FileStream::reset() {
587 savePos = (Guint)ftello(f);
588 fseeko(f, start, SEEK_SET);
590 savePos = (Guint)ftell64(f);
591 fseek64(f, start, SEEK_SET);
593 savePos = (Guint)ftell(f);
594 fseek(f, start, SEEK_SET);
597 bufPtr = bufEnd = buf;
599 #ifndef NO_DECRYPTION
605 void FileStream::close() {
608 fseeko(f, savePos, SEEK_SET);
610 fseek64(f, savePos, SEEK_SET);
612 fseek(f, savePos, SEEK_SET);
618 GBool FileStream::fillBuf() {
620 #ifndef NO_DECRYPTION
624 bufPos += bufEnd - buf;
625 bufPtr = bufEnd = buf;
626 if (limited && bufPos >= start + length) {
629 if (limited && bufPos + fileStreamBufSize > start + length) {
630 n = start + length - bufPos;
632 n = fileStreamBufSize;
634 n = fread(buf, 1, n, f);
636 if (bufPtr >= bufEnd) {
639 #ifndef NO_DECRYPTION
641 for (p = buf; p < bufEnd; ++p) {
642 *p = (char)decrypt->decryptByte((Guchar)*p);
649 void FileStream::setPos(Guint pos, int dir) {
654 fseeko(f, pos, SEEK_SET);
656 fseek64(f, pos, SEEK_SET);
658 fseek(f, pos, SEEK_SET);
663 fseeko(f, 0, SEEK_END);
664 size = (Guint)ftello(f);
666 fseek64(f, 0, SEEK_END);
667 size = (Guint)ftell64(f);
669 fseek(f, 0, SEEK_END);
670 size = (Guint)ftell(f);
675 //~ work around a bug in cygwin's implementation of fseek
679 fseeko(f, -(int)pos, SEEK_END);
680 bufPos = (Guint)ftello(f);
682 fseek64(f, -(int)pos, SEEK_END);
683 bufPos = (Guint)ftell64(f);
685 fseek(f, -(int)pos, SEEK_END);
686 bufPos = (Guint)ftell(f);
689 bufPtr = bufEnd = buf;
692 void FileStream::moveStart(int delta) {
694 bufPtr = bufEnd = buf;
698 //------------------------------------------------------------------------
700 //------------------------------------------------------------------------
702 MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA):
707 bufEnd = buf + start + length;
708 bufPtr = buf + start;
712 MemStream::~MemStream() {
718 Stream *MemStream::makeSubStream(Guint startA, GBool limited,
719 Guint lengthA, Object *dictA) {
723 if (!limited || startA + lengthA > start + length) {
724 newLength = start + length - startA;
728 subStr = new MemStream(buf, startA, newLength, dictA);
732 void MemStream::reset() {
733 bufPtr = buf + start;
734 #ifndef NO_DECRYPTION
741 void MemStream::close() {
744 void MemStream::setPos(Guint pos, int dir) {
750 i = start + length - pos;
754 } else if (i > start + length) {
760 void MemStream::moveStart(int delta) {
762 bufPtr = buf + start;
765 #ifndef NO_DECRYPTION
766 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
767 int objNum, int objGen) {
771 this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
773 newBuf = (char *)gmalloc(length);
774 for (p = buf + start, q = newBuf; p < bufEnd; ++p, ++q) {
775 *q = (char)decrypt->decryptByte((Guchar)*p);
777 bufEnd = newBuf + length;
778 bufPtr = newBuf + (bufPtr - (buf + start));
786 //------------------------------------------------------------------------
788 //------------------------------------------------------------------------
790 EmbedStream::EmbedStream(Stream *strA, Object *dictA,
791 GBool limitedA, Guint lengthA):
798 EmbedStream::~EmbedStream() {
801 Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA,
802 Guint lengthA, Object *dictA) {
803 error(-1, "Internal: called makeSubStream() on EmbedStream");
807 int EmbedStream::getChar() {
808 if (limited && !length) {
812 return str->getChar();
815 int EmbedStream::lookChar() {
816 if (limited && !length) {
819 return str->lookChar();
822 void EmbedStream::setPos(Guint pos, int dir) {
823 error(-1, "Internal: called setPos() on EmbedStream");
826 Guint EmbedStream::getStart() {
827 error(-1, "Internal: called getStart() on EmbedStream");
831 void EmbedStream::moveStart(int delta) {
832 error(-1, "Internal: called moveStart() on EmbedStream");
835 //------------------------------------------------------------------------
837 //------------------------------------------------------------------------
839 ASCIIHexStream::ASCIIHexStream(Stream *strA):
845 ASCIIHexStream::~ASCIIHexStream() {
849 void ASCIIHexStream::reset() {
855 int ASCIIHexStream::lookChar() {
866 } while (isspace(c1));
874 } while (isspace(c2));
879 if (c1 >= '0' && c1 <= '9') {
881 } else if (c1 >= 'A' && c1 <= 'F') {
882 x = (c1 - 'A' + 10) << 4;
883 } else if (c1 >= 'a' && c1 <= 'f') {
884 x = (c1 - 'a' + 10) << 4;
885 } else if (c1 == EOF) {
889 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
892 if (c2 >= '0' && c2 <= '9') {
894 } else if (c2 >= 'A' && c2 <= 'F') {
896 } else if (c2 >= 'a' && c2 <= 'f') {
898 } else if (c2 == EOF) {
902 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
908 GString *ASCIIHexStream::getPSFilter(int psLevel, char *indent) {
914 if (!(s = str->getPSFilter(psLevel, indent))) {
917 s->append(indent)->append("/ASCIIHexDecode filter\n");
921 GBool ASCIIHexStream::isBinary(GBool last) {
922 return str->isBinary(gFalse);
925 //------------------------------------------------------------------------
927 //------------------------------------------------------------------------
929 ASCII85Stream::ASCII85Stream(Stream *strA):
935 ASCII85Stream::~ASCII85Stream() {
939 void ASCII85Stream::reset() {
945 int ASCII85Stream::lookChar() {
954 c[0] = str->getChar();
955 } while (c[0] == '\n' || c[0] == '\r');
956 if (c[0] == '~' || c[0] == EOF) {
960 } else if (c[0] == 'z') {
961 b[0] = b[1] = b[2] = b[3] = 0;
964 for (k = 1; k < 5; ++k) {
966 c[k] = str->getChar();
967 } while (c[k] == '\n' || c[k] == '\r');
968 if (c[k] == '~' || c[k] == EOF)
972 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
973 for (++k; k < 5; ++k)
978 for (k = 0; k < 5; ++k)
979 t = t * 85 + (c[k] - 0x21);
980 for (k = 3; k >= 0; --k) {
981 b[k] = (int)(t & 0xff);
989 GString *ASCII85Stream::getPSFilter(int psLevel, char *indent) {
995 if (!(s = str->getPSFilter(psLevel, indent))) {
998 s->append(indent)->append("/ASCII85Decode filter\n");
1002 GBool ASCII85Stream::isBinary(GBool last) {
1003 return str->isBinary(gFalse);
1006 //------------------------------------------------------------------------
1008 //------------------------------------------------------------------------
1010 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
1011 int bits, int earlyA):
1012 FilterStream(strA) {
1013 if (predictor != 1) {
1014 pred = new StreamPredictor(this, predictor, columns, colors, bits);
1024 LZWStream::~LZWStream() {
1031 int LZWStream::getChar() {
1033 return pred->getChar();
1038 if (seqIndex >= seqLength) {
1039 if (!processNextCode()) {
1043 return seqBuf[seqIndex++];
1046 int LZWStream::lookChar() {
1048 return pred->lookChar();
1053 if (seqIndex >= seqLength) {
1054 if (!processNextCode()) {
1058 return seqBuf[seqIndex];
1061 int LZWStream::getRawChar() {
1065 if (seqIndex >= seqLength) {
1066 if (!processNextCode()) {
1070 return seqBuf[seqIndex++];
1073 void LZWStream::reset() {
1080 GBool LZWStream::processNextCode() {
1090 // check for eod and clear-table codes
1093 if (code == EOF || code == 257) {
1101 if (nextCode >= 4097) {
1102 error(getPos(), "Bad LZW stream - expected clear-table code");
1106 // process the next code
1107 nextLength = seqLength + 1;
1111 } else if (code < nextCode) {
1112 seqLength = table[code].length;
1113 for (i = seqLength - 1, j = code; i > 0; --i) {
1114 seqBuf[i] = table[j].tail;
1118 } else if (code == nextCode) {
1119 seqBuf[seqLength] = newChar;
1122 error(getPos(), "Bad LZW stream - unexpected code");
1126 newChar = seqBuf[0];
1130 table[nextCode].length = nextLength;
1131 table[nextCode].head = prevCode;
1132 table[nextCode].tail = newChar;
1134 if (nextCode + early == 512)
1136 else if (nextCode + early == 1024)
1138 else if (nextCode + early == 2048)
1149 void LZWStream::clearTable() {
1152 seqIndex = seqLength = 0;
1156 int LZWStream::getCode() {
1160 while (inputBits < nextBits) {
1161 if ((c = str->getChar()) == EOF)
1163 inputBuf = (inputBuf << 8) | (c & 0xff);
1166 code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
1167 inputBits -= nextBits;
1171 GString *LZWStream::getPSFilter(int psLevel, char *indent) {
1174 if (psLevel < 2 || pred) {
1177 if (!(s = str->getPSFilter(psLevel, indent))) {
1180 s->append(indent)->append("/LZWDecode filter\n");
1184 GBool LZWStream::isBinary(GBool last) {
1185 return str->isBinary(gTrue);
1188 //------------------------------------------------------------------------
1190 //------------------------------------------------------------------------
1192 RunLengthStream::RunLengthStream(Stream *strA):
1193 FilterStream(strA) {
1194 bufPtr = bufEnd = buf;
1198 RunLengthStream::~RunLengthStream() {
1202 void RunLengthStream::reset() {
1204 bufPtr = bufEnd = buf;
1208 GString *RunLengthStream::getPSFilter(int psLevel, char *indent) {
1214 if (!(s = str->getPSFilter(psLevel, indent))) {
1217 s->append(indent)->append("/RunLengthDecode filter\n");
1221 GBool RunLengthStream::isBinary(GBool last) {
1222 return str->isBinary(gTrue);
1225 GBool RunLengthStream::fillBuf() {
1232 if (c == 0x80 || c == EOF) {
1238 for (i = 0; i < n; ++i)
1239 buf[i] = (char)str->getChar();
1243 for (i = 0; i < n; ++i)
1251 //------------------------------------------------------------------------
1253 //------------------------------------------------------------------------
1255 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
1256 GBool byteAlignA, int columnsA, int rowsA,
1257 GBool endOfBlockA, GBool blackA):
1258 FilterStream(strA) {
1259 encoding = encodingA;
1260 endOfLine = endOfLineA;
1261 byteAlign = byteAlignA;
1264 endOfBlock = endOfBlockA;
1266 refLine = (short *)gmalloc((columns + 3) * sizeof(short));
1267 codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
1271 nextLine2D = encoding < 0;
1274 codingLine[1] = refLine[2] = columns;
1280 CCITTFaxStream::~CCITTFaxStream() {
1286 void CCITTFaxStream::reset() {
1292 nextLine2D = encoding < 0;
1295 codingLine[1] = refLine[2] = columns;
1299 // skip any initial zero bits and end-of-line marker, and get the 2D
1301 while ((code1 = lookBits(12)) == 0) {
1304 if (code1 == 0x001) {
1308 nextLine2D = !lookBits(1);
1313 int CCITTFaxStream::lookChar() {
1314 short code1, code2, code3;
1320 // if at eof just return EOF
1321 if (eof && codingLine[a0] >= columns) {
1325 // read the next row
1327 if (codingLine[a0] >= columns) {
1331 for (i = 0; codingLine[i] < columns; ++i)
1332 refLine[i] = codingLine[i];
1333 refLine[i] = refLine[i + 1] = columns;
1335 a0New = codingLine[a0 = 0] = 0;
1337 code1 = getTwoDimCode();
1340 if (refLine[b1] < columns) {
1341 a0New = refLine[b1 + 1];
1346 if ((a0 & 1) == 0) {
1349 code1 += code3 = getWhiteCode();
1350 } while (code3 >= 64);
1352 code2 += code3 = getBlackCode();
1353 } while (code3 >= 64);
1357 code1 += code3 = getBlackCode();
1358 } while (code3 >= 64);
1360 code2 += code3 = getWhiteCode();
1361 } while (code3 >= 64);
1363 if (code1 > 0 || code2 > 0) {
1364 codingLine[a0 + 1] = a0New + code1;
1366 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
1368 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1373 a0New = codingLine[++a0] = refLine[b1];
1374 if (refLine[b1] < columns) {
1376 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1381 a0New = codingLine[++a0] = refLine[b1] + 1;
1382 if (refLine[b1] < columns) {
1384 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1389 a0New = codingLine[++a0] = refLine[b1] - 1;
1391 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1395 a0New = codingLine[++a0] = refLine[b1] + 2;
1396 if (refLine[b1] < columns) {
1398 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1403 a0New = codingLine[++a0] = refLine[b1] - 2;
1405 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1409 a0New = codingLine[++a0] = refLine[b1] + 3;
1410 if (refLine[b1] < columns) {
1412 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1417 a0New = codingLine[++a0] = refLine[b1] - 3;
1419 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
1424 codingLine[a0 = 0] = columns;
1427 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
1431 } while (codingLine[a0] < columns);
1435 codingLine[a0 = 0] = 0;
1439 code1 += code3 = getWhiteCode();
1440 } while (code3 >= 64);
1441 codingLine[a0+1] = codingLine[a0] + code1;
1443 if (codingLine[a0] >= columns)
1447 code2 += code3 = getBlackCode();
1448 } while (code3 >= 64);
1449 codingLine[a0+1] = codingLine[a0] + code2;
1451 if (codingLine[a0] >= columns)
1456 if (codingLine[a0] != columns) {
1457 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
1458 // force the row to be the correct length
1459 while (codingLine[a0] > columns) {
1462 codingLine[++a0] = columns;
1466 // byte-align the row
1471 // check for end-of-line marker, skipping over any extra zero bits
1473 if (!endOfBlock && row == rows - 1) {
1476 code1 = lookBits(12);
1477 while (code1 == 0) {
1479 code1 = lookBits(12);
1481 if (code1 == 0x001) {
1484 } else if (code1 == EOF) {
1489 // get 2D encoding tag
1490 if (!eof && encoding > 0) {
1491 nextLine2D = !lookBits(1);
1495 // check for end-of-block marker
1496 if (endOfBlock && gotEOL) {
1497 code1 = lookBits(12);
1498 if (code1 == 0x001) {
1504 if (encoding >= 0) {
1505 for (i = 0; i < 4; ++i) {
1506 code1 = lookBits(12);
1507 if (code1 != 0x001) {
1508 error(getPos(), "Bad RTC code in CCITTFax stream");
1520 // look for an end-of-line marker after an error -- we only do
1521 // this if we know the stream contains end-of-line markers because
1522 // the "just plow on" technique tends to work better otherwise
1523 } else if (err && endOfLine) {
1530 code1 = lookBits(13);
1531 } while ((code1 >> 1) != 0x001);
1535 nextLine2D = !(code1 & 1);
1540 outputBits = codingLine[1] - codingLine[0];
1541 if (outputBits == 0) {
1543 outputBits = codingLine[2] - codingLine[1];
1550 if (outputBits >= 8) {
1551 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
1552 if ((outputBits -= 8) == 0) {
1554 if (codingLine[a0] < columns) {
1555 outputBits = codingLine[a0 + 1] - codingLine[a0];
1562 if (outputBits > bits) {
1565 if ((a0 & 1) == 0) {
1566 ret |= 0xff >> (8 - i);
1572 if ((a0 & 1) == 0) {
1573 ret |= (0xff >> (8 - i)) << bits;
1577 if (codingLine[a0] < columns) {
1578 outputBits = codingLine[a0 + 1] - codingLine[a0];
1581 } while (bits > 0 && codingLine[a0] < columns);
1583 buf = black ? (ret ^ 0xff) : ret;
1587 short CCITTFaxStream::getTwoDimCode() {
1592 code = 0; // make gcc happy
1595 p = &twoDimTab1[code];
1601 for (n = 1; n <= 7; ++n) {
1606 p = &twoDimTab1[code];
1613 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
1617 short CCITTFaxStream::getWhiteCode() {
1622 code = 0; // make gcc happy
1624 code = lookBits(12);
1625 if ((code >> 5) == 0) {
1626 p = &whiteTab1[code];
1628 p = &whiteTab2[code >> 3];
1635 for (n = 1; n <= 9; ++n) {
1640 p = &whiteTab2[code];
1646 for (n = 11; n <= 12; ++n) {
1651 p = &whiteTab1[code];
1658 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
1659 // eat a bit and return a positive number so that the caller doesn't
1660 // go into an infinite loop
1665 short CCITTFaxStream::getBlackCode() {
1670 code = 0; // make gcc happy
1672 code = lookBits(13);
1673 if ((code >> 7) == 0) {
1674 p = &blackTab1[code];
1675 } else if ((code >> 9) == 0) {
1676 p = &blackTab2[(code >> 1) - 64];
1678 p = &blackTab3[code >> 7];
1685 for (n = 2; n <= 6; ++n) {
1690 p = &blackTab3[code];
1696 for (n = 7; n <= 12; ++n) {
1702 p = &blackTab2[code - 64];
1709 for (n = 10; n <= 13; ++n) {
1714 p = &blackTab1[code];
1721 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
1722 // eat a bit and return a positive number so that the caller doesn't
1723 // go into an infinite loop
1728 short CCITTFaxStream::lookBits(int n) {
1731 while (inputBits < n) {
1732 if ((c = str->getChar()) == EOF) {
1733 if (inputBits == 0) {
1736 // near the end of the stream, the caller may ask for more bits
1737 // than are available, but there may still be a valid code in
1738 // however many bits are available -- we need to return correct
1739 // data in this case
1740 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
1742 inputBuf = (inputBuf << 8) + c;
1745 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
1748 GString *CCITTFaxStream::getPSFilter(int psLevel, char *indent) {
1755 if (!(s = str->getPSFilter(psLevel, indent))) {
1758 s->append(indent)->append("<< ");
1759 if (encoding != 0) {
1760 sprintf(s1, "/K %d ", encoding);
1764 s->append("/EndOfLine true ");
1767 s->append("/EncodedByteAlign true ");
1769 sprintf(s1, "/Columns %d ", columns);
1772 sprintf(s1, "/Rows %d ", rows);
1776 s->append("/EndOfBlock false ");
1779 s->append("/BlackIs1 true ");
1781 s->append(">> /CCITTFaxDecode filter\n");
1785 GBool CCITTFaxStream::isBinary(GBool last) {
1786 return str->isBinary(gTrue);
1789 //------------------------------------------------------------------------
1791 //------------------------------------------------------------------------
1793 // IDCT constants (20.12 fixed point format)
1794 #define dctCos1 4017 // cos(pi/16)
1795 #define dctSin1 799 // sin(pi/16)
1796 #define dctCos3 3406 // cos(3*pi/16)
1797 #define dctSin3 2276 // sin(3*pi/16)
1798 #define dctCos6 1567 // cos(6*pi/16)
1799 #define dctSin6 3784 // sin(6*pi/16)
1800 #define dctSqrt2 5793 // sqrt(2)
1801 #define dctSqrt1d2 2896 // sqrt(2) / 2
1803 // color conversion parameters (16.16 fixed point format)
1804 #define dctCrToR 91881 // 1.4020
1805 #define dctCbToG -22553 // -0.3441363
1806 #define dctCrToG -46802 // -0.71413636
1807 #define dctCbToB 116130 // 1.772
1809 // clip [-256,511] --> [0,255]
1810 #define dctClipOffset 256
1811 static Guchar dctClip[768];
1812 static int dctClipInit = 0;
1814 // zig zag decode map
1815 static int dctZigZag[64] = {
1821 5, 12, 19, 26, 33, 40,
1822 48, 41, 34, 27, 20, 13, 6,
1823 7, 14, 21, 28, 35, 42, 49, 56,
1824 57, 50, 43, 36, 29, 22, 15,
1825 23, 30, 37, 44, 51, 58,
1833 DCTStream::DCTStream(Stream *strA):
1834 FilterStream(strA) {
1837 progressive = interleaved = gFalse;
1839 mcuWidth = mcuHeight = 0;
1843 for (i = 0; i < 4; ++i) {
1844 for (j = 0; j < 32; ++j) {
1845 rowBuf[i][j] = NULL;
1851 for (i = -256; i < 0; ++i)
1852 dctClip[dctClipOffset + i] = 0;
1853 for (i = 0; i < 256; ++i)
1854 dctClip[dctClipOffset + i] = i;
1855 for (i = 256; i < 512; ++i)
1856 dctClip[dctClipOffset + i] = 255;
1861 DCTStream::~DCTStream() {
1865 if (progressive || !interleaved) {
1866 for (i = 0; i < numComps; ++i) {
1870 for (i = 0; i < numComps; ++i) {
1871 for (j = 0; j < mcuHeight; ++j) {
1872 gfree(rowBuf[i][j]);
1878 void DCTStream::reset() {
1879 int minHSample, minVSample;
1884 progressive = interleaved = gFalse;
1888 numDCHuffTables = 0;
1889 numACHuffTables = 0;
1891 gotJFIFMarker = gFalse;
1892 gotAdobeMarker = gFalse;
1893 restartInterval = 0;
1895 if (!readHeader()) {
1901 mcuWidth = minHSample = compInfo[0].hSample;
1902 mcuHeight = minVSample = compInfo[0].vSample;
1903 for (i = 1; i < numComps; ++i) {
1904 if (compInfo[i].hSample < minHSample)
1905 minHSample = compInfo[i].hSample;
1906 if (compInfo[i].vSample < minVSample)
1907 minVSample = compInfo[i].vSample;
1908 if (compInfo[i].hSample > mcuWidth)
1909 mcuWidth = compInfo[i].hSample;
1910 if (compInfo[i].vSample > mcuHeight)
1911 mcuHeight = compInfo[i].vSample;
1913 for (i = 0; i < numComps; ++i) {
1914 compInfo[i].hSample /= minHSample;
1915 compInfo[i].vSample /= minVSample;
1917 mcuWidth = (mcuWidth / minHSample) * 8;
1918 mcuHeight = (mcuHeight / minVSample) * 8;
1920 // figure out color transform
1921 if (!gotAdobeMarker && numComps == 3) {
1922 if (gotJFIFMarker) {
1924 } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
1925 compInfo[2].id == 66) { // ASCII "RGB"
1932 if (progressive || !interleaved) {
1934 // allocate a buffer for the whole image
1935 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
1936 bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
1937 for (i = 0; i < numComps; ++i) {
1938 frameBuf[i] = (int *)gmalloc(bufWidth * bufHeight * sizeof(int));
1939 memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
1942 // read the image data
1944 restartMarker = 0xd0;
1947 } while (readHeader());
1952 // initialize counters
1959 // allocate a buffer for one row of MCUs
1960 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
1961 for (i = 0; i < numComps; ++i) {
1962 for (j = 0; j < mcuHeight; ++j) {
1963 rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
1967 // initialize counters
1973 restartMarker = 0xd0;
1978 int DCTStream::getChar() {
1984 if (progressive || !interleaved) {
1985 c = frameBuf[comp][y * bufWidth + x];
1986 if (++comp == numComps) {
1994 if (dy >= mcuHeight) {
1995 if (!readMCURow()) {
2003 c = rowBuf[comp][dy][x];
2004 if (++comp == numComps) {
2019 int DCTStream::lookChar() {
2023 if (progressive || !interleaved) {
2024 return frameBuf[comp][y * bufWidth + x];
2026 if (dy >= mcuHeight) {
2027 if (!readMCURow()) {
2035 return rowBuf[comp][dy][x];
2039 void DCTStream::restart() {
2043 restartCtr = restartInterval;
2044 for (i = 0; i < numComps; ++i) {
2045 compInfo[i].prevDC = 0;
2050 // Read one row of MCUs from a sequential JPEG stream.
2051 GBool DCTStream::readMCURow() {
2055 int pY, pCb, pCr, pR, pG, pB;
2056 int h, v, horiz, vert, hSub, vSub;
2057 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2060 for (x1 = 0; x1 < width; x1 += mcuWidth) {
2062 // deal with restart marker
2063 if (restartInterval > 0 && restartCtr == 0) {
2065 if (c != restartMarker) {
2066 error(getPos(), "Bad DCT data: incorrect restart marker");
2069 if (++restartMarker == 0xd8)
2070 restartMarker = 0xd0;
2075 for (cc = 0; cc < numComps; ++cc) {
2076 h = compInfo[cc].hSample;
2077 v = compInfo[cc].vSample;
2078 horiz = mcuWidth / h;
2079 vert = mcuHeight / v;
2082 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2083 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2084 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2085 &acHuffTables[scanInfo.acHuffTable[cc]],
2086 &compInfo[cc].prevDC,
2090 transformDataUnit(quantTables[compInfo[cc].quantTable],
2092 if (hSub == 1 && vSub == 1) {
2093 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2094 p1 = &rowBuf[cc][y2+y3][x1+x2];
2104 } else if (hSub == 2 && vSub == 2) {
2105 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2106 p1 = &rowBuf[cc][y2+y3][x1+x2];
2107 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
2108 p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
2109 p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
2110 p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
2111 p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
2112 p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
2113 p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
2114 p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
2115 p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
2119 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2120 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2121 for (y5 = 0; y5 < vSub; ++y5)
2122 for (x5 = 0; x5 < hSub; ++x5)
2123 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
2133 // color space conversion
2135 // convert YCbCr to RGB
2136 if (numComps == 3) {
2137 for (y2 = 0; y2 < mcuHeight; ++y2) {
2138 for (x2 = 0; x2 < mcuWidth; ++x2) {
2139 pY = rowBuf[0][y2][x1+x2];
2140 pCb = rowBuf[1][y2][x1+x2] - 128;
2141 pCr = rowBuf[2][y2][x1+x2] - 128;
2142 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2143 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
2144 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2145 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
2146 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2147 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
2150 // convert YCbCrK to CMYK (K is passed through unchanged)
2151 } else if (numComps == 4) {
2152 for (y2 = 0; y2 < mcuHeight; ++y2) {
2153 for (x2 = 0; x2 < mcuWidth; ++x2) {
2154 pY = rowBuf[0][y2][x1+x2];
2155 pCb = rowBuf[1][y2][x1+x2] - 128;
2156 pCr = rowBuf[2][y2][x1+x2] - 128;
2157 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2158 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
2159 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
2160 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
2161 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2162 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
2171 // Read one scan from a progressive or non-interleaved JPEG stream.
2172 void DCTStream::readScan() {
2174 int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
2175 int h, v, horiz, vert, vSub;
2179 if (scanInfo.numComps == 1) {
2180 for (cc = 0; cc < numComps; ++cc) {
2181 if (scanInfo.comp[cc]) {
2185 dx1 = mcuWidth / compInfo[cc].hSample;
2186 dy1 = mcuHeight / compInfo[cc].vSample;
2192 for (y1 = 0; y1 < height; y1 += dy1) {
2193 for (x1 = 0; x1 < width; x1 += dx1) {
2195 // deal with restart marker
2196 if (restartInterval > 0 && restartCtr == 0) {
2198 if (c != restartMarker) {
2199 error(getPos(), "Bad DCT data: incorrect restart marker");
2202 if (++restartMarker == 0xd8) {
2203 restartMarker = 0xd0;
2209 for (cc = 0; cc < numComps; ++cc) {
2210 if (!scanInfo.comp[cc]) {
2214 h = compInfo[cc].hSample;
2215 v = compInfo[cc].vSample;
2216 horiz = mcuWidth / h;
2217 vert = mcuHeight / v;
2219 for (y2 = 0; y2 < dy1; y2 += vert) {
2220 for (x2 = 0; x2 < dx1; x2 += horiz) {
2222 // pull out the current values
2223 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2224 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2233 p1 += bufWidth * vSub;
2236 // read one data unit
2238 if (!readProgressiveDataUnit(
2239 &dcHuffTables[scanInfo.dcHuffTable[cc]],
2240 &acHuffTables[scanInfo.acHuffTable[cc]],
2241 &compInfo[cc].prevDC,
2246 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
2247 &acHuffTables[scanInfo.acHuffTable[cc]],
2248 &compInfo[cc].prevDC,
2254 // add the data unit into frameBuf
2255 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2256 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2265 p1 += bufWidth * vSub;
2275 // Read one data unit from a sequential JPEG stream.
2276 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
2277 DCTHuffTable *acHuffTable,
2278 int *prevDC, int data[64]) {
2283 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2287 if ((amp = readAmp(size)) == 9999) {
2293 data[0] = *prevDC += amp;
2294 for (i = 1; i < 64; ++i) {
2300 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
2309 run += (c >> 4) & 0x0f;
2311 amp = readAmp(size);
2325 // Read one data unit from a sequential JPEG stream.
2326 GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
2327 DCTHuffTable *acHuffTable,
2328 int *prevDC, int data[64]) {
2329 int run, size, amp, bit, c;
2332 // get the DC coefficient
2333 i = scanInfo.firstCoeff;
2335 if (scanInfo.ah == 0) {
2336 if ((size = readHuffSym(dcHuffTable)) == 9999) {
2340 if ((amp = readAmp(size)) == 9999) {
2346 data[0] += (*prevDC += amp) << scanInfo.al;
2348 if ((bit = readBit()) == 9999) {
2351 data[0] += bit << scanInfo.al;
2355 if (scanInfo.lastCoeff == 0) {
2359 // check for an EOB run
2361 while (i <= scanInfo.lastCoeff) {
2364 if ((bit = readBit()) == EOF) {
2368 data[j] += 1 << scanInfo.al;
2376 // read the AC coefficients
2377 while (i <= scanInfo.lastCoeff) {
2378 if ((c = readHuffSym(acHuffTable)) == 9999) {
2390 if ((bit = readBit()) == EOF) {
2394 data[j] += 1 << scanInfo.al;
2400 } else if ((c & 0x0f) == 0x00) {
2403 for (k = 0; k < j; ++k) {
2404 if ((bit = readBit()) == EOF) {
2407 eobRun = (eobRun << 1) | bit;
2410 while (i <= scanInfo.lastCoeff) {
2413 if ((bit = readBit()) == EOF) {
2417 data[j] += 1 << scanInfo.al;
2424 // zero run and one AC coefficient
2426 run = (c >> 4) & 0x0f;
2428 if ((amp = readAmp(size)) == 9999) {
2434 while (data[j] != 0) {
2435 if ((bit = readBit()) == EOF) {
2439 data[j] += 1 << scanInfo.al;
2445 data[j] = amp << scanInfo.al;
2452 // Decode a progressive JPEG image.
2453 void DCTStream::decodeImage() {
2457 int pY, pCb, pCr, pR, pG, pB;
2458 int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
2459 int h, v, horiz, vert, hSub, vSub;
2462 for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
2463 for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
2464 for (cc = 0; cc < numComps; ++cc) {
2465 quantTable = quantTables[compInfo[cc].quantTable];
2466 h = compInfo[cc].hSample;
2467 v = compInfo[cc].vSample;
2468 horiz = mcuWidth / h;
2469 vert = mcuHeight / v;
2472 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
2473 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
2475 // pull out the coded data unit
2476 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2477 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2479 dataIn[i+1] = p1[1];
2480 dataIn[i+2] = p1[2];
2481 dataIn[i+3] = p1[3];
2482 dataIn[i+4] = p1[4];
2483 dataIn[i+5] = p1[5];
2484 dataIn[i+6] = p1[6];
2485 dataIn[i+7] = p1[7];
2486 p1 += bufWidth * vSub;
2490 transformDataUnit(quantTable, dataIn, dataOut);
2492 // store back into frameBuf, doing replication for
2493 // subsampled components
2494 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
2495 if (hSub == 1 && vSub == 1) {
2496 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
2497 p1[0] = dataOut[i] & 0xff;
2498 p1[1] = dataOut[i+1] & 0xff;
2499 p1[2] = dataOut[i+2] & 0xff;
2500 p1[3] = dataOut[i+3] & 0xff;
2501 p1[4] = dataOut[i+4] & 0xff;
2502 p1[5] = dataOut[i+5] & 0xff;
2503 p1[6] = dataOut[i+6] & 0xff;
2504 p1[7] = dataOut[i+7] & 0xff;
2507 } else if (hSub == 2 && vSub == 2) {
2509 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
2510 p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
2511 p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
2512 p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
2513 p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
2514 p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
2515 p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
2516 p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
2517 p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
2523 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
2524 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
2526 for (y5 = 0; y5 < vSub; ++y5) {
2527 for (x5 = 0; x5 < hSub; ++x5) {
2528 p2[x5] = dataOut[i] & 0xff;
2534 p1 += bufWidth * vSub;
2541 // color space conversion
2543 // convert YCbCr to RGB
2544 if (numComps == 3) {
2545 for (y2 = 0; y2 < mcuHeight; ++y2) {
2546 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2547 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2548 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2549 for (x2 = 0; x2 < mcuWidth; ++x2) {
2553 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2554 *p0++ = dctClip[dctClipOffset + pR];
2555 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2557 *p1++ = dctClip[dctClipOffset + pG];
2558 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2559 *p2++ = dctClip[dctClipOffset + pB];
2562 // convert YCbCrK to CMYK (K is passed through unchanged)
2563 } else if (numComps == 4) {
2564 for (y2 = 0; y2 < mcuHeight; ++y2) {
2565 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
2566 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
2567 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
2568 for (x2 = 0; x2 < mcuWidth; ++x2) {
2572 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
2573 *p0++ = 255 - dctClip[dctClipOffset + pR];
2574 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
2576 *p1++ = 255 - dctClip[dctClipOffset + pG];
2577 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
2578 *p2++ = 255 - dctClip[dctClipOffset + pB];
2587 // Transform one data unit -- this performs the dequantization and
2588 // IDCT steps. This IDCT algorithm is taken from:
2589 // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
2590 // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
2591 // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
2593 // The stage numbers mentioned in the comments refer to Figure 1 in this
2595 void DCTStream::transformDataUnit(Guchar *quantTable,
2596 int dataIn[64], Guchar dataOut[64]) {
2597 int v0, v1, v2, v3, v4, v5, v6, v7, t;
2602 for (i = 0; i < 64; ++i) {
2603 dataIn[i] *= quantTable[i];
2606 // inverse DCT on rows
2607 for (i = 0; i < 64; i += 8) {
2610 // check for all-zero AC coefficients
2611 if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
2612 p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
2613 t = (dctSqrt2 * p[0] + 512) >> 10;
2626 v0 = (dctSqrt2 * p[0] + 128) >> 8;
2627 v1 = (dctSqrt2 * p[4] + 128) >> 8;
2630 v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
2631 v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
2636 t = (v0 - v1+ 1) >> 1;
2637 v0 = (v0 + v1 + 1) >> 1;
2639 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
2640 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
2642 t = (v4 - v6 + 1) >> 1;
2643 v4 = (v4 + v6 + 1) >> 1;
2645 t = (v7 + v5 + 1) >> 1;
2646 v5 = (v7 - v5 + 1) >> 1;
2650 t = (v0 - v3 + 1) >> 1;
2651 v0 = (v0 + v3 + 1) >> 1;
2653 t = (v1 - v2 + 1) >> 1;
2654 v1 = (v1 + v2 + 1) >> 1;
2656 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2657 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2659 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2660 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2674 // inverse DCT on columns
2675 for (i = 0; i < 8; ++i) {
2678 // check for all-zero AC coefficients
2679 if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
2680 p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
2681 t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
2694 v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
2695 v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
2698 v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
2699 v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
2704 t = (v0 - v1 + 1) >> 1;
2705 v0 = (v0 + v1 + 1) >> 1;
2707 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
2708 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
2710 t = (v4 - v6 + 1) >> 1;
2711 v4 = (v4 + v6 + 1) >> 1;
2713 t = (v7 + v5 + 1) >> 1;
2714 v5 = (v7 - v5 + 1) >> 1;
2718 t = (v0 - v3 + 1) >> 1;
2719 v0 = (v0 + v3 + 1) >> 1;
2721 t = (v1 - v2 + 1) >> 1;
2722 v1 = (v1 + v2 + 1) >> 1;
2724 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
2725 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
2727 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
2728 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
2742 // convert to 8-bit integers
2743 for (i = 0; i < 64; ++i) {
2744 dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
2748 int DCTStream::readHuffSym(DCTHuffTable *table) {
2756 // add a bit to the code
2757 if ((bit = readBit()) == EOF)
2759 code = (code << 1) + bit;
2763 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
2764 code -= table->firstCode[codeBits];
2765 return table->sym[table->firstSym[codeBits] + code];
2767 } while (codeBits < 16);
2769 error(getPos(), "Bad Huffman code in DCT stream");
2773 int DCTStream::readAmp(int size) {
2778 for (bits = 0; bits < size; ++bits) {
2779 if ((bit = readBit()) == EOF)
2781 amp = (amp << 1) + bit;
2783 if (amp < (1 << (size - 1)))
2784 amp -= (1 << size) - 1;
2788 int DCTStream::readBit() {
2792 if (inputBits == 0) {
2793 if ((c = str->getChar()) == EOF)
2797 c2 = str->getChar();
2798 } while (c2 == 0xff);
2800 error(getPos(), "Bad DCT data: missing 00 after ff");
2807 bit = (inputBuf >> (inputBits - 1)) & 1;
2812 GBool DCTStream::readHeader() {
2824 if (!readBaselineSOF()) {
2829 if (!readProgressiveSOF()) {
2834 if (!readHuffmanTables()) {
2843 if (!readScanInfo()) {
2849 if (!readQuantTables()) {
2854 if (!readRestartInterval()) {
2859 if (!readJFIFMarker()) {
2864 if (!readAdobeMarker()) {
2869 error(getPos(), "Bad DCT header");
2872 // skip APPn / COM / etc.
2875 for (i = 0; i < n; ++i) {
2879 error(getPos(), "Unknown DCT marker <%02x>", c);
2889 GBool DCTStream::readBaselineSOF() {
2896 prec = str->getChar();
2899 numComps = str->getChar();
2901 error(getPos(), "Bad DCT precision %d", prec);
2904 for (i = 0; i < numComps; ++i) {
2905 compInfo[i].id = str->getChar();
2907 compInfo[i].hSample = (c >> 4) & 0x0f;
2908 compInfo[i].vSample = c & 0x0f;
2909 compInfo[i].quantTable = str->getChar();
2911 progressive = gFalse;
2915 GBool DCTStream::readProgressiveSOF() {
2922 prec = str->getChar();
2925 numComps = str->getChar();
2927 error(getPos(), "Bad DCT precision %d", prec);
2930 for (i = 0; i < numComps; ++i) {
2931 compInfo[i].id = str->getChar();
2933 compInfo[i].hSample = (c >> 4) & 0x0f;
2934 compInfo[i].vSample = c & 0x0f;
2935 compInfo[i].quantTable = str->getChar();
2937 progressive = gTrue;
2941 GBool DCTStream::readScanInfo() {
2946 length = read16() - 2;
2947 scanInfo.numComps = str->getChar();
2949 if (length != 2 * scanInfo.numComps + 3) {
2950 error(getPos(), "Bad DCT scan info block");
2953 interleaved = scanInfo.numComps == numComps;
2954 for (j = 0; j < numComps; ++j) {
2955 scanInfo.comp[j] = gFalse;
2957 for (i = 0; i < scanInfo.numComps; ++i) {
2958 id = str->getChar();
2959 // some (broken) DCT streams reuse ID numbers, but at least they
2960 // keep the components in order, so we check compInfo[i] first to
2961 // work around the problem
2962 if (id == compInfo[i].id) {
2965 for (j = 0; j < numComps; ++j) {
2966 if (id == compInfo[j].id) {
2970 if (j == numComps) {
2971 error(getPos(), "Bad DCT component ID in scan info block");
2975 scanInfo.comp[j] = gTrue;
2977 scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
2978 scanInfo.acHuffTable[j] = c & 0x0f;
2980 scanInfo.firstCoeff = str->getChar();
2981 scanInfo.lastCoeff = str->getChar();
2983 scanInfo.ah = (c >> 4) & 0x0f;
2984 scanInfo.al = c & 0x0f;
2988 GBool DCTStream::readQuantTables() {
2993 length = read16() - 2;
2994 while (length > 0) {
2995 index = str->getChar();
2996 if ((index & 0xf0) || index >= 4) {
2997 error(getPos(), "Bad DCT quantization table");
3000 if (index == numQuantTables)
3001 numQuantTables = index + 1;
3002 for (i = 0; i < 64; ++i)
3003 quantTables[index][dctZigZag[i]] = str->getChar();
3009 GBool DCTStream::readHuffmanTables() {
3018 length = read16() - 2;
3019 while (length > 0) {
3020 index = str->getChar();
3022 if ((index & 0x0f) >= 4) {
3023 error(getPos(), "Bad DCT Huffman table");
3028 if (index >= numACHuffTables)
3029 numACHuffTables = index+1;
3030 tbl = &acHuffTables[index];
3032 if (index >= numDCHuffTables)
3033 numDCHuffTables = index+1;
3034 tbl = &dcHuffTables[index];
3038 for (i = 1; i <= 16; ++i) {
3040 tbl->firstSym[i] = sym;
3041 tbl->firstCode[i] = code;
3042 tbl->numCodes[i] = c;
3044 code = (code + c) << 1;
3047 for (i = 0; i < sym; ++i)
3048 tbl->sym[i] = str->getChar();
3054 GBool DCTStream::readRestartInterval() {
3059 error(getPos(), "Bad DCT restart interval");
3062 restartInterval = read16();
3066 GBool DCTStream::readJFIFMarker() {
3074 for (i = 0; i < 5; ++i) {
3075 if ((c = str->getChar()) == EOF) {
3076 error(getPos(), "Bad DCT APP0 marker");
3082 if (!memcmp(buf, "JFIF\0", 5)) {
3083 gotJFIFMarker = gTrue;
3086 while (length > 0) {
3087 if (str->getChar() == EOF) {
3088 error(getPos(), "Bad DCT APP0 marker");
3096 GBool DCTStream::readAdobeMarker() {
3105 for (i = 0; i < 12; ++i) {
3106 if ((c = str->getChar()) == EOF) {
3111 if (strncmp(buf, "Adobe", 5)) {
3114 colorXform = buf[11];
3115 gotAdobeMarker = gTrue;
3116 for (i = 14; i < length; ++i) {
3117 if (str->getChar() == EOF) {
3124 error(getPos(), "Bad DCT Adobe APP14 marker");
3128 GBool DCTStream::readTrailer() {
3132 if (c != 0xd9) { // EOI
3133 error(getPos(), "Bad DCT trailer");
3139 int DCTStream::readMarker() {
3145 } while (c != 0xff);
3148 } while (c == 0xff);
3149 } while (c == 0x00);
3153 int DCTStream::read16() {
3156 if ((c1 = str->getChar()) == EOF)
3158 if ((c2 = str->getChar()) == EOF)
3160 return (c1 << 8) + c2;
3163 GString *DCTStream::getPSFilter(int psLevel, char *indent) {
3169 if (!(s = str->getPSFilter(psLevel, indent))) {
3172 s->append(indent)->append("<< >> /DCTDecode filter\n");
3176 GBool DCTStream::isBinary(GBool last) {
3177 return str->isBinary(gTrue);
3180 //------------------------------------------------------------------------
3182 //------------------------------------------------------------------------
3184 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
3185 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
3188 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
3220 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
3253 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
3254 int colors, int bits):
3255 FilterStream(strA) {
3256 if (predictor != 1) {
3257 pred = new StreamPredictor(this, predictor, columns, colors, bits);
3261 litCodeTab.codes = NULL;
3262 distCodeTab.codes = NULL;
3265 FlateStream::~FlateStream() {
3266 gfree(litCodeTab.codes);
3267 gfree(distCodeTab.codes);
3274 void FlateStream::reset() {
3281 compressedBlock = gFalse;
3288 //~ need to look at window size?
3289 endOfBlock = eof = gTrue;
3290 cmf = str->getChar();
3291 flg = str->getChar();
3292 if (cmf == EOF || flg == EOF)
3294 if ((cmf & 0x0f) != 0x08) {
3295 error(getPos(), "Unknown compression method in flate stream");
3298 if ((((cmf << 8) + flg) % 31) != 0) {
3299 error(getPos(), "Bad FCHECK in flate stream");
3303 error(getPos(), "FDICT bit set in flate stream");
3310 int FlateStream::getChar() {
3314 return pred->getChar();
3316 while (remain == 0) {
3317 if (endOfBlock && eof)
3322 index = (index + 1) & flateMask;
3327 int FlateStream::lookChar() {
3331 return pred->lookChar();
3333 while (remain == 0) {
3334 if (endOfBlock && eof)
3342 int FlateStream::getRawChar() {
3345 while (remain == 0) {
3346 if (endOfBlock && eof)
3351 index = (index + 1) & flateMask;
3356 GString *FlateStream::getPSFilter(int psLevel, char *indent) {
3359 if (psLevel < 3 || pred) {
3362 if (!(s = str->getPSFilter(psLevel, indent))) {
3365 s->append(indent)->append("<< >> /FlateDecode filter\n");
3369 GBool FlateStream::isBinary(GBool last) {
3370 return str->isBinary(gTrue);
3373 void FlateStream::readSome() {
3384 if (compressedBlock) {
3385 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
3390 } else if (code1 == 256) {
3395 code2 = lengthDecode[code1].bits;
3396 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3398 len = lengthDecode[code1].first + code2;
3399 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
3401 code2 = distDecode[code1].bits;
3402 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
3404 dist = distDecode[code1].first + code2;
3406 j = (index - dist) & flateMask;
3407 for (k = 0; k < len; ++k) {
3409 i = (i + 1) & flateMask;
3410 j = (j + 1) & flateMask;
3416 len = (blockLen < flateWindow) ? blockLen : flateWindow;
3417 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
3418 if ((c = str->getChar()) == EOF) {
3419 endOfBlock = eof = gTrue;
3433 error(getPos(), "Unexpected end of file in flate stream");
3434 endOfBlock = eof = gTrue;
3438 GBool FlateStream::startBlock() {
3443 // free the code tables from the previous block
3444 gfree(litCodeTab.codes);
3445 litCodeTab.codes = NULL;
3446 gfree(distCodeTab.codes);
3447 distCodeTab.codes = NULL;
3449 // read block header
3450 blockHdr = getCodeWord(3);
3455 // uncompressed block
3456 if (blockHdr == 0) {
3457 compressedBlock = gFalse;
3458 if ((c = str->getChar()) == EOF)
3460 blockLen = c & 0xff;
3461 if ((c = str->getChar()) == EOF)
3463 blockLen |= (c & 0xff) << 8;
3464 if ((c = str->getChar()) == EOF)
3467 if ((c = str->getChar()) == EOF)
3469 check |= (c & 0xff) << 8;
3470 if (check != (~blockLen & 0xffff))
3471 error(getPos(), "Bad uncompressed block length in flate stream");
3475 // compressed block with fixed codes
3476 } else if (blockHdr == 1) {
3477 compressedBlock = gTrue;
3480 // compressed block with dynamic codes
3481 } else if (blockHdr == 2) {
3482 compressedBlock = gTrue;
3483 if (!readDynamicCodes()) {
3487 // unknown block type
3492 endOfBlock = gFalse;
3496 error(getPos(), "Bad block header in flate stream");
3497 endOfBlock = eof = gTrue;
3501 void FlateStream::loadFixedCodes() {
3504 // build the literal code table
3505 for (i = 0; i <= 143; ++i) {
3508 for (i = 144; i <= 255; ++i) {
3511 for (i = 256; i <= 279; ++i) {
3514 for (i = 280; i <= 287; ++i) {
3517 compHuffmanCodes(codeLengths, flateMaxLitCodes, &litCodeTab);
3519 // build the distance code table
3520 for (i = 0; i < flateMaxDistCodes; ++i) {
3523 compHuffmanCodes(codeLengths, flateMaxDistCodes, &distCodeTab);
3526 GBool FlateStream::readDynamicCodes() {
3527 int numCodeLenCodes;
3530 int codeLenCodeLengths[flateMaxCodeLenCodes];
3531 FlateHuffmanTab codeLenCodeTab;
3532 int len, repeat, code;
3535 codeLenCodeTab.codes = NULL;
3538 if ((numLitCodes = getCodeWord(5)) == EOF) {
3542 if ((numDistCodes = getCodeWord(5)) == EOF) {
3546 if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
3549 numCodeLenCodes += 4;
3550 if (numLitCodes > flateMaxLitCodes ||
3551 numDistCodes > flateMaxDistCodes ||
3552 numCodeLenCodes > flateMaxCodeLenCodes) {
3556 // build the code length code table
3557 for (i = 0; i < flateMaxCodeLenCodes; ++i) {
3558 codeLenCodeLengths[i] = 0;
3560 for (i = 0; i < numCodeLenCodes; ++i) {
3561 if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
3565 compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
3567 // build the literal and distance code tables
3571 while (i < numLitCodes + numDistCodes) {
3572 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
3576 if ((repeat = getCodeWord(2)) == EOF) {
3580 if (i + repeat > numLitCodes + numDistCodes) {
3583 for (; repeat > 0; --repeat) {
3584 codeLengths[i++] = len;
3586 } else if (code == 17) {
3587 if ((repeat = getCodeWord(3)) == EOF) {
3591 if (i + repeat > numLitCodes + numDistCodes) {
3595 for (; repeat > 0; --repeat) {
3596 codeLengths[i++] = 0;
3598 } else if (code == 18) {
3599 if ((repeat = getCodeWord(7)) == EOF) {
3603 if (i + repeat > numLitCodes + numDistCodes) {
3607 for (; repeat > 0; --repeat) {
3608 codeLengths[i++] = 0;
3611 codeLengths[i++] = len = code;
3614 compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
3615 compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
3617 gfree(codeLenCodeTab.codes);
3621 error(getPos(), "Bad dynamic code table in flate stream");
3622 gfree(codeLenCodeTab.codes);
3626 // Convert an array <lengths> of <n> lengths, in value order, into a
3627 // Huffman code lookup table.
3628 void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
3629 int tabSize, len, code, code2, skip, val, i, t;
3631 // find max code length
3633 for (val = 0; val < n; ++val) {
3634 if (lengths[val] > tab->maxLen) {
3635 tab->maxLen = lengths[val];
3639 // allocate the table
3640 tabSize = 1 << tab->maxLen;
3641 tab->codes = (FlateCode *)gmalloc(tabSize * sizeof(FlateCode));
3644 for (i = 0; i < tabSize; ++i) {
3645 tab->codes[i].len = 0;
3646 tab->codes[i].val = 0;
3650 for (len = 1, code = 0, skip = 2;
3652 ++len, code <<= 1, skip <<= 1) {
3653 for (val = 0; val < n; ++val) {
3654 if (lengths[val] == len) {
3656 // bit-reverse the code
3659 for (i = 0; i < len; ++i) {
3660 code2 = (code2 << 1) | (t & 1);
3664 // fill in the table entries
3665 for (i = code2; i < tabSize; i += skip) {
3666 tab->codes[i].len = (Gushort)len;
3667 tab->codes[i].val = (Gushort)val;
3676 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
3680 while (codeSize < tab->maxLen) {
3681 if ((c = str->getChar()) == EOF) {
3684 codeBuf |= (c & 0xff) << codeSize;
3687 code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
3688 if (codeSize == 0 || codeSize < code->len || code->len == 0) {
3691 codeBuf >>= code->len;
3692 codeSize -= code->len;
3693 return (int)code->val;
3696 int FlateStream::getCodeWord(int bits) {
3699 while (codeSize < bits) {
3700 if ((c = str->getChar()) == EOF)
3702 codeBuf |= (c & 0xff) << codeSize;
3705 c = codeBuf & ((1 << bits) - 1);
3711 //------------------------------------------------------------------------
3713 //------------------------------------------------------------------------
3715 EOFStream::EOFStream(Stream *strA):
3716 FilterStream(strA) {
3719 EOFStream::~EOFStream() {
3723 //------------------------------------------------------------------------
3724 // FixedLengthEncoder
3725 //------------------------------------------------------------------------
3727 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
3728 FilterStream(strA) {
3733 FixedLengthEncoder::~FixedLengthEncoder() {
3734 if (str->isEncoder())
3738 void FixedLengthEncoder::reset() {
3743 int FixedLengthEncoder::getChar() {
3744 if (length >= 0 && count >= length)
3747 return str->getChar();
3750 int FixedLengthEncoder::lookChar() {
3751 if (length >= 0 && count >= length)
3753 return str->getChar();
3756 GBool FixedLengthEncoder::isBinary(GBool last) {
3757 return str->isBinary(gTrue);
3760 //------------------------------------------------------------------------
3762 //------------------------------------------------------------------------
3764 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
3765 FilterStream(strA) {
3766 bufPtr = bufEnd = buf;
3771 ASCIIHexEncoder::~ASCIIHexEncoder() {
3772 if (str->isEncoder()) {
3777 void ASCIIHexEncoder::reset() {
3779 bufPtr = bufEnd = buf;
3784 GBool ASCIIHexEncoder::fillBuf() {
3785 static char *hex = "0123456789abcdef";
3791 bufPtr = bufEnd = buf;
3792 if ((c = str->getChar()) == EOF) {
3796 if (lineLen >= 64) {
3800 *bufEnd++ = hex[(c >> 4) & 0x0f];
3801 *bufEnd++ = hex[c & 0x0f];
3807 //------------------------------------------------------------------------
3809 //------------------------------------------------------------------------
3811 ASCII85Encoder::ASCII85Encoder(Stream *strA):
3812 FilterStream(strA) {
3813 bufPtr = bufEnd = buf;
3818 ASCII85Encoder::~ASCII85Encoder() {
3819 if (str->isEncoder())
3823 void ASCII85Encoder::reset() {
3825 bufPtr = bufEnd = buf;
3830 GBool ASCII85Encoder::fillBuf() {
3839 for (n = 0; n < 4; ++n) {
3840 if ((c = str->getChar()) == EOF)
3844 bufPtr = bufEnd = buf;
3846 if (n == 4 && t == 0) {
3848 if (++lineLen == 65) {
3855 for (i = 4; i >= 0; --i) {
3856 buf1[i] = (char)(t % 85 + 0x21);
3859 for (i = 0; i <= n; ++i) {
3860 *bufEnd++ = buf1[i];
3861 if (++lineLen == 65) {
3873 return bufPtr < bufEnd;
3876 //------------------------------------------------------------------------
3878 //------------------------------------------------------------------------
3880 RunLengthEncoder::RunLengthEncoder(Stream *strA):
3881 FilterStream(strA) {
3882 bufPtr = bufEnd = nextEnd = buf;
3886 RunLengthEncoder::~RunLengthEncoder() {
3887 if (str->isEncoder())
3891 void RunLengthEncoder::reset() {
3893 bufPtr = bufEnd = nextEnd = buf;
3898 // When fillBuf finishes, buf[] looks like this:
3899 // +-----+--------------+-----------------+--
3900 // + tag | ... data ... | next 0, 1, or 2 |
3901 // +-----+--------------+-----------------+--
3903 // bufPtr bufEnd nextEnd
3905 GBool RunLengthEncoder::fillBuf() {
3914 if (nextEnd < bufEnd + 1) {
3915 if ((c1 = str->getChar()) == EOF) {
3920 c1 = bufEnd[0] & 0xff;
3922 if (nextEnd < bufEnd + 2) {
3923 if ((c2 = str->getChar()) == EOF) {
3932 c2 = bufEnd[1] & 0xff;
3936 c = 0; // make gcc happy
3939 while (n < 128 && (c = str->getChar()) == c1)
3941 buf[0] = (char)(257 - n);
3946 } else if (n < 128) {
3953 // get up to 128 chars
3959 if ((c = str->getChar()) == EOF) {
3965 if (buf[n] == buf[n-1])
3968 if (buf[n] == buf[n-1]) {
3969 buf[0] = (char)(n-2-1);
3971 nextEnd = &buf[n+1];
3973 buf[0] = (char)(n-1);
3974 bufEnd = nextEnd = &buf[n+1];