📄 pdfreader.java
字号:
trailer = new PdfDictionary();
trailer.putAll(stm);
}
stm.setLength(((PdfNumber)stm.get(PdfName.LENGTH)).intValue());
int size = ((PdfNumber)stm.get(PdfName.SIZE)).intValue();
PdfArray index;
PdfObject obj = stm.get(PdfName.INDEX);
if (obj == null) {
index = new PdfArray();
index.add(new int[]{0, size});
}
else
index = (PdfArray)obj;
PdfArray w = (PdfArray)stm.get(PdfName.W);
int prev = -1;
obj = stm.get(PdfName.PREV);
if (obj != null)
prev = ((PdfNumber)obj).intValue();
// Each xref pair is a position
// type 0 -> -1, 0
// type 1 -> offset, 0
// type 2 -> index, obj num
ensureXrefSize(size * 2);
if (objStmMark == null && !partial)
objStmMark = new HashMap();
if (objStmToOffset == null && partial)
objStmToOffset = new IntHashtable();
byte b[] = getStreamBytes(stm, tokens.getFile());
int bptr = 0;
ArrayList wa = w.getArrayList();
int wc[] = new int[3];
for (int k = 0; k < 3; ++k)
wc[k] = ((PdfNumber)wa.get(k)).intValue();
ArrayList sections = index.getArrayList();
for (int idx = 0; idx < sections.size(); idx += 2) {
int start = ((PdfNumber)sections.get(idx)).intValue();
int length = ((PdfNumber)sections.get(idx + 1)).intValue();
ensureXrefSize((start + length) * 2);
while (length-- > 0) {
int type = 1;
if (wc[0] > 0) {
type = 0;
for (int k = 0; k < wc[0]; ++k)
type = (type << 8) + (b[bptr++] & 0xff);
}
int field2 = 0;
for (int k = 0; k < wc[1]; ++k)
field2 = (field2 << 8) + (b[bptr++] & 0xff);
int field3 = 0;
for (int k = 0; k < wc[2]; ++k)
field3 = (field3 << 8) + (b[bptr++] & 0xff);
int base = start * 2;
if (xref[base] == 0 && xref[base + 1] == 0) {
switch (type) {
case 0:
xref[base] = -1;
break;
case 1:
xref[base] = field2;
break;
case 2:
xref[base] = field3;
xref[base + 1] = field2;
if (partial) {
objStmToOffset.put(field2, 0);
}
else {
Integer on = new Integer(field2);
IntHashtable seq = (IntHashtable)objStmMark.get(on);
if (seq == null) {
seq = new IntHashtable();
seq.put(field3, 1);
objStmMark.put(on, seq);
}
else
seq.put(field3, 1);
}
break;
}
}
++start;
}
}
thisStream *= 2;
if (thisStream < xref.length)
xref[thisStream] = -1;
if (prev == -1)
return true;
return readXRefStream(prev);
}
protected void rebuildXref() throws IOException {
hybridXref = false;
newXrefType = false;
tokens.seek(0);
int xr[][] = new int[1024][];
int top = 0;
trailer = null;
byte line[] = new byte[64];
for (;;) {
int pos = tokens.getFilePointer();
if (!tokens.readLineSegment(line))
break;
if (line[0] == 't') {
if (!PdfEncodings.convertToString(line, null).startsWith("trailer"))
continue;
tokens.seek(pos);
tokens.nextToken();
pos = tokens.getFilePointer();
try {
PdfDictionary dic = (PdfDictionary)readPRObject();
if (dic.get(PdfName.ROOT) != null)
trailer = dic;
else
tokens.seek(pos);
}
catch (Exception e) {
tokens.seek(pos);
}
}
else if (line[0] >= '0' && line[0] <= '9') {
int obj[] = PRTokeniser.checkObjectStart(line);
if (obj == null)
continue;
int num = obj[0];
int gen = obj[1];
if (num >= xr.length) {
int newLength = num * 2;
int xr2[][] = new int[newLength][];
System.arraycopy(xr, 0, xr2, 0, top);
xr = xr2;
}
if (num >= top)
top = num + 1;
if (xr[num] == null || gen >= xr[num][1]) {
obj[0] = pos;
xr[num] = obj;
}
}
}
if (trailer == null)
throw new IOException("trailer not found.");
xref = new int[top * 2];
for (int k = 0; k < top; ++k) {
int obj[] = xr[k];
if (obj != null)
xref[k * 2] = obj[0];
}
}
protected PdfDictionary readDictionary() throws IOException {
PdfDictionary dic = new PdfDictionary();
while (true) {
tokens.nextValidToken();
if (tokens.getTokenType() == PRTokeniser.TK_END_DIC)
break;
if (tokens.getTokenType() != PRTokeniser.TK_NAME)
tokens.throwError("Dictionary key is not a name.");
PdfName name = new PdfName(tokens.getStringValue(), false);
PdfObject obj = readPRObject();
int type = obj.type();
if (-type == PRTokeniser.TK_END_DIC)
tokens.throwError("Unexpected '>>'");
if (-type == PRTokeniser.TK_END_ARRAY)
tokens.throwError("Unexpected ']'");
dic.put(name, obj);
}
return dic;
}
protected PdfArray readArray() throws IOException {
PdfArray array = new PdfArray();
while (true) {
PdfObject obj = readPRObject();
int type = obj.type();
if (-type == PRTokeniser.TK_END_ARRAY)
break;
if (-type == PRTokeniser.TK_END_DIC)
tokens.throwError("Unexpected '>>'");
array.add(obj);
}
return array;
}
protected PdfObject readPRObject() throws IOException {
tokens.nextValidToken();
int type = tokens.getTokenType();
switch (type) {
case PRTokeniser.TK_START_DIC: {
PdfDictionary dic = readDictionary();
int pos = tokens.getFilePointer();
// be careful in the trailer. May not be a "next" token.
if (tokens.nextToken() && tokens.getStringValue().equals("stream")) {
int ch = tokens.read();
if (ch != '\n')
ch = tokens.read();
if (ch != '\n')
tokens.backOnePosition(ch);
PRStream stream = new PRStream(this, tokens.getFilePointer());
stream.putAll(dic);
stream.setObjNum(objNum, objGen);
return stream;
}
else {
tokens.seek(pos);
return dic;
}
}
case PRTokeniser.TK_START_ARRAY:
return readArray();
case PRTokeniser.TK_NUMBER:
return new PdfNumber(tokens.getStringValue());
case PRTokeniser.TK_STRING:
PdfString str = new PdfString(tokens.getStringValue(), null).setHexWriting(tokens.isHexString());
str.setObjNum(objNum, objGen);
if (strings != null)
strings.add(str);
return str;
case PRTokeniser.TK_NAME:
return new PdfName(tokens.getStringValue(), false);
case PRTokeniser.TK_REF:
int num = tokens.getReference();
PRIndirectReference ref = new PRIndirectReference(this, num, tokens.getGeneration());
return ref;
default:
String sv = tokens.getStringValue();
if ("null".equals(sv))
return PdfNull.PDFNULL;
else if ("true".equals(sv))
return PdfBoolean.PDFTRUE;
else if ("false".equals(sv))
return PdfBoolean.PDFFALSE;
return new PdfLiteral(-type, tokens.getStringValue());
}
}
/** Decodes a stream that has the FlateDecode filter.
* @param in the input data
* @return the decoded data
*/
public static byte[] FlateDecode(byte in[]) {
byte b[] = FlateDecode(in, true);
if (b == null)
return FlateDecode(in, false);
return b;
}
/**
* @param in
* @param dicPar
* @return a byte array
*/
public static byte[] decodePredictor(byte in[], PdfObject dicPar) {
if (dicPar == null || !dicPar.isDictionary())
return in;
PdfDictionary dic = (PdfDictionary)dicPar;
PdfObject obj = getPdfObject(dic.get(PdfName.PREDICTOR));
if (obj == null || !obj.isNumber())
return in;
int predictor = ((PdfNumber)obj).intValue();
if (predictor < 10)
return in;
int width = 1;
obj = getPdfObject(dic.get(PdfName.COLUMNS));
if (obj != null && obj.isNumber())
width = ((PdfNumber)obj).intValue();
int colors = 1;
obj = getPdfObject(dic.get(PdfName.COLORS));
if (obj != null && obj.isNumber())
colors = ((PdfNumber)obj).intValue();
int bpc = 8;
obj = getPdfObject(dic.get(PdfName.BITSPERCOMPONENT));
if (obj != null && obj.isNumber())
bpc = ((PdfNumber)obj).intValue();
DataInputStream dataStream = new DataInputStream(new ByteArrayInputStream(in));
ByteArrayOutputStream fout = new ByteArrayOutputStream(in.length);
int bytesPerPixel = colors * bpc / 8;
int bytesPerRow = (colors*width*bpc + 7)/8;
byte[] curr = new byte[bytesPerRow];
byte[] prior = new byte[bytesPerRow];
// Decode the (sub)image row-by-row
while (true) {
// Read the filter type byte and a row of data
int filter = 0;
try {
filter = dataStream.read();
if (filter < 0) {
return fout.toByteArray();
}
dataStream.readFully(curr, 0, bytesPerRow);
} catch (Exception e) {
return fout.toByteArray();
}
switch (filter) {
case 0: //PNG_FILTER_NONE
break;
case 1: //PNG_FILTER_SUB
for (int i = bytesPerPixel; i < bytesPerRow; i++) {
curr[i] += curr[i - bytesPerPixel];
}
break;
case 2: //PNG_FILTER_UP
for (int i = 0; i < bytesPerRow; i++) {
curr[i] += prior[i];
}
break;
case 3: //PNG_FILTER_AVERAGE
for (int i = 0; i < bytesPerPixel; i++) {
curr[i] += prior[i] / 2;
}
for (int i = bytesPerPixel; i < bytesPerRow; i++) {
curr[i] += ((curr[i - bytesPerPixel] & 0xff) + (prior[i] & 0xff))/2;
}
break;
case 4: //PNG_FILTER_PAETH
for (int i = 0; i < bytesPerPixel; i++) {
curr[i] += prior[i];
}
for (int i = bytesPerPixel; i < bytesPerRow; i++) {
int a = curr[i - bytesPerPixel] & 0xff;
int b = prior[i] & 0xff;
int c = prior[i - bytesPerPixel] & 0xff;
int p = a + b - c;
int pa = Math.abs(p - a);
int pb = Math.abs(p - b);
int pc = Math.abs(p - c);
int ret;
if ((pa <= pb) && (pa <= pc)) {
ret = a;
} else if (pb <= pc) {
ret = b;
} else {
ret = c;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -