I have the following method that scales an image to A4
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);
}
}
This method is invoked/called in this snippet :
ByteArrayOutputStream mergedPdfStream = new ByteArrayOutputStream();
PdfDocument mergedPdf = new PdfDocument(new PdfWriter(mergedPdfStream));
for (PdfDocument doc : pdfDocuments) {
int n = doc.getNumberOfPages();
for (int i = 1; i <= n; i++) {
PdfPage page = doc.getPage(i).copyTo(mergedPdf);
mergedPdf.addPage(page);
}
Rectangle pageSize = PageSize.A4;
Rectangle pageBodySize = pageSize.clone().applyMargins(72, 72, 72, 72, false);
scale(doc, pageSize, pageBodySize);
}
mergedPdf.close();
However , when it performs this code at the end
new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDocument)
.concatMatrix(transform);
It throws an PDF Exception There is no associate PdfWriter for making indirects:
com.itextpdf.kernel.PdfException: There is no associate PdfWriter for making indirects.
at com.itextpdf.kernel.pdf.PdfObject.makeIndirect(PdfObject.java:228) ~[kernel-7.1.1.jar:?]
at com.itextpdf.kernel.pdf.PdfObject.makeIndirect(PdfObject.java:248) ~[kernel-7.1.1.jar:?]
at com.itextpdf.kernel.pdf.PdfPage.newContentStream(PdfPage.java:1186) ~[kernel-7.1.1.jar:?]
at com.itextpdf.kernel.pdf.PdfPage.newContentStreamBefore(PdfPage.java:244) ~[kernel-7.1.1.jar:?]
How can I fix this problem? Am I doing something wrong ?
You call
scale(doc, pageSize, pageBodySize);
for each PdfDocument doc
in pdfDocuments
. So after copying the pages to mergedPdf
you try to scale the pages in your source documents. You cannot scale the pages in your source PdfDocument
instances as they are opened read-only (i.e. only with a PdfReader
, without a PdfWriter
), and doing so after copying also doesn't make sense as you surely want to scale what's in the result mergedPdf
, not in the sources.
Thus, move the block
Rectangle pageSize = PageSize.A4;
Rectangle pageBodySize = pageSize.clone().applyMargins(72, 72, 72, 72, false);
scale(doc, pageSize, pageBodySize);
out of the outer for
loop body, after it, and replace the last line by
scale(mergedPdf, pageSize, pageBodySize);
to scale the resulting merged PDF.