在现有PDF中使用Rectangle缩小PDF页面的旋转

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

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

我希望保持旋转,但不能这样做。

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

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页面:

在此处输入图像描述

收缩后(缩小内容):

在此处输入图像描述

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

不幸的是,用户单元永远不会小于1,因此您无法使用此技术缩小页面。 如果要缩小页面,则需要引入转换(生成新的CTM)。

这在ShrinkPdf示例中显示。 在这个例子中,我采用了一个名为hero.pdf的PDF,其尺寸为8.26×11.69英寸,我们将它缩小了50%,得到一个名为hero_shrink.pdf的PDF,其尺寸为4.13×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%(如果前两个值不为零,则需要更精细的公式)。

一旦我有了新arrays,我就将媒体盒和裁剪框更改为此arrays,然后我介绍了一个将所有内容缩减到50%的CTM。 我需要使用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%。在这种情况下,我引入了percentage变量,我将其定义为80% )。

请注意,我在X方向和Y方向应用缩放以保持纵横比。 查看屏幕截图,看起来您只想缩小Y方向的内容。 比如像这样:

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

随意调整代码以满足您的需求,但...结果将是丑陋的:所有文本看起来都很有趣,如果你将它应用于垂直站立的人的照片,你会让它们看起来很胖。