我遇到了一些包含Xerox扫描仪创建的旋转属性的PDF的问题。 最初创建以下函数是为了根据变量scaleHeight给出的量来缩放输入PDF的高度。 这适用于没有旋转的输入文档。
当测试旋转270度的文档时,我发现忽略了使文档以纵向显示的旋转属性。相反,文档在输出PDF中以横向方向显示。
所以我更新了下面的函数,仅在没有旋转时应用缩放,并使用我在网上找到的另一个例子来尝试修复旋转。
此不起作用,以纵向格式生成原始文档的镜像。
所以现在我有两个问题: 1.如何正确旋转文档内容。 2.如何缩放旋转的内容。
如果我能解决第1项,我可以再次调用该函数(删除了旋转属性)来修复第2项。
感谢您提供任何帮助,功能如下。 引用rotationEvent的注释掉的行也没有帮助。
public String resizePDF (String pdfIn, float x, float y, float scaleHeight) throws Exception {
String pdfOut = pdfIn.substring(0, pdfIn.length() - 4) + "_resize.pdf";
PdfReader reader = new PdfReader(pdfIn);
int rotation = reader.getPageRotation(1);
com.itextpdf.text.Document doc = new com.itextpdf.text.Document(reader.getPageSizeWithRotation(1), 0, 0, 0, 0);
PdfWriter writer = PdfWriter.getInstance(doc, new FileOutputStream(pdfOut));
doc.open();
PdfContentByte cb = writer.getDirectContent();
Rotate rotationEvent = new Rotate();
writer.setPageEvent(rotationEvent);
for(int i=1; i<=reader.getNumberOfPages(); i++){
float pageWidth = reader.getPageSizeWithRotation(i).getWidth();
float pageHeight = reader.getPageSizeWithRotation(i).getHeight();
doc.newPage();
PdfImportedPage page = writer.getImportedPage(reader, i);
if (rotation == 0) {
cb.addTemplate(page, 1f, 0, 0, scaleHeight, x, y);
//rotationEvent.setRotation(PdfPage.PORTRAIT);
} else if (rotation == 90) {
cb.addTemplate(page, 0, -1f, 1f, 0, 0, pageHeight);
//rotationEvent.setRotation(PdfPage.LANDSCAPE);
} else if (rotation == 180) {
cb.addTemplate(page, 1f, 0, 0, -1f, pageWidth, pageHeight);
//rotationEvent.setRotation(PdfPage.INVERTEDPORTRAIT);
} else if (rotation == 270) {
cb.addTemplate(page, 0, -1f, 1f, 0, 0, pageHeight);
//cb.addTemplate(page, 0, 1f, -1f, 0, pageWidth, 0);
//rotationEvent.setRotation(PdfPage.SEASCAPE);
}
}
doc.close();
return pdfOut;
}
答案 0 :(得分:2)
我不明白你的代码,但是当我告诉别人“请丢掉你的代码然后重新开始”时,很多人都觉得冒犯了(虽然我当然不打算冒犯他们)。
据我所知,您希望缩放现有PDF的内容,并保留旋转或将其删除(该部分并不完全清楚)。
因此我写了一个名为ScaleDown
的例子,可以用来缩小,保持方向。移除一条线以移除方向就足够了。
此示例使用页面事件(我将其命名为ScaleEvent
):
public class ScaleEvent extends PdfPageEventHelper {
protected float scale = 1;
protected PdfDictionary pageDict;
public ScaleEvent(float scale) {
this.scale = scale;
}
public void setPageDict(PdfDictionary pageDict) {
this.pageDict = pageDict;
}
@Override
public void onStartPage(PdfWriter writer, Document document) {
writer.addPageDictEntry(PdfName.ROTATE, pageDict.getAsNumber(PdfName.ROTATE));
writer.addPageDictEntry(PdfName.MEDIABOX, scaleDown(pageDict.getAsArray(PdfName.MEDIABOX), scale));
writer.addPageDictEntry(PdfName.CROPBOX, scaleDown(pageDict.getAsArray(PdfName.CROPBOX), scale));
}
}
创建事件时,您传递的值scale
将定义比例因子。我将比例应用于宽度和高度,如果您只想缩放高度,请随意调整它。
有关页面大小和旋转的信息存储在页面字典中。显然,ScaleEvent
需要原始文档的值,以及为什么我们会为我们复制的每个页面传递pageDict
。
每次创建新页面时,我们都会复制/替换:
/Rotate
值。如果要删除旋转,请删除此行/MediaBox
值。这定义了页面的完整大小。/CropBox
值。这定义了页面的可见大小。由于我们要缩放页面,因此我们使用以下scaleDown()
方法:
public PdfArray scaleDown(PdfArray original, float scale) {
if (original == null)
return null;
float width = original.getAsNumber(2).floatValue()
- original.getAsNumber(0).floatValue();
float height = original.getAsNumber(3).floatValue()
- original.getAsNumber(1).floatValue();
return new PdfRectangle(width * scale, height * scale);
}
假设我想将页面宽度和高度减小到原始宽度和高度的50%,那么我就像这样创建事件:
PdfReader reader = new PdfReader(src);
float scale = 0.5f;
ScaleEvent event = new ScaleEvent(scale);
event.setPageDict(reader.getPageN(1));
我可以使用我想要的任何页面大小定义Document
,因为无论如何都会在ScaleEvent
中更改大小。显然,为了实现这一点,我需要将事件声明到PdfWriter
实例:
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
writer.setPageEvent(event);
document.open();
现在只需循环遍历页面:
int n = reader.getNumberOfPages();
Image page;
for (int p = 1; p <= n; p++) {
page = Image.getInstance(writer.getImportedPage(reader, p));
page.setAbsolutePosition(0, 0);
page.scalePercent(scale * 100);
document.add(page);
if (p < n) {
event.setPageDict(reader.getPageN(p + 1));
}
document.newPage();
}
document.close();
我将导入的页面包装在Image
中,因为我个人认为Image
类可用的方法比定义addTemplate()
方法的参数更容易使用。如果您想使用addTemplate()
代替Image
,请随意执行此操作;结果将是相同的(与您在评论中写的相反,在图像中包装页面不会导致任何“分辨率”丢失,因为所有文本仍然可用作矢量数据)。
请注意,我为每个新页面更新了pageDict
。
此代码将文件orientations.pdf测量为8.26乘11.69 in并将其转换为文件scaled_down.pdf,测量4.13乘5.85英寸。
如果您希望所有页面都是纵向的,只需删除以下行:
writer.addPageDictEntry(PdfName.ROTATE, pageDict.getAsNumber(PdfName.ROTATE));