Java iText skaliert Dokument auf A4
Ich habe die folgende Methode, mit der alle Seiten eines Dokuments auf A4-Seitenabmessungen "angepasst" werden:
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");
}
}
Dies funktioniert jedoch nicht wie erwartet. Die Seiten werden in A4 (297 x 210) umgewandelt. Der Inhalt wird jedoch nicht in das Format (skaliert) eingepasst. Der Inhalt wird zugeschnitten angezeigt, da die Originalseiten größer als 297 x 210 sind. Wie kann ich das beheben?
Antworten
In einem Kommentar haben Sie klargestellt
Ich möchte, dass der Begrenzungsrahmen des vorherigen Inhalts skaliert und dem Ziel ein Rand hinzugefügt wird
Wir müssen also zuerst den Begrenzungsrahmen des ursprünglichen Seiteninhalts bestimmen . Dies kann mit der MarginFinderKlasse aus dieser Antwort erfolgen . Achtung: Diese Klasse bestimmt den Begrenzungsrahmen für alle Inhalte, auch wenn es sich lediglich um ein weißes Rechteck handelt, das sich visuell nicht von keinem Inhalt oder etwas unterscheidet, das sich früher außerhalb des Zuschneidefelds befand. Wenn Ihr Anwendungsfall dies erfordert, müssen Sie diese Klasse möglicherweise erweitern auch solche Umstände zu berücksichtigen.
Nachdem der Inhaltsbegrenzungsrahmen festgelegt wurde, bleibt nur noch ein wenig Berechnung.
Die folgende Methode bestimmt den Begrenzungsrahmen mithilfe der obigen Klasse, transformiert den Inhalt entsprechend und ändert den Ergebnis-Zuschneidebereich.
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- Methode scale)
Für eine A4-Ergebnisseitengröße mit einem Zoll Rand auf jeder Seite können Sie dies folgendermaßen nennen PdfDocument pdfDocument:
Rectangle pageSize = PageSize.A4;
Rectangle pageBodySize = pageSize.clone().applyMargins(72, 72, 72, 72, false);
scale(pdfDocument, pageSize, pageBodySize);
(Auszug aus dem ScaleToA4- Test testFdaRequiresUseOfEctdFormatAndStandardizedStudyDataInFutureRegulatorySubmissionsSept)