我正在使用以下代码使用iText库缩小每个页面(顶部和底部)现有pdf。
代码工作正常。 但是现在如果我处理结果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页:
收缩后(缩小内容):
答案 0 :(得分:2)
缩放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%(如果前两个值不为零,则需要更复杂的公式)。 / p>
获得新阵列后,我将媒体框和裁剪框更改为此阵列,然后我引入了一个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%。在这种情况下,我引入了percentage
变量,我定义了它为80%)。
请注意,我在X方向和Y方向应用缩放以保持宽高比。查看屏幕截图,看起来您只想缩小Y方向的内容。例如:
String.format("\nq 1 0 0 %s 0 %s cm\nq\n", percentage, offsetY)
随意调整代码以满足您的需求,但......结果将是丑陋的:所有文本看起来都很有趣,如果将它应用于垂直站立的人的照片,您将使它们看起来很胖。