00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <aconf.h>
00010
00011 #ifdef USE_GCC_PRAGMAS
00012 #pragma implementation
00013 #endif
00014
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <stddef.h>
00018 #include <limits.h>
00019 #ifndef WIN32
00020 #include <unistd.h>
00021 #endif
00022 #include <string.h>
00023 #include <ctype.h>
00024 #include "gmem.h"
00025 #include "gfile.h"
00026 #include "xpdf_config.h"
00027 #include "Error.h"
00028 #include "Object.h"
00029 #ifndef NO_DECRYPTION
00030 #include "Decrypt.h"
00031 #endif
00032 #include "Stream.h"
00033 #include "JBIG2Stream.h"
00034 #include "Stream-CCITT.h"
00035
00036 #ifdef __DJGPP__
00037 static GBool setDJSYSFLAGS = gFalse;
00038 #endif
00039
00040 #ifdef VMS
00041 #ifdef __GNUC__
00042 #define SEEK_SET 0
00043 #define SEEK_CUR 1
00044 #define SEEK_END 2
00045 #endif
00046 #endif
00047
00048
00049
00050
00051
00052 Stream::Stream() {
00053 ref = 1;
00054 }
00055
00056 Stream::~Stream() {
00057 }
00058
00059 void Stream::close() {
00060 }
00061
00062 int Stream::getRawChar() {
00063 error(-1, "Internal: called getRawChar() on non-predictor stream");
00064 return EOF;
00065 }
00066
00067 char *Stream::getLine(char *buf, int size) {
00068 int i;
00069 int c;
00070
00071 if (lookChar() == EOF)
00072 return NULL;
00073 for (i = 0; i < size - 1; ++i) {
00074 c = getChar();
00075 if (c == EOF || c == '\n')
00076 break;
00077 if (c == '\r') {
00078 if ((c = lookChar()) == '\n')
00079 getChar();
00080 break;
00081 }
00082 buf[i] = c;
00083 }
00084 buf[i] = '\0';
00085 return buf;
00086 }
00087
00088 GString *Stream::getPSFilter(const char *) {
00089 return new GString();
00090 }
00091
00092 Stream *Stream::addFilters(Object *dict) {
00093 Object obj, obj2;
00094 Object params, params2;
00095 Stream *str;
00096 int i;
00097
00098 str = this;
00099 dict->dictLookup("Filter", &obj);
00100 if (obj.isNull()) {
00101 obj.free();
00102 dict->dictLookup("F", &obj);
00103 }
00104 dict->dictLookup("DecodeParms", ¶ms);
00105 if (params.isNull()) {
00106 params.free();
00107 dict->dictLookup("DP", ¶ms);
00108 }
00109 if (obj.isName()) {
00110 str = makeFilter(obj.getName(), str, ¶ms);
00111 } else if (obj.isArray()) {
00112 for (i = 0; i < obj.arrayGetLength(); ++i) {
00113 obj.arrayGet(i, &obj2);
00114 if (params.isArray())
00115 params.arrayGet(i, ¶ms2);
00116 else
00117 params2.initNull();
00118 if (obj2.isName()) {
00119 str = makeFilter(obj2.getName(), str, ¶ms2);
00120 } else {
00121 error(getPos(), "Bad filter name");
00122 str = new EOFStream(str);
00123 }
00124 obj2.free();
00125 params2.free();
00126 }
00127 } else if (!obj.isNull()) {
00128 error(getPos(), "Bad 'Filter' attribute in stream");
00129 }
00130 obj.free();
00131 params.free();
00132
00133 return str;
00134 }
00135
00136 Stream *Stream::makeFilter(const char *name, Stream *str, Object *params) {
00137 int pred;
00138 int colors;
00139 int bits;
00140 int early;
00141 int encoding;
00142 GBool endOfLine, byteAlign, endOfBlock, black;
00143 int columns, rows;
00144 Object globals, obj;
00145
00146 if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
00147 str = new ASCIIHexStream(str);
00148 } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
00149 str = new ASCII85Stream(str);
00150 } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
00151 pred = 1;
00152 columns = 1;
00153 colors = 1;
00154 bits = 8;
00155 early = 1;
00156 if (params->isDict()) {
00157 params->dictLookup("Predictor", &obj);
00158 if (obj.isInt())
00159 pred = obj.getInt();
00160 obj.free();
00161 params->dictLookup("Columns", &obj);
00162 if (obj.isInt())
00163 columns = obj.getInt();
00164 obj.free();
00165 params->dictLookup("Colors", &obj);
00166 if (obj.isInt())
00167 colors = obj.getInt();
00168 obj.free();
00169 params->dictLookup("BitsPerComponent", &obj);
00170 if (obj.isInt())
00171 bits = obj.getInt();
00172 obj.free();
00173 params->dictLookup("EarlyChange", &obj);
00174 if (obj.isInt())
00175 early = obj.getInt();
00176 obj.free();
00177 }
00178 str = new LZWStream(str, pred, columns, colors, bits, early);
00179 } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
00180 str = new RunLengthStream(str);
00181 } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
00182 encoding = 0;
00183 endOfLine = gFalse;
00184 byteAlign = gFalse;
00185 columns = 1728;
00186 rows = 0;
00187 endOfBlock = gTrue;
00188 black = gFalse;
00189 if (params->isDict()) {
00190 params->dictLookup("K", &obj);
00191 if (obj.isInt()) {
00192 encoding = obj.getInt();
00193 }
00194 obj.free();
00195 params->dictLookup("EndOfLine", &obj);
00196 if (obj.isBool()) {
00197 endOfLine = obj.getBool();
00198 }
00199 obj.free();
00200 params->dictLookup("EncodedByteAlign", &obj);
00201 if (obj.isBool()) {
00202 byteAlign = obj.getBool();
00203 }
00204 obj.free();
00205 params->dictLookup("Columns", &obj);
00206 if (obj.isInt()) {
00207 columns = obj.getInt();
00208 }
00209 obj.free();
00210 params->dictLookup("Rows", &obj);
00211 if (obj.isInt()) {
00212 rows = obj.getInt();
00213 }
00214 obj.free();
00215 params->dictLookup("EndOfBlock", &obj);
00216 if (obj.isBool()) {
00217 endOfBlock = obj.getBool();
00218 }
00219 obj.free();
00220 params->dictLookup("BlackIs1", &obj);
00221 if (obj.isBool()) {
00222 black = obj.getBool();
00223 }
00224 obj.free();
00225 }
00226 str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
00227 columns, rows, endOfBlock, black);
00228 } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
00229 str = new DCTStream(str);
00230 } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
00231 pred = 1;
00232 columns = 1;
00233 colors = 1;
00234 bits = 8;
00235 if (params->isDict()) {
00236 params->dictLookup("Predictor", &obj);
00237 if (obj.isInt())
00238 pred = obj.getInt();
00239 obj.free();
00240 params->dictLookup("Columns", &obj);
00241 if (obj.isInt())
00242 columns = obj.getInt();
00243 obj.free();
00244 params->dictLookup("Colors", &obj);
00245 if (obj.isInt())
00246 colors = obj.getInt();
00247 obj.free();
00248 params->dictLookup("BitsPerComponent", &obj);
00249 if (obj.isInt())
00250 bits = obj.getInt();
00251 obj.free();
00252 }
00253 str = new FlateStream(str, pred, columns, colors, bits);
00254 } else if (!strcmp(name, "JBIG2Decode")) {
00255 if (params->isDict()) {
00256 params->dictLookup("JBIG2Globals", &globals);
00257 }
00258 str = new JBIG2Stream(str, &globals);
00259 globals.free();
00260 } else {
00261 error(getPos(), "Unknown filter '%s'", name);
00262 str = new EOFStream(str);
00263 }
00264 return str;
00265 }
00266
00267
00268
00269
00270
00271 BaseStream::BaseStream(Object *dictA) {
00272 dict = *dictA;
00273 #ifndef NO_DECRYPTION
00274 decrypt = NULL;
00275 #endif
00276 }
00277
00278 BaseStream::~BaseStream() {
00279 dict.free();
00280 #ifndef NO_DECRYPTION
00281 if (decrypt)
00282 delete decrypt;
00283 #endif
00284 }
00285
00286 #ifndef NO_DECRYPTION
00287 void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
00288 int objNum, int objGen) {
00289 decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
00290 }
00291 #endif
00292
00293
00294
00295
00296
00297 FilterStream::FilterStream(Stream *strA) {
00298 str = strA;
00299 }
00300
00301 FilterStream::~FilterStream() {
00302 }
00303
00304 void FilterStream::close() {
00305 str->close();
00306 }
00307
00308 void FilterStream::setPos(Guint , int ) {
00309 error(-1, "Internal: called setPos() on FilterStream");
00310 }
00311
00312
00313
00314
00315
00316 ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
00317 int imgLineSize;
00318
00319 str = strA;
00320 width = widthA;
00321 nComps = nCompsA;
00322 nBits = nBitsA;
00323
00324 nVals = width * nComps;
00325 if (nBits == 1) {
00326 imgLineSize = (nVals + 7) & ~7;
00327 } else {
00328 imgLineSize = nVals;
00329 }
00330 imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
00331 imgIdx = nVals;
00332 }
00333
00334 ImageStream::~ImageStream() {
00335 gfree(imgLine);
00336 }
00337
00338 void ImageStream::reset() {
00339 str->reset();
00340 }
00341
00342 GBool ImageStream::getPixel(Guchar *pix) {
00343 int i;
00344
00345 if (imgIdx >= nVals) {
00346 getLine();
00347 imgIdx = 0;
00348 }
00349 for (i = 0; i < nComps; ++i) {
00350 pix[i] = imgLine[imgIdx++];
00351 }
00352 return gTrue;
00353 }
00354
00355 Guchar *ImageStream::getLine() {
00356 Gulong buf, bitMask;
00357 int bits;
00358 int c;
00359 int i;
00360
00361 if (nBits == 1) {
00362 for (i = 0; i < nVals; i += 8) {
00363 c = str->getChar();
00364 imgLine[i+0] = (Guchar)((c >> 7) & 1);
00365 imgLine[i+1] = (Guchar)((c >> 6) & 1);
00366 imgLine[i+2] = (Guchar)((c >> 5) & 1);
00367 imgLine[i+3] = (Guchar)((c >> 4) & 1);
00368 imgLine[i+4] = (Guchar)((c >> 3) & 1);
00369 imgLine[i+5] = (Guchar)((c >> 2) & 1);
00370 imgLine[i+6] = (Guchar)((c >> 1) & 1);
00371 imgLine[i+7] = (Guchar)(c & 1);
00372 }
00373 } else if (nBits == 8) {
00374 for (i = 0; i < nVals; ++i) {
00375 imgLine[i] = str->getChar();
00376 }
00377 } else {
00378 bitMask = (1 << nBits) - 1;
00379 buf = 0;
00380 bits = 0;
00381 for (i = 0; i < nVals; ++i) {
00382 if (bits < nBits) {
00383 buf = (buf << 8) | (str->getChar() & 0xff);
00384 bits += 8;
00385 }
00386 imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
00387 bits -= nBits;
00388 }
00389 }
00390 return imgLine;
00391 }
00392
00393 void ImageStream::skipLine() {
00394 int n, i;
00395
00396 n = (nVals * nBits + 7) >> 3;
00397 for (i = 0; i < n; ++i) {
00398 str->getChar();
00399 }
00400 }
00401
00402
00403
00404
00405
00406 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
00407 int widthA, int nCompsA, int nBitsA) {
00408 str = strA;
00409 predictor = predictorA;
00410 width = widthA;
00411 nComps = nCompsA;
00412 nBits = nBitsA;
00413 predLine = NULL;
00414 ok = gFalse;
00415
00416 nVals = width * nComps;
00417 if (width <= 0 || nComps <= 0 || nBits <= 0 ||
00418 nComps >= 4 || nBits > 16 ||
00419 width >= INT_MAX / nComps ||
00420 nVals >= (INT_MAX - 7) / nBits)
00421 return;
00422
00423 pixBytes = (nComps * nBits + 7) >> 3;
00424 rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
00425 if (rowBytes < 0)
00426 return;
00427
00428 predLine = (Guchar *)gmalloc(rowBytes);
00429 memset(predLine, 0, rowBytes);
00430 predIdx = rowBytes;
00431
00432 ok = gTrue;
00433 }
00434
00435 StreamPredictor::~StreamPredictor() {
00436 gfree(predLine);
00437 }
00438
00439 int StreamPredictor::lookChar() {
00440 if (predIdx >= rowBytes) {
00441 if (!getNextLine()) {
00442 return EOF;
00443 }
00444 }
00445 return predLine[predIdx];
00446 }
00447
00448 int StreamPredictor::getChar() {
00449 if (predIdx >= rowBytes) {
00450 if (!getNextLine()) {
00451 return EOF;
00452 }
00453 }
00454 return predLine[predIdx++];
00455 }
00456
00457 GBool StreamPredictor::getNextLine() {
00458 int curPred;
00459 Guchar upLeftBuf[4];
00460 int left, up, upLeft, p, pa, pb, pc;
00461 int c;
00462 Gulong inBuf, outBuf, bitMask;
00463 int inBits, outBits;
00464 int i, j, k;
00465
00466
00467 if (predictor == 15) {
00468 if ((curPred = str->getRawChar()) == EOF) {
00469 return gFalse;
00470 }
00471 curPred += 10;
00472 } else {
00473 curPred = predictor;
00474 }
00475
00476
00477 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
00478 for (i = pixBytes; i < rowBytes; ++i) {
00479 upLeftBuf[3] = upLeftBuf[2];
00480 upLeftBuf[2] = upLeftBuf[1];
00481 upLeftBuf[1] = upLeftBuf[0];
00482 upLeftBuf[0] = predLine[i];
00483 if ((c = str->getRawChar()) == EOF) {
00484 break;
00485 }
00486 switch (curPred) {
00487 case 11:
00488 predLine[i] = predLine[i - pixBytes] + (Guchar)c;
00489 break;
00490 case 12:
00491 predLine[i] = predLine[i] + (Guchar)c;
00492 break;
00493 case 13:
00494 predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
00495 (Guchar)c;
00496 break;
00497 case 14:
00498 left = predLine[i - pixBytes];
00499 up = predLine[i];
00500 upLeft = upLeftBuf[pixBytes];
00501 p = left + up - upLeft;
00502 if ((pa = p - left) < 0)
00503 pa = -pa;
00504 if ((pb = p - up) < 0)
00505 pb = -pb;
00506 if ((pc = p - upLeft) < 0)
00507 pc = -pc;
00508 if (pa <= pb && pa <= pc)
00509 predLine[i] = left + (Guchar)c;
00510 else if (pb <= pc)
00511 predLine[i] = up + (Guchar)c;
00512 else
00513 predLine[i] = upLeft + (Guchar)c;
00514 break;
00515 case 10:
00516 default:
00517 predLine[i] = (Guchar)c;
00518 break;
00519 }
00520 }
00521
00522
00523
00524 if (predictor == 2) {
00525 if (nBits == 1) {
00526 inBuf = predLine[pixBytes - 1];
00527 for (i = pixBytes; i < rowBytes; i += 8) {
00528
00529 inBuf = (inBuf << 8) | predLine[i];
00530 predLine[i] ^= inBuf >> nComps;
00531 }
00532 } else if (nBits == 8) {
00533 for (i = pixBytes; i < rowBytes; ++i) {
00534 predLine[i] += predLine[i - nComps];
00535 }
00536 } else {
00537 upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
00538 bitMask = (1 << nBits) - 1;
00539 inBuf = outBuf = 0;
00540 inBits = outBits = 0;
00541 j = k = pixBytes;
00542 for (i = 0; i < nVals; ++i) {
00543 if (inBits < nBits) {
00544 inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
00545 inBits += 8;
00546 }
00547 upLeftBuf[3] = upLeftBuf[2];
00548 upLeftBuf[2] = upLeftBuf[1];
00549 upLeftBuf[1] = upLeftBuf[0];
00550 upLeftBuf[0] = (upLeftBuf[nComps] +
00551 (inBuf >> (inBits - nBits))) & bitMask;
00552 outBuf = (outBuf << nBits) | upLeftBuf[0];
00553 inBits -= nBits;
00554 outBits += nBits;
00555 if (outBits > 8) {
00556 predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
00557 }
00558 }
00559 if (outBits > 0) {
00560 predLine[k++] = (Guchar)(outBuf << (8 - outBits));
00561 }
00562 }
00563 }
00564
00565
00566 predIdx = pixBytes;
00567
00568 return gTrue;
00569 }
00570
00571
00572
00573
00574
00575 FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
00576 Guint lengthA, Object *dictA):
00577 BaseStream(dictA) {
00578 f = fA;
00579 start = startA;
00580 limited = limitedA;
00581 length = lengthA;
00582 bufPtr = bufEnd = buf;
00583 bufPos = start;
00584 savePos = 0;
00585 saved = gFalse;
00586 }
00587
00588 FileStream::~FileStream() {
00589 close();
00590 }
00591
00592 Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
00593 Guint lengthA, Object *dictA) {
00594 return new FileStream(f, startA, limitedA, lengthA, dictA);
00595 }
00596
00597 void FileStream::reset() {
00598 #ifdef HAVE_FSEEKO
00599 savePos = (Guint)ftello(f);
00600 fseeko(f, start, SEEK_SET);
00601 #elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
00602 savePos = (Guint)ftell64(f);
00603 fseek64(f, start, SEEK_SET);
00604 #else
00605 savePos = (Guint)ftell(f);
00606 fseek(f, start, SEEK_SET);
00607 #endif
00608 saved = gTrue;
00609 bufPtr = bufEnd = buf;
00610 bufPos = start;
00611 #ifndef NO_DECRYPTION
00612 if (decrypt)
00613 decrypt->reset();
00614 #endif
00615 }
00616
00617 void FileStream::close() {
00618 if (saved) {
00619 #ifdef HAVE_FSEEKO
00620 fseeko(f, savePos, SEEK_SET);
00621 #elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
00622 fseek64(f, savePos, SEEK_SET);
00623 #else
00624 fseek(f, savePos, SEEK_SET);
00625 #endif
00626 saved = gFalse;
00627 }
00628 }
00629
00630 GBool FileStream::fillBuf() {
00631 int n;
00632 #ifndef NO_DECRYPTION
00633 char *p;
00634 #endif
00635
00636 bufPos += bufEnd - buf;
00637 bufPtr = bufEnd = buf;
00638 if (limited && bufPos >= start + length) {
00639 return gFalse;
00640 }
00641 if (limited && bufPos + fileStreamBufSize > start + length) {
00642 n = start + length - bufPos;
00643 } else {
00644 n = fileStreamBufSize;
00645 }
00646 n = fread(buf, 1, n, f);
00647 bufEnd = buf + n;
00648 if (bufPtr >= bufEnd) {
00649 return gFalse;
00650 }
00651 #ifndef NO_DECRYPTION
00652 if (decrypt) {
00653 for (p = buf; p < bufEnd; ++p) {
00654 *p = (char)decrypt->decryptByte((Guchar)*p);
00655 }
00656 }
00657 #endif
00658 return gTrue;
00659 }
00660
00661 void FileStream::setPos(Guint pos, int dir) {
00662 Guint size;
00663
00664 if (dir >= 0) {
00665 #ifdef HAVE_FSEEKO
00666 fseeko(f, pos, SEEK_SET);
00667 #elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
00668 fseek64(f, pos, SEEK_SET);
00669 #else
00670 fseek(f, pos, SEEK_SET);
00671 #endif
00672 bufPos = pos;
00673 } else {
00674 #ifdef HAVE_FSEEKO
00675 fseeko(f, 0, SEEK_END);
00676 size = (Guint)ftello(f);
00677 #elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
00678 fseek64(f, 0, SEEK_END);
00679 size = (Guint)ftell64(f);
00680 #else
00681 fseek(f, 0, SEEK_END);
00682 size = (Guint)ftell(f);
00683 #endif
00684 if (pos > size)
00685 pos = (Guint)size;
00686 #ifdef __CYGWIN32__
00687
00688 rewind(f);
00689 #endif
00690 #ifdef HAVE_FSEEKO
00691 fseeko(f, -(int)pos, SEEK_END);
00692 bufPos = (Guint)ftello(f);
00693 #elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
00694 fseek64(f, -(int)pos, SEEK_END);
00695 bufPos = (Guint)ftell64(f);
00696 #else
00697 fseek(f, -(int)pos, SEEK_END);
00698 bufPos = (Guint)ftell(f);
00699 #endif
00700 }
00701 bufPtr = bufEnd = buf;
00702 }
00703
00704 void FileStream::moveStart(int delta) {
00705 start += delta;
00706 bufPtr = bufEnd = buf;
00707 bufPos = start;
00708 }
00709
00710
00711
00712
00713
00714 MemStream::MemStream(char *bufA, Guint lengthA, Object *dictA):
00715 BaseStream(dictA) {
00716 buf = bufA;
00717 needFree = gFalse;
00718 length = lengthA;
00719 bufEnd = buf + length;
00720 bufPtr = buf;
00721 }
00722
00723 MemStream::~MemStream() {
00724 if (needFree) {
00725 gfree(buf);
00726 }
00727 }
00728
00729 Stream *MemStream::makeSubStream(Guint start, GBool limited,
00730 Guint lengthA, Object *dictA) {
00731 Guint newLength;
00732
00733 if (!limited || start + lengthA > length) {
00734 newLength = length - start;
00735 } else {
00736 newLength = lengthA;
00737 }
00738 return new MemStream(buf + start, newLength, dictA);
00739 }
00740
00741 void MemStream::reset() {
00742 bufPtr = buf;
00743 #ifndef NO_DECRYPTION
00744 if (decrypt) {
00745 decrypt->reset();
00746 }
00747 #endif
00748 }
00749
00750 void MemStream::close() {
00751 }
00752
00753 void MemStream::setPos(Guint pos, int dir) {
00754 if (dir >= 0) {
00755 if (pos > length) {
00756 bufPtr = bufEnd;
00757 } else {
00758 bufPtr = buf + pos;
00759 }
00760 } else {
00761 if (pos > length) {
00762 bufPtr = buf;
00763 } else {
00764 bufPtr = bufEnd - pos;
00765 }
00766 }
00767 }
00768
00769 void MemStream::moveStart(int delta) {
00770 buf += delta;
00771 bufPtr = buf;
00772 }
00773
00774 #ifndef NO_DECRYPTION
00775 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
00776 int objNum, int objGen) {
00777 char *newBuf;
00778 char *p, *q;
00779
00780 this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
00781 if (decrypt) {
00782 newBuf = (char *)gmalloc(bufEnd - buf);
00783 for (p = buf, q = newBuf; p < bufEnd; ++p, ++q) {
00784 *q = (char)decrypt->decryptByte((Guchar)*p);
00785 }
00786 bufEnd = newBuf + (bufEnd - buf);
00787 bufPtr = newBuf + (bufPtr - buf);
00788 buf = newBuf;
00789 needFree = gTrue;
00790 }
00791 }
00792 #endif
00793
00794
00795
00796
00797
00798 EmbedStream::EmbedStream(Stream *strA, Object *dictA):
00799 BaseStream(dictA) {
00800 str = strA;
00801 }
00802
00803 EmbedStream::~EmbedStream() {
00804 }
00805
00806 Stream *EmbedStream::makeSubStream(Guint , GBool ,
00807 Guint , Object *) {
00808 error(-1, "Internal: called makeSubStream() on EmbedStream");
00809 return NULL;
00810 }
00811
00812 void EmbedStream::setPos(Guint , int ) {
00813 error(-1, "Internal: called setPos() on EmbedStream");
00814 }
00815
00816 Guint EmbedStream::getStart() {
00817 error(-1, "Internal: called getStart() on EmbedStream");
00818 return 0;
00819 }
00820
00821 void EmbedStream::moveStart(int ) {
00822 error(-1, "Internal: called moveStart() on EmbedStream");
00823 }
00824
00825
00826
00827
00828
00829 ASCIIHexStream::ASCIIHexStream(Stream *strA):
00830 FilterStream(strA) {
00831 buf = EOF;
00832 eof = gFalse;
00833 }
00834
00835 ASCIIHexStream::~ASCIIHexStream() {
00836 delete str;
00837 }
00838
00839 void ASCIIHexStream::reset() {
00840 str->reset();
00841 buf = EOF;
00842 eof = gFalse;
00843 }
00844
00845 int ASCIIHexStream::lookChar() {
00846 int c1, c2, x;
00847
00848 if (buf != EOF)
00849 return buf;
00850 if (eof) {
00851 buf = EOF;
00852 return EOF;
00853 }
00854 do {
00855 c1 = str->getChar();
00856 } while (isspace(c1));
00857 if (c1 == '>') {
00858 eof = gTrue;
00859 buf = EOF;
00860 return buf;
00861 }
00862 do {
00863 c2 = str->getChar();
00864 } while (isspace(c2));
00865 if (c2 == '>') {
00866 eof = gTrue;
00867 c2 = '0';
00868 }
00869 if (c1 >= '0' && c1 <= '9') {
00870 x = (c1 - '0') << 4;
00871 } else if (c1 >= 'A' && c1 <= 'F') {
00872 x = (c1 - 'A' + 10) << 4;
00873 } else if (c1 >= 'a' && c1 <= 'f') {
00874 x = (c1 - 'a' + 10) << 4;
00875 } else if (c1 == EOF) {
00876 eof = gTrue;
00877 x = 0;
00878 } else {
00879 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
00880 x = 0;
00881 }
00882 if (c2 >= '0' && c2 <= '9') {
00883 x += c2 - '0';
00884 } else if (c2 >= 'A' && c2 <= 'F') {
00885 x += c2 - 'A' + 10;
00886 } else if (c2 >= 'a' && c2 <= 'f') {
00887 x += c2 - 'a' + 10;
00888 } else if (c2 == EOF) {
00889 eof = gTrue;
00890 x = 0;
00891 } else {
00892 error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
00893 }
00894 buf = x & 0xff;
00895 return buf;
00896 }
00897
00898 GString *ASCIIHexStream::getPSFilter(const char *indent) {
00899 GString *s;
00900
00901 if (!(s = str->getPSFilter(indent))) {
00902 return NULL;
00903 }
00904 s->append(indent)->append("/ASCIIHexDecode filter\n");
00905 return s;
00906 }
00907
00908 GBool ASCIIHexStream::isBinary(GBool ) {
00909 return str->isBinary(gFalse);
00910 }
00911
00912
00913
00914
00915
00916 ASCII85Stream::ASCII85Stream(Stream *strA):
00917 FilterStream(strA) {
00918 index = n = 0;
00919 eof = gFalse;
00920 }
00921
00922 ASCII85Stream::~ASCII85Stream() {
00923 delete str;
00924 }
00925
00926 void ASCII85Stream::reset() {
00927 str->reset();
00928 index = n = 0;
00929 eof = gFalse;
00930 }
00931
00932 int ASCII85Stream::lookChar() {
00933 int k;
00934 Gulong t;
00935
00936 if (index >= n) {
00937 if (eof)
00938 return EOF;
00939 index = 0;
00940 do {
00941 c[0] = str->getChar();
00942 } while (c[0] == '\n' || c[0] == '\r');
00943 if (c[0] == '~' || c[0] == EOF) {
00944 eof = gTrue;
00945 n = 0;
00946 return EOF;
00947 } else if (c[0] == 'z') {
00948 b[0] = b[1] = b[2] = b[3] = 0;
00949 n = 4;
00950 } else {
00951 for (k = 1; k < 5; ++k) {
00952 do {
00953 c[k] = str->getChar();
00954 } while (c[k] == '\n' || c[k] == '\r');
00955 if (c[k] == '~' || c[k] == EOF)
00956 break;
00957 }
00958 n = k - 1;
00959 if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
00960 for (++k; k < 5; ++k)
00961 c[k] = 0x21 + 84;
00962 eof = gTrue;
00963 }
00964 t = 0;
00965 for (k = 0; k < 5; ++k)
00966 t = t * 85 + (c[k] - 0x21);
00967 for (k = 3; k >= 0; --k) {
00968 b[k] = (int)(t & 0xff);
00969 t >>= 8;
00970 }
00971 }
00972 }
00973 return b[index];
00974 }
00975
00976 GString *ASCII85Stream::getPSFilter(const char *indent) {
00977 GString *s;
00978
00979 if (!(s = str->getPSFilter(indent))) {
00980 return NULL;
00981 }
00982 s->append(indent)->append("/ASCII85Decode filter\n");
00983 return s;
00984 }
00985
00986 GBool ASCII85Stream::isBinary(GBool ) {
00987 return str->isBinary(gFalse);
00988 }
00989
00990
00991
00992
00993
00994 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
00995 int bits, int earlyA):
00996 FilterStream(strA) {
00997 if (predictor != 1) {
00998 pred = new StreamPredictor(this, predictor, columns, colors, bits);
00999 if ( !pred->isOk()) {
01000 delete pred;
01001 pred = NULL;
01002 }
01003 } else {
01004 pred = NULL;
01005 }
01006 early = earlyA;
01007 eof = gFalse;
01008 inputBits = 0;
01009 clearTable();
01010 }
01011
01012 LZWStream::~LZWStream() {
01013 if (pred) {
01014 delete pred;
01015 }
01016 delete str;
01017 }
01018
01019 int LZWStream::getChar() {
01020 if (pred) {
01021 return pred->getChar();
01022 }
01023 if (eof) {
01024 return EOF;
01025 }
01026 if (seqIndex >= seqLength) {
01027 if (!processNextCode()) {
01028 return EOF;
01029 }
01030 }
01031 return seqBuf[seqIndex++];
01032 }
01033
01034 int LZWStream::lookChar() {
01035 if (pred) {
01036 return pred->lookChar();
01037 }
01038 if (eof) {
01039 return EOF;
01040 }
01041 if (seqIndex >= seqLength) {
01042 if (!processNextCode()) {
01043 return EOF;
01044 }
01045 }
01046 return seqBuf[seqIndex];
01047 }
01048
01049 int LZWStream::getRawChar() {
01050 if (eof) {
01051 return EOF;
01052 }
01053 if (seqIndex >= seqLength) {
01054 if (!processNextCode()) {
01055 return EOF;
01056 }
01057 }
01058 return seqBuf[seqIndex++];
01059 }
01060
01061 void LZWStream::reset() {
01062 str->reset();
01063 eof = gFalse;
01064 inputBits = 0;
01065 clearTable();
01066 }
01067
01068 GBool LZWStream::processNextCode() {
01069 int code;
01070 int nextLength;
01071 int i, j;
01072
01073
01074 if (eof) {
01075 return gFalse;
01076 }
01077
01078
01079 start:
01080 code = getCode();
01081 if (code == EOF || code == 257) {
01082 eof = gTrue;
01083 return gFalse;
01084 }
01085 if (code == 256) {
01086 clearTable();
01087 goto start;
01088 }
01089 if (nextCode >= 4097) {
01090 error(getPos(), "Bad LZW stream - expected clear-table code");
01091 clearTable();
01092 }
01093
01094
01095 nextLength = seqLength + 1;
01096 if (code < 256) {
01097 seqBuf[0] = code;
01098 seqLength = 1;
01099 } else if (code < nextCode) {
01100 seqLength = table[code].length;
01101 for (i = seqLength - 1, j = code; i > 0; --i) {
01102 seqBuf[i] = table[j].tail;
01103 j = table[j].head;
01104 }
01105 seqBuf[0] = j;
01106 } else if (code == nextCode) {
01107 seqBuf[seqLength] = newChar;
01108 ++seqLength;
01109 } else {
01110 error(getPos(), "Bad LZW stream - unexpected code");
01111 eof = gTrue;
01112 return gFalse;
01113 }
01114 newChar = seqBuf[0];
01115 if (first) {
01116 first = gFalse;
01117 } else {
01118 table[nextCode].length = nextLength;
01119 table[nextCode].head = prevCode;
01120 table[nextCode].tail = newChar;
01121 ++nextCode;
01122 if (nextCode + early == 512)
01123 nextBits = 10;
01124 else if (nextCode + early == 1024)
01125 nextBits = 11;
01126 else if (nextCode + early == 2048)
01127 nextBits = 12;
01128 }
01129 prevCode = code;
01130
01131
01132 seqIndex = 0;
01133
01134 return gTrue;
01135 }
01136
01137 void LZWStream::clearTable() {
01138 nextCode = 258;
01139 nextBits = 9;
01140 seqIndex = seqLength = 0;
01141 first = gTrue;
01142 }
01143
01144 int LZWStream::getCode() {
01145 int c;
01146 int code;
01147
01148 while (inputBits < nextBits) {
01149 if ((c = str->getChar()) == EOF)
01150 return EOF;
01151 inputBuf = (inputBuf << 8) | (c & 0xff);
01152 inputBits += 8;
01153 }
01154 code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
01155 inputBits -= nextBits;
01156 return code;
01157 }
01158
01159 GString *LZWStream::getPSFilter(const char *indent) {
01160 GString *s;
01161
01162 if (pred) {
01163 return NULL;
01164 }
01165 if (!(s = str->getPSFilter(indent))) {
01166 return NULL;
01167 }
01168 s->append(indent)->append("/LZWDecode filter\n");
01169 return s;
01170 }
01171
01172 GBool LZWStream::isBinary(GBool ) {
01173 return str->isBinary(gTrue);
01174 }
01175
01176
01177
01178
01179
01180 RunLengthStream::RunLengthStream(Stream *strA):
01181 FilterStream(strA) {
01182 bufPtr = bufEnd = buf;
01183 eof = gFalse;
01184 }
01185
01186 RunLengthStream::~RunLengthStream() {
01187 delete str;
01188 }
01189
01190 void RunLengthStream::reset() {
01191 str->reset();
01192 bufPtr = bufEnd = buf;
01193 eof = gFalse;
01194 }
01195
01196 GString *RunLengthStream::getPSFilter(const char *indent) {
01197 GString *s;
01198
01199 if (!(s = str->getPSFilter(indent))) {
01200 return NULL;
01201 }
01202 s->append(indent)->append("/RunLengthDecode filter\n");
01203 return s;
01204 }
01205
01206 GBool RunLengthStream::isBinary(GBool ) {
01207 return str->isBinary(gTrue);
01208 }
01209
01210 GBool RunLengthStream::fillBuf() {
01211 int c;
01212 int n, i;
01213
01214 if (eof)
01215 return gFalse;
01216 c = str->getChar();
01217 if (c == 0x80 || c == EOF) {
01218 eof = gTrue;
01219 return gFalse;
01220 }
01221 if (c < 0x80) {
01222 n = c + 1;
01223 for (i = 0; i < n; ++i)
01224 buf[i] = (char)str->getChar();
01225 } else {
01226 n = 0x101 - c;
01227 c = str->getChar();
01228 for (i = 0; i < n; ++i)
01229 buf[i] = (char)c;
01230 }
01231 bufPtr = buf;
01232 bufEnd = buf + n;
01233 return gTrue;
01234 }
01235
01236
01237
01238
01239
01240 #if 0
01241 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
01242 GBool byteAlignA, int columnsA, int rowsA,
01243 GBool endOfBlockA, GBool blackA):
01244 FilterStream(strA) {
01245 encoding = encodingA;
01246 endOfLine = endOfLineA;
01247 byteAlign = byteAlignA;
01248 columns = columnsA;
01249 if (columns < 1 || columns >= INT_MAX / sizeof(short)) {
01250 error(-1, "invalid number of columns");
01251 exit(1);
01252 }
01253 rows = rowsA;
01254 endOfBlock = endOfBlockA;
01255 black = blackA;
01256 refLine = (short *)gmalloc((columns + 3) * sizeof(short));
01257 codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
01258
01259 eof = gFalse;
01260 row = 0;
01261 nextLine2D = encoding < 0;
01262 inputBits = 0;
01263 codingLine[0] = 0;
01264 codingLine[1] = refLine[2] = columns;
01265 a0 = 1;
01266
01267 buf = EOF;
01268 }
01269
01270 CCITTFaxStream::~CCITTFaxStream() {
01271 delete str;
01272 gfree(refLine);
01273 gfree(codingLine);
01274 }
01275
01276 void CCITTFaxStream::reset() {
01277 int n;
01278
01279 str->reset();
01280 eof = gFalse;
01281 row = 0;
01282 nextLine2D = encoding < 0;
01283 inputBits = 0;
01284 codingLine[0] = 0;
01285 codingLine[1] = refLine[2] = columns;
01286 a0 = 1;
01287 buf = EOF;
01288
01289
01290 if (endOfBlock) {
01291 if (lookBits(12) == 0x001) {
01292 eatBits(12);
01293 }
01294 } else {
01295 for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
01296 if (n == 11 && lookBits(12) == 0x001) {
01297 eatBits(12);
01298 }
01299 }
01300 if (encoding > 0) {
01301 nextLine2D = !lookBits(1);
01302 eatBits(1);
01303 }
01304 }
01305
01306 int CCITTFaxStream::lookChar() {
01307 short code1, code2, code3;
01308 int a0New;
01309 #if 0
01310 GBool err;
01311 #endif
01312 GBool gotEOL;
01313 int ret;
01314 int bits, i;
01315
01316
01317 if (eof && codingLine[a0] >= columns) {
01318 return EOF;
01319 }
01320
01321
01322 #if 0
01323 err = gFalse;
01324 #endif
01325 if (codingLine[a0] >= columns) {
01326
01327
01328 if (nextLine2D) {
01329 for (i = 0; codingLine[i] < columns; ++i)
01330 refLine[i] = codingLine[i];
01331 refLine[i] = refLine[i + 1] = columns;
01332 b1 = 1;
01333 a0New = codingLine[a0 = 0] = 0;
01334 do {
01335 code1 = getTwoDimCode();
01336 switch (code1) {
01337 case twoDimPass:
01338 if (refLine[b1] < columns) {
01339 a0New = refLine[b1 + 1];
01340 b1 += 2;
01341 }
01342 break;
01343 case twoDimHoriz:
01344 if ((a0 & 1) == 0) {
01345 code1 = code2 = 0;
01346 do {
01347 code1 += code3 = getWhiteCode();
01348 } while (code3 >= 64);
01349 do {
01350 code2 += code3 = getBlackCode();
01351 } while (code3 >= 64);
01352 } else {
01353 code1 = code2 = 0;
01354 do {
01355 code1 += code3 = getBlackCode();
01356 } while (code3 >= 64);
01357 do {
01358 code2 += code3 = getWhiteCode();
01359 } while (code3 >= 64);
01360 }
01361 codingLine[a0 + 1] = a0New + code1;
01362 ++a0;
01363 a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
01364 ++a0;
01365 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01366 b1 += 2;
01367 break;
01368 case twoDimVert0:
01369 a0New = codingLine[++a0] = refLine[b1];
01370 if (refLine[b1] < columns) {
01371 ++b1;
01372 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01373 b1 += 2;
01374 }
01375 break;
01376 case twoDimVertR1:
01377 a0New = codingLine[++a0] = refLine[b1] + 1;
01378 if (refLine[b1] < columns) {
01379 ++b1;
01380 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01381 b1 += 2;
01382 }
01383 break;
01384 case twoDimVertL1:
01385 a0New = codingLine[++a0] = refLine[b1] - 1;
01386 --b1;
01387 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01388 b1 += 2;
01389 break;
01390 case twoDimVertR2:
01391 a0New = codingLine[++a0] = refLine[b1] + 2;
01392 if (refLine[b1] < columns) {
01393 ++b1;
01394 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01395 b1 += 2;
01396 }
01397 break;
01398 case twoDimVertL2:
01399 a0New = codingLine[++a0] = refLine[b1] - 2;
01400 --b1;
01401 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01402 b1 += 2;
01403 break;
01404 case twoDimVertR3:
01405 a0New = codingLine[++a0] = refLine[b1] + 3;
01406 if (refLine[b1] < columns) {
01407 ++b1;
01408 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01409 b1 += 2;
01410 }
01411 break;
01412 case twoDimVertL3:
01413 a0New = codingLine[++a0] = refLine[b1] - 3;
01414 --b1;
01415 while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01416 b1 += 2;
01417 break;
01418 case EOF:
01419 eof = gTrue;
01420 codingLine[a0 = 0] = columns;
01421 return EOF;
01422 default:
01423 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
01424 #if 0
01425 err = gTrue;
01426 break;
01427 #else
01428 eof = gTrue;
01429 return EOF;
01430 #endif
01431 }
01432 } while (codingLine[a0] < columns);
01433
01434
01435 } else {
01436 codingLine[a0 = 0] = 0;
01437 while (1) {
01438 code1 = 0;
01439 do {
01440 code1 += code3 = getWhiteCode();
01441 } while (code3 >= 64);
01442 codingLine[a0+1] = codingLine[a0] + code1;
01443 ++a0;
01444 if (codingLine[a0] >= columns)
01445 break;
01446 code2 = 0;
01447 do {
01448 code2 += code3 = getBlackCode();
01449 } while (code3 >= 64);
01450 codingLine[a0+1] = codingLine[a0] + code2;
01451 ++a0;
01452 if (codingLine[a0] >= columns)
01453 break;
01454 }
01455 }
01456
01457 if (codingLine[a0] != columns) {
01458 error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
01459 #if 0
01460 err = gTrue;
01461 #endif
01462 }
01463
01464
01465 if (byteAlign) {
01466 inputBits &= ~7;
01467 }
01468
01469
01470 gotEOL = gFalse;
01471 if (!endOfBlock && row == rows - 1) {
01472 eof = gTrue;
01473 } else {
01474 code1 = lookBits(12);
01475 while (code1 == 0) {
01476 eatBits(1);
01477 code1 = lookBits(12);
01478 }
01479 if (code1 == 0x001) {
01480 eatBits(12);
01481 gotEOL = gTrue;
01482 } else if (code1 == EOF) {
01483 eof = gTrue;
01484 }
01485 }
01486
01487
01488 if (!eof && encoding > 0) {
01489 nextLine2D = !lookBits(1);
01490 eatBits(1);
01491 }
01492
01493
01494 if (endOfBlock && gotEOL) {
01495 code1 = lookBits(12);
01496 if (code1 == 0x001) {
01497 eatBits(12);
01498 if (encoding > 0) {
01499 lookBits(1);
01500 eatBits(1);
01501 }
01502 if (encoding >= 0) {
01503 for (i = 0; i < 4; ++i) {
01504 code1 = lookBits(12);
01505 if (code1 != 0x001) {
01506 error(getPos(), "Bad RTC code in CCITTFax stream");
01507 }
01508 eatBits(12);
01509 if (encoding > 0) {
01510 lookBits(1);
01511 eatBits(1);
01512 }
01513 }
01514 }
01515 eof = gTrue;
01516 }
01517 }
01518
01519 #if 0
01520
01521
01522
01523
01524 else if (err) {
01525 do {
01526 if (code1 == EOF) {
01527 eof = gTrue;
01528 return EOF;
01529 }
01530 eatBits(1);
01531 code1 = look13Bits();
01532 } while ((code1 >> 1) != 0x001);
01533 eatBits(12);
01534 codingLine[++a0] = columns;
01535 if (encoding > 0) {
01536 eatBits(1);
01537 nextLine2D = !(code1 & 1);
01538 }
01539 }
01540 #endif
01541
01542 a0 = 0;
01543 outputBits = codingLine[1] - codingLine[0];
01544 if (outputBits == 0) {
01545 a0 = 1;
01546 outputBits = codingLine[2] - codingLine[1];
01547 }
01548
01549 ++row;
01550 }
01551
01552
01553 if (outputBits >= 8) {
01554 ret = ((a0 & 1) == 0) ? 0xff : 0x00;
01555 if ((outputBits -= 8) == 0) {
01556 ++a0;
01557 if (codingLine[a0] < columns) {
01558 outputBits = codingLine[a0 + 1] - codingLine[a0];
01559 }
01560 }
01561 } else {
01562 bits = 8;
01563 ret = 0;
01564 do {
01565 if (outputBits > bits) {
01566 i = bits;
01567 bits = 0;
01568 if ((a0 & 1) == 0) {
01569 ret |= 0xff >> (8 - i);
01570 }
01571 outputBits -= i;
01572 } else {
01573 i = outputBits;
01574 bits -= outputBits;
01575 if ((a0 & 1) == 0) {
01576 ret |= (0xff >> (8 - i)) << bits;
01577 }
01578 outputBits = 0;
01579 ++a0;
01580 if (codingLine[a0] < columns) {
01581 outputBits = codingLine[a0 + 1] - codingLine[a0];
01582 }
01583 }
01584 } while (bits > 0 && codingLine[a0] < columns);
01585 }
01586 buf = black ? (ret ^ 0xff) : ret;
01587 return buf;
01588 }
01589
01590 short CCITTFaxStream::getTwoDimCode() {
01591 short code;
01592 CCITTCode *p;
01593 int n;
01594
01595 code = 0;
01596 if (endOfBlock) {
01597 code = lookBits(7);
01598 p = &twoDimTab1[code];
01599 if (p->bits > 0) {
01600 eatBits(p->bits);
01601 return p->n;
01602 }
01603 } else {
01604 for (n = 1; n <= 7; ++n) {
01605 code = lookBits(n);
01606 if (n < 7) {
01607 code <<= 7 - n;
01608 }
01609 p = &twoDimTab1[code];
01610 if (p->bits == n) {
01611 eatBits(n);
01612 return p->n;
01613 }
01614 }
01615 }
01616 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
01617 return EOF;
01618 }
01619
01620 short CCITTFaxStream::getWhiteCode() {
01621 short code;
01622 CCITTCode *p;
01623 int n;
01624
01625 code = 0;
01626 if (endOfBlock) {
01627 code = lookBits(12);
01628 if ((code >> 5) == 0) {
01629 p = &whiteTab1[code];
01630 } else {
01631 p = &whiteTab2[code >> 3];
01632 }
01633 if (p->bits > 0) {
01634 eatBits(p->bits);
01635 return p->n;
01636 }
01637 } else {
01638 for (n = 1; n <= 9; ++n) {
01639 code = lookBits(n);
01640 if (n < 9) {
01641 code <<= 9 - n;
01642 }
01643 p = &whiteTab2[code];
01644 if (p->bits == n) {
01645 eatBits(n);
01646 return p->n;
01647 }
01648 }
01649 for (n = 11; n <= 12; ++n) {
01650 code = lookBits(n);
01651 if (n < 12) {
01652 code <<= 12 - n;
01653 }
01654 p = &whiteTab1[code];
01655 if (p->bits == n) {
01656 eatBits(n);
01657 return p->n;
01658 }
01659 }
01660 }
01661 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
01662
01663
01664 eatBits(1);
01665 return 1;
01666 }
01667
01668 short CCITTFaxStream::getBlackCode() {
01669 short code;
01670 CCITTCode *p;
01671 int n;
01672
01673 code = 0;
01674 if (endOfBlock) {
01675 code = lookBits(13);
01676 if ((code >> 7) == 0) {
01677 p = &blackTab1[code];
01678 } else if ((code >> 9) == 0) {
01679 p = &blackTab2[(code >> 1) - 64];
01680 } else {
01681 p = &blackTab3[code >> 7];
01682 }
01683 if (p->bits > 0) {
01684 eatBits(p->bits);
01685 return p->n;
01686 }
01687 } else {
01688 for (n = 2; n <= 6; ++n) {
01689 code = lookBits(n);
01690 if (n < 6) {
01691 code <<= 6 - n;
01692 }
01693 p = &blackTab3[code];
01694 if (p->bits == n) {
01695 eatBits(n);
01696 return p->n;
01697 }
01698 }
01699 for (n = 7; n <= 12; ++n) {
01700 code = lookBits(n);
01701 if (n < 12) {
01702 code <<= 12 - n;
01703 }
01704 if (code >= 64) {
01705 p = &blackTab2[code - 64];
01706 if (p->bits == n) {
01707 eatBits(n);
01708 return p->n;
01709 }
01710 }
01711 }
01712 for (n = 10; n <= 13; ++n) {
01713 code = lookBits(n);
01714 if (n < 13) {
01715 code <<= 13 - n;
01716 }
01717 p = &blackTab1[code];
01718 if (p->bits == n) {
01719 eatBits(n);
01720 return p->n;
01721 }
01722 }
01723 }
01724 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
01725
01726
01727 eatBits(1);
01728 return 1;
01729 }
01730
01731 short CCITTFaxStream::lookBits(int n) {
01732 int c;
01733
01734 while (inputBits < n) {
01735 if ((c = str->getChar()) == EOF) {
01736 if (inputBits == 0) {
01737 return EOF;
01738 }
01739
01740
01741
01742
01743 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
01744 }
01745 inputBuf = (inputBuf << 8) + c;
01746 inputBits += 8;
01747 }
01748 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
01749 }
01750 #else // secfix
01751 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
01752 GBool byteAlignA, int columnsA, int rowsA,
01753 GBool endOfBlockA, GBool blackA):
01754 FilterStream(strA) {
01755 encoding = encodingA;
01756 endOfLine = endOfLineA;
01757 byteAlign = byteAlignA;
01758 columns = columnsA;
01759 if (columns < 1) {
01760 columns = 1;
01761 } else if (columns > (INT_MAX - 2)/sizeof(int)) {
01762 columns = (INT_MAX - 2)/sizeof(int);
01763 }
01764 rows = rowsA;
01765 endOfBlock = endOfBlockA;
01766 black = blackA;
01767
01768
01769
01770
01771 codingLine = (int *)gmalloc((columns + 1) * sizeof(int));
01772 refLine = (int *)gmalloc((columns + 2) * sizeof(int));
01773
01774 eof = gFalse;
01775 row = 0;
01776 nextLine2D = encoding < 0;
01777 inputBits = 0;
01778 codingLine[0] = columns;
01779 a0i = 0;
01780 outputBits = 0;
01781
01782 buf = EOF;
01783 }
01784
01785 CCITTFaxStream::~CCITTFaxStream() {
01786 delete str;
01787 gfree(refLine);
01788 gfree(codingLine);
01789 }
01790
01791 void CCITTFaxStream::reset() {
01792 short code1;
01793
01794 str->reset();
01795 eof = gFalse;
01796 row = 0;
01797 nextLine2D = encoding < 0;
01798 inputBits = 0;
01799 codingLine[0] = columns;
01800 a0i = 0;
01801 outputBits = 0;
01802 buf = EOF;
01803
01804
01805
01806 while ((code1 = lookBits(12)) == 0) {
01807 eatBits(1);
01808 }
01809 if (code1 == 0x001) {
01810 eatBits(12);
01811 }
01812 if (encoding > 0) {
01813 nextLine2D = !lookBits(1);
01814 eatBits(1);
01815 }
01816 }
01817
01818 inline void CCITTFaxStream::addPixels(int a1, int blackPixels) {
01819 if (a1 > codingLine[a0i]) {
01820 if (a1 > columns) {
01821 error(getPos(), "CCITTFax row is wrong length (%d)", a1);
01822 err = gTrue;
01823 a1 = columns;
01824 }
01825 if ((a0i & 1) ^ blackPixels) {
01826 ++a0i;
01827 }
01828 codingLine[a0i] = a1;
01829 }
01830 }
01831
01832 inline void CCITTFaxStream::addPixelsNeg(int a1, int blackPixels) {
01833 if (a1 > codingLine[a0i]) {
01834 if (a1 > columns) {
01835 error(getPos(), "CCITTFax row is wrong length (%d)", a1);
01836 err = gTrue;
01837 a1 = columns;
01838 }
01839 if ((a0i & 1) ^ blackPixels) {
01840 ++a0i;
01841 }
01842 codingLine[a0i] = a1;
01843 } else if (a1 < codingLine[a0i]) {
01844 if (a1 < 0) {
01845 error(getPos(), "Invalid CCITTFax code");
01846 err = gTrue;
01847 a1 = 0;
01848 }
01849 while (a0i > 0 && a1 <= codingLine[a0i - 1]) {
01850 --a0i;
01851 }
01852 codingLine[a0i] = a1;
01853 }
01854 }
01855
01856 int CCITTFaxStream::lookChar() {
01857 short code1, code2, code3;
01858 int b1i, blackPixels, i, bits;
01859 GBool gotEOL;
01860
01861 if (buf != EOF) {
01862 return buf;
01863 }
01864
01865
01866 if (outputBits == 0) {
01867
01868
01869 if (eof) {
01870 return EOF;
01871 }
01872
01873 err = gFalse;
01874
01875
01876 if (nextLine2D) {
01877 for (i = 0; codingLine[i] < columns; ++i) {
01878 refLine[i] = codingLine[i];
01879 }
01880 refLine[i++] = columns;
01881 refLine[i] = columns;
01882 codingLine[0] = 0;
01883 a0i = 0;
01884 b1i = 0;
01885 blackPixels = 0;
01886
01887
01888
01889
01890
01891
01892
01893 while (codingLine[a0i] < columns) {
01894 code1 = getTwoDimCode();
01895 switch (code1) {
01896 case twoDimPass:
01897 addPixels(refLine[b1i + 1], blackPixels);
01898 if (refLine[b1i + 1] < columns) {
01899 b1i += 2;
01900 }
01901 break;
01902 case twoDimHoriz:
01903 code1 = code2 = 0;
01904 if (blackPixels) {
01905 do {
01906 code1 += code3 = getBlackCode();
01907 } while (code3 >= 64);
01908 do {
01909 code2 += code3 = getWhiteCode();
01910 } while (code3 >= 64);
01911 } else {
01912 do {
01913 code1 += code3 = getWhiteCode();
01914 } while (code3 >= 64);
01915 do {
01916 code2 += code3 = getBlackCode();
01917 } while (code3 >= 64);
01918 }
01919 addPixels(codingLine[a0i] + code1, blackPixels);
01920 if (codingLine[a0i] < columns) {
01921 addPixels(codingLine[a0i] + code2, blackPixels ^ 1);
01922 }
01923 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
01924 b1i += 2;
01925 }
01926 break;
01927 case twoDimVertR3:
01928 addPixels(refLine[b1i] + 3, blackPixels);
01929 blackPixels ^= 1;
01930 if (codingLine[a0i] < columns) {
01931 ++b1i;
01932 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
01933 b1i += 2;
01934 }
01935 }
01936 break;
01937 case twoDimVertR2:
01938 addPixels(refLine[b1i] + 2, blackPixels);
01939 blackPixels ^= 1;
01940 if (codingLine[a0i] < columns) {
01941 ++b1i;
01942 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
01943 b1i += 2;
01944 }
01945 }
01946 break;
01947 case twoDimVertR1:
01948 addPixels(refLine[b1i] + 1, blackPixels);
01949 blackPixels ^= 1;
01950 if (codingLine[a0i] < columns) {
01951 ++b1i;
01952 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
01953 b1i += 2;
01954 }
01955 }
01956 break;
01957 case twoDimVert0:
01958 addPixels(refLine[b1i], blackPixels);
01959 blackPixels ^= 1;
01960 if (codingLine[a0i] < columns) {
01961 ++b1i;
01962 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
01963 b1i += 2;
01964 }
01965 }
01966 break;
01967 case twoDimVertL3:
01968 addPixelsNeg(refLine[b1i] - 3, blackPixels);
01969 blackPixels ^= 1;
01970 if (codingLine[a0i] < columns) {
01971 if (b1i > 0) {
01972 --b1i;
01973 } else {
01974 ++b1i;
01975 }
01976 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
01977 b1i += 2;
01978 }
01979 }
01980 break;
01981 case twoDimVertL2:
01982 addPixelsNeg(refLine[b1i] - 2, blackPixels);
01983 blackPixels ^= 1;
01984 if (codingLine[a0i] < columns) {
01985 if (b1i > 0) {
01986 --b1i;
01987 } else {
01988 ++b1i;
01989 }
01990 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
01991 b1i += 2;
01992 }
01993 }
01994 break;
01995 case twoDimVertL1:
01996 addPixelsNeg(refLine[b1i] - 1, blackPixels);
01997 blackPixels ^= 1;
01998 if (codingLine[a0i] < columns) {
01999 if (b1i > 0) {
02000 --b1i;
02001 } else {
02002 ++b1i;
02003 }
02004 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
02005 b1i += 2;
02006 }
02007 }
02008 break;
02009 case EOF:
02010 addPixels(columns, 0);
02011 eof = gTrue;
02012 break;
02013 default:
02014 error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
02015 addPixels(columns, 0);
02016 err = gTrue;
02017 break;
02018 }
02019 }
02020
02021
02022 } else {
02023 codingLine[0] = 0;
02024 a0i = 0;
02025 blackPixels = 0;
02026 while (codingLine[a0i] < columns) {
02027 code1 = 0;
02028 if (blackPixels) {
02029 do {
02030 code1 += code3 = getBlackCode();
02031 } while (code3 >= 64);
02032 } else {
02033 do {
02034 code1 += code3 = getWhiteCode();
02035 } while (code3 >= 64);
02036 }
02037 addPixels(codingLine[a0i] + code1, blackPixels);
02038 blackPixels ^= 1;
02039 }
02040 }
02041
02042
02043 if (byteAlign) {
02044 inputBits &= ~7;
02045 }
02046
02047
02048 gotEOL = gFalse;
02049 if (!endOfBlock && row == rows - 1) {
02050 eof = gTrue;
02051 } else {
02052 code1 = lookBits(12);
02053 while (code1 == 0) {
02054 eatBits(1);
02055 code1 = lookBits(12);
02056 }
02057 if (code1 == 0x001) {
02058 eatBits(12);
02059 gotEOL = gTrue;
02060 } else if (code1 == EOF) {
02061 eof = gTrue;
02062 }
02063 }
02064
02065
02066 if (!eof && encoding > 0) {
02067 nextLine2D = !lookBits(1);
02068 eatBits(1);
02069 }
02070
02071
02072 if (endOfBlock && gotEOL) {
02073 code1 = lookBits(12);
02074 if (code1 == 0x001) {
02075 eatBits(12);
02076 if (encoding > 0) {
02077 lookBits(1);
02078 eatBits(1);
02079 }
02080 if (encoding >= 0) {
02081 for (i = 0; i < 4; ++i) {
02082 code1 = lookBits(12);
02083 if (code1 != 0x001) {
02084 error(getPos(), "Bad RTC code in CCITTFax stream");
02085 }
02086 eatBits(12);
02087 if (encoding > 0) {
02088 lookBits(1);
02089 eatBits(1);
02090 }
02091 }
02092 }
02093 eof = gTrue;
02094 }
02095
02096
02097
02098
02099 } else if (err && endOfLine) {
02100 while (1) {
02101 code1 = lookBits(13);
02102 if (code1 == EOF) {
02103 eof = gTrue;
02104 return EOF;
02105 }
02106 if ((code1 >> 1) == 0x001) {
02107 break;
02108 }
02109 eatBits(1);
02110 }
02111 eatBits(12);
02112 if (encoding > 0) {
02113 eatBits(1);
02114 nextLine2D = !(code1 & 1);
02115 }
02116 }
02117
02118
02119 if (codingLine[0] > 0) {
02120 outputBits = codingLine[a0i = 0];
02121 } else {
02122 outputBits = codingLine[a0i = 1];
02123 }
02124
02125 ++row;
02126 }
02127
02128
02129 if (outputBits >= 8) {
02130 buf = (a0i & 1) ? 0x00 : 0xff;
02131 outputBits -= 8;
02132 if (outputBits == 0 && codingLine[a0i] < columns) {
02133 ++a0i;
02134 outputBits = codingLine[a0i] - codingLine[a0i - 1];
02135 }
02136 } else {
02137 bits = 8;
02138 buf = 0;
02139 do {
02140 if (outputBits > bits) {
02141 buf <<= bits;
02142 if (!(a0i & 1)) {
02143 buf |= 0xff >> (8 - bits);
02144 }
02145 outputBits -= bits;
02146 bits = 0;
02147 } else {
02148 buf <<= outputBits;
02149 if (!(a0i & 1)) {
02150 buf |= 0xff >> (8 - outputBits);
02151 }
02152 bits -= outputBits;
02153 outputBits = 0;
02154 if (codingLine[a0i] < columns) {
02155 ++a0i;
02156 outputBits = codingLine[a0i] - codingLine[a0i - 1];
02157 } else if (bits > 0) {
02158 buf <<= bits;
02159 bits = 0;
02160 }
02161 }
02162 } while (bits);
02163 }
02164 if (black) {
02165 buf ^= 0xff;
02166 }
02167 return buf;
02168 }
02169
02170 short CCITTFaxStream::getTwoDimCode() {
02171 short code;
02172 CCITTCode *p;
02173 int n;
02174
02175 code = 0;
02176 if (endOfBlock) {
02177 code = lookBits(7);
02178 p = &twoDimTab1[code];
02179 if (p->bits > 0) {
02180 eatBits(p->bits);
02181 return p->n;
02182 }
02183 } else {
02184 for (n = 1; n <= 7; ++n) {
02185 code = lookBits(n);
02186 if (n < 7) {
02187 code <<= 7 - n;
02188 }
02189 p = &twoDimTab1[code];
02190 if (p->bits == n) {
02191 eatBits(n);
02192 return p->n;
02193 }
02194 }
02195 }
02196 error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
02197 return EOF;
02198 }
02199
02200 short CCITTFaxStream::getWhiteCode() {
02201 short code;
02202 CCITTCode *p;
02203 int n;
02204
02205 code = 0;
02206 if (endOfBlock) {
02207 code = lookBits(12);
02208 if (code == EOF) {
02209 return 1;
02210 }
02211 if ((code >> 5) == 0) {
02212 p = &whiteTab1[code];
02213 } else {
02214 p = &whiteTab2[code >> 3];
02215 }
02216 if (p->bits > 0) {
02217 eatBits(p->bits);
02218 return p->n;
02219 }
02220 } else {
02221 for (n = 1; n <= 9; ++n) {
02222 code = lookBits(n);
02223 if (code == EOF) {
02224 return 1;
02225 }
02226 if (n < 9) {
02227 code <<= 9 - n;
02228 }
02229 p = &whiteTab2[code];
02230 if (p->bits == n) {
02231 eatBits(n);
02232 return p->n;
02233 }
02234 }
02235 for (n = 11; n <= 12; ++n) {
02236 code = lookBits(n);
02237 if (code == EOF) {
02238 return 1;
02239 }
02240 if (n < 12) {
02241 code <<= 12 - n;
02242 }
02243 p = &whiteTab1[code];
02244 if (p->bits == n) {
02245 eatBits(n);
02246 return p->n;
02247 }
02248 }
02249 }
02250 error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
02251
02252
02253 eatBits(1);
02254 return 1;
02255 }
02256
02257 short CCITTFaxStream::getBlackCode() {
02258 short code;
02259 CCITTCode *p;
02260 int n;
02261
02262 code = 0;
02263 if (endOfBlock) {
02264 code = lookBits(13);
02265 if (code == EOF) {
02266 return 1;
02267 }
02268 if ((code >> 7) == 0) {
02269 p = &blackTab1[code];
02270 } else if ((code >> 9) == 0 && (code >> 7) != 0) {
02271 p = &blackTab2[(code >> 1) - 64];
02272 } else {
02273 p = &blackTab3[code >> 7];
02274 }
02275 if (p->bits > 0) {
02276 eatBits(p->bits);
02277 return p->n;
02278 }
02279 } else {
02280 for (n = 2; n <= 6; ++n) {
02281 code = lookBits(n);
02282 if (code == EOF) {
02283 return 1;
02284 }
02285 if (n < 6) {
02286 code <<= 6 - n;
02287 }
02288 p = &blackTab3[code];
02289 if (p->bits == n) {
02290 eatBits(n);
02291 return p->n;
02292 }
02293 }
02294 for (n = 7; n <= 12; ++n) {
02295 code = lookBits(n);
02296 if (code == EOF) {
02297 return 1;
02298 }
02299 if (n < 12) {
02300 code <<= 12 - n;
02301 }
02302 if (code >= 64) {
02303 p = &blackTab2[code - 64];
02304 if (p->bits == n) {
02305 eatBits(n);
02306 return p->n;
02307 }
02308 }
02309 }
02310 for (n = 10; n <= 13; ++n) {
02311 code = lookBits(n);
02312 if (code == EOF) {
02313 return 1;
02314 }
02315 if (n < 13) {
02316 code <<= 13 - n;
02317 }
02318 p = &blackTab1[code];
02319 if (p->bits == n) {
02320 eatBits(n);
02321 return p->n;
02322 }
02323 }
02324 }
02325 error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
02326
02327
02328 eatBits(1);
02329 return 1;
02330 }
02331
02332 short CCITTFaxStream::lookBits(int n) {
02333 int c;
02334
02335 while (inputBits < n) {
02336 if ((c = str->getChar()) == EOF) {
02337 if (inputBits == 0) {
02338 return EOF;
02339 }
02340
02341
02342
02343
02344 return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
02345 }
02346 inputBuf = (inputBuf << 8) + c;
02347 inputBits += 8;
02348 }
02349 return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
02350 }
02351
02352 #endif
02353
02354 GString *CCITTFaxStream::getPSFilter(const char *indent) {
02355 GString *s;
02356 char s1[50];
02357
02358 if (!(s = str->getPSFilter(indent))) {
02359 return NULL;
02360 }
02361 s->append(indent)->append("<< ");
02362 if (encoding != 0) {
02363 sprintf(s1, "/K %d ", encoding);
02364 s->append(s1);
02365 }
02366 if (endOfLine) {
02367 s->append("/EndOfLine true ");
02368 }
02369 if (byteAlign) {
02370 s->append("/EncodedByteAlign true ");
02371 }
02372 sprintf(s1, "/Columns %d ", columns);
02373 s->append(s1);
02374 if (rows != 0) {
02375 sprintf(s1, "/Rows %d ", rows);
02376 s->append(s1);
02377 }
02378 if (!endOfBlock) {
02379 s->append("/EndOfBlock false ");
02380 }
02381 if (black) {
02382 s->append("/BlackIs1 true ");
02383 }
02384 s->append(">> /CCITTFaxDecode filter\n");
02385 return s;
02386 }
02387
02388 GBool CCITTFaxStream::isBinary(GBool ) {
02389 return str->isBinary(gTrue);
02390 }
02391
02392
02393
02394
02395
02396
02397 #define dctCos1 4017 // cos(pi/16)
02398 #define dctSin1 799 // sin(pi/16)
02399 #define dctCos3 3406 // cos(3*pi/16)
02400 #define dctSin3 2276 // sin(3*pi/16)
02401 #define dctCos6 1567 // cos(6*pi/16)
02402 #define dctSin6 3784 // sin(6*pi/16)
02403 #define dctSqrt2 5793 // sqrt(2)
02404 #define dctSqrt1d2 2896 // sqrt(2) / 2
02405
02406
02407 #define dctCrToR 91881 // 1.4020
02408 #define dctCbToG -22553 // -0.3441363
02409 #define dctCrToG -46802 // -0.71413636
02410 #define dctCbToB 116130 // 1.772
02411
02412
02413 #define dctClipOffset 256
02414 static Guchar dctClip[768];
02415 static int dctClipInit = 0;
02416
02417
02418 static int dctZigZag[64] = {
02419 0,
02420 1, 8,
02421 16, 9, 2,
02422 3, 10, 17, 24,
02423 32, 25, 18, 11, 4,
02424 5, 12, 19, 26, 33, 40,
02425 48, 41, 34, 27, 20, 13, 6,
02426 7, 14, 21, 28, 35, 42, 49, 56,
02427 57, 50, 43, 36, 29, 22, 15,
02428 23, 30, 37, 44, 51, 58,
02429 59, 52, 45, 38, 31,
02430 39, 46, 53, 60,
02431 61, 54, 47,
02432 55, 62,
02433 63
02434 };
02435
02436 DCTStream::DCTStream(Stream *strA):
02437 FilterStream(strA) {
02438 int i, j;
02439
02440 progressive = interleaved = gFalse;
02441 width = height = 0;
02442 mcuWidth = mcuHeight = 0;
02443 numComps = 0;
02444 comp = 0;
02445 x = y = dy = 0;
02446 for (i = 0; i < 4; ++i) {
02447 for (j = 0; j < 32; ++j) {
02448 rowBuf[i][j] = NULL;
02449 }
02450 frameBuf[i] = NULL;
02451 }
02452
02453 if (!dctClipInit) {
02454 for (i = -256; i < 0; ++i)
02455 dctClip[dctClipOffset + i] = 0;
02456 for (i = 0; i < 256; ++i)
02457 dctClip[dctClipOffset + i] = i;
02458 for (i = 256; i < 512; ++i)
02459 dctClip[dctClipOffset + i] = 255;
02460 dctClipInit = 1;
02461 }
02462 }
02463
02464 DCTStream::~DCTStream() {
02465 int i, j;
02466
02467 delete str;
02468 if (progressive || !interleaved) {
02469 for (i = 0; i < numComps; ++i) {
02470 gfree(frameBuf[i]);
02471 }
02472 } else {
02473 for (i = 0; i < numComps; ++i) {
02474 for (j = 0; j < mcuHeight; ++j) {
02475 gfree(rowBuf[i][j]);
02476 }
02477 }
02478 }
02479 }
02480
02481 void DCTStream::reset() {
02482 int minHSample, minVSample;
02483 int i, j;
02484
02485 str->reset();
02486
02487 progressive = interleaved = gFalse;
02488 width = height = 0;
02489 numComps = 0;
02490 numQuantTables = 0;
02491 numDCHuffTables = 0;
02492 numACHuffTables = 0;
02493 colorXform = 0;
02494 gotAdobeMarker = gFalse;
02495 restartInterval = 0;
02496
02497 if (!readHeader()) {
02498 y = height;
02499 return;
02500 }
02501
02502
02503 mcuWidth = minHSample = compInfo[0].hSample;
02504 mcuHeight = minVSample = compInfo[0].vSample;
02505 for (i = 1; i < numComps; ++i) {
02506 if (compInfo[i].hSample < minHSample)
02507 minHSample = compInfo[i].hSample;
02508 if (compInfo[i].vSample < minVSample)
02509 minVSample = compInfo[i].vSample;
02510 if (compInfo[i].hSample > mcuWidth)
02511 mcuWidth = compInfo[i].hSample;
02512 if (compInfo[i].vSample > mcuHeight)
02513 mcuHeight = compInfo[i].vSample;
02514 }
02515 for (i = 0; i < numComps; ++i) {
02516 compInfo[i].hSample /= minHSample;
02517 compInfo[i].vSample /= minVSample;
02518 }
02519 mcuWidth = (mcuWidth / minHSample) * 8;
02520 mcuHeight = (mcuHeight / minVSample) * 8;
02521
02522
02523 if (!gotAdobeMarker && numComps == 3) {
02524 if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
02525 colorXform = 1;
02526 }
02527 }
02528
02529 if (progressive || !interleaved) {
02530
02531
02532 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
02533 bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
02534 if (bufWidth <= 0 || bufHeight <= 0 ||
02535 bufWidth > INT_MAX / bufWidth / (int)sizeof(int)) {
02536 error(getPos(), "Invalid image size in DCT stream");
02537 y = height;
02538 return;
02539 }
02540 for (i = 0; i < numComps; ++i) {
02541 frameBuf[i] = (int *)gmalloc(bufWidth * bufHeight * sizeof(int));
02542 memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
02543 }
02544
02545
02546 do {
02547 restartMarker = 0xd0;
02548 restart();
02549 readScan();
02550 } while (readHeader());
02551
02552
02553 decodeImage();
02554
02555
02556 comp = 0;
02557 x = 0;
02558 y = 0;
02559
02560 } else {
02561
02562
02563 bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
02564 for (i = 0; i < numComps; ++i) {
02565 for (j = 0; j < mcuHeight; ++j) {
02566 rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
02567 }
02568 }
02569
02570
02571 comp = 0;
02572 x = 0;
02573 y = 0;
02574 dy = mcuHeight;
02575
02576 restartMarker = 0xd0;
02577 restart();
02578 }
02579 }
02580
02581 int DCTStream::getChar() {
02582 int c;
02583
02584 if (y >= height) {
02585 return EOF;
02586 }
02587 if (progressive || !interleaved) {
02588 c = frameBuf[comp][y * bufWidth + x];
02589 if (++comp == numComps) {
02590 comp = 0;
02591 if (++x == width) {
02592 x = 0;
02593 ++y;
02594 }
02595 }
02596 } else {
02597 if (dy >= mcuHeight) {
02598 if (!readMCURow()) {
02599 y = height;
02600 return EOF;
02601 }
02602 comp = 0;
02603 x = 0;
02604 dy = 0;
02605 }
02606 c = rowBuf[comp][dy][x];
02607 if (++comp == numComps) {
02608 comp = 0;
02609 if (++x == width) {
02610 x = 0;
02611 ++y;
02612 ++dy;
02613 if (y == height) {
02614 readTrailer();
02615 }
02616 }
02617 }
02618 }
02619 return c;
02620 }
02621
02622 int DCTStream::lookChar() {
02623 if (y >= height) {
02624 return EOF;
02625 }
02626 if (progressive || !interleaved) {
02627 return frameBuf[comp][y * bufWidth + x];
02628 } else {
02629 if (dy >= mcuHeight) {
02630 if (!readMCURow()) {
02631 y = height;
02632 return EOF;
02633 }
02634 comp = 0;
02635 x = 0;
02636 dy = 0;
02637 }
02638 return rowBuf[comp][dy][x];
02639 }
02640 }
02641
02642 void DCTStream::restart() {
02643 int i;
02644
02645 inputBits = 0;
02646 restartCtr = restartInterval;
02647 for (i = 0; i < numComps; ++i) {
02648 compInfo[i].prevDC = 0;
02649 }
02650 eobRun = 0;
02651 }
02652
02653
02654 GBool DCTStream::readMCURow() {
02655 int data1[64];
02656 Guchar data2[64];
02657 Guchar *p1, *p2;
02658 int pY, pCb, pCr, pR, pG, pB;
02659 int h, v, horiz, vert, hSub, vSub;
02660 int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
02661 int c;
02662
02663 for (x1 = 0; x1 < width; x1 += mcuWidth) {
02664
02665
02666 if (restartInterval > 0 && restartCtr == 0) {
02667 c = readMarker();
02668 if (c != restartMarker) {
02669 error(getPos(), "Bad DCT data: incorrect restart marker");
02670 return gFalse;
02671 }
02672 if (++restartMarker == 0xd8)
02673 restartMarker = 0xd0;
02674 restart();
02675 }
02676
02677
02678 for (cc = 0; cc < numComps; ++cc) {
02679 h = compInfo[cc].hSample;
02680 v = compInfo[cc].vSample;
02681 horiz = mcuWidth / h;
02682 vert = mcuHeight / v;
02683 hSub = horiz / 8;
02684 vSub = vert / 8;
02685 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
02686 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
02687 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
02688 &acHuffTables[scanInfo.acHuffTable[cc]],
02689 &compInfo[cc].prevDC,
02690 data1)) {
02691 return gFalse;
02692 }
02693 transformDataUnit(quantTables[compInfo[cc].quantTable],
02694 data1, data2);
02695 if (hSub == 1 && vSub == 1) {
02696 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
02697 p1 = &rowBuf[cc][y2+y3][x1+x2];
02698 p1[0] = data2[i];
02699 p1[1] = data2[i+1];
02700 p1[2] = data2[i+2];
02701 p1[3] = data2[i+3];
02702 p1[4] = data2[i+4];
02703 p1[5] = data2[i+5];
02704 p1[6] = data2[i+6];
02705 p1[7] = data2[i+7];
02706 }
02707 } else if (hSub == 2 && vSub == 2) {
02708 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
02709 p1 = &rowBuf[cc][y2+y3][x1+x2];
02710 p2 = &rowBuf[cc][y2+y3+1][x1+x2];
02711 p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
02712 p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
02713 p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
02714 p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
02715 p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
02716 p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
02717 p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
02718 p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
02719 }
02720 } else {
02721 i = 0;
02722 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
02723 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
02724 for (y5 = 0; y5 < vSub; ++y5)
02725 for (x5 = 0; x5 < hSub; ++x5)
02726 rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
02727 ++i;
02728 }
02729 }
02730 }
02731 }
02732 }
02733 }
02734 --restartCtr;
02735
02736
02737 if (colorXform) {
02738
02739 if (numComps == 3) {
02740 for (y2 = 0; y2 < mcuHeight; ++y2) {
02741 for (x2 = 0; x2 < mcuWidth; ++x2) {
02742 pY = rowBuf[0][y2][x1+x2];
02743 pCb = rowBuf[1][y2][x1+x2] - 128;
02744 pCr = rowBuf[2][y2][x1+x2] - 128;
02745 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
02746 rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
02747 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
02748 rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
02749 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
02750 rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
02751 }
02752 }
02753
02754 } else if (numComps == 4) {
02755 for (y2 = 0; y2 < mcuHeight; ++y2) {
02756 for (x2 = 0; x2 < mcuWidth; ++x2) {
02757 pY = rowBuf[0][y2][x1+x2];
02758 pCb = rowBuf[1][y2][x1+x2] - 128;
02759 pCr = rowBuf[2][y2][x1+x2] - 128;
02760 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
02761 rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
02762 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
02763 rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
02764 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
02765 rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
02766 }
02767 }
02768 }
02769 }
02770 }
02771 return gTrue;
02772 }
02773
02774
02775 void DCTStream::readScan() {
02776 int data[64];
02777 int x1, y1, dy1, x2, y2, y3, cc, i;
02778 int h, v, horiz, vert, hSub, vSub;
02779 int *p1;
02780 int c;
02781
02782 if (scanInfo.numComps == 1) {
02783 for (cc = 0; cc < numComps; ++cc) {
02784 if (scanInfo.comp[cc]) {
02785 break;
02786 }
02787 }
02788 dy1 = mcuHeight / compInfo[cc].vSample;
02789 } else {
02790 dy1 = mcuHeight;
02791 }
02792
02793 for (y1 = 0; y1 < bufHeight; y1 += dy1) {
02794 for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
02795
02796
02797 if (restartInterval > 0 && restartCtr == 0) {
02798 c = readMarker();
02799 if (c != restartMarker) {
02800 error(getPos(), "Bad DCT data: incorrect restart marker");
02801 return;
02802 }
02803 if (++restartMarker == 0xd8) {
02804 restartMarker = 0xd0;
02805 }
02806 restart();
02807 }
02808
02809
02810 for (cc = 0; cc < numComps; ++cc) {
02811 if (!scanInfo.comp[cc]) {
02812 continue;
02813 }
02814
02815 h = compInfo[cc].hSample;
02816 v = compInfo[cc].vSample;
02817 horiz = mcuWidth / h;
02818 vert = mcuHeight / v;
02819 hSub = horiz / 8;
02820 vSub = vert / 8;
02821 for (y2 = 0; y2 < dy1; y2 += vert) {
02822 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
02823
02824
02825 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
02826 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
02827 data[i] = p1[0];
02828 data[i+1] = p1[1];
02829 data[i+2] = p1[2];
02830 data[i+3] = p1[3];
02831 data[i+4] = p1[4];
02832 data[i+5] = p1[5];
02833 data[i+6] = p1[6];
02834 data[i+7] = p1[7];
02835 p1 += bufWidth * vSub;
02836 }
02837
02838
02839 if (progressive) {
02840 if (!readProgressiveDataUnit(
02841 &dcHuffTables[scanInfo.dcHuffTable[cc]],
02842 &acHuffTables[scanInfo.acHuffTable[cc]],
02843 &compInfo[cc].prevDC,
02844 data)) {
02845 return;
02846 }
02847 } else {
02848 if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
02849 &acHuffTables[scanInfo.acHuffTable[cc]],
02850 &compInfo[cc].prevDC,
02851 data)) {
02852 return;
02853 }
02854 }
02855
02856
02857 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
02858 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
02859 p1[0] = data[i];
02860 p1[1] = data[i+1];
02861 p1[2] = data[i+2];
02862 p1[3] = data[i+3];
02863 p1[4] = data[i+4];
02864 p1[5] = data[i+5];
02865 p1[6] = data[i+6];
02866 p1[7] = data[i+7];
02867 p1 += bufWidth * vSub;
02868 }
02869 }
02870 }
02871 }
02872 --restartCtr;
02873 }
02874 }
02875 }
02876
02877
02878 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
02879 DCTHuffTable *acHuffTable,
02880 int *prevDC, int data[64]) {
02881 int run, size, amp;
02882 int c;
02883 int i, j;
02884
02885 if ((size = readHuffSym(dcHuffTable)) == 9999) {
02886 return gFalse;
02887 }
02888 if (size > 0) {
02889 if ((amp = readAmp(size)) == 9999) {
02890 return gFalse;
02891 }
02892 } else {
02893 amp = 0;
02894 }
02895 data[0] = *prevDC += amp;
02896 for (i = 1; i < 64; ++i) {
02897 data[i] = 0;
02898 }
02899 i = 1;
02900 while (i < 64) {
02901 run = 0;
02902 while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
02903 run += 0x10;
02904 }
02905 if (c == 9999) {
02906 return gFalse;
02907 }
02908 if (c == 0x00) {
02909 break;
02910 } else {
02911 run += (c >> 4) & 0x0f;
02912 size = c & 0x0f;
02913 amp = readAmp(size);
02914 if (amp == 9999) {
02915 return gFalse;
02916 }
02917 i += run;
02918 j = dctZigZag[i++];
02919 data[j] = amp;
02920 }
02921 }
02922 return gTrue;
02923 }
02924
02925
02926 GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
02927 DCTHuffTable *acHuffTable,
02928 int *prevDC, int data[64]) {
02929 int run, size, amp, bit, c;
02930 int i, j, k;
02931
02932
02933 i = scanInfo.firstCoeff;
02934 if (i == 0) {
02935 if (scanInfo.ah == 0) {
02936 if ((size = readHuffSym(dcHuffTable)) == 9999) {
02937 return gFalse;
02938 }
02939 if (size > 0) {
02940 if ((amp = readAmp(size)) == 9999) {
02941 return gFalse;
02942 }
02943 } else {
02944 amp = 0;
02945 }
02946 data[0] += (*prevDC += amp) << scanInfo.al;
02947 } else {
02948 if ((bit = readBit()) == 9999) {
02949 return gFalse;
02950 }
02951 data[0] += bit << scanInfo.al;
02952 }
02953 ++i;
02954 }
02955 if (scanInfo.lastCoeff == 0) {
02956 return gTrue;
02957 }
02958
02959
02960 if (eobRun > 0) {
02961 while (i <= scanInfo.lastCoeff) {
02962 j = dctZigZag[i++];
02963 if (data[j] != 0) {
02964 if ((bit = readBit()) == EOF) {
02965 return gFalse;
02966 }
02967 if (bit) {
02968 data[j] += 1 << scanInfo.al;
02969 }
02970 }
02971 }
02972 --eobRun;
02973 return gTrue;
02974 }
02975
02976
02977 while (i <= scanInfo.lastCoeff) {
02978 if ((c = readHuffSym(acHuffTable)) == 9999) {
02979 return gFalse;
02980 }
02981
02982
02983 if (c == 0xf0) {
02984 k = 0;
02985 while (k < 16) {
02986 j = dctZigZag[i++];
02987 if (data[j] == 0) {
02988 ++k;
02989 } else {
02990 if ((bit = readBit()) == EOF) {
02991 return gFalse;
02992 }
02993 if (bit) {
02994 data[j] += 1 << scanInfo.al;
02995 }
02996 }
02997 }
02998
02999
03000 } else if ((c & 0x0f) == 0x00) {
03001 j = c >> 4;
03002 eobRun = 0;
03003 for (k = 0; k < j; ++k) {
03004 if ((bit = readBit()) == EOF) {
03005 return 9999;
03006 }
03007 eobRun = (eobRun << 1) | bit;
03008 }
03009 eobRun += 1 << j;
03010 while (i <= scanInfo.lastCoeff) {
03011 j = dctZigZag[i++];
03012 if (data[j] != 0) {
03013 if ((bit = readBit()) == EOF) {
03014 return gFalse;
03015 }
03016 if (bit) {
03017 data[j] += 1 << scanInfo.al;
03018 }
03019 }
03020 }
03021 --eobRun;
03022 break;
03023
03024
03025 } else {
03026 run = (c >> 4) & 0x0f;
03027 size = c & 0x0f;
03028 if ((amp = readAmp(size)) == 9999) {
03029 return gFalse;
03030 }
03031 k = 0;
03032 do {
03033 j = dctZigZag[i++];
03034 while (data[j] != 0) {
03035 if ((bit = readBit()) == EOF) {
03036 return gFalse;
03037 }
03038 if (bit) {
03039 data[j] += 1 << scanInfo.al;
03040 }
03041 j = dctZigZag[i++];
03042 }
03043 ++k;
03044 } while (k <= run);
03045 data[j] = amp << scanInfo.al;
03046 }
03047 }
03048
03049 return gTrue;
03050 }
03051
03052
03053 void DCTStream::decodeImage() {
03054 int dataIn[64];
03055 Guchar dataOut[64];
03056 Guchar *quantTable;
03057 int pY, pCb, pCr, pR, pG, pB;
03058 int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
03059 int h, v, horiz, vert, hSub, vSub;
03060 int *p0, *p1, *p2;
03061
03062 for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
03063 for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
03064 for (cc = 0; cc < numComps; ++cc) {
03065 quantTable = quantTables[compInfo[cc].quantTable];
03066 h = compInfo[cc].hSample;
03067 v = compInfo[cc].vSample;
03068 horiz = mcuWidth / h;
03069 vert = mcuHeight / v;
03070 hSub = horiz / 8;
03071 vSub = vert / 8;
03072 for (y2 = 0; y2 < mcuHeight; y2 += vert) {
03073 for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
03074
03075
03076 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
03077 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
03078 dataIn[i] = p1[0];
03079 dataIn[i+1] = p1[1];
03080 dataIn[i+2] = p1[2];
03081 dataIn[i+3] = p1[3];
03082 dataIn[i+4] = p1[4];
03083 dataIn[i+5] = p1[5];
03084 dataIn[i+6] = p1[6];
03085 dataIn[i+7] = p1[7];
03086 p1 += bufWidth * vSub;
03087 }
03088
03089
03090 transformDataUnit(quantTable, dataIn, dataOut);
03091
03092
03093
03094 p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
03095 if (hSub == 1 && vSub == 1) {
03096 for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
03097 p1[0] = dataOut[i] & 0xff;
03098 p1[1] = dataOut[i+1] & 0xff;
03099 p1[2] = dataOut[i+2] & 0xff;
03100 p1[3] = dataOut[i+3] & 0xff;
03101 p1[4] = dataOut[i+4] & 0xff;
03102 p1[5] = dataOut[i+5] & 0xff;
03103 p1[6] = dataOut[i+6] & 0xff;
03104 p1[7] = dataOut[i+7] & 0xff;
03105 p1 += bufWidth;
03106 }
03107 } else if (hSub == 2 && vSub == 2) {
03108 p2 = p1 + bufWidth;
03109 for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
03110 p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
03111 p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
03112 p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
03113 p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
03114 p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
03115 p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
03116 p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
03117 p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
03118 p1 += bufWidth * 2;
03119 p2 += bufWidth * 2;
03120 }
03121 } else {
03122 i = 0;
03123 for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
03124 for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
03125 p2 = p1 + x4;
03126 for (y5 = 0; y5 < vSub; ++y5) {
03127 for (x5 = 0; x5 < hSub; ++x5) {
03128 p2[x5] = dataOut[i] & 0xff;
03129 }
03130 p2 += bufWidth;
03131 }
03132 ++i;
03133 }
03134 p1 += bufWidth * vSub;
03135 }
03136 }
03137 }
03138 }
03139 }
03140
03141
03142 if (colorXform) {
03143
03144 if (numComps == 3) {
03145 for (y2 = 0; y2 < mcuHeight; ++y2) {
03146 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
03147 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
03148 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
03149 for (x2 = 0; x2 < mcuWidth; ++x2) {
03150 pY = *p0;
03151 pCb = *p1 - 128;
03152 pCr = *p2 - 128;
03153 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
03154 *p0++ = dctClip[dctClipOffset + pR];
03155 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
03156 32768) >> 16;
03157 *p1++ = dctClip[dctClipOffset + pG];
03158 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
03159 *p2++ = dctClip[dctClipOffset + pB];
03160 }
03161 }
03162
03163 } else if (numComps == 4) {
03164 for (y2 = 0; y2 < mcuHeight; ++y2) {
03165 p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
03166 p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
03167 p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
03168 for (x2 = 0; x2 < mcuWidth; ++x2) {
03169 pY = *p0;
03170 pCb = *p1 - 128;
03171 pCr = *p2 - 128;
03172 pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
03173 *p0++ = 255 - dctClip[dctClipOffset + pR];
03174 pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
03175 32768) >> 16;
03176 *p1++ = 255 - dctClip[dctClipOffset + pG];
03177 pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
03178 *p2++ = 255 - dctClip[dctClipOffset + pB];
03179 }
03180 }
03181 }
03182 }
03183 }
03184 }
03185 }
03186
03187
03188
03189
03190
03191
03192
03193
03194
03195 void DCTStream::transformDataUnit(Guchar *quantTable,
03196 int dataIn[64], Guchar dataOut[64]) {
03197 int v0, v1, v2, v3, v4, v5, v6, v7, t;
03198 int *p;
03199 int i;
03200
03201
03202 for (i = 0; i < 64; ++i) {
03203 dataIn[i] *= quantTable[i];
03204 }
03205
03206
03207 for (i = 0; i < 64; i += 8) {
03208 p = dataIn + i;
03209
03210
03211 if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
03212 p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
03213 t = (dctSqrt2 * p[0] + 512) >> 10;
03214 p[0] = t;
03215 p[1] = t;
03216 p[2] = t;
03217 p[3] = t;
03218 p[4] = t;
03219 p[5] = t;
03220 p[6] = t;
03221 p[7] = t;
03222 continue;
03223 }
03224
03225
03226 v0 = (dctSqrt2 * p[0] + 128) >> 8;
03227 v1 = (dctSqrt2 * p[4] + 128) >> 8;
03228 v2 = p[2];
03229 v3 = p[6];
03230 v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
03231 v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
03232 v5 = p[3] << 4;
03233 v6 = p[5] << 4;
03234
03235
03236 t = (v0 - v1+ 1) >> 1;
03237 v0 = (v0 + v1 + 1) >> 1;
03238 v1 = t;
03239 t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
03240 v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
03241 v3 = t;
03242 t = (v4 - v6 + 1) >> 1;
03243 v4 = (v4 + v6 + 1) >> 1;
03244 v6 = t;
03245 t = (v7 + v5 + 1) >> 1;
03246 v5 = (v7 - v5 + 1) >> 1;
03247 v7 = t;
03248
03249
03250 t = (v0 - v3 + 1) >> 1;
03251 v0 = (v0 + v3 + 1) >> 1;
03252 v3 = t;
03253 t = (v1 - v2 + 1) >> 1;
03254 v1 = (v1 + v2 + 1) >> 1;
03255 v2 = t;
03256 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
03257 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
03258 v7 = t;
03259 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
03260 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
03261 v6 = t;
03262
03263
03264 p[0] = v0 + v7;
03265 p[7] = v0 - v7;
03266 p[1] = v1 + v6;
03267 p[6] = v1 - v6;
03268 p[2] = v2 + v5;
03269 p[5] = v2 - v5;
03270 p[3] = v3 + v4;
03271 p[4] = v3 - v4;
03272 }
03273
03274
03275 for (i = 0; i < 8; ++i) {
03276 p = dataIn + i;
03277
03278
03279 if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
03280 p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
03281 t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
03282 p[0*8] = t;
03283 p[1*8] = t;
03284 p[2*8] = t;
03285 p[3*8] = t;
03286 p[4*8] = t;
03287 p[5*8] = t;
03288 p[6*8] = t;
03289 p[7*8] = t;
03290 continue;
03291 }
03292
03293
03294 v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
03295 v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
03296 v2 = p[2*8];
03297 v3 = p[6*8];
03298 v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
03299 v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
03300 v5 = p[3*8];
03301 v6 = p[5*8];
03302
03303
03304 t = (v0 - v1 + 1) >> 1;
03305 v0 = (v0 + v1 + 1) >> 1;
03306 v1 = t;
03307 t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
03308 v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
03309 v3 = t;
03310 t = (v4 - v6 + 1) >> 1;
03311 v4 = (v4 + v6 + 1) >> 1;
03312 v6 = t;
03313 t = (v7 + v5 + 1) >> 1;
03314 v5 = (v7 - v5 + 1) >> 1;
03315 v7 = t;
03316
03317
03318 t = (v0 - v3 + 1) >> 1;
03319 v0 = (v0 + v3 + 1) >> 1;
03320 v3 = t;
03321 t = (v1 - v2 + 1) >> 1;
03322 v1 = (v1 + v2 + 1) >> 1;
03323 v2 = t;
03324 t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
03325 v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
03326 v7 = t;
03327 t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
03328 v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
03329 v6 = t;
03330
03331
03332 p[0*8] = v0 + v7;
03333 p[7*8] = v0 - v7;
03334 p[1*8] = v1 + v6;
03335 p[6*8] = v1 - v6;
03336 p[2*8] = v2 + v5;
03337 p[5*8] = v2 - v5;
03338 p[3*8] = v3 + v4;
03339 p[4*8] = v3 - v4;
03340 }
03341
03342
03343 for (i = 0; i < 64; ++i) {
03344 dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
03345 }
03346 }
03347
03348 int DCTStream::readHuffSym(DCTHuffTable *table) {
03349 Gushort code;
03350 int bit;
03351 int codeBits;
03352
03353 code = 0;
03354 codeBits = 0;
03355 do {
03356
03357 if ((bit = readBit()) == EOF)
03358 return 9999;
03359 code = (code << 1) + bit;
03360 ++codeBits;
03361
03362
03363 if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
03364 code -= table->firstCode[codeBits];
03365 return table->sym[table->firstSym[codeBits] + code];
03366 }
03367 } while (codeBits < 16);
03368
03369 error(getPos(), "Bad Huffman code in DCT stream");
03370 return 9999;
03371 }
03372
03373 int DCTStream::readAmp(int size) {
03374 int amp, bit;
03375 int bits;
03376
03377 amp = 0;
03378 for (bits = 0; bits < size; ++bits) {
03379 if ((bit = readBit()) == EOF)
03380 return 9999;
03381 amp = (amp << 1) + bit;
03382 }
03383 if (amp < (1 << (size - 1)))
03384 amp -= (1 << size) - 1;
03385 return amp;
03386 }
03387
03388 int DCTStream::readBit() {
03389 int bit;
03390 int c, c2;
03391
03392 if (inputBits == 0) {
03393 if ((c = str->getChar()) == EOF)
03394 return EOF;
03395 if (c == 0xff) {
03396 do {
03397 c2 = str->getChar();
03398 } while (c2 == 0xff);
03399 if (c2 != 0x00) {
03400 error(getPos(), "Bad DCT data: missing 00 after ff");
03401 return EOF;
03402 }
03403 }
03404 inputBuf = c;
03405 inputBits = 8;
03406 }
03407 bit = (inputBuf >> (inputBits - 1)) & 1;
03408 --inputBits;
03409 return bit;
03410 }
03411
03412 GBool DCTStream::readHeader() {
03413 GBool doScan;
03414 int n;
03415 int c = 0;
03416 int i;
03417
03418
03419 doScan = gFalse;
03420 while (!doScan) {
03421 c = readMarker();
03422 switch (c) {
03423 case 0xc0:
03424 if (!readBaselineSOF()) {
03425 return gFalse;
03426 }
03427 break;
03428 case 0xc2:
03429 if (!readProgressiveSOF()) {
03430 return gFalse;
03431 }
03432 break;
03433 case 0xc4:
03434 if (!readHuffmanTables()) {
03435 return gFalse;
03436 }
03437 break;
03438 case 0xd8:
03439 break;
03440 case 0xd9:
03441 return gFalse;
03442 break;
03443 case 0xda:
03444 if (!readScanInfo()) {
03445 return gFalse;
03446 }
03447 doScan = gTrue;
03448 break;
03449 case 0xdb:
03450 if (!readQuantTables()) {
03451 return gFalse;
03452 }
03453 break;
03454 case 0xdd:
03455 if (!readRestartInterval()) {
03456 return gFalse;
03457 }
03458 break;
03459 case 0xee:
03460 if (!readAdobeMarker()) {
03461 return gFalse;
03462 }
03463 break;
03464 case EOF:
03465 error(getPos(), "Bad DCT header");
03466 return gFalse;
03467 default:
03468
03469 if (c >= 0xe0) {
03470 n = read16() - 2;
03471 for (i = 0; i < n; ++i) {
03472 str->getChar();
03473 }
03474 } else {
03475 error(getPos(), "Unknown DCT marker <%02x>", c);
03476 return gFalse;
03477 }
03478 break;
03479 }
03480 }
03481
03482 return gTrue;
03483 }
03484
03485 GBool DCTStream::readBaselineSOF() {
03486 int length;
03487 int prec;
03488 int i;
03489 int c;
03490
03491 length = read16();
03492 prec = str->getChar();
03493 height = read16();
03494 width = read16();
03495 numComps = str->getChar();
03496 if (numComps <= 0 || numComps > 4) {
03497 numComps = 0;
03498 error(getPos(), "Bad number of components in DCT stream");
03499 return gFalse;
03500 }
03501 if (prec != 8) {
03502 error(getPos(), "Bad DCT precision %d", prec);
03503 return gFalse;
03504 }
03505 for (i = 0; i < numComps; ++i) {
03506 compInfo[i].id = str->getChar();
03507 c = str->getChar();
03508 compInfo[i].hSample = (c >> 4) & 0x0f;
03509 compInfo[i].vSample = c & 0x0f;
03510 compInfo[i].quantTable = str->getChar();
03511 }
03512 progressive = gFalse;
03513 return gTrue;
03514 }
03515
03516 GBool DCTStream::readProgressiveSOF() {
03517 int length;
03518 int prec;
03519 int i;
03520 int c;
03521
03522 length = read16();
03523 prec = str->getChar();
03524 height = read16();
03525 width = read16();
03526 numComps = str->getChar();
03527 if (numComps <= 0 || numComps > 4) {
03528 numComps = 0;
03529 error(getPos(), "Bad number of components in DCT stream");
03530 return gFalse;
03531 }
03532 if (prec != 8) {
03533 error(getPos(), "Bad DCT precision %d", prec);
03534 return gFalse;
03535 }
03536 for (i = 0; i < numComps; ++i) {
03537 compInfo[i].id = str->getChar();
03538 c = str->getChar();
03539 compInfo[i].hSample = (c >> 4) & 0x0f;
03540 compInfo[i].vSample = c & 0x0f;
03541 compInfo[i].quantTable = str->getChar();
03542 }
03543 progressive = gTrue;
03544 return gTrue;
03545 }
03546
03547 GBool DCTStream::readScanInfo() {
03548 int length;
03549 int id, c;
03550 int i, j;
03551
03552 length = read16() - 2;
03553 scanInfo.numComps = str->getChar();
03554 if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) {
03555 scanInfo.numComps = 0;
03556 error(getPos(), "Bad number of components in DCT stream");
03557 return gFalse;
03558 }
03559 --length;
03560 if (length != 2 * scanInfo.numComps + 3) {
03561 error(getPos(), "Bad DCT scan info block");
03562 return gFalse;
03563 }
03564 interleaved = scanInfo.numComps == numComps;
03565 for (j = 0; j < numComps; ++j) {
03566 scanInfo.comp[j] = gFalse;
03567 }
03568 for (i = 0; i < scanInfo.numComps; ++i) {
03569 id = str->getChar();
03570 for (j = 0; j < numComps; ++j) {
03571 if (id == compInfo[j].id) {
03572 break;
03573 }
03574 }
03575 if (j == numComps) {
03576 error(getPos(), "Bad DCT component ID in scan info block");
03577 return gFalse;
03578 }
03579 scanInfo.comp[j] = gTrue;
03580 c = str->getChar();
03581 scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
03582 scanInfo.acHuffTable[j] = c & 0x0f;
03583 }
03584 scanInfo.firstCoeff = str->getChar();
03585 scanInfo.lastCoeff = str->getChar();
03586 if (scanInfo.firstCoeff < 0 || scanInfo.lastCoeff > 63 ||
03587 scanInfo.firstCoeff > scanInfo.lastCoeff) {
03588 error(getPos(), "Bad DCT coefficient numbers in scan info block");
03589 return gFalse;
03590 }
03591 c = str->getChar();
03592 scanInfo.ah = (c >> 4) & 0x0f;
03593 scanInfo.al = c & 0x0f;
03594 return gTrue;
03595 }
03596
03597 GBool DCTStream::readQuantTables() {
03598 int length;
03599 int i;
03600 int index;
03601
03602 length = read16() - 2;
03603 while (length > 0) {
03604 index = str->getChar();
03605 if ((index & 0xf0) || index >= 4) {
03606 error(getPos(), "Bad DCT quantization table");
03607 return gFalse;
03608 }
03609 if (index == numQuantTables)
03610 numQuantTables = index + 1;
03611 for (i = 0; i < 64; ++i)
03612 quantTables[index][dctZigZag[i]] = str->getChar();
03613 length -= 65;
03614 }
03615 return gTrue;
03616 }
03617
03618 GBool DCTStream::readHuffmanTables() {
03619 DCTHuffTable *tbl;
03620 int length;
03621 int index;
03622 Gushort code;
03623 Guchar sym;
03624 int i;
03625 int c;
03626
03627 length = read16() - 2;
03628 while (length > 0) {
03629 index = str->getChar();
03630 --length;
03631 if ((index & ~0x10) >= 4 || (index & ~0x10) < 0) {
03632 error(getPos(), "Bad DCT Huffman table");
03633 return gFalse;
03634 }
03635 if (index & 0x10) {
03636 index &= 0x03;
03637 if (index >= numACHuffTables)
03638 numACHuffTables = index+1;
03639 tbl = &acHuffTables[index];
03640 } else {
03641 if (index >= numDCHuffTables)
03642 numDCHuffTables = index+1;
03643 tbl = &dcHuffTables[index];
03644 }
03645 sym = 0;
03646 code = 0;
03647 for (i = 1; i <= 16; ++i) {
03648 c = str->getChar();
03649 tbl->firstSym[i] = sym;
03650 tbl->firstCode[i] = code;
03651 tbl->numCodes[i] = c;
03652 sym += c;
03653 code = (code + c) << 1;
03654 }
03655 length -= 16;
03656 for (i = 0; i < sym; ++i)
03657 tbl->sym[i] = str->getChar();
03658 length -= sym;
03659 }
03660 return gTrue;
03661 }
03662
03663 GBool DCTStream::readRestartInterval() {
03664 int length;
03665
03666 length = read16();
03667 if (length != 4) {
03668 error(getPos(), "Bad DCT restart interval");
03669 return gFalse;
03670 }
03671 restartInterval = read16();
03672 return gTrue;
03673 }
03674
03675 GBool DCTStream::readAdobeMarker() {
03676 int length, i;
03677 char buf[12];
03678 int c;
03679
03680 length = read16();
03681 if (length < 14) {
03682 goto err;
03683 }
03684 for (i = 0; i < 12; ++i) {
03685 if ((c = str->getChar()) == EOF) {
03686 goto err;
03687 }
03688 buf[i] = c;
03689 }
03690 if (strncmp(buf, "Adobe", 5)) {
03691 goto err;
03692 }
03693 colorXform = buf[11];
03694 gotAdobeMarker = gTrue;
03695 for (i = 14; i < length; ++i) {
03696 if (str->getChar() == EOF) {
03697 goto err;
03698 }
03699 }
03700 return gTrue;
03701
03702 err:
03703 error(getPos(), "Bad DCT Adobe APP14 marker");
03704 return gFalse;
03705 }
03706
03707 GBool DCTStream::readTrailer() {
03708 int c;
03709
03710 c = readMarker();
03711 if (c != 0xd9) {
03712 error(getPos(), "Bad DCT trailer");
03713 return gFalse;
03714 }
03715 return gTrue;
03716 }
03717
03718 int DCTStream::readMarker() {
03719 int c;
03720
03721 do {
03722 do {
03723 c = str->getChar();
03724 if(c == EOF) return EOF;
03725 } while (c != 0xff);
03726 do {
03727 c = str->getChar();
03728 if(c == EOF) return EOF;
03729 } while (c == 0xff);
03730 } while (c == 0x00);
03731 return c;
03732 }
03733
03734 int DCTStream::read16() {
03735 int c1, c2;
03736
03737 if ((c1 = str->getChar()) == EOF)
03738 return EOF;
03739 if ((c2 = str->getChar()) == EOF)
03740 return EOF;
03741 return (c1 << 8) + c2;
03742 }
03743
03744 GString *DCTStream::getPSFilter(const char *indent) {
03745 GString *s;
03746
03747 if (!(s = str->getPSFilter(indent))) {
03748 return NULL;
03749 }
03750 s->append(indent)->append("<< >> /DCTDecode filter\n");
03751 return s;
03752 }
03753
03754 GBool DCTStream::isBinary(GBool ) {
03755 return str->isBinary(gTrue);
03756 }
03757
03758
03759
03760
03761
03762 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
03763 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
03764 };
03765
03766 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
03767 {0, 3},
03768 {0, 4},
03769 {0, 5},
03770 {0, 6},
03771 {0, 7},
03772 {0, 8},
03773 {0, 9},
03774 {0, 10},
03775 {1, 11},
03776 {1, 13},
03777 {1, 15},
03778 {1, 17},
03779 {2, 19},
03780 {2, 23},
03781 {2, 27},
03782 {2, 31},
03783 {3, 35},
03784 {3, 43},
03785 {3, 51},
03786 {3, 59},
03787 {4, 67},
03788 {4, 83},
03789 {4, 99},
03790 {4, 115},
03791 {5, 131},
03792 {5, 163},
03793 {5, 195},
03794 {5, 227},
03795 {0, 258}
03796 };
03797
03798 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
03799 { 0, 1},
03800 { 0, 2},
03801 { 0, 3},
03802 { 0, 4},
03803 { 1, 5},
03804 { 1, 7},
03805 { 2, 9},
03806 { 2, 13},
03807 { 3, 17},
03808 { 3, 25},
03809 { 4, 33},
03810 { 4, 49},
03811 { 5, 65},
03812 { 5, 97},
03813 { 6, 129},
03814 { 6, 193},
03815 { 7, 257},
03816 { 7, 385},
03817 { 8, 513},
03818 { 8, 769},
03819 { 9, 1025},
03820 { 9, 1537},
03821 {10, 2049},
03822 {10, 3073},
03823 {11, 4097},
03824 {11, 6145},
03825 {12, 8193},
03826 {12, 12289},
03827 {13, 16385},
03828 {13, 24577}
03829 };
03830
03831 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
03832 int colors, int bits):
03833 FilterStream(strA) {
03834 if (predictor != 1) {
03835 pred = new StreamPredictor(this, predictor, columns, colors, bits);
03836 if ( !pred->isOk()) {
03837 delete pred;
03838 pred = NULL;
03839 }
03840 } else {
03841 pred = NULL;
03842 }
03843 litCodeTab.codes = NULL;
03844 distCodeTab.codes = NULL;
03845 }
03846
03847 FlateStream::~FlateStream() {
03848 gfree(litCodeTab.codes);
03849 gfree(distCodeTab.codes);
03850 if (pred) {
03851 delete pred;
03852 }
03853 delete str;
03854 }
03855
03856 void FlateStream::reset() {
03857 int cmf, flg;
03858
03859 index = 0;
03860 remain = 0;
03861 codeBuf = 0;
03862 codeSize = 0;
03863 compressedBlock = gFalse;
03864 endOfBlock = gTrue;
03865 eof = gTrue;
03866
03867 str->reset();
03868
03869
03870
03871 endOfBlock = eof = gTrue;
03872 cmf = str->getChar();
03873 flg = str->getChar();
03874 if (cmf == EOF || flg == EOF)
03875 return;
03876 if ((cmf & 0x0f) != 0x08) {
03877 error(getPos(), "Unknown compression method in flate stream");
03878 return;
03879 }
03880 if ((((cmf << 8) + flg) % 31) != 0) {
03881 error(getPos(), "Bad FCHECK in flate stream");
03882 return;
03883 }
03884 if (flg & 0x20) {
03885 error(getPos(), "FDICT bit set in flate stream");
03886 return;
03887 }
03888
03889 eof = gFalse;
03890 }
03891
03892 int FlateStream::getChar() {
03893 int c;
03894
03895 if (pred) {
03896 return pred->getChar();
03897 }
03898 while (remain == 0) {
03899 if (endOfBlock && eof)
03900 return EOF;
03901 readSome();
03902 }
03903 c = buf[index];
03904 index = (index + 1) & flateMask;
03905 --remain;
03906 return c;
03907 }
03908
03909 int FlateStream::lookChar() {
03910 int c;
03911
03912 if (pred) {
03913 return pred->lookChar();
03914 }
03915 while (remain == 0) {
03916 if (endOfBlock && eof)
03917 return EOF;
03918 readSome();
03919 }
03920 c = buf[index];
03921 return c;
03922 }
03923
03924 int FlateStream::getRawChar() {
03925 int c;
03926
03927 while (remain == 0) {
03928 if (endOfBlock && eof)
03929 return EOF;
03930 readSome();
03931 }
03932 c = buf[index];
03933 index = (index + 1) & flateMask;
03934 --remain;
03935 return c;
03936 }
03937
03938 GString *FlateStream::getPSFilter(const char *) {
03939 return NULL;
03940 }
03941
03942 GBool FlateStream::isBinary(GBool ) {
03943 return str->isBinary(gTrue);
03944 }
03945
03946 void FlateStream::readSome() {
03947 int code1, code2;
03948 int len, dist;
03949 int i, j, k;
03950 int c;
03951
03952 if (endOfBlock) {
03953 if (!startBlock())
03954 return;
03955 }
03956
03957 if (compressedBlock) {
03958 if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
03959 goto err;
03960 if (code1 < 256) {
03961 buf[index] = code1;
03962 remain = 1;
03963 } else if (code1 == 256) {
03964 endOfBlock = gTrue;
03965 remain = 0;
03966 } else {
03967 code1 -= 257;
03968 code2 = lengthDecode[code1].bits;
03969 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
03970 goto err;
03971 len = lengthDecode[code1].first + code2;
03972 if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
03973 goto err;
03974 code2 = distDecode[code1].bits;
03975 if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
03976 goto err;
03977 dist = distDecode[code1].first + code2;
03978 i = index;
03979 j = (index - dist) & flateMask;
03980 for (k = 0; k < len; ++k) {
03981 buf[i] = buf[j];
03982 i = (i + 1) & flateMask;
03983 j = (j + 1) & flateMask;
03984 }
03985 remain = len;
03986 }
03987
03988 } else {
03989 len = (blockLen < flateWindow) ? blockLen : flateWindow;
03990 for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
03991 if ((c = str->getChar()) == EOF) {
03992 endOfBlock = eof = gTrue;
03993 break;
03994 }
03995 buf[j] = c & 0xff;
03996 }
03997 remain = i;
03998 blockLen -= len;
03999 if (blockLen == 0)
04000 endOfBlock = gTrue;
04001 }
04002
04003 return;
04004
04005 err:
04006 error(getPos(), "Unexpected end of file in flate stream");
04007 endOfBlock = eof = gTrue;
04008 remain = 0;
04009 }
04010
04011 GBool FlateStream::startBlock() {
04012 int blockHdr;
04013 int c;
04014 int check;
04015
04016
04017 gfree(litCodeTab.codes);
04018 litCodeTab.codes = NULL;
04019 gfree(distCodeTab.codes);
04020 distCodeTab.codes = NULL;
04021
04022
04023 blockHdr = getCodeWord(3);
04024 if (blockHdr & 1)
04025 eof = gTrue;
04026 blockHdr >>= 1;
04027
04028
04029 if (blockHdr == 0) {
04030 compressedBlock = gFalse;
04031 if ((c = str->getChar()) == EOF)
04032 goto err;
04033 blockLen = c & 0xff;
04034 if ((c = str->getChar()) == EOF)
04035 goto err;
04036 blockLen |= (c & 0xff) << 8;
04037 if ((c = str->getChar()) == EOF)
04038 goto err;
04039 check = c & 0xff;
04040 if ((c = str->getChar()) == EOF)
04041 goto err;
04042 check |= (c & 0xff) << 8;
04043 if (check != (~blockLen & 0xffff))
04044 error(getPos(), "Bad uncompressed block length in flate stream");
04045 codeBuf = 0;
04046 codeSize = 0;
04047
04048
04049 } else if (blockHdr == 1) {
04050 compressedBlock = gTrue;
04051 loadFixedCodes();
04052
04053
04054 } else if (blockHdr == 2) {
04055 compressedBlock = gTrue;
04056 if (!readDynamicCodes()) {
04057 goto err;
04058 }
04059
04060
04061 } else {
04062 goto err;
04063 }
04064
04065 endOfBlock = gFalse;
04066 return gTrue;
04067
04068 err:
04069 error(getPos(), "Bad block header in flate stream");
04070 endOfBlock = eof = gTrue;
04071 return gFalse;
04072 }
04073
04074 void FlateStream::loadFixedCodes() {
04075 int i;
04076
04077
04078 for (i = 0; i <= 143; ++i) {
04079 codeLengths[i] = 8;
04080 }
04081 for (i = 144; i <= 255; ++i) {
04082 codeLengths[i] = 9;
04083 }
04084 for (i = 256; i <= 279; ++i) {
04085 codeLengths[i] = 7;
04086 }
04087 for (i = 280; i <= 287; ++i) {
04088 codeLengths[i] = 8;
04089 }
04090 compHuffmanCodes(codeLengths, flateMaxLitCodes, &litCodeTab);
04091
04092
04093 for (i = 0; i < flateMaxDistCodes; ++i) {
04094 codeLengths[i] = 5;
04095 }
04096 compHuffmanCodes(codeLengths, flateMaxDistCodes, &distCodeTab);
04097 }
04098
04099 GBool FlateStream::readDynamicCodes() {
04100 int numCodeLenCodes;
04101 int numLitCodes;
04102 int numDistCodes;
04103 int codeLenCodeLengths[flateMaxCodeLenCodes];
04104 FlateHuffmanTab codeLenCodeTab;
04105 int len, repeat, code;
04106 int i;
04107
04108
04109 if ((numLitCodes = getCodeWord(5)) == EOF) {
04110 goto err;
04111 }
04112 numLitCodes += 257;
04113 if ((numDistCodes = getCodeWord(5)) == EOF) {
04114 goto err;
04115 }
04116 numDistCodes += 1;
04117 if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
04118 goto err;
04119 }
04120 numCodeLenCodes += 4;
04121 if (numLitCodes > flateMaxLitCodes ||
04122 numDistCodes > flateMaxDistCodes ||
04123 numCodeLenCodes > flateMaxCodeLenCodes) {
04124 goto err;
04125 }
04126
04127
04128 for (i = 0; i < flateMaxCodeLenCodes; ++i) {
04129 codeLenCodeLengths[i] = 0;
04130 }
04131 for (i = 0; i < numCodeLenCodes; ++i) {
04132 if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
04133 goto err;
04134 }
04135 }
04136 compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
04137
04138
04139 len = 0;
04140 repeat = 0;
04141 i = 0;
04142 while (i < numLitCodes + numDistCodes) {
04143 if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
04144 goto err;
04145 }
04146 if (code == 16) {
04147 if ((repeat = getCodeWord(2)) == EOF) {
04148 goto err;
04149 }
04150 for (repeat += 3; repeat > 0; --repeat) {
04151 codeLengths[i++] = len;
04152 }
04153 } else if (code == 17) {
04154 if ((repeat = getCodeWord(3)) == EOF) {
04155 goto err;
04156 }
04157 len = 0;
04158 for (repeat += 3; repeat > 0; --repeat) {
04159 codeLengths[i++] = 0;
04160 }
04161 } else if (code == 18) {
04162 if ((repeat = getCodeWord(7)) == EOF) {
04163 goto err;
04164 }
04165 len = 0;
04166 for (repeat += 11; repeat > 0; --repeat) {
04167 codeLengths[i++] = 0;
04168 }
04169 } else {
04170 codeLengths[i++] = len = code;
04171 }
04172 }
04173 compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
04174 compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
04175
04176 gfree(codeLenCodeTab.codes);
04177 return gTrue;
04178
04179 err:
04180 error(getPos(), "Bad dynamic code table in flate stream");
04181 gfree(codeLenCodeTab.codes);
04182 return gFalse;
04183 }
04184
04185
04186
04187 void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
04188 int tabSize, len, code, code2, skip, val, i, t;
04189
04190
04191 tab->maxLen = 0;
04192 for (val = 0; val < n; ++val) {
04193 if (lengths[val] > tab->maxLen) {
04194 tab->maxLen = lengths[val];
04195 }
04196 }
04197
04198
04199 tabSize = 1 << tab->maxLen;
04200 tab->codes = (FlateCode *)gmalloc(tabSize * sizeof(FlateCode));
04201
04202
04203 for (i = 0; i < tabSize; ++i) {
04204 tab->codes[i].len = 0;
04205 tab->codes[i].val = 0;
04206 }
04207
04208
04209 for (len = 1, code = 0, skip = 2;
04210 len <= tab->maxLen;
04211 ++len, code <<= 1, skip <<= 1) {
04212 for (val = 0; val < n; ++val) {
04213 if (lengths[val] == len) {
04214
04215
04216 code2 = 0;
04217 t = code;
04218 for (i = 0; i < len; ++i) {
04219 code2 = (code2 << 1) | (t & 1);
04220 t >>= 1;
04221 }
04222
04223
04224 for (i = code2; i < tabSize; i += skip) {
04225 tab->codes[i].len = (Gushort)len;
04226 tab->codes[i].val = (Gushort)val;
04227 }
04228
04229 ++code;
04230 }
04231 }
04232 }
04233 }
04234
04235 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
04236 FlateCode *code;
04237 int c;
04238
04239 while (codeSize < tab->maxLen) {
04240 if ((c = str->getChar()) == EOF) {
04241 break;
04242 }
04243 codeBuf |= (c & 0xff) << codeSize;
04244 codeSize += 8;
04245 }
04246 code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
04247 if (codeSize == 0 || codeSize < code->len || code->len == 0) {
04248 return EOF;
04249 }
04250 codeBuf >>= code->len;
04251 codeSize -= code->len;
04252 return (int)code->val;
04253 }
04254
04255 int FlateStream::getCodeWord(int bits) {
04256 int c;
04257
04258 while (codeSize < bits) {
04259 if ((c = str->getChar()) == EOF)
04260 return EOF;
04261 codeBuf |= (c & 0xff) << codeSize;
04262 codeSize += 8;
04263 }
04264 c = codeBuf & ((1 << bits) - 1);
04265 codeBuf >>= bits;
04266 codeSize -= bits;
04267 return c;
04268 }
04269
04270
04271
04272
04273
04274 EOFStream::EOFStream(Stream *strA):
04275 FilterStream(strA) {
04276 }
04277
04278 EOFStream::~EOFStream() {
04279 delete str;
04280 }
04281
04282
04283
04284
04285
04286 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
04287 FilterStream(strA) {
04288 length = lengthA;
04289 count = 0;
04290 }
04291
04292 FixedLengthEncoder::~FixedLengthEncoder() {
04293 if (str->isEncoder())
04294 delete str;
04295 }
04296
04297 void FixedLengthEncoder::reset() {
04298 str->reset();
04299 count = 0;
04300 }
04301
04302 void FixedLengthEncoder::close() {
04303 }
04304
04305 int FixedLengthEncoder::getChar() {
04306 if (length >= 0 && count >= length)
04307 return EOF;
04308 ++count;
04309 return str->getChar();
04310 }
04311
04312 int FixedLengthEncoder::lookChar() {
04313 if (length >= 0 && count >= length)
04314 return EOF;
04315 return str->getChar();
04316 }
04317
04318
04319
04320
04321
04322 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
04323 FilterStream(strA) {
04324 bufPtr = bufEnd = buf;
04325 lineLen = 0;
04326 eof = gFalse;
04327 }
04328
04329 ASCIIHexEncoder::~ASCIIHexEncoder() {
04330 if (str->isEncoder()) {
04331 delete str;
04332 }
04333 }
04334
04335 void ASCIIHexEncoder::reset() {
04336 str->reset();
04337 bufPtr = bufEnd = buf;
04338 lineLen = 0;
04339 eof = gFalse;
04340 }
04341
04342 void ASCIIHexEncoder::close() {
04343 }
04344
04345 GBool ASCIIHexEncoder::fillBuf() {
04346 static const char *hex = "0123456789abcdef";
04347 int c;
04348
04349 if (eof) {
04350 return gFalse;
04351 }
04352 bufPtr = bufEnd = buf;
04353 if ((c = str->getChar()) == EOF) {
04354 *bufEnd++ = '>';
04355 eof = gTrue;
04356 } else {
04357 if (lineLen >= 64) {
04358 *bufEnd++ = '\n';
04359 lineLen = 0;
04360 }
04361 *bufEnd++ = hex[(c >> 4) & 0x0f];
04362 *bufEnd++ = hex[c & 0x0f];
04363 lineLen += 2;
04364 }
04365 return gTrue;
04366 }
04367
04368
04369
04370
04371
04372 ASCII85Encoder::ASCII85Encoder(Stream *strA):
04373 FilterStream(strA) {
04374 bufPtr = bufEnd = buf;
04375 lineLen = 0;
04376 eof = gFalse;
04377 }
04378
04379 ASCII85Encoder::~ASCII85Encoder() {
04380 if (str->isEncoder())
04381 delete str;
04382 }
04383
04384 void ASCII85Encoder::reset() {
04385 str->reset();
04386 bufPtr = bufEnd = buf;
04387 lineLen = 0;
04388 eof = gFalse;
04389 }
04390
04391 void ASCII85Encoder::close() {
04392 }
04393
04394 GBool ASCII85Encoder::fillBuf() {
04395 Gulong t;
04396 char buf1[5];
04397 int c;
04398 int n, i;
04399
04400 if (eof)
04401 return gFalse;
04402 t = 0;
04403 for (n = 0; n < 4; ++n) {
04404 if ((c = str->getChar()) == EOF)
04405 break;
04406 t = (t << 8) + c;
04407 }
04408 bufPtr = bufEnd = buf;
04409 if (n > 0) {
04410 if (n == 4 && t == 0) {
04411 *bufEnd++ = 'z';
04412 if (++lineLen == 65) {
04413 *bufEnd++ = '\n';
04414 lineLen = 0;
04415 }
04416 } else {
04417 if (n < 4)
04418 t <<= 8 * (4 - n);
04419 for (i = 4; i >= 0; --i) {
04420 buf1[i] = (char)(t % 85 + 0x21);
04421 t /= 85;
04422 }
04423 for (i = 0; i <= n; ++i) {
04424 *bufEnd++ = buf1[i];
04425 if (++lineLen == 65) {
04426 *bufEnd++ = '\n';
04427 lineLen = 0;
04428 }
04429 }
04430 }
04431 }
04432 if (n < 4) {
04433 *bufEnd++ = '~';
04434 *bufEnd++ = '>';
04435 eof = gTrue;
04436 }
04437 return bufPtr < bufEnd;
04438 }
04439
04440
04441
04442
04443
04444 RunLengthEncoder::RunLengthEncoder(Stream *strA):
04445 FilterStream(strA) {
04446 bufPtr = bufEnd = nextEnd = buf;
04447 eof = gFalse;
04448 }
04449
04450 RunLengthEncoder::~RunLengthEncoder() {
04451 if (str->isEncoder())
04452 delete str;
04453 }
04454
04455 void RunLengthEncoder::reset() {
04456 str->reset();
04457 bufPtr = bufEnd = nextEnd = buf;
04458 eof = gFalse;
04459 }
04460
04461 void RunLengthEncoder::close() {
04462 }
04463
04464
04465
04466
04467
04468
04469
04470
04471
04472 GBool RunLengthEncoder::fillBuf() {
04473 int c, c1, c2;
04474 int n;
04475
04476
04477 if (eof)
04478 return gFalse;
04479
04480
04481 if (nextEnd < bufEnd + 1) {
04482 if ((c1 = str->getChar()) == EOF) {
04483 eof = gTrue;
04484 return gFalse;
04485 }
04486 } else {
04487 c1 = bufEnd[0] & 0xff;
04488 }
04489 if (nextEnd < bufEnd + 2) {
04490 if ((c2 = str->getChar()) == EOF) {
04491 eof = gTrue;
04492 buf[0] = 0;
04493 buf[1] = c1;
04494 bufPtr = buf;
04495 bufEnd = &buf[2];
04496 return gTrue;
04497 }
04498 } else {
04499 c2 = bufEnd[1] & 0xff;
04500 }
04501
04502
04503 c = 0;
04504 if (c1 == c2) {
04505 n = 2;
04506 while (n < 128 && (c = str->getChar()) == c1)
04507 ++n;
04508 buf[0] = (char)(257 - n);
04509 buf[1] = c1;
04510 bufEnd = &buf[2];
04511 if (c == EOF) {
04512 eof = gTrue;
04513 } else if (n < 128) {
04514 buf[2] = c;
04515 nextEnd = &buf[3];
04516 } else {
04517 nextEnd = bufEnd;
04518 }
04519
04520
04521 } else {
04522 buf[1] = c1;
04523 buf[2] = c2;
04524 n = 2;
04525 while (n < 128) {
04526 if ((c = str->getChar()) == EOF) {
04527 eof = gTrue;
04528 break;
04529 }
04530 ++n;
04531 buf[n] = c;
04532 if (buf[n] == buf[n-1])
04533 break;
04534 }
04535 if (buf[n] == buf[n-1]) {
04536 buf[0] = (char)(n-2-1);
04537 bufEnd = &buf[n-1];
04538 nextEnd = &buf[n+1];
04539 } else {
04540 buf[0] = (char)(n-1);
04541 bufEnd = nextEnd = &buf[n+1];
04542 }
04543 }
04544 bufPtr = buf;
04545 return gTrue;
04546 }