📄 pdfreader.java
字号:
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; } curr[i] += (byte)(ret); } break; default: // Error -- unknown filter type throw new RuntimeException("PNG filter unknown."); } try { fout.write(curr); } catch (IOException ioe) { // Never happens } // Swap curr and prior byte[] tmp = prior; prior = curr; curr = tmp; } } /** A helper to FlateDecode. * @param in the input data * @param strict <CODE>true</CODE> to read a correct stream. <CODE>false</CODE> * to try to read a corrupted stream * @return the decoded data */ public static byte[] FlateDecode(byte in[], boolean strict) { ByteArrayInputStream stream = new ByteArrayInputStream(in); InflaterInputStream zip = new InflaterInputStream(stream); ByteArrayOutputStream out = new ByteArrayOutputStream(); byte b[] = new byte[strict ? 4092 : 1]; try { int n; while ((n = zip.read(b)) >= 0) { out.write(b, 0, n); } zip.close(); out.close(); return out.toByteArray(); } catch (Exception e) { if (strict)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -