使用itext 7将页码文本添加到pdf副本会被翻转/镜像

时间:2018-10-10 15:18:37

标签: pdf copy itext7

所以...我一直在尝试使用itext文档中提供的示例来合并文档并为合并结果创建TOC。但是,将页码文本添加到每个页面的部分无法正常工作。发生的情况是添加的文本在某个水平轴上翻转,如下图所示:

enter image description here

此外,用于为添加的文本(public T setFixedPosition(int pageNumber, float left, float bottom, float width)设置固定位置的方法的Java文档对我来说没有意义:

  

设置元素绝对位置的值。指定的坐标对应于元素的左下角,并且它向上增长。

但是当我运行setFixedPosition(pageNumber, 0, 0, 50)时,文本最终显示在左上角,同样也翻转了。而且,如果我使用源PdfDocument页面大小中的宽度和高度分别作为左侧和底部位置的参数,那么它甚至都不会到达右下角。

我可能做错了什么或误解了。无论哪种方式,这是我正在使用的代码:

private static int copyPdfPages(PdfDocument source, Document document, Integer start, Integer pages, Integer number) {
    int oldC;
    int max = start + pages - 1;
    Text text;
    for (oldC = start; oldC <= max; oldC++) {
        text = new Text(String.format("Page %d", number));
        PageSize pageSize = source.getDefaultPageSize();
        source.copyPagesTo(oldC, oldC, document.getPdfDocument());
        document.add(new Paragraph(text).setBorder(new SolidBorder(ColorConstants.RED, 1))
                .setFixedPosition(number++, pageSize.getWidth() - 55, pageSize.getHeight() - 30, 50));
    }
    return oldC - start;
}

public static void main(String[] args) throws IOException {
    String path = "/path/to/target";

    FileOutputStream fos = new FileOutputStream(path);
    PdfDocument pdfDocTgt = new PdfDocument(new PdfWriter(fos));
    Document document = new Document(pdfDocTgt);

    PdfDocument pdfDocSrc = new PdfDocument(new PdfReader(new FileInputStream("path/to/source")));

    copyPdfPages(pdfDocSrc, document, 1, pdfDocSrc.getNumberOfPages(), 1);

    pdfDocTgt.close();
    pdfDocSrc.close();
    document.flush();
    document.flush();
    fos.flush();
    fos.close();
}

这是pdf来源:https://drive.google.com/open?id=11_9ptuoRqS91hI3fDcs2FRsIUEiX0a84

请帮忙(对不起我的英语)。

1 个答案:

答案 0 :(得分:1)

问题

问题是Document.add假设当前页面当前内容末尾的指令的图形状态基本上恢复到了初始状态(否则,差异对输出的影响是所需)。

在您的样本PDF中,不满足此假设,特别是页面内容说明以

开头
0.750000 0.000000 0.000000 -0.750000 0.000000 841.920044 cm

将当前转换矩阵更改为

  • 将所有内容缩小到75%,并且
  • 垂直翻转坐标系。

以前的更改使您添加的内容不在页面角落,而是位于中心位置;后者导致它被垂直镜像,并更多地位于页面底部而不是页面顶部。

修复

如果不知道页面的当前内容最后是否具有从本质上恢复的图形状态(通常是一种处理页面内容的人没有自己生成的图像的情况),应该避免通过Document实例添加内容,而应使用通过构造函数生成的PdfCanvas,该构造函数将当前页面内容包装在save-graphics-state ... restore-graphics-state信封中。

例如为您的任务:

private static int copyPdfPagesFixed(PdfDocument source, PdfDocument target, int start, int pages, int number) {
    int oldC;
    int max = start + pages - 1;
    Text text;
    for (oldC = start; oldC <= max; oldC++) {
        text = new Text(String.format("Page %d", number));
        source.copyPagesTo(oldC, oldC, target);
        PdfPage newPage = target.getLastPage();
        Rectangle pageSize = newPage.getCropBox();
        try (   Canvas canvas = new Canvas(new PdfCanvas(newPage, true), target, pageSize)  ) {
            canvas.add(new Paragraph(text).setBorder(new SolidBorder(ColorConstants.RED, 1))
                  .setFixedPosition(number++, pageSize.getWidth() - 55, pageSize.getHeight() - 30, 50));
        }
    }
    return oldC - start;
}

AddPagenumberToCopy方法)

上面使用的PdfCanvas构造函数记录为

/**
 * Convenience method for fast PdfCanvas creation by a certain page.
 *
 * @param page           page to create canvas from.
 * @param wrapOldContent true to wrap all old content streams into q/Q operators so that the state of old
 *                       content streams would not affect the new one
 */
public PdfCanvas(PdfPage page, boolean wrapOldContent)

像这样使用

try (   PdfDocument pdfDocSrc = new PdfDocument(new PdfReader(SOURCE));
        PdfDocument pdfDocTgt = new PdfDocument(new PdfWriter(TARGET))    ) {
    copyPdfPagesFixed(pdfDocSrc, pdfDocTgt, 1, pdfDocSrc.getNumberOfPages(), 1);
}

AddPagenumberToCopy测试testLikeAibanezFixed

第一个结果页面的顶部如下所示:

screen shot