📄 stream.cc
字号:
//========================================================================//// Stream.cc//// Copyright 1996-2003 Glyph & Cog, LLC////========================================================================#include <aconf.h>#ifdef USE_GCC_PRAGMAS#pragma implementation#endif#include <stdio.h>#include <stdlib.h>#include <stddef.h>#include <limits.h>#ifndef WIN32#include <unistd.h>#endif#include <string.h>#include <ctype.h>#include "gmem.h"#include "gfile.h"#include "config.h"#include "Error.h"#include "Object.h"#include "Lexer.h"#include "GfxState.h"#include "Stream.h"#include "JBIG2Stream.h"#include "JPXStream.h"#include "Stream-CCITT.h"#ifdef __DJGPP__static GBool setDJSYSFLAGS = gFalse;#endif#ifdef VMS#ifdef __GNUC__#define SEEK_SET 0#define SEEK_CUR 1#define SEEK_END 2#endif#endif//------------------------------------------------------------------------// Stream (base class)//------------------------------------------------------------------------Stream::Stream() { ref = 1;}Stream::~Stream() {}void Stream::close() {}int Stream::getRawChar() { error(-1, "Internal: called getRawChar() on non-predictor stream"); return EOF;}char *Stream::getLine(char *buf, int size) { int i; int c; if (lookChar() == EOF) return NULL; for (i = 0; i < size - 1; ++i) { c = getChar(); if (c == EOF || c == '\n') break; if (c == '\r') { if ((c = lookChar()) == '\n') getChar(); break; } buf[i] = c; } buf[i] = '\0'; return buf;}GString *Stream::getPSFilter(int psLevel, char *indent) { return new GString();}Stream *Stream::addFilters(Object *dict) { Object obj, obj2; Object params, params2; Stream *str; int i; str = this; dict->dictLookup("Filter", &obj); if (obj.isNull()) { obj.free(); dict->dictLookup("F", &obj); } dict->dictLookup("DecodeParms", ¶ms); if (params.isNull()) { params.free(); dict->dictLookup("DP", ¶ms); } if (obj.isName()) { str = makeFilter(obj.getName(), str, ¶ms); } else if (obj.isArray()) { for (i = 0; i < obj.arrayGetLength(); ++i) { obj.arrayGet(i, &obj2); if (params.isArray()) params.arrayGet(i, ¶ms2); else params2.initNull(); if (obj2.isName()) { str = makeFilter(obj2.getName(), str, ¶ms2); } else { error(getPos(), "Bad filter name"); str = new EOFStream(str); } obj2.free(); params2.free(); } } else if (!obj.isNull()) { error(getPos(), "Bad 'Filter' attribute in stream"); } obj.free(); params.free(); return str;}Stream *Stream::makeFilter(char *name, Stream *str, Object *params) { int pred; // parameters int colors; int bits; int early; int encoding; GBool endOfLine, byteAlign, endOfBlock, black; int columns, rows; int colorXform; Object globals, obj; if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) { str = new ASCIIHexStream(str); } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) { str = new ASCII85Stream(str); } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) { pred = 1; columns = 1; colors = 1; bits = 8; early = 1; if (params->isDict()) { params->dictLookup("Predictor", &obj); if (obj.isInt()) pred = obj.getInt(); obj.free(); params->dictLookup("Columns", &obj); if (obj.isInt()) columns = obj.getInt(); obj.free(); params->dictLookup("Colors", &obj); if (obj.isInt()) colors = obj.getInt(); obj.free(); params->dictLookup("BitsPerComponent", &obj); if (obj.isInt()) bits = obj.getInt(); obj.free(); params->dictLookup("EarlyChange", &obj); if (obj.isInt()) early = obj.getInt(); obj.free(); } str = new LZWStream(str, pred, columns, colors, bits, early); } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) { str = new RunLengthStream(str); } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) { encoding = 0; endOfLine = gFalse; byteAlign = gFalse; columns = 1728; rows = 0; endOfBlock = gTrue; black = gFalse; if (params->isDict()) { params->dictLookup("K", &obj); if (obj.isInt()) { encoding = obj.getInt(); } obj.free(); params->dictLookup("EndOfLine", &obj); if (obj.isBool()) { endOfLine = obj.getBool(); } obj.free(); params->dictLookup("EncodedByteAlign", &obj); if (obj.isBool()) { byteAlign = obj.getBool(); } obj.free(); params->dictLookup("Columns", &obj); if (obj.isInt()) { columns = obj.getInt(); } obj.free(); params->dictLookup("Rows", &obj); if (obj.isInt()) { rows = obj.getInt(); } obj.free(); params->dictLookup("EndOfBlock", &obj); if (obj.isBool()) { endOfBlock = obj.getBool(); } obj.free(); params->dictLookup("BlackIs1", &obj); if (obj.isBool()) { black = obj.getBool(); } obj.free(); } str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign, columns, rows, endOfBlock, black); } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) { colorXform = -1; if (params->isDict()) { if (params->dictLookup("ColorTransform", &obj)->isInt()) { colorXform = obj.getInt(); } obj.free(); } str = new DCTStream(str, colorXform); } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) { pred = 1; columns = 1; colors = 1; bits = 8; if (params->isDict()) { params->dictLookup("Predictor", &obj); if (obj.isInt()) pred = obj.getInt(); obj.free(); params->dictLookup("Columns", &obj); if (obj.isInt()) columns = obj.getInt(); obj.free(); params->dictLookup("Colors", &obj); if (obj.isInt()) colors = obj.getInt(); obj.free(); params->dictLookup("BitsPerComponent", &obj); if (obj.isInt()) bits = obj.getInt(); obj.free(); } str = new FlateStream(str, pred, columns, colors, bits); } else if (!strcmp(name, "JBIG2Decode")) { if (params->isDict()) { params->dictLookup("JBIG2Globals", &globals); } str = new JBIG2Stream(str, &globals); globals.free(); } else if (!strcmp(name, "JPXDecode")) { str = new JPXStream(str); } else { error(getPos(), "Unknown filter '%s'", name); str = new EOFStream(str); } return str;}//------------------------------------------------------------------------// BaseStream//------------------------------------------------------------------------BaseStream::BaseStream(Object *dictA) { dict = *dictA;}BaseStream::~BaseStream() { dict.free();}//------------------------------------------------------------------------// FilterStream//------------------------------------------------------------------------FilterStream::FilterStream(Stream *strA) { str = strA;}FilterStream::~FilterStream() {}void FilterStream::close() { str->close();}void FilterStream::setPos(Guint pos, int dir) { error(-1, "Internal: called setPos() on FilterStream");}//------------------------------------------------------------------------// ImageStream//------------------------------------------------------------------------ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) { int imgLineSize; str = strA; width = widthA; nComps = nCompsA; nBits = nBitsA; nVals = width * nComps; if (nBits == 1) { imgLineSize = (nVals + 7) & ~7; } else { imgLineSize = nVals; } imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar)); imgIdx = nVals;}ImageStream::~ImageStream() { gfree(imgLine);}void ImageStream::reset() { str->reset();}GBool ImageStream::getPixel(Guchar *pix) { int i; if (imgIdx >= nVals) { getLine(); imgIdx = 0; } for (i = 0; i < nComps; ++i) { pix[i] = imgLine[imgIdx++]; } return gTrue;}Guchar *ImageStream::getLine() { Gulong buf, bitMask; int bits; int c; int i; if (nBits == 1) { for (i = 0; i < nVals; i += 8) { c = str->getChar(); imgLine[i+0] = (Guchar)((c >> 7) & 1); imgLine[i+1] = (Guchar)((c >> 6) & 1); imgLine[i+2] = (Guchar)((c >> 5) & 1); imgLine[i+3] = (Guchar)((c >> 4) & 1); imgLine[i+4] = (Guchar)((c >> 3) & 1); imgLine[i+5] = (Guchar)((c >> 2) & 1); imgLine[i+6] = (Guchar)((c >> 1) & 1); imgLine[i+7] = (Guchar)(c & 1); } } else if (nBits == 8) { for (i = 0; i < nVals; ++i) { imgLine[i] = str->getChar(); } } else { bitMask = (1 << nBits) - 1; buf = 0; bits = 0; for (i = 0; i < nVals; ++i) { if (bits < nBits) { buf = (buf << 8) | (str->getChar() & 0xff); bits += 8; } imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask); bits -= nBits; } } return imgLine;}void ImageStream::skipLine() { int n, i; n = (nVals * nBits + 7) >> 3; for (i = 0; i < n; ++i) { str->getChar(); }}//------------------------------------------------------------------------// StreamPredictor//------------------------------------------------------------------------StreamPredictor::StreamPredictor(Stream *strA, int predictorA, int widthA, int nCompsA, int nBitsA) { str = strA; predictor = predictorA; width = widthA; nComps = nCompsA; nBits = nBitsA; predLine = NULL; ok = gFalse; nVals = width * nComps; if (width <= 0 || nComps <= 0 || nBits <= 0 || nComps >= INT_MAX / nBits || width >= INT_MAX / nComps / nBits || nVals * nBits + 7 < 0) { return; } pixBytes = (nComps * nBits + 7) >> 3; rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes; if (rowBytes <= 0) { return; } predLine = (Guchar *)gmalloc(rowBytes); memset(predLine, 0, rowBytes); predIdx = rowBytes; ok = gTrue;}StreamPredictor::~StreamPredictor() { gfree(predLine);}int StreamPredictor::lookChar() { if (predIdx >= rowBytes) { if (!getNextLine()) { return EOF; } } return predLine[predIdx];}int StreamPredictor::getChar() { if (predIdx >= rowBytes) { if (!getNextLine()) { return EOF; } } return predLine[predIdx++];}GBool StreamPredictor::getNextLine() { int curPred; Guchar upLeftBuf[gfxColorMaxComps * 2 + 1]; int left, up, upLeft, p, pa, pb, pc; int c; Gulong inBuf, outBuf, bitMask; int inBits, outBits; int i, j, k, kk; // get PNG optimum predictor number if (predictor >= 10) { if ((curPred = str->getRawChar()) == EOF) { return gFalse; } curPred += 10; } else { curPred = predictor; } // read the raw line, apply PNG (byte) predictor memset(upLeftBuf, 0, pixBytes + 1); for (i = pixBytes; i < rowBytes; ++i) { for (j = pixBytes; j > 0; --j) { upLeftBuf[j] = upLeftBuf[j-1]; } upLeftBuf[0] = predLine[i]; if ((c = str->getRawChar()) == EOF) { if (i > pixBytes) { // this ought to return false, but some (broken) PDF files // contain truncated image data, and Adobe apparently reads the // last partial line break; } return gFalse; } switch (curPred) { case 11: // PNG sub predLine[i] = predLine[i - pixBytes] + (Guchar)c; break; case 12: // PNG up predLine[i] = predLine[i] + (Guchar)c; break; case 13: // PNG average predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) + (Guchar)c; break; case 14: // PNG Paeth left = predLine[i - pixBytes]; up = predLine[i]; upLeft = upLeftBuf[pixBytes]; p = left + up - upLeft; if ((pa = p - left) < 0) pa = -pa; if ((pb = p - up) < 0) pb = -pb; if ((pc = p - upLeft) < 0) pc = -pc; if (pa <= pb && pa <= pc) predLine[i] = left + (Guchar)c; else if (pb <= pc) predLine[i] = up + (Guchar)c; else predLine[i] = upLeft + (Guchar)c; break; case 10: // PNG none default: // no predictor or TIFF predictor predLine[i] = (Guchar)c; break; } } // apply TIFF (component) predictor if (predictor == 2) { if (nBits == 1) { inBuf = predLine[pixBytes - 1]; for (i = pixBytes; i < rowBytes; i += 8) { // 1-bit add is just xor inBuf = (inBuf << 8) | predLine[i]; predLine[i] ^= inBuf >> nComps; } } else if (nBits == 8) { for (i = pixBytes; i < rowBytes; ++i) { predLine[i] += predLine[i - nComps]; } } else { memset(upLeftBuf, 0, nComps + 1); bitMask = (1 << nBits) - 1; inBuf = outBuf = 0; inBits = outBits = 0; j = k = pixBytes; for (i = 0; i < width; ++i) { for (kk = 0; kk < nComps; ++kk) { if (inBits < nBits) { inBuf = (inBuf << 8) | (predLine[j++] & 0xff); inBits += 8; } upLeftBuf[kk] = (Guchar)((upLeftBuf[kk] + (inBuf >> (inBits - nBits))) & bitMask); inBits -= nBits; outBuf = (outBuf << nBits) | upLeftBuf[kk]; outBits += nBits; if (outBits >= 8) { predLine[k++] = (Guchar)(outBuf >> (outBits - 8)); outBits -= 8; } } } if (outBits > 0) { predLine[k++] = (Guchar)((outBuf << (8 - outBits)) + (inBuf & ((1 << (8 - outBits)) - 1))); } } } // reset to start of line predIdx = pixBytes; return gTrue;}//------------------------------------------------------------------------// FileStream//------------------------------------------------------------------------FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA, Guint lengthA, Object *dictA): BaseStream(dictA) { f = fA; start = startA; limited = limitedA; length = lengthA;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -