-
PDPage 对象是否包含对其所属PDDocument 的引用?换句话说,PDPage 是否知道其PDDocument?
不幸的是,PDPage 不包含对其父 PDDocument 的引用,但它具有文档中所有其他页面的列表,可用于在页面之间导航而无需引用父 PDDocument。
- 如果您有一个
PDPage 对象,您可以从中获取信息,例如其页码,还是可以通过其他方式获取?
有一种解决方法可以在没有PDDocument 可用的情况下获取有关PDPage 在文档中的位置的信息。每个PDPage 都有一个字典,其中包含有关页面大小、资源、字体、内容等的信息。其中一个属性称为Parent,这是一个数组页面,其中包含使用构造函数PDPage(COSDictionary) 创建PDPage 的浅层克隆所需的所有信息。页面顺序正确,因此可以通过数组中记录的位置获取页码。
- 如果我遍历列表中这些拆分的
PDDocuments 的页面,有没有办法知道一个页面最初属于哪个PDDocument?
一旦您将文档列表合并到一个文档中,所有对原始文档的引用都将丢失。您可以通过查看 PDPage 中的 Parent 对象来确认这一点,转到 Parent > Kids > COSObject[n] > Parent 并查看 Parent 的编号是否为数组中的所有元素都相同。在此示例中,所有页面的父级都是 COSName {Parent} : 1781256139;。
COSName {Parent} : COSObject {
COSDictionary {
COSName {Kids} : COSArray {
COSObject {
COSDictionary {
COSName {TrimBox} : COSArray {0; 0; 612; 792;};
COSName {MediaBox} : COSArray {0; 0; 612; 792;};
COSName {CropBox} : COSArray {0; 0; 612; 792;};
COSName {Resources} : COSDictionary {
...
};
COSName {Contents} : COSObject {
...
};
COSName {Parent} : 1781256139;
COSName {StructParents} : COSInt {68};
COSName {ArtBox} : COSArray {0; 0; 612; 792; };
COSName {BleedBox} : COSArray {0; 0; 612; 792; };
COSName {Type} : COSName {Page};
}
}
...
COSName {Count} : COSInt {4};
COSName {Type} : COSName {Pages};
}
};
源代码
我编写了以下代码来展示如何使用来自PDPage 字典的信息来前后导航页面并使用数组中的位置获取页码。
public class PDPageUtils {
public static void main(String[] args) throws InvalidPasswordException, IOException {
System.setProperty("sun.java2d.cmm", "sun.java2d.cmm.kcms.KcmsServiceProvider");
PDDocument document = null;
try {
String filename = "src/main/resources/pdf/us-017.pdf";
document = PDDocument.load(new File(filename));
System.out.println("listIterator(PDPage)");
ListIterator<PDPage> pageIterator = listIterator(document.getPage(0));
while (pageIterator.hasNext()) {
PDPage page = pageIterator.next();
System.out.println("page #: " + pageIterator.nextIndex() + ", Structural Parent Key: " + page.getStructParents());
}
} finally {
if (document != null) {
document.close();
}
}
}
/**
* Returns a <code>ListIterator</code> initialized with the list of pages from
* the dictionary embedded in the specified <code>PDPage</code>. The current
* position of this <code>ListIterator</code> is set to the position of the
* specified <code>PDPage</code>.
*
* @param page the specified <code>PDPage</code>
*
* @see {@link java.util.ListIterator}
* @see {@link org.apache.pdfbox.pdmodel.PDPage}
*/
public static ListIterator<PDPage> listIterator(PDPage page) {
List<PDPage> pages = new LinkedList<PDPage>();
COSDictionary pageDictionary = page.getCOSObject();
COSDictionary parentDictionary = pageDictionary.getCOSDictionary(COSName.PARENT);
COSArray kidsArray = parentDictionary.getCOSArray(COSName.KIDS);
List<? extends COSBase> kidList = kidsArray.toList();
for (COSBase kid : kidList) {
if (kid instanceof COSObject) {
COSObject kidObject = (COSObject) kid;
COSBase type = kidObject.getDictionaryObject(COSName.TYPE);
if (type == COSName.PAGE) {
COSBase kidPageBase = kidObject.getObject();
if (kidPageBase instanceof COSDictionary) {
COSDictionary kidPageDictionary = (COSDictionary) kidPageBase;
pages.add(new PDPage(kidPageDictionary));
}
}
}
}
int index = pages.indexOf(page);
return pages.listIterator(index);
}
}
样本输出
在本例中,PDF 文档有 4 页,迭代器用第一页初始化。注意页码是previousIndex()
System.out.println("listIterator(PDPage)");
ListIterator<PDPage> pageIterator = listIterator(document.getPage(0));
while (pageIterator.hasNext()) {
PDPage page = pageIterator.next();
System.out.println("page #: " + pageIterator.previousIndex() + ", Structural Parent Key: " + page.getStructParents());
}
列表迭代器(PDPage)
页码:0,结构父键:68
页码:1,结构父键:69
页码:2,结构父键:70
页码:3,结构父键:71
您还可以从最后一页开始向后导航。现在请注意,页码是nextIndex()。
ListIterator<PDPage> pageIterator = listIterator(document.getPage(3));
pageIterator.next();
while (pageIterator.hasPrevious()) {
PDPage page = pageIterator.previous();
System.out.println("page #: " + pageIterator.nextIndex() + ", Structural Parent Key: " + page.getStructParents());
}
列表迭代器(PDPage)
页码:3,结构父键:71
页码:2,结构父键:70
页码:1,结构父键:69
页码:0,结构父键:68