当前位置: 首页 > 知识库问答 >
问题:

在现有PDF中使用矩形收缩旋转PDF页面

陆博易
2023-03-14

我使用以下代码使用iText库缩小现有pdf的每一页(顶部和底部)。

代码工作正常。但现在,如果我处理结果pdf,则每个页面的旋转值为0,而旧pdf也有其他旋转(即90度)。

我想保持旋转,但做不到。

我使用下面的代码来缩小页面

public void shrinkPDFPages() throws Exception {
        PdfReader reader = new PdfReader("D:/testpdfs/test.pdf");

        Document doc = new Document();
        PdfWriter writer = PdfWriter.getInstance(doc, new FileOutputStream(
                "D://testpdfs/result.pdf"));
        doc.open();
        PdfContentByte cb = writer.getDirectContent();
        for (int i = 1; i <= reader.getNumberOfPages(); i++) {

            PdfImportedPage page = writer.getImportedPage(reader, i);
            float pageHeight = reader.getPageSizeWithRotation(i).getHeight();
            float pageWidth = reader.getPageSizeWithRotation(i).getWidth();
            int rotation = reader.getPageRotation(i);

            Rectangle pageRectangle = reader.getPageSizeWithRotation(i);
            Rectangle PageRect = null;

            System.out.println(rotation);

            switch (rotation) {
            case 0:
                PageRect = new Rectangle(pageRectangle.getWidth(), pageRectangle
                        .getHeight());
                doc.setPageSize(PageRect);
                doc.newPage();
                AffineTransform af = new AffineTransform();
                af.scale(1, 0.84f);
                af.translate(1, 50);

                cb.addTemplate(page, af);
                break;
            case 90:
                PageRect = new Rectangle(pageRectangle.getWidth(), pageRectangle
                        .getHeight());
                doc.setPageSize(PageRect);
                doc.newPage();

                cb.addTemplate(page, 0, -1f, 0.84f, 0, 50, pageHeight);
                break;
            case 270:
                PageRect = new Rectangle(pageRectangle.getWidth(), pageRectangle
                        .getHeight());
                doc.setPageSize(PageRect);
                doc.newPage();
                cb.addTemplate(page, 0, 1f, -0.84f, 0, pageWidth - 50, 0);
                break;

            case 180:
                PageRect = new Rectangle(pageRectangle.getWidth(), pageRectangle
                        .getHeight());
                doc.setPageSize(PageRect);
                doc.newPage();
                cb.addTemplate(page, -1f, 0, 0, -0.84f, pageWidth,
                        pageHeight - 50);
                break;
            default:
                break;

            }
        }
        doc.close();
    }

怎么办?所以轮换还是这样。

我正在获取的另一个问题是,无法保留内部超链接。

实际pdf页面:

收缩后(缩小内容):

共有1个答案

董喜
2023-03-14

缩放PDF以使页面更大很容易。这在ScaleRotate示例中显示。这只是更改用户单元的默认版本的问题。默认情况下,此单位为1,表示1个用户单元等于1点。您可以将此值增加到75,000。用户单元的值越大,将导致页面越大。

不幸的是,用户单位永远不能小于1,因此不能使用此技术来收缩页面。如果要缩小页面,需要引入转换(生成新的CTM)。

这在ShrinkPdf示例中显示。在本例中,我使用一个名为hero的PDF。pdf的尺寸为8.26 x 11.69英寸,我们将其缩小了50%,生成了一个名为hero\u shrink的pdf。pdf尺寸为4.13 x 5.85英寸。

要实现这一点,我们需要一个肮脏的黑客:

public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    int n = reader.getNumberOfPages();
    PdfDictionary page;
    PdfArray crop;
    PdfArray media;
    for (int p = 1; p <= n; p++) {
        page = reader.getPageN(p);
        media = page.getAsArray(PdfName.CROPBOX);
        if (media == null) {
            media = page.getAsArray(PdfName.MEDIABOX);
        }
        crop = new PdfArray();
        crop.add(new PdfNumber(0));
        crop.add(new PdfNumber(0));
        crop.add(new PdfNumber(media.getAsNumber(2).floatValue() / 2));
        crop.add(new PdfNumber(media.getAsNumber(3).floatValue() / 2));
        page.put(PdfName.MEDIABOX, crop);
        page.put(PdfName.CROPBOX, crop);
        stamper.getUnderContent(p).setLiteral("\nq 0.5 0 0 0.5 0 0 cm\nq\n");
        stamper.getOverContent(p).setLiteral("\nQ\nQ\n");
    }
    stamper.close();
    reader.close();
}

