更改PDF文件中轮廓(书签)的缩放级别

时间:2019-11-04 19:12:39

标签: java itext itext7

我想使用iText7更改轮廓的缩放级别。请注意,与iText 5中的处理方式相比,这可能已经改变。

通过反复试验,我得出了以下代码:

List<PdfOutline> outlines = pdfDoc.getOutlines(true).getAllChildren();

for (int i = 0; i < outlines.size(); i++) {

    PdfOutline outline = outlines.get(i);
    PdfDictionary content = outline.getContent();
    PdfDictionary pdfDictionary = (PdfDictionary) content.get(PdfName.A);
    if (pdfDictionary != null) {
        PdfArray arr = (PdfArray) pdfDictionary.get(PdfName.D);
        if (arr.size() == 5) { // for XYZ zoom type
            PdfName xyz = (PdfName) arr.get(1);
            arr.set(3, new PdfNumber(2_000));
            arr.set(4, new PdfNumber(2_000));
        }
    }  

编辑

问题在于上面的代码似乎不起作用,因为保存了生成的pdf,但是缩放级别没有变化。

更新 我想出了一个不同的解决方案(受different question at SO的启发):

PdfNameTree destsTree = document.getCatalog().getNameTree(PdfName.Dests);
PdfOutline outline = document.getOutlines(false);
if (outline != null) {
    walkOutlines(outline, destsTree.getNames(), document);
}      

private static void walkOutlines(PdfOutline outline, Map<String, PdfObject> names,
            PdfDocument document) {

    if (outline.getDestination() != null) {

        int pageNumber = document.getPageNumber(
                (PdfDictionary) outline.getDestination().getDestinationPage(names));

        float height = document.getPage(pageNumber).getPageSize().getHeight();

        outline.setOpen(false);
        outline.addDestination(PdfExplicitRemoteGoToDestination.createXYZ(
                pageNumber, 0F, height, ZOOM_LEVEL));

    }
    for (PdfOutline child : outline.getAllChildren()) {
        walkOutlines(child, names, document);
    }
}

2 个答案:

答案 0 :(得分:0)

是这样吗?

    PdfDocument pdfDoc = new PdfDocument(new PdfReader(SRC), new PdfWriter(DEST));                                                   
    pdfDoc.getCatalog().setOpenAction(PdfExplicitDestination.createXYZ(pdfDoc.getPage(1), 0,                                                       pdfDoc.getPage(1).getPageSize().getHeight(), 0.75f)); 
    pdfDoc.close();

https://itextpdf.com/en/resources/faq/technical-support/itext-7/how-can-i-set-zoom-level-pdf-using-itext-7

答案 1 :(得分:0)

您的原始代码

  

问题在于上面的代码似乎不起作用,因为保存了生成的pdf,但是缩放级别没有变化。

尝试原始代码我无法确认,标题页轮廓的缩放级别和y坐标(为什么还要更改?)也已更改!

其他轮廓没有更改,原因有两个:

  • 您的原始代码仅在顶级轮廓上进行迭代(直接目录概述子级),因此仅可以更改顶级轮廓条目。
  • 您的原始代码假定大纲中有一个 GoTo Action A ),其中包装了一个明确的 XYZ目标 D 映射到5个元素的数组)。

    这仅在您的文档适用于标题页的情况下,所有其他轮廓立即包含一个非显式的名称, Destination Dest 映射到名称)

您的备用代码

您的备用代码确实可以解决问题

    它还递归访问顶级大纲的所有祖先,因此可以更改所有大纲条目;和
  • 它使用iText类来识别和评估各种目的地,无论它们是否包装在一个动作中,无论它们是显式的还是命名的,...

在Adobe Reader中,结果似乎可以按预期工作,但仔细观察后发现存在问题:

  • 标题页大纲(这是您仅有的带有 Action 条目的大纲)现在同时具有 和旧的 Action 条目,一个新的目的地条目。严格来说,该规范是禁止的。因此,您应该删除现有的 Action 条目。
  • 创建的目标数组包含目标页(第一个数组条目)作为整数页号。仅在远程转到操作中的目标位置允许。由于您的新目的地显然不是远程的,也不是非行动的,因此这仅是有效的,因为Adobe Reader非常宽松。应该使用页面对象而不是页码,并且不应该使用PdfExplicitRemoteGoToDestination开头。

改进您的备用代码

要解决上述问题,请更改

outline.addDestination(PdfExplicitRemoteGoToDestination.createXYZ(
        pageNumber, 0F, height, ZOOM_LEVEL));

outline.getContent().remove(PdfName.A);
outline.addDestination(PdfExplicitDestination.createXYZ(
        document.GetPage(pageNumber), 0F, height, ZOOM_LEVEL));

严格来说,您的代码可以得到进一步的改进。

  • 您使用PageSize,但是对于可见页面区域,您应该使用CropBox
  • 然后使用0F, height作为目标视图左上角的坐标。假设坐标系的原点位于页面的左下角,则应使用box.getLeft(), box.getTop()而不是box作为相关页面的裁剪框。

但是,在示例文档中,媒体框和裁切框重合,并且原点确实位于左下角。因此,对于该文档,您不需要进行改进。