I seem to have a workaround. The solution is that when a PDF page has
markup, use PDFRenderer to create a BufferedImage of the page at 300dpi,
add the markup to the image (adjusting the markup to 300dpi), add the image
to a new PDpage, and add that new page to outDocument. If there is no
markup, I just add the inDocument PDPage to outDocument.

There's a time-image quality tradeoff, but I don't know if working Overlay
would be faster. 300dpi seems to be good enough for my purposes.

On Thu, Oct 21, 2021 at 11:21 AM Thad Humphries <thad.humphr...@gmail.com>
wrote:

> Yes, I can do that. It was meant as a simple illustration. The problem
> returns when there are intermediate PDDocuments inside the for-loop
>
> I must create intermediary PDDocuments in order to Overlay a BufferedImage
> onto each page. Even that can work if the overlay is the same for each page
> *and* I don't close the overlay in the for-loop. But in my case the image
> will change with each page.
>
> So this function works:
>
>   @Test
>
>   *public* *void* testCopyAnnotationOverlay() *throws* Exception {
>
>     File inPdfFile = *new* File(*this*.getClass().getResource(
> "/patent-3_139_857.pdf").toURI());
>
>     PDDocument inDocument = PDDocument.*load*(inPdfFile);
>
>
>     BufferedImage imageOverlay = ImageIO.*read*(*new* File(*this*
> .getClass().getResource("/sample-annotation.png").toURI()));
>
>
>     PDDocument outDocument = *new* PDDocument();
>
>     *int* pages = inDocument.getNumberOfPages();
>
>
>
>     PDDocument overlayDocument;
>
>     *for* (*int* page = 0; page < pages; page++) {
>
>       PDPage pdPage = inDocument.getPage(page);
>
>
>       // Draw an image into a PDF page.
>
>       PDPage imagePage = *new* PDPage(pdPage.getCropBox());
>
>       PDDocument imageDocument = *new* PDDocument();
>
>       imageDocument.addPage(imagePage);
>
>       PDPageContentStream cos = *new* PDPageContentStream(imageDocument,
> imagePage);
>
>       PDImageXObject ximage = LosslessFactory.*createFromImage*(
> imageDocument, imageOverlay);
>
>       cos.drawImage(ximage, 0, 0);
>
>       cos.close(); // this also close imageDocument
>
>
>
>       overlayDocument = *new* PDDocument();
>
>       overlayDocument.addPage(pdPage);
>
>       Overlay overlay = *new* Overlay();
>
>       overlay.setInputPDF(overlayDocument);
>
>       overlay.setOverlayPosition(Overlay.Position.*FOREGROUND*);
>
>       overlay.setAllPagesOverlayPDF(imageDocument);
>
>       HashMap<Integer, String> overlayProps = *new* HashMap<Integer,
> String>();
>
>       overlay.overlay(overlayProps);
>
>
>
>       outDocument.importPage(overlayDocument.getPage(0));
>
> //      overlay.close();
>
>     }
>
>     outDocument.save(*OUT_DIR* + "/out-pdf-patent.pdf");
>
>     inDocument.close();
>
>     outDocument.close();
>
>     Assert.*assertTrue*(*true*);
>
>   }
>
> Note the commented out "overlay.close()". Leave that in and there will be
> a COSStream error on save(). (Let the JVM clean it up.)
>
> Now alter the function so that "imageOverlay" is created inside the
> for-loop (because I'll have a different markup on each page). There will be
> a COSStream error on save(), even if I also comment out "cos.close()".
>
> On Thu, Oct 21, 2021 at 2:06 AM Tilman Hausherr <thaush...@t-online.de>
> wrote:
>
>> close inDocument after saving the other.
>>
>> Tilman
>>
>> Am 20.10.2021 um 21:15 schrieb Thad Humphries:
>> > I am using PDFBox 2.0.24. I am attempting to copy a PDF file to a new
>> > PDDocument and save that new document. The eventual goal is to use
>> Overlay
>> > to overlay various images onto pages of the old document  before
>> > adding them to the new document.
>> >
>> >
>> > The problem I'm having is that when I close the old document or any
>> > intermediary document (like one created when making the Overlay), I get
>> an
>> > error "COSStream has been closed and cannot be read" when I save the new
>> > document.
>> >
>> >
>> > I can demonstrate this error simply with just a simple function:
>> >
>> >
>> >    @Test
>> >
>> >    *public* *void* testCopyAnnotation() *throws* Exception {
>> >
>> >      File inPdfFile = *new* File(*this*.getClass().getResource(
>> > "/patent-3_139_857.pdf").toURI());
>> >
>> >      PDDocument inDocument = PDDocument.*load*(inPdfFile);
>> >
>> >      PDDocument outDocument = *new* PDDocument();
>> >
>> >      *int* pages = inDocument.getNumberOfPages();
>> >
>> >      *for* (*int* page = 0; page < pages; page++) {
>> >
>> >        PDPage pdPage = inDocument.getPage(page);
>> >
>> >        outDocument.importPage(pdPage);
>> >
>> >      }
>> >
>> >      inDocument.close();
>> >
>> >      outDocument.save(*OUT_DIR* + "/out-pdf-patente.pdf");
>> >
>> >      outDocument.close();
>> >
>> >      Assert.*assertTrue*(*true*);
>> >
>> >    }
>> >
>> >
>> > The stack trace below is triggered by the line
>> "outDocument.save(*OUT_DIR*
>> >   + "/out-pdf-patente.pdf");".
>> >
>> >
>> > What is wrong here and how might I correct this?
>> >
>> >
>> > *java.io.IOException*: COSStream has been closed and cannot be read.
>> > Perhaps its enclosing PDDocument has been closed?
>> >
>> > at org.apache.pdfbox.cos.COSStream.checkClosed(COSStream.java:83)
>> >
>> > at
>> org.apache.pdfbox.cos.COSStream.createRawInputStream(COSStream.java:133)
>> >
>> > at
>> org.apache.pdfbox.pdfwriter.COSWriter.visitFromStream(COSWriter.java:1268
>> > )
>> >
>> > at org.apache.pdfbox.cos.COSStream.accept(COSStream.java:416)
>> >
>> > at org.apache.pdfbox.cos.COSObject.accept(COSObject.java:158)
>> >
>> > at
>> org.apache.pdfbox.pdfwriter.COSWriter.doWriteObject(COSWriter.java:572)
>> >
>> > at
>> org.apache.pdfbox.pdfwriter.COSWriter.doWriteObjects(COSWriter.java:497)
>> >
>> > at org.apache.pdfbox.pdfwriter.COSWriter.doWriteBody(COSWriter.java:481)
>> >
>> > at org.apache.pdfbox.pdfwriter.COSWriter.visitFromDocument(
>> > COSWriter.java:1162)
>> >
>> > at org.apache.pdfbox.cos.COSDocument.accept(COSDocument.java:452)
>> >
>> > at org.apache.pdfbox.pdfwriter.COSWriter.write(COSWriter.java:1435)
>> >
>> > at org.apache.pdfbox.pdfwriter.COSWriter.write(COSWriter.java:1322)
>> >
>> > at org.apache.pdfbox.pdmodel.PDDocument.save(PDDocument.java:1375)
>> >
>> > at org.apache.pdfbox.pdmodel.PDDocument.save(PDDocument.java:1342)
>> >
>> > at org.apache.pdfbox.pdmodel.PDDocument.save(PDDocument.java:1326)
>> >
>> >     -->> at com.optix.server.rest.TestFileServlet.testCopyAnnotation(
>> > TestFileServlet.java:152)
>> >
>> > at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>> >
>> > at sun.reflect.NativeMethodAccessorImpl.invoke(
>> > NativeMethodAccessorImpl.java:62)
>> >
>> > at sun.reflect.DelegatingMethodAccessorImpl.invoke(
>> > DelegatingMethodAccessorImpl.java:43)
>> >
>> > at java.lang.reflect.Method.invoke(Method.java:498)
>> >
>> > at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(
>> > FrameworkMethod.java:50)
>> >
>> > at org.junit.internal.runners.model.ReflectiveCallable.run(
>> > ReflectiveCallable.java:12)
>> >
>> > at org.junit.runners.model.FrameworkMethod.invokeExplosively(
>> > FrameworkMethod.java:47)
>> >
>> > at org.junit.internal.runners.statements.InvokeMethod.evaluate(
>> > InvokeMethod.java:17)
>> >
>> > at org.junit.internal.runners.statements.RunBefores.evaluate(
>> > RunBefores.java:26)
>> >
>> > at org.junit.internal.runners.statements.RunAfters.evaluate(
>> > RunAfters.java:27)
>> >
>> > at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
>> >
>> > at org.junit.rules.RunRules.evaluate(RunRules.java:20)
>> >
>> > at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
>> >
>> > at org.junit.runners.BlockJUnit4ClassRunner.runChild(
>> > BlockJUnit4ClassRunner.java:78)
>> >
>> > at org.junit.runners.BlockJUnit4ClassRunner.runChild(
>> > BlockJUnit4ClassRunner.java:57)
>> >
>> > at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
>> >
>> > at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
>> >
>> > at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
>> >
>> > at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
>> >
>> > at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
>> >
>> > at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
>> >
>> > at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(
>> > JUnit4TestReference.java:93)
>> >
>> > at org.eclipse.jdt.internal.junit.runner.TestExecution.run(
>> > TestExecution.java:40)
>> >
>> > at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(
>> > RemoteTestRunner.java:529)
>> >
>> > at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(
>> > RemoteTestRunner.java:756)
>> >
>> > at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(
>> > RemoteTestRunner.java:452)
>> >
>> > at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(
>> > RemoteTestRunner.java:210)
>> >
>> >
>> >
>> >
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscr...@pdfbox.apache.org
>> For additional commands, e-mail: users-h...@pdfbox.apache.org
>>
>>
>
> --
> "Hell hath no limits, nor is circumscrib'd In one self-place; but where we
> are is hell, And where hell is, there must we ever be" --Christopher
> Marlowe, *Doctor Faustus* (v. 111-13)
>


-- 
"Hell hath no limits, nor is circumscrib'd In one self-place; but where we
are is hell, And where hell is, there must we ever be" --Christopher
Marlowe, *Doctor Faustus* (v. 111-13)

Reply via email to