Java iText中没有关联的PdfWriter用于创建间接对象。

huangapple go评论74阅读模式
英文:

Java iText There is no associate PdfWriter for making indirects

问题

我有以下方法将图像缩放到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("无法使用边界框 %s 缩放页面 %d 内容\n", boundingBox, i);
            continue;
        } else {
            // 缩放并移动内容到带有页边距的A4页面
            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);
    }
}

这个方法在下面的代码片段中被调用:

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();

然而,当它执行最后的代码时:

new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDocument)
        .concatMatrix(transform);

它会抛出一个PDF异常: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:?]

我应该如何修复这个问题?我做错了什么吗?

英文:

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 &lt;= 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(&quot;Cannot scale page %d contents with bounding box %s\n&quot;, 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 &lt; 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 &lt;= 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 ?

答案1

得分: 1

你在每个pdfDocuments中的PdfDocument doc上调用

scale(doc, pageSize, pageBodySize);

因此,在将页面复制到mergedPdf后,您尝试调整源文档中的页面。您不能调整源PdfDocument实例中的页面,因为它们以只读方式打开(即仅使用PdfReader打开,而没有PdfWriter),而在复制之后这样做也没有意义,因为您肯定希望调整结果mergedPdf中的内容,而不是源文档中的内容。

因此,将以下代码块移到外部for循环体之外,在循环之后,并将最后一行替换为

scale(mergedPdf, pageSize, pageBodySize);

以调整生成的合并PDF的大小。

英文:

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.

huangapple
  • 本文由 发表于 2020年8月25日 17:39:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/63576068.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定