我们遍历每个页面,并获取每个页面的裁剪框。如果没有裁剪框,我们获取媒体框。这些框存储为4个数字的数组。在本例中,我假设前两个数字为零,并将接下来的两个值除以2以将页面缩小到50%(如果前两个值不为零,则需要更详细的公式)。

有了新阵列后,我将媒体盒和裁剪盒更改为该阵列,并引入了一种CTM,可将所有内容的比例降低到50%。我需要使用setLiteral()方法来愚弄iText。

根据您在评论部分的反馈,您似乎不理解我的示例中解释的机制。因此,我制作了第二个示例,名为ShrinkPdf2:

public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    int n = reader.getNumberOfPages();
    float percentage = 0.8f;
    for (int p = 1; p <= n; p++) {
        float offsetX = (reader.getPageSize(p).getWidth() * (1 - percentage)) / 2;
        float offsetY = (reader.getPageSize(p).getHeight() * (1 - percentage)) / 2;
        stamper.getUnderContent(p).setLiteral(
                String.format("\nq %s 0 0 %s %s %s cm\nq\n", percentage, percentage, offsetX, offsetY));
        stamper.getOverContent(p).setLiteral("\nQ\nQ\n");
    }
    stamper.close();
    reader.close();
}

在这个例子中,我不改变页面大小(不改变媒体或裁剪框),我只缩小内容(在这种情况下为80%),并将缩小的内容居中放在页面上,在顶部、底部、左侧和右侧留下更大的边距。

如您所见,这只是应用正确数学的问题。第二个例子比第一个例子更简单,所以我引入了一些额外的复杂性:现在您可以轻松更改百分比(在第一个例子中,我硬编码了50%。在这种情况下,我引入了百分比变量,我将其定义为80%)。

请注意,我在X方向和Y方向上应用缩放以保持纵横比。查看屏幕截图,您似乎只想在Y方向收缩内容。例如:

String.format("\nq 1 0 0 %s 0 %s cm\nq\n", percentage, offsetY)

可以随意调整代码以满足您的需要,但是。。。结果会很难看:所有的文字看起来都很有趣,如果你把它应用到人们垂直站立的照片上,你会让他们看起来很胖。

 类似资料:
  • 我尝试使用iTextSharp创建一个多页pdf文档。我有一个包含自身方向(横向或纵向)的对象。当第一个对象包含需要横向模式的信息时,我用< code > Document doc = new Document(PageSize。A4.Rotate(),10f,10f,10f,0f)。这工作得很好,直到下一个元素是肖像模式!如果一个元素处于纵向模式,我再次设置页面大小:< code>doc。Set

  • 问题内容: 我需要创建围绕其中心旋转的矩形(因此它们不必平行于坐标系的轴)。因此,基本上每个矩形都可以由 center-X , center-Y , width , height 和 angle定义 。然后,我要做的是对这些矩形中是否包含某些点进行计算(因此不会涉及任何绘图)。我想我不能使用该类,因为这些矩形将始终与坐标系的x和y轴平行。是通过编写自己的矩形类来获得此功能的唯一方法,还是可以使用任

  • 在我的情况下,矩形接触圆形,但我认为没关系。 起初,我试着用两个Ficture来做同样的身体,但旋转有一个问题:我不能有一个带旋转的Ficture,另一个没有。 我认为,它应该与关节有某种联系,但我不知道我应该使用什么关节。也许还有其他解决方案?

  • 旋转到纵向视图后,如何确保所有内容都可见(在页面范围内)? 当旋转90度时,PDFSharp会截断我的页面,但当旋转-90度时不会截断。 以上对一些pdf测试案例有效,但我怀疑这是巧合/运气 我使用的是1.50 Beta版的PDF夏普。

  • 我想生产一个PDF的网页在景观。虽然可以使用以下方法将页面大小设置为横向: 这并没有达到我想要的,因为我添加的任何内容仍然是面向左->右的,而我希望它是底部->顶部的。 即。这就是我得到的: 我已经能够实现所需的输出打开PDF后,它已经创建并使用iText旋转它,但我想要一个解决方案,让我旋转后立即与iText添加内容。

  • 我刚开始使用JavaFX,有一个问题。在我的项目中,我想使用旋转矩形。但矩形只围绕其中心旋转,我希望它围绕其左上角旋转。 就像这张照片(从这里开始): 下面是我的项目中的一些代码: 在这种情况下,如果按下箭头键,矩形会旋转。