filters

Stream.cc

00001 //========================================================================
00002 //
00003 // Stream.cc
00004 //
00005 // Copyright 1996-2002 Glyph & Cog, LLC
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 // Stream (base class)
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 */*indent*/) {
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", &params);
00105   if (params.isNull()) {
00106     params.free();
00107     dict->dictLookup("DP", &params);
00108   }
00109   if (obj.isName()) {
00110     str = makeFilter(obj.getName(), str, &params);
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, &params2);
00116       else
00117     params2.initNull();
00118       if (obj2.isName()) {
00119     str = makeFilter(obj2.getName(), str, &params2);
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;         // parameters
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 // BaseStream
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 // FilterStream
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 /*pos*/, int /*dir*/) {
00309   error(-1, "Internal: called setPos() on FilterStream");
00310 }
00311 
00312 //------------------------------------------------------------------------
00313 // ImageStream
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 // StreamPredictor
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   if (width <= 0 || nComps <= 0 || nBits <= 0 ||
00417      nComps >= INT_MAX / nBits ||
00418       width >= INT_MAX / nComps / nBits)
00419     return;
00420 
00421   nVals = width * nComps;
00422   if (nVals * nBits + 7 <= 0)
00423     return;
00424 
00425   pixBytes = (nComps * nBits + 7) >> 3;
00426   rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
00427   if (rowBytes < 0)
00428     return;
00429 
00430   predLine = (Guchar *)gmalloc(rowBytes);
00431   memset(predLine, 0, rowBytes);
00432   predIdx = rowBytes;
00433 
00434   ok = gTrue;
00435 }
00436 
00437 StreamPredictor::~StreamPredictor() {
00438   gfree(predLine);
00439 }
00440 
00441 int StreamPredictor::lookChar() {
00442   if (predIdx >= rowBytes) {
00443     if (!getNextLine()) {
00444       return EOF;
00445     }
00446   }
00447   return predLine[predIdx];
00448 }
00449 
00450 int StreamPredictor::getChar() {
00451   if (predIdx >= rowBytes) {
00452     if (!getNextLine()) {
00453       return EOF;
00454     }
00455   }
00456   return predLine[predIdx++];
00457 }
00458 
00459 GBool StreamPredictor::getNextLine() {
00460   int curPred;
00461   Guchar upLeftBuf[4];
00462   int left, up, upLeft, p, pa, pb, pc;
00463   int c;
00464   Gulong inBuf, outBuf, bitMask;
00465   int inBits, outBits;
00466   int i, j, k;
00467 
00468   // get PNG optimum predictor number
00469   if (predictor == 15) {
00470     if ((curPred = str->getRawChar()) == EOF) {
00471       return gFalse;
00472     }
00473     curPred += 10;
00474   } else {
00475     curPred = predictor;
00476   }
00477 
00478   // read the raw line, apply PNG (byte) predictor
00479   upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
00480   for (i = pixBytes; i < rowBytes; ++i) {
00481     upLeftBuf[3] = upLeftBuf[2];
00482     upLeftBuf[2] = upLeftBuf[1];
00483     upLeftBuf[1] = upLeftBuf[0];
00484     upLeftBuf[0] = predLine[i];
00485     if ((c = str->getRawChar()) == EOF) {
00486       break;
00487     }
00488     switch (curPred) {
00489     case 11:            // PNG sub
00490       predLine[i] = predLine[i - pixBytes] + (Guchar)c;
00491       break;
00492     case 12:            // PNG up
00493       predLine[i] = predLine[i] + (Guchar)c;
00494       break;
00495     case 13:            // PNG average
00496       predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
00497                 (Guchar)c;
00498       break;
00499     case 14:            // PNG Paeth
00500       left = predLine[i - pixBytes];
00501       up = predLine[i];
00502       upLeft = upLeftBuf[pixBytes];
00503       p = left + up - upLeft;
00504       if ((pa = p - left) < 0)
00505     pa = -pa;
00506       if ((pb = p - up) < 0)
00507     pb = -pb;
00508       if ((pc = p - upLeft) < 0)
00509     pc = -pc;
00510       if (pa <= pb && pa <= pc)
00511     predLine[i] = left + (Guchar)c;
00512       else if (pb <= pc)
00513     predLine[i] = up + (Guchar)c;
00514       else
00515     predLine[i] = upLeft + (Guchar)c;
00516       break;
00517     case 10:            // PNG none
00518     default:            // no predictor or TIFF predictor
00519       predLine[i] = (Guchar)c;
00520       break;
00521     }
00522   }
00523 
00524   // apply TIFF (component) predictor
00525   //~ this is completely untested
00526   if (predictor == 2) {
00527     if (nBits == 1) {
00528       inBuf = predLine[pixBytes - 1];
00529       for (i = pixBytes; i < rowBytes; i += 8) {
00530     // 1-bit add is just xor
00531     inBuf = (inBuf << 8) | predLine[i];
00532     predLine[i] ^= inBuf >> nComps;
00533       }
00534     } else if (nBits == 8) {
00535       for (i = pixBytes; i < rowBytes; ++i) {
00536     predLine[i] += predLine[i - nComps];
00537       }
00538     } else {
00539       upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
00540       bitMask = (1 << nBits) - 1;
00541       inBuf = outBuf = 0;
00542       inBits = outBits = 0;
00543       j = k = pixBytes;
00544       for (i = 0; i < nVals; ++i) {
00545     if (inBits < nBits) {
00546       inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
00547       inBits += 8;
00548     }
00549     upLeftBuf[3] = upLeftBuf[2];
00550     upLeftBuf[2] = upLeftBuf[1];
00551     upLeftBuf[1] = upLeftBuf[0];
00552     upLeftBuf[0] = (upLeftBuf[nComps] +
00553             (inBuf >> (inBits - nBits))) & bitMask;
00554     outBuf = (outBuf << nBits) | upLeftBuf[0];
00555     inBits -= nBits;
00556     outBits += nBits;
00557     if (outBits > 8) {
00558       predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
00559     }
00560       }
00561       if (outBits > 0) {
00562     predLine[k++] = (Guchar)(outBuf << (8 - outBits));
00563       }
00564     }
00565   }
00566 
00567   // reset to start of line
00568   predIdx = pixBytes;
00569 
00570   return gTrue;
00571 }
00572 
00573 //------------------------------------------------------------------------
00574 // FileStream
00575 //------------------------------------------------------------------------
00576 
00577 FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
00578                Guint lengthA, Object *dictA):
00579     BaseStream(dictA) {
00580   f = fA;
00581   start = startA;
00582   limited = limitedA;
00583   length = lengthA;
00584   bufPtr = bufEnd = buf;
00585   bufPos = start;
00586   savePos = 0;
00587   saved = gFalse;
00588 }
00589 
00590 FileStream::~FileStream() {
00591   close();
00592 }
00593 
00594 Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
00595                   Guint lengthA, Object *dictA) {
00596   return new FileStream(f, startA, limitedA, lengthA, dictA);
00597 }
00598 
00599 void FileStream::reset() {
00600 #ifdef HAVE_FSEEKO
00601   savePos = (Guint)ftello(f);
00602   fseeko(f, start, SEEK_SET);
00603 #elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
00604   savePos = (Guint)ftell64(f);
00605   fseek64(f, start, SEEK_SET);
00606 #else
00607   savePos = (Guint)ftell(f);
00608   fseek(f, start, SEEK_SET);
00609 #endif
00610   saved = gTrue;
00611   bufPtr = bufEnd = buf;
00612   bufPos = start;
00613 #ifndef NO_DECRYPTION
00614   if (decrypt)
00615     decrypt->reset();
00616 #endif
00617 }
00618 
00619 void FileStream::close() {
00620   if (saved) {
00621 #ifdef HAVE_FSEEKO
00622     fseeko(f, savePos, SEEK_SET);
00623 #elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
00624     fseek64(f, savePos, SEEK_SET);
00625 #else
00626     fseek(f, savePos, SEEK_SET);
00627 #endif
00628     saved = gFalse;
00629   }
00630 }
00631 
00632 GBool FileStream::fillBuf() {
00633   int n;
00634 #ifndef NO_DECRYPTION
00635   char *p;
00636 #endif
00637 
00638   bufPos += bufEnd - buf;
00639   bufPtr = bufEnd = buf;
00640   if (limited && bufPos >= start + length) {
00641     return gFalse;
00642   }
00643   if (limited && bufPos + fileStreamBufSize > start + length) {
00644     n = start + length - bufPos;
00645   } else {
00646     n = fileStreamBufSize;
00647   }
00648   n = fread(buf, 1, n, f);
00649   bufEnd = buf + n;
00650   if (bufPtr >= bufEnd) {
00651     return gFalse;
00652   }
00653 #ifndef NO_DECRYPTION
00654   if (decrypt) {
00655     for (p = buf; p < bufEnd; ++p) {
00656       *p = (char)decrypt->decryptByte((Guchar)*p);
00657     }
00658   }
00659 #endif
00660   return gTrue;
00661 }
00662 
00663 void FileStream::setPos(Guint pos, int dir) {
00664   Guint size;
00665 
00666   if (dir >= 0) {
00667 #ifdef HAVE_FSEEKO
00668     fseeko(f, pos, SEEK_SET);
00669 #elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
00670     fseek64(f, pos, SEEK_SET);
00671 #else
00672     fseek(f, pos, SEEK_SET);
00673 #endif
00674     bufPos = pos;
00675   } else {
00676 #ifdef HAVE_FSEEKO
00677     fseeko(f, 0, SEEK_END);
00678     size = (Guint)ftello(f);
00679 #elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
00680     fseek64(f, 0, SEEK_END);
00681     size = (Guint)ftell64(f);
00682 #else
00683     fseek(f, 0, SEEK_END);
00684     size = (Guint)ftell(f);
00685 #endif
00686     if (pos > size)
00687       pos = (Guint)size;
00688 #ifdef __CYGWIN32__
00689     //~ work around a bug in cygwin's implementation of fseek
00690     rewind(f);
00691 #endif
00692 #ifdef HAVE_FSEEKO
00693     fseeko(f, -(int)pos, SEEK_END);
00694     bufPos = (Guint)ftello(f);
00695 #elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
00696     fseek64(f, -(int)pos, SEEK_END);
00697     bufPos = (Guint)ftell64(f);
00698 #else
00699     fseek(f, -(int)pos, SEEK_END);
00700     bufPos = (Guint)ftell(f);
00701 #endif
00702   }
00703   bufPtr = bufEnd = buf;
00704 }
00705 
00706 void FileStream::moveStart(int delta) {
00707   start += delta;
00708   bufPtr = bufEnd = buf;
00709   bufPos = start;
00710 }
00711 
00712 //------------------------------------------------------------------------
00713 // MemStream
00714 //------------------------------------------------------------------------
00715 
00716 MemStream::MemStream(char *bufA, Guint lengthA, Object *dictA):
00717     BaseStream(dictA) {
00718   buf = bufA;
00719   needFree = gFalse;
00720   length = lengthA;
00721   bufEnd = buf + length;
00722   bufPtr = buf;
00723 }
00724 
00725 MemStream::~MemStream() {
00726   if (needFree) {
00727     gfree(buf);
00728   }
00729 }
00730 
00731 Stream *MemStream::makeSubStream(Guint start, GBool limited,
00732                  Guint lengthA, Object *dictA) {
00733   Guint newLength;
00734 
00735   if (!limited || start + lengthA > length) {
00736     newLength = length - start;
00737   } else {
00738     newLength = lengthA;
00739   }
00740   return new MemStream(buf + start, newLength, dictA);
00741 }
00742 
00743 void MemStream::reset() {
00744   bufPtr = buf;
00745 #ifndef NO_DECRYPTION
00746   if (decrypt) {
00747     decrypt->reset();
00748   }
00749 #endif
00750 }
00751 
00752 void MemStream::close() {
00753 }
00754 
00755 void MemStream::setPos(Guint pos, int dir) {
00756   if (dir >= 0) {
00757     if (pos > length) {
00758       bufPtr = bufEnd;
00759     } else {
00760       bufPtr = buf + pos;
00761     }
00762   } else {
00763     if (pos > length) {
00764       bufPtr = buf;
00765     } else {
00766       bufPtr = bufEnd - pos;
00767     }
00768   }
00769 }
00770 
00771 void MemStream::moveStart(int delta) {
00772   buf += delta;
00773   bufPtr = buf;
00774 }
00775 
00776 #ifndef NO_DECRYPTION
00777 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
00778                  int objNum, int objGen) {
00779   char *newBuf;
00780   char *p, *q;
00781 
00782   this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
00783   if (decrypt) {
00784     newBuf = (char *)gmalloc(bufEnd - buf);
00785     for (p = buf, q = newBuf; p < bufEnd; ++p, ++q) {
00786       *q = (char)decrypt->decryptByte((Guchar)*p);
00787     }
00788     bufEnd = newBuf + (bufEnd - buf);
00789     bufPtr = newBuf + (bufPtr - buf);
00790     buf = newBuf;
00791     needFree = gTrue;
00792   }
00793 }
00794 #endif
00795 
00796 //------------------------------------------------------------------------
00797 // EmbedStream
00798 //------------------------------------------------------------------------
00799 
00800 EmbedStream::EmbedStream(Stream *strA, Object *dictA):
00801     BaseStream(dictA) {
00802   str = strA;
00803 }
00804 
00805 EmbedStream::~EmbedStream() {
00806 }
00807 
00808 Stream *EmbedStream::makeSubStream(Guint /*start*/, GBool /*limited*/,
00809                                    Guint /*length*/, Object */*dictA*/) {
00810   error(-1, "Internal: called makeSubStream() on EmbedStream");
00811   return NULL;
00812 }
00813 
00814 void EmbedStream::setPos(Guint /*pos*/, int /*dir*/) {
00815   error(-1, "Internal: called setPos() on EmbedStream");
00816 }
00817 
00818 Guint EmbedStream::getStart() {
00819   error(-1, "Internal: called getStart() on EmbedStream");
00820   return 0;
00821 }
00822 
00823 void EmbedStream::moveStart(int /*delta*/) {
00824   error(-1, "Internal: called moveStart() on EmbedStream");
00825 }
00826 
00827 //------------------------------------------------------------------------
00828 // ASCIIHexStream
00829 //------------------------------------------------------------------------
00830 
00831 ASCIIHexStream::ASCIIHexStream(Stream *strA):
00832     FilterStream(strA) {
00833   buf = EOF;
00834   eof = gFalse;
00835 }
00836 
00837 ASCIIHexStream::~ASCIIHexStream() {
00838   delete str;
00839 }
00840 
00841 void ASCIIHexStream::reset() {
00842   str->reset();
00843   buf = EOF;
00844   eof = gFalse;
00845 }
00846 
00847 int ASCIIHexStream::lookChar() {
00848   int c1, c2, x;
00849 
00850   if (buf != EOF)
00851     return buf;
00852   if (eof) {
00853     buf = EOF;
00854     return EOF;
00855   }
00856   do {
00857     c1 = str->getChar();
00858   } while (isspace(c1));
00859   if (c1 == '>') {
00860     eof = gTrue;
00861     buf = EOF;
00862     return buf;
00863   }
00864   do {
00865     c2 = str->getChar();
00866   } while (isspace(c2));
00867   if (c2 == '>') {
00868     eof = gTrue;
00869     c2 = '0';
00870   }
00871   if (c1 >= '0' && c1 <= '9') {
00872     x = (c1 - '0') << 4;
00873   } else if (c1 >= 'A' && c1 <= 'F') {
00874     x = (c1 - 'A' + 10) << 4;
00875   } else if (c1 >= 'a' && c1 <= 'f') {
00876     x = (c1 - 'a' + 10) << 4;
00877   } else if (c1 == EOF) {
00878     eof = gTrue;
00879     x = 0;
00880   } else {
00881     error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
00882     x = 0;
00883   }
00884   if (c2 >= '0' && c2 <= '9') {
00885     x += c2 - '0';
00886   } else if (c2 >= 'A' && c2 <= 'F') {
00887     x += c2 - 'A' + 10;
00888   } else if (c2 >= 'a' && c2 <= 'f') {
00889     x += c2 - 'a' + 10;
00890   } else if (c2 == EOF) {
00891     eof = gTrue;
00892     x = 0;
00893   } else {
00894     error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
00895   }
00896   buf = x & 0xff;
00897   return buf;
00898 }
00899 
00900 GString *ASCIIHexStream::getPSFilter(const char *indent) {
00901   GString *s;
00902 
00903   if (!(s = str->getPSFilter(indent))) {
00904     return NULL;
00905   }
00906   s->append(indent)->append("/ASCIIHexDecode filter\n");
00907   return s;
00908 }
00909 
00910 GBool ASCIIHexStream::isBinary(GBool /*last*/) {
00911   return str->isBinary(gFalse);
00912 }
00913 
00914 //------------------------------------------------------------------------
00915 // ASCII85Stream
00916 //------------------------------------------------------------------------
00917 
00918 ASCII85Stream::ASCII85Stream(Stream *strA):
00919     FilterStream(strA) {
00920   index = n = 0;
00921   eof = gFalse;
00922 }
00923 
00924 ASCII85Stream::~ASCII85Stream() {
00925   delete str;
00926 }
00927 
00928 void ASCII85Stream::reset() {
00929   str->reset();
00930   index = n = 0;
00931   eof = gFalse;
00932 }
00933 
00934 int ASCII85Stream::lookChar() {
00935   int k;
00936   Gulong t;
00937 
00938   if (index >= n) {
00939     if (eof)
00940       return EOF;
00941     index = 0;
00942     do {
00943       c[0] = str->getChar();
00944     } while (c[0] == '\n' || c[0] == '\r');
00945     if (c[0] == '~' || c[0] == EOF) {
00946       eof = gTrue;
00947       n = 0;
00948       return EOF;
00949     } else if (c[0] == 'z') {
00950       b[0] = b[1] = b[2] = b[3] = 0;
00951       n = 4;
00952     } else {
00953       for (k = 1; k < 5; ++k) {
00954     do {
00955       c[k] = str->getChar();
00956     } while (c[k] == '\n' || c[k] == '\r');
00957     if (c[k] == '~' || c[k] == EOF)
00958       break;
00959       }
00960       n = k - 1;
00961       if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
00962     for (++k; k < 5; ++k)
00963       c[k] = 0x21 + 84;
00964     eof = gTrue;
00965       }
00966       t = 0;
00967       for (k = 0; k < 5; ++k)
00968     t = t * 85 + (c[k] - 0x21);
00969       for (k = 3; k >= 0; --k) {
00970     b[k] = (int)(t & 0xff);
00971     t >>= 8;
00972       }
00973     }
00974   }
00975   return b[index];
00976 }
00977 
00978 GString *ASCII85Stream::getPSFilter(const char *indent) {
00979   GString *s;
00980 
00981   if (!(s = str->getPSFilter(indent))) {
00982     return NULL;
00983   }
00984   s->append(indent)->append("/ASCII85Decode filter\n");
00985   return s;
00986 }
00987 
00988 GBool ASCII85Stream::isBinary(GBool /*last*/) {
00989   return str->isBinary(gFalse);
00990 }
00991 
00992 //------------------------------------------------------------------------
00993 // LZWStream
00994 //------------------------------------------------------------------------
00995 
00996 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
00997              int bits, int earlyA):
00998     FilterStream(strA) {
00999   if (predictor != 1) {
01000     pred = new StreamPredictor(this, predictor, columns, colors, bits);
01001     if ( !pred->isOk()) {
01002        delete pred;
01003        pred = NULL;
01004     }
01005   } else {
01006     pred = NULL;
01007   }
01008   early = earlyA;
01009   eof = gFalse;
01010   inputBits = 0;
01011   clearTable();
01012 }
01013 
01014 LZWStream::~LZWStream() {
01015   if (pred) {
01016     delete pred;
01017   }
01018   delete str;
01019 }
01020 
01021 int LZWStream::getChar() {
01022   if (pred) {
01023     return pred->getChar();
01024   }
01025   if (eof) {
01026     return EOF;
01027   }
01028   if (seqIndex >= seqLength) {
01029     if (!processNextCode()) {
01030       return EOF;
01031     }
01032   }
01033   return seqBuf[seqIndex++];
01034 }
01035 
01036 int LZWStream::lookChar() {
01037   if (pred) {
01038     return pred->lookChar();
01039   }
01040   if (eof) {
01041     return EOF;
01042   }
01043   if (seqIndex >= seqLength) {
01044     if (!processNextCode()) {
01045       return EOF;
01046     }
01047   }
01048   return seqBuf[seqIndex];
01049 }
01050 
01051 int LZWStream::getRawChar() {
01052   if (eof) {
01053     return EOF;
01054   }
01055   if (seqIndex >= seqLength) {
01056     if (!processNextCode()) {
01057       return EOF;
01058     }
01059   }
01060   return seqBuf[seqIndex++];
01061 }
01062 
01063 void LZWStream::reset() {
01064   str->reset();
01065   eof = gFalse;
01066   inputBits = 0;
01067   clearTable();
01068 }
01069 
01070 GBool LZWStream::processNextCode() {
01071   int code;
01072   int nextLength;
01073   int i, j;
01074 
01075   // check for EOF
01076   if (eof) {
01077     return gFalse;
01078   }
01079 
01080   // check for eod and clear-table codes
01081  start:
01082   code = getCode();
01083   if (code == EOF || code == 257) {
01084     eof = gTrue;
01085     return gFalse;
01086   }
01087   if (code == 256) {
01088     clearTable();
01089     goto start;
01090   }
01091   if (nextCode >= 4097) {
01092     error(getPos(), "Bad LZW stream - expected clear-table code");
01093     clearTable();
01094   }
01095 
01096   // process the next code
01097   nextLength = seqLength + 1;
01098   if (code < 256) {
01099     seqBuf[0] = code;
01100     seqLength = 1;
01101   } else if (code < nextCode) {
01102     seqLength = table[code].length;
01103     for (i = seqLength - 1, j = code; i > 0; --i) {
01104       seqBuf[i] = table[j].tail;
01105       j = table[j].head;
01106     }
01107     seqBuf[0] = j;
01108   } else if (code == nextCode) {
01109     seqBuf[seqLength] = newChar;
01110     ++seqLength;
01111   } else {
01112     error(getPos(), "Bad LZW stream - unexpected code");
01113     eof = gTrue;
01114     return gFalse;
01115   }
01116   newChar = seqBuf[0];
01117   if (first) {
01118     first = gFalse;
01119   } else {
01120     table[nextCode].length = nextLength;
01121     table[nextCode].head = prevCode;
01122     table[nextCode].tail = newChar;
01123     ++nextCode;
01124     if (nextCode + early == 512)
01125       nextBits = 10;
01126     else if (nextCode + early == 1024)
01127       nextBits = 11;
01128     else if (nextCode + early == 2048)
01129       nextBits = 12;
01130   }
01131   prevCode = code;
01132 
01133   // reset buffer
01134   seqIndex = 0;
01135 
01136   return gTrue;
01137 }
01138 
01139 void LZWStream::clearTable() {
01140   nextCode = 258;
01141   nextBits = 9;
01142   seqIndex = seqLength = 0;
01143   first = gTrue;
01144 }
01145 
01146 int LZWStream::getCode() {
01147   int c;
01148   int code;
01149 
01150   while (inputBits < nextBits) {
01151     if ((c = str->getChar()) == EOF)
01152       return EOF;
01153     inputBuf = (inputBuf << 8) | (c & 0xff);
01154     inputBits += 8;
01155   }
01156   code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
01157   inputBits -= nextBits;
01158   return code;
01159 }
01160 
01161 GString *LZWStream::getPSFilter(const char *indent) {
01162   GString *s;
01163 
01164   if (pred) {
01165     return NULL;
01166   }
01167   if (!(s = str->getPSFilter(indent))) {
01168     return NULL;
01169   }
01170   s->append(indent)->append("/LZWDecode filter\n");
01171   return s;
01172 }
01173 
01174 GBool LZWStream::isBinary(GBool /*last*/) {
01175   return str->isBinary(gTrue);
01176 }
01177 
01178 //------------------------------------------------------------------------
01179 // RunLengthStream
01180 //------------------------------------------------------------------------
01181 
01182 RunLengthStream::RunLengthStream(Stream *strA):
01183     FilterStream(strA) {
01184   bufPtr = bufEnd = buf;
01185   eof = gFalse;
01186 }
01187 
01188 RunLengthStream::~RunLengthStream() {
01189   delete str;
01190 }
01191 
01192 void RunLengthStream::reset() {
01193   str->reset();
01194   bufPtr = bufEnd = buf;
01195   eof = gFalse;
01196 }
01197 
01198 GString *RunLengthStream::getPSFilter(const char *indent) {
01199   GString *s;
01200 
01201   if (!(s = str->getPSFilter(indent))) {
01202     return NULL;
01203   }
01204   s->append(indent)->append("/RunLengthDecode filter\n");
01205   return s;
01206 }
01207 
01208 GBool RunLengthStream::isBinary(GBool /*last*/) {
01209   return str->isBinary(gTrue);
01210 }
01211 
01212 GBool RunLengthStream::fillBuf() {
01213   int c;
01214   int n, i;
01215 
01216   if (eof)
01217     return gFalse;
01218   c = str->getChar();
01219   if (c == 0x80 || c == EOF) {
01220     eof = gTrue;
01221     return gFalse;
01222   }
01223   if (c < 0x80) {
01224     n = c + 1;
01225     for (i = 0; i < n; ++i)
01226       buf[i] = (char)str->getChar();
01227   } else {
01228     n = 0x101 - c;
01229     c = str->getChar();
01230     for (i = 0; i < n; ++i)
01231       buf[i] = (char)c;
01232   }
01233   bufPtr = buf;
01234   bufEnd = buf + n;
01235   return gTrue;
01236 }
01237 
01238 //------------------------------------------------------------------------
01239 // CCITTFaxStream
01240 //------------------------------------------------------------------------
01241 
01242 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
01243                    GBool byteAlignA, int columnsA, int rowsA,
01244                    GBool endOfBlockA, GBool blackA):
01245     FilterStream(strA) {
01246   encoding = encodingA;
01247   endOfLine = endOfLineA;
01248   byteAlign = byteAlignA;
01249   columns = columnsA;
01250   if (columns < 1 || columns >= INT_MAX / sizeof(short)) {
01251     error(-1, "invalid number of columns");
01252     exit(1);
01253   }
01254   rows = rowsA;
01255   endOfBlock = endOfBlockA;
01256   black = blackA;
01257   refLine = (short *)gmalloc((columns + 3) * sizeof(short));
01258   codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
01259 
01260   eof = gFalse;
01261   row = 0;
01262   nextLine2D = encoding < 0;
01263   inputBits = 0;
01264   codingLine[0] = 0;
01265   codingLine[1] = refLine[2] = columns;
01266   a0 = 1;
01267 
01268   buf = EOF;
01269 }
01270 
01271 CCITTFaxStream::~CCITTFaxStream() {
01272   delete str;
01273   gfree(refLine);
01274   gfree(codingLine);
01275 }
01276 
01277 void CCITTFaxStream::reset() {
01278   int n;
01279 
01280   str->reset();
01281   eof = gFalse;
01282   row = 0;
01283   nextLine2D = encoding < 0;
01284   inputBits = 0;
01285   codingLine[0] = 0;
01286   codingLine[1] = refLine[2] = columns;
01287   a0 = 1;
01288   buf = EOF;
01289 
01290   // get initial end-of-line marker and 2D encoding tag
01291   if (endOfBlock) {
01292     if (lookBits(12) == 0x001) {
01293       eatBits(12);
01294     }
01295   } else {
01296     for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
01297     if (n == 11 && lookBits(12) == 0x001) {
01298       eatBits(12);
01299     }
01300   }
01301   if (encoding > 0) {
01302     nextLine2D = !lookBits(1);
01303     eatBits(1);
01304   }
01305 }
01306 
01307 int CCITTFaxStream::lookChar() {
01308   short code1, code2, code3;
01309   int a0New;
01310 #if 0
01311   GBool err;
01312 #endif
01313   GBool gotEOL;
01314   int ret;
01315   int bits, i;
01316 
01317   // if at eof just return EOF
01318   if (eof && codingLine[a0] >= columns) {
01319     return EOF;
01320   }
01321 
01322   // read the next row
01323 #if 0
01324   err = gFalse;
01325 #endif
01326   if (codingLine[a0] >= columns) {
01327 
01328     // 2-D encoding
01329     if (nextLine2D) {
01330       for (i = 0; codingLine[i] < columns; ++i)
01331     refLine[i] = codingLine[i];
01332       refLine[i] = refLine[i + 1] = columns;
01333       b1 = 1;
01334       a0New = codingLine[a0 = 0] = 0;
01335       do {
01336     code1 = getTwoDimCode();
01337     switch (code1) {
01338     case twoDimPass:
01339       if (refLine[b1] < columns) {
01340         a0New = refLine[b1 + 1];
01341         b1 += 2;
01342       }
01343       break;
01344     case twoDimHoriz:
01345       if ((a0 & 1) == 0) {
01346         code1 = code2 = 0;
01347         do {
01348           code1 += code3 = getWhiteCode();
01349         } while (code3 >= 64);
01350         do {
01351           code2 += code3 = getBlackCode();
01352         } while (code3 >= 64);
01353       } else {
01354         code1 = code2 = 0;
01355         do {
01356           code1 += code3 = getBlackCode();
01357         } while (code3 >= 64);
01358         do {
01359           code2 += code3 = getWhiteCode();
01360         } while (code3 >= 64);
01361       }
01362       codingLine[a0 + 1] = a0New + code1;
01363       ++a0;
01364       a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
01365       ++a0;
01366       while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01367         b1 += 2;
01368       break;
01369     case twoDimVert0:
01370       a0New = codingLine[++a0] = refLine[b1];
01371       if (refLine[b1] < columns) {
01372         ++b1;
01373         while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01374           b1 += 2;
01375       }
01376       break;
01377     case twoDimVertR1:
01378       a0New = codingLine[++a0] = refLine[b1] + 1;
01379       if (refLine[b1] < columns) {
01380         ++b1;
01381         while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01382           b1 += 2;
01383       }
01384       break;
01385     case twoDimVertL1:
01386       a0New = codingLine[++a0] = refLine[b1] - 1;
01387       --b1;
01388       while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01389         b1 += 2;
01390       break;
01391     case twoDimVertR2:
01392       a0New = codingLine[++a0] = refLine[b1] + 2;
01393       if (refLine[b1] < columns) {
01394         ++b1;
01395         while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01396           b1 += 2;
01397       }
01398       break;
01399     case twoDimVertL2:
01400       a0New = codingLine[++a0] = refLine[b1] - 2;
01401       --b1;
01402       while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01403         b1 += 2;
01404       break;
01405     case twoDimVertR3:
01406       a0New = codingLine[++a0] = refLine[b1] + 3;
01407       if (refLine[b1] < columns) {
01408         ++b1;
01409         while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01410           b1 += 2;
01411       }
01412       break;
01413     case twoDimVertL3:
01414       a0New = codingLine[++a0] = refLine[b1] - 3;
01415       --b1;
01416       while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01417         b1 += 2;
01418       break;
01419     case EOF:
01420       eof = gTrue;
01421       codingLine[a0 = 0] = columns;
01422       return EOF;
01423     default:
01424       error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
01425 #if 0
01426       err = gTrue;
01427       break;
01428 #else
01429       eof = gTrue;
01430       return EOF;
01431 #endif
01432     }
01433       } while (codingLine[a0] < columns);
01434 
01435     // 1-D encoding
01436     } else {
01437       codingLine[a0 = 0] = 0;
01438       while (1) {
01439     code1 = 0;
01440     do {
01441       code1 += code3 = getWhiteCode();
01442     } while (code3 >= 64);
01443     codingLine[a0+1] = codingLine[a0] + code1;
01444     ++a0;
01445     if (codingLine[a0] >= columns)
01446       break;
01447     code2 = 0;
01448     do {
01449       code2 += code3 = getBlackCode();
01450     } while (code3 >= 64);
01451     codingLine[a0+1] = codingLine[a0] + code2;
01452     ++a0;
01453     if (codingLine[a0] >= columns)
01454       break;
01455       }
01456     }
01457 
01458     if (codingLine[a0] != columns) {
01459       error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
01460 #if 0
01461       err = gTrue;
01462 #endif
01463     }
01464 
01465     // byte-align the row
01466     if (byteAlign) {
01467       inputBits &= ~7;
01468     }
01469 
01470     // check for end-of-line marker, skipping over any extra zero bits
01471     gotEOL = gFalse;
01472     if (!endOfBlock && row == rows - 1) {
01473       eof = gTrue;
01474     } else {
01475       code1 = lookBits(12);
01476       while (code1 == 0) {
01477     eatBits(1);
01478     code1 = lookBits(12);
01479       }
01480       if (code1 == 0x001) {
01481     eatBits(12);
01482     gotEOL = gTrue;
01483       } else if (code1 == EOF) {
01484     eof = gTrue;
01485       }
01486     }
01487 
01488     // get 2D encoding tag
01489     if (!eof && encoding > 0) {
01490       nextLine2D = !lookBits(1);
01491       eatBits(1);
01492     }
01493 
01494     // check for end-of-block marker
01495     if (endOfBlock && gotEOL) {
01496       code1 = lookBits(12);
01497       if (code1 == 0x001) {
01498     eatBits(12);
01499     if (encoding > 0) {
01500       lookBits(1);
01501       eatBits(1);
01502     }
01503     if (encoding >= 0) {
01504       for (i = 0; i < 4; ++i) {
01505         code1 = lookBits(12);
01506         if (code1 != 0x001) {
01507           error(getPos(), "Bad RTC code in CCITTFax stream");
01508         }
01509         eatBits(12);
01510         if (encoding > 0) {
01511           lookBits(1);
01512           eatBits(1);
01513         }
01514       }
01515     }
01516     eof = gTrue;
01517       }
01518     }
01519 
01520 #if 0
01521     // This looks for an end-of-line marker after an error, however
01522     // some (most?) CCITT streams in PDF files don't use end-of-line
01523     // markers, and the just-plow-on technique works better in those
01524     // cases.
01525     else if (err) {
01526       do {
01527     if (code1 == EOF) {
01528       eof = gTrue;
01529       return EOF;
01530     }
01531     eatBits(1);
01532     code1 = look13Bits();
01533       } while ((code1 >> 1) != 0x001);
01534       eatBits(12);
01535       codingLine[++a0] = columns;
01536       if (encoding > 0) {
01537     eatBits(1);
01538     nextLine2D = !(code1 & 1);
01539       }
01540     }
01541 #endif
01542 
01543     a0 = 0;
01544     outputBits = codingLine[1] - codingLine[0];
01545     if (outputBits == 0) {
01546       a0 = 1;
01547       outputBits = codingLine[2] - codingLine[1];
01548     }
01549 
01550     ++row;
01551   }
01552 
01553   // get a byte
01554   if (outputBits >= 8) {
01555     ret = ((a0 & 1) == 0) ? 0xff : 0x00;
01556     if ((outputBits -= 8) == 0) {
01557       ++a0;
01558       if (codingLine[a0] < columns) {
01559     outputBits = codingLine[a0 + 1] - codingLine[a0];
01560       }
01561     }
01562   } else {
01563     bits = 8;
01564     ret = 0;
01565     do {
01566       if (outputBits > bits) {
01567     i = bits;
01568     bits = 0;
01569     if ((a0 & 1) == 0) {
01570       ret |= 0xff >> (8 - i);
01571     }
01572     outputBits -= i;
01573       } else {
01574     i = outputBits;
01575     bits -= outputBits;
01576     if ((a0 & 1) == 0) {
01577       ret |= (0xff >> (8 - i)) << bits;
01578     }
01579     outputBits = 0;
01580     ++a0;
01581     if (codingLine[a0] < columns) {
01582       outputBits = codingLine[a0 + 1] - codingLine[a0];
01583     }
01584       }
01585     } while (bits > 0 && codingLine[a0] < columns);
01586   }
01587   buf = black ? (ret ^ 0xff) : ret;
01588   return buf;
01589 }
01590 
01591 short CCITTFaxStream::getTwoDimCode() {
01592   short code;
01593   CCITTCode *p;
01594   int n;
01595 
01596   code = 0; // make gcc happy
01597   if (endOfBlock) {
01598     code = lookBits(7);
01599     p = &twoDimTab1[code];
01600     if (p->bits > 0) {
01601       eatBits(p->bits);
01602       return p->n;
01603     }
01604   } else {
01605     for (n = 1; n <= 7; ++n) {
01606       code = lookBits(n);
01607       if (n < 7) {
01608     code <<= 7 - n;
01609       }
01610       p = &twoDimTab1[code];
01611       if (p->bits == n) {
01612     eatBits(n);
01613     return p->n;
01614       }
01615     }
01616   }
01617   error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
01618   return EOF;
01619 }
01620 
01621 short CCITTFaxStream::getWhiteCode() {
01622   short code;
01623   CCITTCode *p;
01624   int n;
01625 
01626   code = 0; // make gcc happy
01627   if (endOfBlock) {
01628     code = lookBits(12);
01629     if ((code >> 5) == 0) {
01630       p = &whiteTab1[code];
01631     } else {
01632       p = &whiteTab2[code >> 3];
01633     }
01634     if (p->bits > 0) {
01635       eatBits(p->bits);
01636       return p->n;
01637     }
01638   } else {
01639     for (n = 1; n <= 9; ++n) {
01640       code = lookBits(n);
01641       if (n < 9) {
01642     code <<= 9 - n;
01643       }
01644       p = &whiteTab2[code];
01645       if (p->bits == n) {
01646     eatBits(n);
01647     return p->n;
01648       }
01649     }
01650     for (n = 11; n <= 12; ++n) {
01651       code = lookBits(n);
01652       if (n < 12) {
01653     code <<= 12 - n;
01654       }
01655       p = &whiteTab1[code];
01656       if (p->bits == n) {
01657     eatBits(n);
01658     return p->n;
01659       }
01660     }
01661   }
01662   error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
01663   // eat a bit and return a positive number so that the caller doesn't
01664   // go into an infinite loop
01665   eatBits(1);
01666   return 1;
01667 }
01668 
01669 short CCITTFaxStream::getBlackCode() {
01670   short code;
01671   CCITTCode *p;
01672   int n;
01673 
01674   code = 0; // make gcc happy
01675   if (endOfBlock) {
01676     code = lookBits(13);
01677     if ((code >> 7) == 0) {
01678       p = &blackTab1[code];
01679     } else if ((code >> 9) == 0) {
01680       p = &blackTab2[(code >> 1) - 64];
01681     } else {
01682       p = &blackTab3[code >> 7];
01683     }
01684     if (p->bits > 0) {
01685       eatBits(p->bits);
01686       return p->n;
01687     }
01688   } else {
01689     for (n = 2; n <= 6; ++n) {
01690       code = lookBits(n);
01691       if (n < 6) {
01692     code <<= 6 - n;
01693       }
01694       p = &blackTab3[code];
01695       if (p->bits == n) {
01696     eatBits(n);
01697     return p->n;
01698       }
01699     }
01700     for (n = 7; n <= 12; ++n) {
01701       code = lookBits(n);
01702       if (n < 12) {
01703     code <<= 12 - n;
01704       }
01705       if (code >= 64) {
01706     p = &blackTab2[code - 64];
01707     if (p->bits == n) {
01708       eatBits(n);
01709       return p->n;
01710     }
01711       }
01712     }
01713     for (n = 10; n <= 13; ++n) {
01714       code = lookBits(n);
01715       if (n < 13) {
01716     code <<= 13 - n;
01717       }
01718       p = &blackTab1[code];
01719       if (p->bits == n) {
01720     eatBits(n);
01721     return p->n;
01722       }
01723     }
01724   }
01725   error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
01726   // eat a bit and return a positive number so that the caller doesn't
01727   // go into an infinite loop
01728   eatBits(1);
01729   return 1;
01730 }
01731 
01732 short CCITTFaxStream::lookBits(int n) {
01733   int c;
01734 
01735   while (inputBits < n) {
01736     if ((c = str->getChar()) == EOF) {
01737       if (inputBits == 0) {
01738     return EOF;
01739       }
01740       // near the end of the stream, the caller may ask for more bits
01741       // than are available, but there may still be a valid code in
01742       // however many bits are available -- we need to return correct
01743       // data in this case
01744       return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
01745     }
01746     inputBuf = (inputBuf << 8) + c;
01747     inputBits += 8;
01748   }
01749   return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
01750 }
01751 
01752 GString *CCITTFaxStream::getPSFilter(const char *indent) {
01753   GString *s;
01754   char s1[50];
01755 
01756   if (!(s = str->getPSFilter(indent))) {
01757     return NULL;
01758   }
01759   s->append(indent)->append("<< ");
01760   if (encoding != 0) {
01761     sprintf(s1, "/K %d ", encoding);
01762     s->append(s1);
01763   }
01764   if (endOfLine) {
01765     s->append("/EndOfLine true ");
01766   }
01767   if (byteAlign) {
01768     s->append("/EncodedByteAlign true ");
01769   }
01770   sprintf(s1, "/Columns %d ", columns);
01771   s->append(s1);
01772   if (rows != 0) {
01773     sprintf(s1, "/Rows %d ", rows);
01774     s->append(s1);
01775   }
01776   if (!endOfBlock) {
01777     s->append("/EndOfBlock false ");
01778   }
01779   if (black) {
01780     s->append("/BlackIs1 true ");
01781   }
01782   s->append(">> /CCITTFaxDecode filter\n");
01783   return s;
01784 }
01785 
01786 GBool CCITTFaxStream::isBinary(GBool /*last*/) {
01787   return str->isBinary(gTrue);
01788 }
01789 
01790 //------------------------------------------------------------------------
01791 // DCTStream
01792 //------------------------------------------------------------------------
01793 
01794 // IDCT constants (20.12 fixed point format)
01795 #define dctCos1    4017     // cos(pi/16)
01796 #define dctSin1     799     // sin(pi/16)
01797 #define dctCos3    3406     // cos(3*pi/16)
01798 #define dctSin3    2276     // sin(3*pi/16)
01799 #define dctCos6    1567     // cos(6*pi/16)
01800 #define dctSin6    3784     // sin(6*pi/16)
01801 #define dctSqrt2   5793     // sqrt(2)
01802 #define dctSqrt1d2 2896     // sqrt(2) / 2
01803 
01804 // color conversion parameters (16.16 fixed point format)
01805 #define dctCrToR   91881    //  1.4020
01806 #define dctCbToG  -22553    // -0.3441363
01807 #define dctCrToG  -46802    // -0.71413636
01808 #define dctCbToB  116130    //  1.772
01809 
01810 // clip [-256,511] --> [0,255]
01811 #define dctClipOffset 256
01812 static Guchar dctClip[768];
01813 static int dctClipInit = 0;
01814 
01815 // zig zag decode map
01816 static int dctZigZag[64] = {
01817    0,
01818    1,  8,
01819   16,  9,  2,
01820    3, 10, 17, 24,
01821   32, 25, 18, 11, 4,
01822    5, 12, 19, 26, 33, 40,
01823   48, 41, 34, 27, 20, 13,  6,
01824    7, 14, 21, 28, 35, 42, 49, 56,
01825   57, 50, 43, 36, 29, 22, 15,
01826   23, 30, 37, 44, 51, 58,
01827   59, 52, 45, 38, 31,
01828   39, 46, 53, 60,
01829   61, 54, 47,
01830   55, 62,
01831   63
01832 };
01833 
01834 DCTStream::DCTStream(Stream *strA):
01835     FilterStream(strA) {
01836   int i, j;
01837 
01838   progressive = interleaved = gFalse;
01839   width = height = 0;
01840   mcuWidth = mcuHeight = 0;
01841   numComps = 0;
01842   comp = 0;
01843   x = y = dy = 0;
01844   for (i = 0; i < 4; ++i) {
01845     for (j = 0; j < 32; ++j) {
01846       rowBuf[i][j] = NULL;
01847     }
01848     frameBuf[i] = NULL;
01849   }
01850 
01851   if (!dctClipInit) {
01852     for (i = -256; i < 0; ++i)
01853       dctClip[dctClipOffset + i] = 0;
01854     for (i = 0; i < 256; ++i)
01855       dctClip[dctClipOffset + i] = i;
01856     for (i = 256; i < 512; ++i)
01857       dctClip[dctClipOffset + i] = 255;
01858     dctClipInit = 1;
01859   }
01860 }
01861 
01862 DCTStream::~DCTStream() {
01863   int i, j;
01864 
01865   delete str;
01866   if (progressive || !interleaved) {
01867     for (i = 0; i < numComps; ++i) {
01868       gfree(frameBuf[i]);
01869     }
01870   } else {
01871     for (i = 0; i < numComps; ++i) {
01872       for (j = 0; j < mcuHeight; ++j) {
01873     gfree(rowBuf[i][j]);
01874       }
01875     }
01876   }
01877 }
01878 
01879 void DCTStream::reset() {
01880   int minHSample, minVSample;
01881   int i, j;
01882 
01883   str->reset();
01884 
01885   progressive = interleaved = gFalse;
01886   width = height = 0;
01887   numComps = 0;
01888   numQuantTables = 0;
01889   numDCHuffTables = 0;
01890   numACHuffTables = 0;
01891   colorXform = 0;
01892   gotAdobeMarker = gFalse;
01893   restartInterval = 0;
01894 
01895   if (!readHeader()) {
01896     y = height;
01897     return;
01898   }
01899 
01900   // compute MCU size
01901   mcuWidth = minHSample = compInfo[0].hSample;
01902   mcuHeight = minVSample = compInfo[0].vSample;
01903   for (i = 1; i < numComps; ++i) {
01904     if (compInfo[i].hSample < minHSample)
01905       minHSample = compInfo[i].hSample;
01906     if (compInfo[i].vSample < minVSample)
01907       minVSample = compInfo[i].vSample;
01908     if (compInfo[i].hSample > mcuWidth)
01909       mcuWidth = compInfo[i].hSample;
01910     if (compInfo[i].vSample > mcuHeight)
01911       mcuHeight = compInfo[i].vSample;
01912   }
01913   for (i = 0; i < numComps; ++i) {
01914     compInfo[i].hSample /= minHSample;
01915     compInfo[i].vSample /= minVSample;
01916   }
01917   mcuWidth = (mcuWidth / minHSample) * 8;
01918   mcuHeight = (mcuHeight / minVSample) * 8;
01919 
01920   // figure out color transform
01921   if (!gotAdobeMarker && numComps == 3) {
01922     if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
01923       colorXform = 1;
01924     }
01925   }
01926 
01927   if (progressive || !interleaved) {
01928 
01929     // allocate a buffer for the whole image
01930     bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
01931     bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
01932     for (i = 0; i < numComps; ++i) {
01933       frameBuf[i] = (int *)gmalloc(bufWidth * bufHeight * sizeof(int));
01934       memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
01935     }
01936 
01937     // read the image data
01938     do {
01939       restartMarker = 0xd0;
01940       restart();
01941       readScan();
01942     } while (readHeader());
01943 
01944     // decode
01945     decodeImage();
01946 
01947     // initialize counters
01948     comp = 0;
01949     x = 0;
01950     y = 0;
01951 
01952   } else {
01953 
01954     // allocate a buffer for one row of MCUs
01955     bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
01956     for (i = 0; i < numComps; ++i) {
01957       for (j = 0; j < mcuHeight; ++j) {
01958     rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
01959       }
01960     }
01961 
01962     // initialize counters
01963     comp = 0;
01964     x = 0;
01965     y = 0;
01966     dy = mcuHeight;
01967 
01968     restartMarker = 0xd0;
01969     restart();
01970   }
01971 }
01972 
01973 int DCTStream::getChar() {
01974   int c;
01975 
01976   if (y >= height) {
01977     return EOF;
01978   }
01979   if (progressive || !interleaved) {
01980     c = frameBuf[comp][y * bufWidth + x];
01981     if (++comp == numComps) {
01982       comp = 0;
01983       if (++x == width) {
01984     x = 0;
01985     ++y;
01986       }
01987     }
01988   } else {
01989     if (dy >= mcuHeight) {
01990       if (!readMCURow()) {
01991     y = height;
01992     return EOF;
01993       }
01994       comp = 0;
01995       x = 0;
01996       dy = 0;
01997     }
01998     c = rowBuf[comp][dy][x];
01999     if (++comp == numComps) {
02000       comp = 0;
02001       if (++x == width) {
02002     x = 0;
02003     ++y;
02004     ++dy;
02005     if (y == height) {
02006       readTrailer();
02007     }
02008       }
02009     }
02010   }
02011   return c;
02012 }
02013 
02014 int DCTStream::lookChar() {
02015   if (y >= height) {
02016     return EOF;
02017   }
02018   if (progressive || !interleaved) {
02019     return frameBuf[comp][y * bufWidth + x];
02020   } else {
02021     if (dy >= mcuHeight) {
02022       if (!readMCURow()) {
02023     y = height;
02024     return EOF;
02025       }
02026       comp = 0;
02027       x = 0;
02028       dy = 0;
02029     }
02030     return rowBuf[comp][dy][x];
02031   }
02032 }
02033 
02034 void DCTStream::restart() {
02035   int i;
02036 
02037   inputBits = 0;
02038   restartCtr = restartInterval;
02039   for (i = 0; i < numComps; ++i) {
02040     compInfo[i].prevDC = 0;
02041   }
02042   eobRun = 0;
02043 }
02044 
02045 // Read one row of MCUs from a sequential JPEG stream.
02046 GBool DCTStream::readMCURow() {
02047   int data1[64];
02048   Guchar data2[64];
02049   Guchar *p1, *p2;
02050   int pY, pCb, pCr, pR, pG, pB;
02051   int h, v, horiz, vert, hSub, vSub;
02052   int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
02053   int c;
02054 
02055   for (x1 = 0; x1 < width; x1 += mcuWidth) {
02056 
02057     // deal with restart marker
02058     if (restartInterval > 0 && restartCtr == 0) {
02059       c = readMarker();
02060       if (c != restartMarker) {
02061     error(getPos(), "Bad DCT data: incorrect restart marker");
02062     return gFalse;
02063       }
02064       if (++restartMarker == 0xd8)
02065     restartMarker = 0xd0;
02066       restart();
02067     }
02068 
02069     // read one MCU
02070     for (cc = 0; cc < numComps; ++cc) {
02071       h = compInfo[cc].hSample;
02072       v = compInfo[cc].vSample;
02073       horiz = mcuWidth / h;
02074       vert = mcuHeight / v;
02075       hSub = horiz / 8;
02076       vSub = vert / 8;
02077       for (y2 = 0; y2 < mcuHeight; y2 += vert) {
02078     for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
02079       if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
02080                 &acHuffTables[scanInfo.acHuffTable[cc]],
02081                 &compInfo[cc].prevDC,
02082                 data1)) {
02083         return gFalse;
02084       }
02085       transformDataUnit(quantTables[compInfo[cc].quantTable],
02086                 data1, data2);
02087       if (hSub == 1 && vSub == 1) {
02088         for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
02089           p1 = &rowBuf[cc][y2+y3][x1+x2];
02090           p1[0] = data2[i];
02091           p1[1] = data2[i+1];
02092           p1[2] = data2[i+2];
02093           p1[3] = data2[i+3];
02094           p1[4] = data2[i+4];
02095           p1[5] = data2[i+5];
02096           p1[6] = data2[i+6];
02097           p1[7] = data2[i+7];
02098         }
02099       } else if (hSub == 2 && vSub == 2) {
02100         for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
02101           p1 = &rowBuf[cc][y2+y3][x1+x2];
02102           p2 = &rowBuf[cc][y2+y3+1][x1+x2];
02103           p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
02104           p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
02105           p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
02106           p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
02107           p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
02108           p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
02109           p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
02110           p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
02111         }
02112       } else {
02113         i = 0;
02114         for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
02115           for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
02116         for (y5 = 0; y5 < vSub; ++y5)
02117           for (x5 = 0; x5 < hSub; ++x5)
02118             rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
02119         ++i;
02120           }
02121         }
02122       }
02123     }
02124       }
02125     }
02126     --restartCtr;
02127 
02128     // color space conversion
02129     if (colorXform) {
02130       // convert YCbCr to RGB
02131       if (numComps == 3) {
02132     for (y2 = 0; y2 < mcuHeight; ++y2) {
02133       for (x2 = 0; x2 < mcuWidth; ++x2) {
02134         pY = rowBuf[0][y2][x1+x2];
02135         pCb = rowBuf[1][y2][x1+x2] - 128;
02136         pCr = rowBuf[2][y2][x1+x2] - 128;
02137         pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
02138         rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
02139         pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
02140         rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
02141         pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
02142         rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
02143       }
02144     }
02145       // convert YCbCrK to CMYK (K is passed through unchanged)
02146       } else if (numComps == 4) {
02147     for (y2 = 0; y2 < mcuHeight; ++y2) {
02148       for (x2 = 0; x2 < mcuWidth; ++x2) {
02149         pY = rowBuf[0][y2][x1+x2];
02150         pCb = rowBuf[1][y2][x1+x2] - 128;
02151         pCr = rowBuf[2][y2][x1+x2] - 128;
02152         pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
02153         rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
02154         pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
02155         rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
02156         pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
02157         rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
02158       }
02159     }
02160       }
02161     }
02162   }
02163   return gTrue;
02164 }
02165 
02166 // Read one scan from a progressive or non-interleaved JPEG stream.
02167 void DCTStream::readScan() {
02168   int data[64];
02169   int x1, y1, dy1, x2, y2, y3, cc, i;
02170   int h, v, horiz, vert, hSub, vSub;
02171   int *p1;
02172   int c;
02173 
02174   if (scanInfo.numComps == 1) {
02175     for (cc = 0; cc < numComps; ++cc) {
02176       if (scanInfo.comp[cc]) {
02177     break;
02178       }
02179     }
02180     dy1 = mcuHeight / compInfo[cc].vSample;
02181   } else {
02182     dy1 = mcuHeight;
02183   }
02184 
02185   for (y1 = 0; y1 < bufHeight; y1 += dy1) {
02186     for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
02187 
02188       // deal with restart marker
02189       if (restartInterval > 0 && restartCtr == 0) {
02190     c = readMarker();
02191     if (c != restartMarker) {
02192       error(getPos(), "Bad DCT data: incorrect restart marker");
02193       return;
02194     }
02195     if (++restartMarker == 0xd8) {
02196       restartMarker = 0xd0;
02197     }
02198     restart();
02199       }
02200 
02201       // read one MCU
02202       for (cc = 0; cc < numComps; ++cc) {
02203     if (!scanInfo.comp[cc]) {
02204       continue;
02205     }
02206 
02207     h = compInfo[cc].hSample;
02208     v = compInfo[cc].vSample;
02209     horiz = mcuWidth / h;
02210     vert = mcuHeight / v;
02211     hSub = horiz / 8;
02212     vSub = vert / 8;
02213     for (y2 = 0; y2 < dy1; y2 += vert) {
02214       for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
02215 
02216         // pull out the current values
02217         p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
02218         for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
02219           data[i] = p1[0];
02220           data[i+1] = p1[1];
02221           data[i+2] = p1[2];
02222           data[i+3] = p1[3];
02223           data[i+4] = p1[4];
02224           data[i+5] = p1[5];
02225           data[i+6] = p1[6];
02226           data[i+7] = p1[7];
02227           p1 += bufWidth * vSub;
02228         }
02229 
02230         // read one data unit
02231         if (progressive) {
02232           if (!readProgressiveDataUnit(
02233                &dcHuffTables[scanInfo.dcHuffTable[cc]],
02234                &acHuffTables[scanInfo.acHuffTable[cc]],
02235                &compInfo[cc].prevDC,
02236                data)) {
02237         return;
02238           }
02239         } else {
02240           if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
02241                 &acHuffTables[scanInfo.acHuffTable[cc]],
02242                 &compInfo[cc].prevDC,
02243                 data)) {
02244         return;
02245           }
02246         }
02247 
02248         // add the data unit into frameBuf
02249         p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
02250         for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
02251           p1[0] = data[i];
02252           p1[1] = data[i+1];
02253           p1[2] = data[i+2];
02254           p1[3] = data[i+3];
02255           p1[4] = data[i+4];
02256           p1[5] = data[i+5];
02257           p1[6] = data[i+6];
02258           p1[7] = data[i+7];
02259           p1 += bufWidth * vSub;
02260         }
02261       }
02262     }
02263       }
02264       --restartCtr;
02265     }
02266   }
02267 }
02268 
02269 // Read one data unit from a sequential JPEG stream.
02270 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
02271                   DCTHuffTable *acHuffTable,
02272                   int *prevDC, int data[64]) {
02273   int run, size, amp;
02274   int c;
02275   int i, j;
02276 
02277   if ((size = readHuffSym(dcHuffTable)) == 9999) {
02278     return gFalse;
02279   }
02280   if (size > 0) {
02281     if ((amp = readAmp(size)) == 9999) {
02282       return gFalse;
02283     }
02284   } else {
02285     amp = 0;
02286   }
02287   data[0] = *prevDC += amp;
02288   for (i = 1; i < 64; ++i) {
02289     data[i] = 0;
02290   }
02291   i = 1;
02292   while (i < 64) {
02293     run = 0;
02294     while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
02295       run += 0x10;
02296     }
02297     if (c == 9999) {
02298       return gFalse;
02299     }
02300     if (c == 0x00) {
02301       break;
02302     } else {
02303       run += (c >> 4) & 0x0f;
02304       size = c & 0x0f;
02305       amp = readAmp(size);
02306       if (amp == 9999) {
02307     return gFalse;
02308       }
02309       i += run;
02310       j = dctZigZag[i++];
02311       data[j] = amp;
02312     }
02313   }
02314   return gTrue;
02315 }
02316 
02317 // Read one data unit from a sequential JPEG stream.
02318 GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
02319                      DCTHuffTable *acHuffTable,
02320                      int *prevDC, int data[64]) {
02321   int run, size, amp, bit, c;
02322   int i, j, k;
02323 
02324   // get the DC coefficient
02325   i = scanInfo.firstCoeff;
02326   if (i == 0) {
02327     if (scanInfo.ah == 0) {
02328       if ((size = readHuffSym(dcHuffTable)) == 9999) {
02329     return gFalse;
02330       }
02331       if (size > 0) {
02332     if ((amp = readAmp(size)) == 9999) {
02333       return gFalse;
02334     }
02335       } else {
02336     amp = 0;
02337       }
02338       data[0] += (*prevDC += amp) << scanInfo.al;
02339     } else {
02340       if ((bit = readBit()) == 9999) {
02341     return gFalse;
02342       }
02343       data[0] += bit << scanInfo.al;
02344     }
02345     ++i;
02346   }
02347   if (scanInfo.lastCoeff == 0) {
02348     return gTrue;
02349   }
02350 
02351   // check for an EOB run
02352   if (eobRun > 0) {
02353     while (i <= scanInfo.lastCoeff) {
02354       j = dctZigZag[i++];
02355       if (data[j] != 0) {
02356     if ((bit = readBit()) == EOF) {
02357       return gFalse;
02358     }
02359     if (bit) {
02360       data[j] += 1 << scanInfo.al;
02361     }
02362       }
02363     }
02364     --eobRun;
02365     return gTrue;
02366   }
02367 
02368   // read the AC coefficients
02369   while (i <= scanInfo.lastCoeff) {
02370     if ((c = readHuffSym(acHuffTable)) == 9999) {
02371       return gFalse;
02372     }
02373 
02374     // ZRL
02375     if (c == 0xf0) {
02376       k = 0;
02377       while (k < 16) {
02378     j = dctZigZag[i++];
02379     if (data[j] == 0) {
02380       ++k;
02381     } else {
02382       if ((bit = readBit()) == EOF) {
02383         return gFalse;
02384       }
02385       if (bit) {
02386         data[j] += 1 << scanInfo.al;
02387       }
02388     }
02389       }
02390 
02391     // EOB run
02392     } else if ((c & 0x0f) == 0x00) {
02393       j = c >> 4;
02394       eobRun = 0;
02395       for (k = 0; k < j; ++k) {
02396     if ((bit = readBit()) == EOF) {
02397       return 9999;
02398     }
02399     eobRun = (eobRun << 1) | bit;
02400       }
02401       eobRun += 1 << j;
02402       while (i <= scanInfo.lastCoeff) {
02403     j = dctZigZag[i++];
02404     if (data[j] != 0) {
02405       if ((bit = readBit()) == EOF) {
02406         return gFalse;
02407       }
02408       if (bit) {
02409         data[j] += 1 << scanInfo.al;
02410       }
02411     }
02412       }
02413       --eobRun;
02414       break;
02415 
02416     // zero run and one AC coefficient
02417     } else {
02418       run = (c >> 4) & 0x0f;
02419       size = c & 0x0f;
02420       if ((amp = readAmp(size)) == 9999) {
02421     return gFalse;
02422       }
02423       k = 0;
02424       do {
02425     j = dctZigZag[i++];
02426     while (data[j] != 0) {
02427       if ((bit = readBit()) == EOF) {
02428         return gFalse;
02429       }
02430       if (bit) {
02431         data[j] += 1 << scanInfo.al;
02432       }
02433       j = dctZigZag[i++];
02434     }
02435     ++k;
02436       } while (k <= run);
02437       data[j] = amp << scanInfo.al;
02438     }
02439   }
02440 
02441   return gTrue;
02442 }
02443 
02444 // Decode a progressive JPEG image.
02445 void DCTStream::decodeImage() {
02446   int dataIn[64];
02447   Guchar dataOut[64];
02448   Guchar *quantTable;
02449   int pY, pCb, pCr, pR, pG, pB;
02450   int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
02451   int h, v, horiz, vert, hSub, vSub;
02452   int *p0, *p1, *p2;
02453 
02454   for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
02455     for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
02456       for (cc = 0; cc < numComps; ++cc) {
02457     quantTable = quantTables[compInfo[cc].quantTable];
02458     h = compInfo[cc].hSample;
02459     v = compInfo[cc].vSample;
02460     horiz = mcuWidth / h;
02461     vert = mcuHeight / v;
02462     hSub = horiz / 8;
02463     vSub = vert / 8;
02464     for (y2 = 0; y2 < mcuHeight; y2 += vert) {
02465       for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
02466 
02467         // pull out the coded data unit
02468         p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
02469         for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
02470           dataIn[i]   = p1[0];
02471           dataIn[i+1] = p1[1];
02472           dataIn[i+2] = p1[2];
02473           dataIn[i+3] = p1[3];
02474           dataIn[i+4] = p1[4];
02475           dataIn[i+5] = p1[5];
02476           dataIn[i+6] = p1[6];
02477           dataIn[i+7] = p1[7];
02478           p1 += bufWidth * vSub;
02479         }
02480 
02481         // transform
02482         transformDataUnit(quantTable, dataIn, dataOut);
02483 
02484         // store back into frameBuf, doing replication for
02485         // subsampled components
02486         p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
02487         if (hSub == 1 && vSub == 1) {
02488           for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
02489         p1[0] = dataOut[i] & 0xff;
02490         p1[1] = dataOut[i+1] & 0xff;
02491         p1[2] = dataOut[i+2] & 0xff;
02492         p1[3] = dataOut[i+3] & 0xff;
02493         p1[4] = dataOut[i+4] & 0xff;
02494         p1[5] = dataOut[i+5] & 0xff;
02495         p1[6] = dataOut[i+6] & 0xff;
02496         p1[7] = dataOut[i+7] & 0xff;
02497         p1 += bufWidth;
02498           }
02499         } else if (hSub == 2 && vSub == 2) {
02500           p2 = p1 + bufWidth;
02501           for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
02502         p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
02503         p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
02504         p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
02505         p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
02506         p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
02507         p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
02508         p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
02509         p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
02510         p1 += bufWidth * 2;
02511         p2 += bufWidth * 2;
02512           }
02513         } else {
02514           i = 0;
02515           for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
02516         for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
02517           p2 = p1 + x4;
02518           for (y5 = 0; y5 < vSub; ++y5) {
02519             for (x5 = 0; x5 < hSub; ++x5) {
02520               p2[x5] = dataOut[i] & 0xff;
02521             }
02522             p2 += bufWidth;
02523           }
02524           ++i;
02525         }
02526         p1 += bufWidth * vSub;
02527           }
02528         }
02529       }
02530     }
02531       }
02532 
02533       // color space conversion
02534       if (colorXform) {
02535     // convert YCbCr to RGB
02536     if (numComps == 3) {
02537       for (y2 = 0; y2 < mcuHeight; ++y2) {
02538         p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
02539         p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
02540         p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
02541         for (x2 = 0; x2 < mcuWidth; ++x2) {
02542           pY = *p0;
02543           pCb = *p1 - 128;
02544           pCr = *p2 - 128;
02545           pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
02546           *p0++ = dctClip[dctClipOffset + pR];
02547           pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
02548             32768) >> 16;
02549           *p1++ = dctClip[dctClipOffset + pG];
02550           pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
02551           *p2++ = dctClip[dctClipOffset + pB];
02552         }
02553       }
02554     // convert YCbCrK to CMYK (K is passed through unchanged)
02555     } else if (numComps == 4) {
02556       for (y2 = 0; y2 < mcuHeight; ++y2) {
02557         p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
02558         p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
02559         p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
02560         for (x2 = 0; x2 < mcuWidth; ++x2) {
02561           pY = *p0;
02562           pCb = *p1 - 128;
02563           pCr = *p2 - 128;
02564           pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
02565           *p0++ = 255 - dctClip[dctClipOffset + pR];
02566           pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
02567             32768) >> 16;
02568           *p1++ = 255 - dctClip[dctClipOffset + pG];
02569           pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
02570           *p2++ = 255 - dctClip[dctClipOffset + pB];
02571         }
02572       }
02573     }
02574       }
02575     }
02576   }
02577 }
02578 
02579 // Transform one data unit -- this performs the dequantization and
02580 // IDCT steps.  This IDCT algorithm is taken from:
02581 //   Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
02582 //   "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
02583 //   IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
02584 //   988-991.
02585 // The stage numbers mentioned in the comments refer to Figure 1 in this
02586 // paper.
02587 void DCTStream::transformDataUnit(Guchar *quantTable,
02588                   int dataIn[64], Guchar dataOut[64]) {
02589   int v0, v1, v2, v3, v4, v5, v6, v7, t;
02590   int *p;
02591   int i;
02592 
02593   // dequant
02594   for (i = 0; i < 64; ++i) {
02595     dataIn[i] *= quantTable[i];
02596   }
02597 
02598   // inverse DCT on rows
02599   for (i = 0; i < 64; i += 8) {
02600     p = dataIn + i;
02601 
02602     // check for all-zero AC coefficients
02603     if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
02604     p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
02605       t = (dctSqrt2 * p[0] + 512) >> 10;
02606       p[0] = t;
02607       p[1] = t;
02608       p[2] = t;
02609       p[3] = t;
02610       p[4] = t;
02611       p[5] = t;
02612       p[6] = t;
02613       p[7] = t;
02614       continue;
02615     }
02616 
02617     // stage 4
02618     v0 = (dctSqrt2 * p[0] + 128) >> 8;
02619     v1 = (dctSqrt2 * p[4] + 128) >> 8;
02620     v2 = p[2];
02621     v3 = p[6];
02622     v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
02623     v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
02624     v5 = p[3] << 4;
02625     v6 = p[5] << 4;
02626 
02627     // stage 3
02628     t = (v0 - v1+ 1) >> 1;
02629     v0 = (v0 + v1 + 1) >> 1;
02630     v1 = t;
02631     t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
02632     v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
02633     v3 = t;
02634     t = (v4 - v6 + 1) >> 1;
02635     v4 = (v4 + v6 + 1) >> 1;
02636     v6 = t;
02637     t = (v7 + v5 + 1) >> 1;
02638     v5 = (v7 - v5 + 1) >> 1;
02639     v7 = t;
02640 
02641     // stage 2
02642     t = (v0 - v3 + 1) >> 1;
02643     v0 = (v0 + v3 + 1) >> 1;
02644     v3 = t;
02645     t = (v1 - v2 + 1) >> 1;
02646     v1 = (v1 + v2 + 1) >> 1;
02647     v2 = t;
02648     t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
02649     v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
02650     v7 = t;
02651     t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
02652     v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
02653     v6 = t;
02654 
02655     // stage 1
02656     p[0] = v0 + v7;
02657     p[7] = v0 - v7;
02658     p[1] = v1 + v6;
02659     p[6] = v1 - v6;
02660     p[2] = v2 + v5;
02661     p[5] = v2 - v5;
02662     p[3] = v3 + v4;
02663     p[4] = v3 - v4;
02664   }
02665 
02666   // inverse DCT on columns
02667   for (i = 0; i < 8; ++i) {
02668     p = dataIn + i;
02669 
02670     // check for all-zero AC coefficients
02671     if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
02672     p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
02673       t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
02674       p[0*8] = t;
02675       p[1*8] = t;
02676       p[2*8] = t;
02677       p[3*8] = t;
02678       p[4*8] = t;
02679       p[5*8] = t;
02680       p[6*8] = t;
02681       p[7*8] = t;
02682       continue;
02683     }
02684 
02685     // stage 4
02686     v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
02687     v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
02688     v2 = p[2*8];
02689     v3 = p[6*8];
02690     v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
02691     v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
02692     v5 = p[3*8];
02693     v6 = p[5*8];
02694 
02695     // stage 3
02696     t = (v0 - v1 + 1) >> 1;
02697     v0 = (v0 + v1 + 1) >> 1;
02698     v1 = t;
02699     t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
02700     v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
02701     v3 = t;
02702     t = (v4 - v6 + 1) >> 1;
02703     v4 = (v4 + v6 + 1) >> 1;
02704     v6 = t;
02705     t = (v7 + v5 + 1) >> 1;
02706     v5 = (v7 - v5 + 1) >> 1;
02707     v7 = t;
02708 
02709     // stage 2
02710     t = (v0 - v3 + 1) >> 1;
02711     v0 = (v0 + v3 + 1) >> 1;
02712     v3 = t;
02713     t = (v1 - v2 + 1) >> 1;
02714     v1 = (v1 + v2 + 1) >> 1;
02715     v2 = t;
02716     t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
02717     v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
02718     v7 = t;
02719     t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
02720     v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
02721     v6 = t;
02722 
02723     // stage 1
02724     p[0*8] = v0 + v7;
02725     p[7*8] = v0 - v7;
02726     p[1*8] = v1 + v6;
02727     p[6*8] = v1 - v6;
02728     p[2*8] = v2 + v5;
02729     p[5*8] = v2 - v5;
02730     p[3*8] = v3 + v4;
02731     p[4*8] = v3 - v4;
02732   }
02733 
02734   // convert to 8-bit integers
02735   for (i = 0; i < 64; ++i) {
02736     dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
02737   }
02738 }
02739 
02740 int DCTStream::readHuffSym(DCTHuffTable *table) {
02741   Gushort code;
02742   int bit;
02743   int codeBits;
02744 
02745   code = 0;
02746   codeBits = 0;
02747   do {
02748     // add a bit to the code
02749     if ((bit = readBit()) == EOF)
02750       return 9999;
02751     code = (code << 1) + bit;
02752     ++codeBits;
02753 
02754     // look up code
02755     if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
02756       code -= table->firstCode[codeBits];
02757       return table->sym[table->firstSym[codeBits] + code];
02758     }
02759   } while (codeBits < 16);
02760 
02761   error(getPos(), "Bad Huffman code in DCT stream");
02762   return 9999;
02763 }
02764 
02765 int DCTStream::readAmp(int size) {
02766   int amp, bit;
02767   int bits;
02768 
02769   amp = 0;
02770   for (bits = 0; bits < size; ++bits) {
02771     if ((bit = readBit()) == EOF)
02772       return 9999;
02773     amp = (amp << 1) + bit;
02774   }
02775   if (amp < (1 << (size - 1)))
02776     amp -= (1 << size) - 1;
02777   return amp;
02778 }
02779 
02780 int DCTStream::readBit() {
02781   int bit;
02782   int c, c2;
02783 
02784   if (inputBits == 0) {
02785     if ((c = str->getChar()) == EOF)
02786       return EOF;
02787     if (c == 0xff) {
02788       do {
02789     c2 = str->getChar();
02790       } while (c2 == 0xff);
02791       if (c2 != 0x00) {
02792     error(getPos(), "Bad DCT data: missing 00 after ff");
02793     return EOF;
02794       }
02795     }
02796     inputBuf = c;
02797     inputBits = 8;
02798   }
02799   bit = (inputBuf >> (inputBits - 1)) & 1;
02800   --inputBits;
02801   return bit;
02802 }
02803 
02804 GBool DCTStream::readHeader() {
02805   GBool doScan;
02806   int n;
02807   int c = 0;
02808   int i;
02809 
02810   // read headers
02811   doScan = gFalse;
02812   while (!doScan) {
02813     c = readMarker();
02814     switch (c) {
02815     case 0xc0:          // SOF0
02816       if (!readBaselineSOF()) {
02817     return gFalse;
02818       }
02819       break;
02820     case 0xc2:          // SOF2
02821       if (!readProgressiveSOF()) {
02822     return gFalse;
02823       }
02824       break;
02825     case 0xc4:          // DHT
02826       if (!readHuffmanTables()) {
02827     return gFalse;
02828       }
02829       break;
02830     case 0xd8:          // SOI
02831       break;
02832     case 0xd9:          // EOI
02833       return gFalse;
02834       break;
02835     case 0xda:          // SOS
02836       if (!readScanInfo()) {
02837     return gFalse;
02838       }
02839       doScan = gTrue;
02840       break;
02841     case 0xdb:          // DQT
02842       if (!readQuantTables()) {
02843     return gFalse;
02844       }
02845       break;
02846     case 0xdd:          // DRI
02847       if (!readRestartInterval()) {
02848     return gFalse;
02849       }
02850       break;
02851     case 0xee:          // APP14
02852       if (!readAdobeMarker()) {
02853     return gFalse;
02854       }
02855       break;
02856     case EOF:
02857       error(getPos(), "Bad DCT header");
02858       return gFalse;
02859     default:
02860       // skip APPn / COM / etc.
02861       if (c >= 0xe0) {
02862     n = read16() - 2;
02863     for (i = 0; i < n; ++i) {
02864       str->getChar();
02865     }
02866       } else {
02867     error(getPos(), "Unknown DCT marker <%02x>", c);
02868     return gFalse;
02869       }
02870       break;
02871     }
02872   }
02873 
02874   return gTrue;
02875 }
02876 
02877 GBool DCTStream::readBaselineSOF() {
02878   int length;
02879   int prec;
02880   int i;
02881   int c;
02882 
02883   length = read16();
02884   prec = str->getChar();
02885   height = read16();
02886   width = read16();
02887   numComps = str->getChar();
02888   if (numComps <= 0 || numComps > 4) {
02889      numComps = 0;
02890      error(getPos(), "Bad number of components in DCT stream");
02891      return gFalse;
02892   }
02893   if (prec != 8) {
02894     error(getPos(), "Bad DCT precision %d", prec);
02895     return gFalse;
02896   }
02897   for (i = 0; i < numComps; ++i) {
02898     compInfo[i].id = str->getChar();
02899     c = str->getChar();
02900     compInfo[i].hSample = (c >> 4) & 0x0f;
02901     compInfo[i].vSample = c & 0x0f;
02902     compInfo[i].quantTable = str->getChar();
02903   }
02904   progressive = gFalse;
02905   return gTrue;
02906 }
02907 
02908 GBool DCTStream::readProgressiveSOF() {
02909   int length;
02910   int prec;
02911   int i;
02912   int c;
02913 
02914   length = read16();
02915   prec = str->getChar();
02916   height = read16();
02917   width = read16();
02918   numComps = str->getChar();
02919   if (numComps <= 0 || numComps > 4) {
02920      numComps = 0;
02921      error(getPos(), "Bad number of components in DCT stream");
02922      return gFalse;
02923   }
02924   if (prec != 8) {
02925     error(getPos(), "Bad DCT precision %d", prec);
02926     return gFalse;
02927   }
02928   for (i = 0; i < numComps; ++i) {
02929     compInfo[i].id = str->getChar();
02930     c = str->getChar();
02931     compInfo[i].hSample = (c >> 4) & 0x0f;
02932     compInfo[i].vSample = c & 0x0f;
02933     compInfo[i].quantTable = str->getChar();
02934   }
02935   progressive = gTrue;
02936   return gTrue;
02937 }
02938 
02939 GBool DCTStream::readScanInfo() {
02940   int length;
02941   int id, c;
02942   int i, j;
02943 
02944   length = read16() - 2;
02945   scanInfo.numComps = str->getChar();
02946   if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) {
02947      scanInfo.numComps = 0;
02948      error(getPos(), "Bad number of components in DCT stream");
02949      return gFalse;
02950   }
02951   --length;
02952   if (length != 2 * scanInfo.numComps + 3) {
02953     error(getPos(), "Bad DCT scan info block");
02954     return gFalse;
02955   }
02956   interleaved = scanInfo.numComps == numComps;
02957   for (j = 0; j < numComps; ++j) {
02958     scanInfo.comp[j] = gFalse;
02959   }
02960   for (i = 0; i < scanInfo.numComps; ++i) {
02961     id = str->getChar();
02962     for (j = 0; j < numComps; ++j) {
02963       if (id == compInfo[j].id) {
02964     break;
02965       }
02966     }
02967     if (j == numComps) {
02968       error(getPos(), "Bad DCT component ID in scan info block");
02969       return gFalse;
02970     }
02971     scanInfo.comp[j] = gTrue;
02972     c = str->getChar();
02973     scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
02974     scanInfo.acHuffTable[j] = c & 0x0f;
02975   }
02976   scanInfo.firstCoeff = str->getChar();
02977   scanInfo.lastCoeff = str->getChar();
02978   c = str->getChar();
02979   scanInfo.ah = (c >> 4) & 0x0f;
02980   scanInfo.al = c & 0x0f;
02981   return gTrue;
02982 }
02983 
02984 GBool DCTStream::readQuantTables() {
02985   int length;
02986   int i;
02987   int index;
02988 
02989   length = read16() - 2;
02990   while (length > 0) {
02991     index = str->getChar();
02992     if ((index & 0xf0) || index >= 4) {
02993       error(getPos(), "Bad DCT quantization table");
02994       return gFalse;
02995     }
02996     if (index == numQuantTables)
02997       numQuantTables = index + 1;
02998     for (i = 0; i < 64; ++i)
02999       quantTables[index][dctZigZag[i]] = str->getChar();
03000     length -= 65;
03001   }
03002   return gTrue;
03003 }
03004 
03005 GBool DCTStream::readHuffmanTables() {
03006   DCTHuffTable *tbl;
03007   int length;
03008   int index;
03009   Gushort code;
03010   Guchar sym;
03011   int i;
03012   int c;
03013 
03014   length = read16() - 2;
03015   while (length > 0) {
03016     index = str->getChar();
03017     --length;
03018     if ((index & ~0x10) >= 4 || (index & ~0x10) < 0) {
03019       error(getPos(), "Bad DCT Huffman table");
03020       return gFalse;
03021     }
03022     if (index & 0x10) {
03023       index &= 0x03;
03024       if (index >= numACHuffTables)
03025     numACHuffTables = index+1;
03026       tbl = &acHuffTables[index];
03027     } else {
03028       if (index >= numDCHuffTables)
03029     numDCHuffTables = index+1;
03030       tbl = &dcHuffTables[index];
03031     }
03032     sym = 0;
03033     code = 0;
03034     for (i = 1; i <= 16; ++i) {
03035       c = str->getChar();
03036       tbl->firstSym[i] = sym;
03037       tbl->firstCode[i] = code;
03038       tbl->numCodes[i] = c;
03039       sym += c;
03040       code = (code + c) << 1;
03041     }
03042     length -= 16;
03043     for (i = 0; i < sym; ++i)
03044       tbl->sym[i] = str->getChar();
03045     length -= sym;
03046   }
03047   return gTrue;
03048 }
03049 
03050 GBool DCTStream::readRestartInterval() {
03051   int length;
03052 
03053   length = read16();
03054   if (length != 4) {
03055     error(getPos(), "Bad DCT restart interval");
03056     return gFalse;
03057   }
03058   restartInterval = read16();
03059   return gTrue;
03060 }
03061 
03062 GBool DCTStream::readAdobeMarker() {
03063   int length, i;
03064   char buf[12];
03065   int c;
03066 
03067   length = read16();
03068   if (length < 14) {
03069     goto err;
03070   }
03071   for (i = 0; i < 12; ++i) {
03072     if ((c = str->getChar()) == EOF) {
03073       goto err;
03074     }
03075     buf[i] = c;
03076   }
03077   if (strncmp(buf, "Adobe", 5)) {
03078     goto err;
03079   }
03080   colorXform = buf[11];
03081   gotAdobeMarker = gTrue;
03082   for (i = 14; i < length; ++i) {
03083     if (str->getChar() == EOF) {
03084       goto err;
03085     }
03086   }
03087   return gTrue;
03088 
03089  err:
03090   error(getPos(), "Bad DCT Adobe APP14 marker");
03091   return gFalse;
03092 }
03093 
03094 GBool DCTStream::readTrailer() {
03095   int c;
03096 
03097   c = readMarker();
03098   if (c != 0xd9) {      // EOI
03099     error(getPos(), "Bad DCT trailer");
03100     return gFalse;
03101   }
03102   return gTrue;
03103 }
03104 
03105 int DCTStream::readMarker() {
03106   int c;
03107 
03108   do {
03109     do {
03110       c = str->getChar();
03111       if(c == EOF) return EOF;
03112     } while (c != 0xff);
03113     do {
03114       c = str->getChar();
03115       if(c == EOF) return EOF;
03116     } while (c == 0xff);
03117   } while (c == 0x00);
03118   return c;
03119 }
03120 
03121 int DCTStream::read16() {
03122   int c1, c2;
03123 
03124   if ((c1 = str->getChar()) == EOF)
03125     return EOF;
03126   if ((c2 = str->getChar()) == EOF)
03127     return EOF;
03128   return (c1 << 8) + c2;
03129 }
03130 
03131 GString *DCTStream::getPSFilter(const char *indent) {
03132   GString *s;
03133 
03134   if (!(s = str->getPSFilter(indent))) {
03135     return NULL;
03136   }
03137   s->append(indent)->append("<< >> /DCTDecode filter\n");
03138   return s;
03139 }
03140 
03141 GBool DCTStream::isBinary(GBool /*last*/) {
03142   return str->isBinary(gTrue);
03143 }
03144 
03145 //------------------------------------------------------------------------
03146 // FlateStream
03147 //------------------------------------------------------------------------
03148 
03149 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
03150   16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
03151 };
03152 
03153 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
03154   {0,   3},
03155   {0,   4},
03156   {0,   5},
03157   {0,   6},
03158   {0,   7},
03159   {0,   8},
03160   {0,   9},
03161   {0,  10},
03162   {1,  11},
03163   {1,  13},
03164   {1,  15},
03165   {1,  17},
03166   {2,  19},
03167   {2,  23},
03168   {2,  27},
03169   {2,  31},
03170   {3,  35},
03171   {3,  43},
03172   {3,  51},
03173   {3,  59},
03174   {4,  67},
03175   {4,  83},
03176   {4,  99},
03177   {4, 115},
03178   {5, 131},
03179   {5, 163},
03180   {5, 195},
03181   {5, 227},
03182   {0, 258}
03183 };
03184 
03185 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
03186   { 0,     1},
03187   { 0,     2},
03188   { 0,     3},
03189   { 0,     4},
03190   { 1,     5},
03191   { 1,     7},
03192   { 2,     9},
03193   { 2,    13},
03194   { 3,    17},
03195   { 3,    25},
03196   { 4,    33},
03197   { 4,    49},
03198   { 5,    65},
03199   { 5,    97},
03200   { 6,   129},
03201   { 6,   193},
03202   { 7,   257},
03203   { 7,   385},
03204   { 8,   513},
03205   { 8,   769},
03206   { 9,  1025},
03207   { 9,  1537},
03208   {10,  2049},
03209   {10,  3073},
03210   {11,  4097},
03211   {11,  6145},
03212   {12,  8193},
03213   {12, 12289},
03214   {13, 16385},
03215   {13, 24577}
03216 };
03217 
03218 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
03219              int colors, int bits):
03220     FilterStream(strA) {
03221   if (predictor != 1) {
03222     pred = new StreamPredictor(this, predictor, columns, colors, bits);
03223     if ( !pred->isOk()) {
03224         delete pred;
03225         pred = NULL;
03226     }
03227   } else {
03228     pred = NULL;
03229   }
03230   litCodeTab.codes = NULL;
03231   distCodeTab.codes = NULL;
03232 }
03233 
03234 FlateStream::~FlateStream() {
03235   gfree(litCodeTab.codes);
03236   gfree(distCodeTab.codes);
03237   if (pred) {
03238     delete pred;
03239   }
03240   delete str;
03241 }
03242 
03243 void FlateStream::reset() {
03244   int cmf, flg;
03245 
03246   index = 0;
03247   remain = 0;
03248   codeBuf = 0;
03249   codeSize = 0;
03250   compressedBlock = gFalse;
03251   endOfBlock = gTrue;
03252   eof = gTrue;
03253 
03254   str->reset();
03255 
03256   // read header
03257   //~ need to look at window size?
03258   endOfBlock = eof = gTrue;
03259   cmf = str->getChar();
03260   flg = str->getChar();
03261   if (cmf == EOF || flg == EOF)
03262     return;
03263   if ((cmf & 0x0f) != 0x08) {
03264     error(getPos(), "Unknown compression method in flate stream");
03265     return;
03266   }
03267   if ((((cmf << 8) + flg) % 31) != 0) {
03268     error(getPos(), "Bad FCHECK in flate stream");
03269     return;
03270   }
03271   if (flg & 0x20) {
03272     error(getPos(), "FDICT bit set in flate stream");
03273     return;
03274   }
03275 
03276   eof = gFalse;
03277 }
03278 
03279 int FlateStream::getChar() {
03280   int c;
03281 
03282   if (pred) {
03283     return pred->getChar();
03284   }
03285   while (remain == 0) {
03286     if (endOfBlock && eof)
03287       return EOF;
03288     readSome();
03289   }
03290   c = buf[index];
03291   index = (index + 1) & flateMask;
03292   --remain;
03293   return c;
03294 }
03295 
03296 int FlateStream::lookChar() {
03297   int c;
03298 
03299   if (pred) {
03300     return pred->lookChar();
03301   }
03302   while (remain == 0) {
03303     if (endOfBlock && eof)
03304       return EOF;
03305     readSome();
03306   }
03307   c = buf[index];
03308   return c;
03309 }
03310 
03311 int FlateStream::getRawChar() {
03312   int c;
03313 
03314   while (remain == 0) {
03315     if (endOfBlock && eof)
03316       return EOF;
03317     readSome();
03318   }
03319   c = buf[index];
03320   index = (index + 1) & flateMask;
03321   --remain;
03322   return c;
03323 }
03324 
03325 GString *FlateStream::getPSFilter(const char */*indent*/) {
03326   return NULL;
03327 }
03328 
03329 GBool FlateStream::isBinary(GBool /*last*/) {
03330   return str->isBinary(gTrue);
03331 }
03332 
03333 void FlateStream::readSome() {
03334   int code1, code2;
03335   int len, dist;
03336   int i, j, k;
03337   int c;
03338 
03339   if (endOfBlock) {
03340     if (!startBlock())
03341       return;
03342   }
03343 
03344   if (compressedBlock) {
03345     if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
03346       goto err;
03347     if (code1 < 256) {
03348       buf[index] = code1;
03349       remain = 1;
03350     } else if (code1 == 256) {
03351       endOfBlock = gTrue;
03352       remain = 0;
03353     } else {
03354       code1 -= 257;
03355       code2 = lengthDecode[code1].bits;
03356       if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
03357     goto err;
03358       len = lengthDecode[code1].first + code2;
03359       if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
03360     goto err;
03361       code2 = distDecode[code1].bits;
03362       if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
03363     goto err;
03364       dist = distDecode[code1].first + code2;
03365       i = index;
03366       j = (index - dist) & flateMask;
03367       for (k = 0; k < len; ++k) {
03368     buf[i] = buf[j];
03369     i = (i + 1) & flateMask;
03370     j = (j + 1) & flateMask;
03371       }
03372       remain = len;
03373     }
03374 
03375   } else {
03376     len = (blockLen < flateWindow) ? blockLen : flateWindow;
03377     for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
03378       if ((c = str->getChar()) == EOF) {
03379     endOfBlock = eof = gTrue;
03380     break;
03381       }
03382       buf[j] = c & 0xff;
03383     }
03384     remain = i;
03385     blockLen -= len;
03386     if (blockLen == 0)
03387       endOfBlock = gTrue;
03388   }
03389 
03390   return;
03391 
03392 err:
03393   error(getPos(), "Unexpected end of file in flate stream");
03394   endOfBlock = eof = gTrue;
03395   remain = 0;
03396 }
03397 
03398 GBool FlateStream::startBlock() {
03399   int blockHdr;
03400   int c;
03401   int check;
03402 
03403   // free the code tables from the previous block
03404   gfree(litCodeTab.codes);
03405   litCodeTab.codes = NULL;
03406   gfree(distCodeTab.codes);
03407   distCodeTab.codes = NULL;
03408 
03409   // read block header
03410   blockHdr = getCodeWord(3);
03411   if (blockHdr & 1)
03412     eof = gTrue;
03413   blockHdr >>= 1;
03414 
03415   // uncompressed block
03416   if (blockHdr == 0) {
03417     compressedBlock = gFalse;
03418     if ((c = str->getChar()) == EOF)
03419       goto err;
03420     blockLen = c & 0xff;
03421     if ((c = str->getChar()) == EOF)
03422       goto err;
03423     blockLen |= (c & 0xff) << 8;
03424     if ((c = str->getChar()) == EOF)
03425       goto err;
03426     check = c & 0xff;
03427     if ((c = str->getChar()) == EOF)
03428       goto err;
03429     check |= (c & 0xff) << 8;
03430     if (check != (~blockLen & 0xffff))
03431       error(getPos(), "Bad uncompressed block length in flate stream");
03432     codeBuf = 0;
03433     codeSize = 0;
03434 
03435   // compressed block with fixed codes
03436   } else if (blockHdr == 1) {
03437     compressedBlock = gTrue;
03438     loadFixedCodes();
03439 
03440   // compressed block with dynamic codes
03441   } else if (blockHdr == 2) {
03442     compressedBlock = gTrue;
03443     if (!readDynamicCodes()) {
03444       goto err;
03445     }
03446 
03447   // unknown block type
03448   } else {
03449     goto err;
03450   }
03451 
03452   endOfBlock = gFalse;
03453   return gTrue;
03454 
03455 err:
03456   error(getPos(), "Bad block header in flate stream");
03457   endOfBlock = eof = gTrue;
03458   return gFalse;
03459 }
03460 
03461 void FlateStream::loadFixedCodes() {
03462   int i;
03463 
03464   // build the literal code table
03465   for (i = 0; i <= 143; ++i) {
03466     codeLengths[i] = 8;
03467   }
03468   for (i = 144; i <= 255; ++i) {
03469     codeLengths[i] = 9;
03470   }
03471   for (i = 256; i <= 279; ++i) {
03472     codeLengths[i] = 7;
03473   }
03474   for (i = 280; i <= 287; ++i) {
03475     codeLengths[i] = 8;
03476   }
03477   compHuffmanCodes(codeLengths, flateMaxLitCodes, &litCodeTab);
03478 
03479   // build the distance code table
03480   for (i = 0; i < flateMaxDistCodes; ++i) {
03481     codeLengths[i] = 5;
03482   }
03483   compHuffmanCodes(codeLengths, flateMaxDistCodes, &distCodeTab);
03484 }
03485 
03486 GBool FlateStream::readDynamicCodes() {
03487   int numCodeLenCodes;
03488   int numLitCodes;
03489   int numDistCodes;
03490   int codeLenCodeLengths[flateMaxCodeLenCodes];
03491   FlateHuffmanTab codeLenCodeTab;
03492   int len, repeat, code;
03493   int i;
03494 
03495   // read lengths
03496   if ((numLitCodes = getCodeWord(5)) == EOF) {
03497     goto err;
03498   }
03499   numLitCodes += 257;
03500   if ((numDistCodes = getCodeWord(5)) == EOF) {
03501     goto err;
03502   }
03503   numDistCodes += 1;
03504   if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
03505     goto err;
03506   }
03507   numCodeLenCodes += 4;
03508   if (numLitCodes > flateMaxLitCodes ||
03509       numDistCodes > flateMaxDistCodes ||
03510       numCodeLenCodes > flateMaxCodeLenCodes) {
03511     goto err;
03512   }
03513 
03514   // build the code length code table
03515   for (i = 0; i < flateMaxCodeLenCodes; ++i) {
03516     codeLenCodeLengths[i] = 0;
03517   }
03518   for (i = 0; i < numCodeLenCodes; ++i) {
03519     if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
03520       goto err;
03521     }
03522   }
03523   compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
03524 
03525   // build the literal and distance code tables
03526   len = 0;
03527   repeat = 0;
03528   i = 0;
03529   while (i < numLitCodes + numDistCodes) {
03530     if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
03531       goto err;
03532     }
03533     if (code == 16) {
03534       if ((repeat = getCodeWord(2)) == EOF) {
03535     goto err;
03536       }
03537       for (repeat += 3; repeat > 0; --repeat) {
03538     codeLengths[i++] = len;
03539       }
03540     } else if (code == 17) {
03541       if ((repeat = getCodeWord(3)) == EOF) {
03542     goto err;
03543       }
03544       len = 0;
03545       for (repeat += 3; repeat > 0; --repeat) {
03546     codeLengths[i++] = 0;
03547       }
03548     } else if (code == 18) {
03549       if ((repeat = getCodeWord(7)) == EOF) {
03550     goto err;
03551       }
03552       len = 0;
03553       for (repeat += 11; repeat > 0; --repeat) {
03554     codeLengths[i++] = 0;
03555       }
03556     } else {
03557       codeLengths[i++] = len = code;
03558     }
03559   }
03560   compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
03561   compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
03562 
03563   gfree(codeLenCodeTab.codes);
03564   return gTrue;
03565 
03566 err:
03567   error(getPos(), "Bad dynamic code table in flate stream");
03568   gfree(codeLenCodeTab.codes);
03569   return gFalse;
03570 }
03571 
03572 // Convert an array <lengths> of <n> lengths, in value order, into a
03573 // Huffman code lookup table.
03574 void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
03575   int tabSize, len, code, code2, skip, val, i, t;
03576 
03577   // find max code length
03578   tab->maxLen = 0;
03579   for (val = 0; val < n; ++val) {
03580     if (lengths[val] > tab->maxLen) {
03581       tab->maxLen = lengths[val];
03582     }
03583   }
03584 
03585   // allocate the table
03586   tabSize = 1 << tab->maxLen;
03587   tab->codes = (FlateCode *)gmalloc(tabSize * sizeof(FlateCode));
03588 
03589   // clear the table
03590   for (i = 0; i < tabSize; ++i) {
03591     tab->codes[i].len = 0;
03592     tab->codes[i].val = 0;
03593   }
03594 
03595   // build the table
03596   for (len = 1, code = 0, skip = 2;
03597        len <= tab->maxLen;
03598        ++len, code <<= 1, skip <<= 1) {
03599     for (val = 0; val < n; ++val) {
03600       if (lengths[val] == len) {
03601 
03602     // bit-reverse the code
03603     code2 = 0;
03604     t = code;
03605     for (i = 0; i < len; ++i) {
03606       code2 = (code2 << 1) | (t & 1);
03607       t >>= 1;
03608     }
03609 
03610     // fill in the table entries
03611     for (i = code2; i < tabSize; i += skip) {
03612       tab->codes[i].len = (Gushort)len;
03613       tab->codes[i].val = (Gushort)val;
03614     }
03615 
03616     ++code;
03617       }
03618     }
03619   }
03620 }
03621 
03622 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
03623   FlateCode *code;
03624   int c;
03625 
03626   while (codeSize < tab->maxLen) {
03627     if ((c = str->getChar()) == EOF) {
03628       break;
03629     }
03630     codeBuf |= (c & 0xff) << codeSize;
03631     codeSize += 8;
03632   }
03633   code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
03634   if (codeSize == 0 || codeSize < code->len || code->len == 0) {
03635     return EOF;
03636   }
03637   codeBuf >>= code->len;
03638   codeSize -= code->len;
03639   return (int)code->val;
03640 }
03641 
03642 int FlateStream::getCodeWord(int bits) {
03643   int c;
03644 
03645   while (codeSize < bits) {
03646     if ((c = str->getChar()) == EOF)
03647       return EOF;
03648     codeBuf |= (c & 0xff) << codeSize;
03649     codeSize += 8;
03650   }
03651   c = codeBuf & ((1 << bits) - 1);
03652   codeBuf >>= bits;
03653   codeSize -= bits;
03654   return c;
03655 }
03656 
03657 //------------------------------------------------------------------------
03658 // EOFStream
03659 //------------------------------------------------------------------------
03660 
03661 EOFStream::EOFStream(Stream *strA):
03662     FilterStream(strA) {
03663 }
03664 
03665 EOFStream::~EOFStream() {
03666   delete str;
03667 }
03668 
03669 //------------------------------------------------------------------------
03670 // FixedLengthEncoder
03671 //------------------------------------------------------------------------
03672 
03673 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
03674     FilterStream(strA) {
03675   length = lengthA;
03676   count = 0;
03677 }
03678 
03679 FixedLengthEncoder::~FixedLengthEncoder() {
03680   if (str->isEncoder())
03681     delete str;
03682 }
03683 
03684 void FixedLengthEncoder::reset() {
03685   str->reset();
03686   count = 0;
03687 }
03688 
03689 void FixedLengthEncoder::close() {
03690 }
03691 
03692 int FixedLengthEncoder::getChar() {
03693   if (length >= 0 && count >= length)
03694     return EOF;
03695   ++count;
03696   return str->getChar();
03697 }
03698 
03699 int FixedLengthEncoder::lookChar() {
03700   if (length >= 0 && count >= length)
03701     return EOF;
03702   return str->getChar();
03703 }
03704 
03705 //------------------------------------------------------------------------
03706 // ASCIIHexEncoder
03707 //------------------------------------------------------------------------
03708 
03709 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
03710     FilterStream(strA) {
03711   bufPtr = bufEnd = buf;
03712   lineLen = 0;
03713   eof = gFalse;
03714 }
03715 
03716 ASCIIHexEncoder::~ASCIIHexEncoder() {
03717   if (str->isEncoder()) {
03718     delete str;
03719   }
03720 }
03721 
03722 void ASCIIHexEncoder::reset() {
03723   str->reset();
03724   bufPtr = bufEnd = buf;
03725   lineLen = 0;
03726   eof = gFalse;
03727 }
03728 
03729 void ASCIIHexEncoder::close() {
03730 }
03731 
03732 GBool ASCIIHexEncoder::fillBuf() {
03733   static const char *hex = "0123456789abcdef";
03734   int c;
03735 
03736   if (eof) {
03737     return gFalse;
03738   }
03739   bufPtr = bufEnd = buf;
03740   if ((c = str->getChar()) == EOF) {
03741     *bufEnd++ = '>';
03742     eof = gTrue;
03743   } else {
03744     if (lineLen >= 64) {
03745       *bufEnd++ = '\n';
03746       lineLen = 0;
03747     }
03748     *bufEnd++ = hex[(c >> 4) & 0x0f];
03749     *bufEnd++ = hex[c & 0x0f];
03750     lineLen += 2;
03751   }
03752   return gTrue;
03753 }
03754 
03755 //------------------------------------------------------------------------
03756 // ASCII85Encoder
03757 //------------------------------------------------------------------------
03758 
03759 ASCII85Encoder::ASCII85Encoder(Stream *strA):
03760     FilterStream(strA) {
03761   bufPtr = bufEnd = buf;
03762   lineLen = 0;
03763   eof = gFalse;
03764 }
03765 
03766 ASCII85Encoder::~ASCII85Encoder() {
03767   if (str->isEncoder())
03768     delete str;
03769 }
03770 
03771 void ASCII85Encoder::reset() {
03772   str->reset();
03773   bufPtr = bufEnd = buf;
03774   lineLen = 0;
03775   eof = gFalse;
03776 }
03777 
03778 void ASCII85Encoder::close() {
03779 }
03780 
03781 GBool ASCII85Encoder::fillBuf() {
03782   Gulong t;
03783   char buf1[5];
03784   int c;
03785   int n, i;
03786 
03787   if (eof)
03788     return gFalse;
03789   t = 0;
03790   for (n = 0; n < 4; ++n) {
03791     if ((c = str->getChar()) == EOF)
03792       break;
03793     t = (t << 8) + c;
03794   }
03795   bufPtr = bufEnd = buf;
03796   if (n > 0) {
03797     if (n == 4 && t == 0) {
03798       *bufEnd++ = 'z';
03799       if (++lineLen == 65) {
03800     *bufEnd++ = '\n';
03801     lineLen = 0;
03802       }
03803     } else {
03804       if (n < 4)
03805     t <<= 8 * (4 - n);
03806       for (i = 4; i >= 0; --i) {
03807     buf1[i] = (char)(t % 85 + 0x21);
03808     t /= 85;
03809       }
03810       for (i = 0; i <= n; ++i) {
03811     *bufEnd++ = buf1[i];
03812     if (++lineLen == 65) {
03813       *bufEnd++ = '\n';
03814       lineLen = 0;
03815     }
03816       }
03817     }
03818   }
03819   if (n < 4) {
03820     *bufEnd++ = '~';
03821     *bufEnd++ = '>';
03822     eof = gTrue;
03823   }
03824   return bufPtr < bufEnd;
03825 }
03826 
03827 //------------------------------------------------------------------------
03828 // RunLengthEncoder
03829 //------------------------------------------------------------------------
03830 
03831 RunLengthEncoder::RunLengthEncoder(Stream *strA):
03832     FilterStream(strA) {
03833   bufPtr = bufEnd = nextEnd = buf;
03834   eof = gFalse;
03835 }
03836 
03837 RunLengthEncoder::~RunLengthEncoder() {
03838   if (str->isEncoder())
03839     delete str;
03840 }
03841 
03842 void RunLengthEncoder::reset() {
03843   str->reset();
03844   bufPtr = bufEnd = nextEnd = buf;
03845   eof = gFalse;
03846 }
03847 
03848 void RunLengthEncoder::close() {
03849 }
03850 
03851 //
03852 // When fillBuf finishes, buf[] looks like this:
03853 //   +-----+--------------+-----------------+--
03854 //   + tag | ... data ... | next 0, 1, or 2 |
03855 //   +-----+--------------+-----------------+--
03856 //    ^                    ^                 ^
03857 //    bufPtr               bufEnd            nextEnd
03858 //
03859 GBool RunLengthEncoder::fillBuf() {
03860   int c, c1, c2;
03861   int n;
03862 
03863   // already hit EOF?
03864   if (eof)
03865     return gFalse;
03866 
03867   // grab two bytes
03868   if (nextEnd < bufEnd + 1) {
03869     if ((c1 = str->getChar()) == EOF) {
03870       eof = gTrue;
03871       return gFalse;
03872     }
03873   } else {
03874     c1 = bufEnd[0] & 0xff;
03875   }
03876   if (nextEnd < bufEnd + 2) {
03877     if ((c2 = str->getChar()) == EOF) {
03878       eof = gTrue;
03879       buf[0] = 0;
03880       buf[1] = c1;
03881       bufPtr = buf;
03882       bufEnd = &buf[2];
03883       return gTrue;
03884     }
03885   } else {
03886     c2 = bufEnd[1] & 0xff;
03887   }
03888 
03889   // check for repeat
03890   c = 0; // make gcc happy
03891   if (c1 == c2) {
03892     n = 2;
03893     while (n < 128 && (c = str->getChar()) == c1)
03894       ++n;
03895     buf[0] = (char)(257 - n);
03896     buf[1] = c1;
03897     bufEnd = &buf[2];
03898     if (c == EOF) {
03899       eof = gTrue;
03900     } else if (n < 128) {
03901       buf[2] = c;
03902       nextEnd = &buf[3];
03903     } else {
03904       nextEnd = bufEnd;
03905     }
03906 
03907   // get up to 128 chars
03908   } else {
03909     buf[1] = c1;
03910     buf[2] = c2;
03911     n = 2;
03912     while (n < 128) {
03913       if ((c = str->getChar()) == EOF) {
03914     eof = gTrue;
03915     break;
03916       }
03917       ++n;
03918       buf[n] = c;
03919       if (buf[n] == buf[n-1])
03920     break;
03921     }
03922     if (buf[n] == buf[n-1]) {
03923       buf[0] = (char)(n-2-1);
03924       bufEnd = &buf[n-1];
03925       nextEnd = &buf[n+1];
03926     } else {
03927       buf[0] = (char)(n-1);
03928       bufEnd = nextEnd = &buf[n+1];
03929     }
03930   }
03931   bufPtr = buf;
03932   return gTrue;
03933 }
KDE Home | KDE Accessibility Home | Description of Access Keys