java - Java iText 将文档缩放到 A4
问题描述
我有以下方法将文档的所有页面“调整”为 A4 页面尺寸:
for (PdfDocument doc : pdfDocuments) {
int n = doc.getNumberOfPages();
for (int i = 1; i <= n; i++) {
PdfPage page = doc.getPage(i);
Rectangle media = page.getCropBox();
if (media == null) {
media = page.getMediaBox();
}
Rectangle crop = new Rectangle(0, 0, 210, 297);
page.setMediaBox(crop);
page.setCropBox(crop);
// The content, placed on a content stream before, will be rendered before the other content
// and, therefore, could be understood as a background (bottom "layer")
new PdfCanvas(page.newContentStreamBefore(),
page.getResources(), doc).writeLiteral("\nq 0.5 0 0 0.5 0 0 cm\nq\n");
// The content, placed on a content stream after, will be rendered after the other content
// and, therefore, could be understood as a foreground (top "layer")
new PdfCanvas(page.newContentStreamAfter(),
page.getResources(), doc).writeLiteral("\nQ\nQ\n");
}
}
但是,这并没有按预期工作,页面正在转换为 A4 (297x210) 但内容不适合在里面(缩放),因为原始页面大于 297X210,所以内容似乎被剪切了。我怎样才能解决这个问题 ?
解决方案
在您澄清的评论中
我希望缩放前内容的边界框并在目标中添加边距
所以,我们首先要确定原始页面内容的边界框。这可以使用这个答案MarginFinder
中的类来完成。注意:该类确定所有内容的边界框,即使它只是一个白色矩形,在视觉上与没有内容或以前在裁剪框之外的东西没有区别......如果您的用例需要它,您可能必须扩展该类也要考虑到这种情况。
确定了内容边界框后,剩下要做的就是一些计算。
以下方法使用上面的类确定边界框,相应地转换内容,并更改结果裁剪框。
void scale(PdfDocument pdfDocument, Rectangle pageSize, Rectangle pageBodySize) {
int n = pdfDocument.getNumberOfPages();
for (int i = 1; i <= n; i++) {
PdfPage page = pdfDocument.getPage(i);
MarginFinder marginFinder = new MarginFinder();
PdfCanvasProcessor pdfCanvasProcessor = new PdfCanvasProcessor(marginFinder);
pdfCanvasProcessor.processPageContent(page);
Rectangle boundingBox = marginFinder.getBoundingBox();
if (boundingBox == null || boundingBox.getWidth() == 0 || boundingBox.getHeight() == 0) {
System.err.printf("Cannot scale page %d contents with bounding box %s\n", i , boundingBox);
continue;
} else {
// Scale and move content into A4 with margin
double scale = 0, xDiff= 0, yDiff = 0;
double xScale = pageBodySize.getWidth()/boundingBox.getWidth();
double yScale = pageBodySize.getHeight()/boundingBox.getHeight();
if (xScale < yScale) {
yDiff = boundingBox.getHeight() * (yScale / xScale - 1) / 2;
scale = xScale;
} else {
xDiff = boundingBox.getWidth() * (xScale / yScale - 1) / 2;
scale = yScale;
}
AffineTransform transform = AffineTransform.getTranslateInstance(pageBodySize.getLeft() + xDiff, pageBodySize.getBottom() + yDiff);
transform.scale(scale, scale);
transform.translate(-boundingBox.getLeft(), -boundingBox.getBottom());
new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDocument)
.concatMatrix(transform);
}
page.setMediaBox(pageSize);
page.setCropBox(pageSize);
}
}
(ScaleToA4方法scale
)
对于每边有一英寸边距的 A4 结果页面大小,您可以这样称呼它PdfDocument pdfDocument
:
Rectangle pageSize = PageSize.A4;
Rectangle pageBodySize = pageSize.clone().applyMargins(72, 72, 72, 72, false);
scale(pdfDocument, pageSize, pageBodySize);
(摘自ScaleToA4测试testFdaRequiresUseOfEctdFormatAndStandardizedStudyDataInFutureRegulatorySubmissionsSept
)
推荐阅读
- html - 为什么最小高度样式对 div 没有影响
- ajax - 使用 ajax get 使用 rest api
- sql-server - SQL SERVER - 找出哪个字段不同
- android - Gradle 同步失败..缺少谷歌
- c# - C#无法将类型转换为字符串
- c - 我如何在这个程序中使用模运算符
- shell - SHELL : 连接变量名
- angular - 单击一个组件,通过 Angular 服务切换另一个组件
- reactjs - Redux 表单初始化,但当我希望它不是 Pristine 时仍然保持 Pristine
- c++ - 如何使用 ClangCodeModel 插件在 QtCreator 中设置 C++ 标准?