Back to index

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