filters

Stream.cc

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