title: PDFBox 2.0.8 - Extracting an image from one document and using it in another
body: <p>I am writing a Java application to work as a template reader and writer. I have had success with working with text, but having some dificulty with the images...</p>
  
  <p>Getting the images was the easy part - using a class extending PDFStreamEngine</p>
  
  <pre><code>package readingPdf;
  
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.List;
  
  import org.apache.pdfbox.contentstream.PDFStreamEngine;
  import org.apache.pdfbox.contentstream.operator.DrawObject;
  import org.apache.pdfbox.contentstream.operator.Operator;
  import org.apache.pdfbox.contentstream.operator.state.Concatenate;
  import org.apache.pdfbox.contentstream.operator.state.Restore;
  import org.apache.pdfbox.contentstream.operator.state.Save;
  import org.apache.pdfbox.contentstream.operator.state.SetGraphicsStateParameters;
  import org.apache.pdfbox.contentstream.operator.state.SetMatrix;
  import org.apache.pdfbox.cos.COSBase;
  import org.apache.pdfbox.cos.COSName;
  import org.apache.pdfbox.pdmodel.graphics.PDXObject;
  import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
  import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
  import org.apache.pdfbox.util.Matrix;
  
  public class ImageStripper extends PDFStreamEngine {
  
      ArrayList&lt;Object  []&gt; imagesData = null;
      public ImageStripper() throws IOException {
          // preparing PDFStreamEngine
          addOperator(new Concatenate());
          addOperator(new DrawObject());
          addOperator(new SetGraphicsStateParameters());
          addOperator(new Save());
          addOperator(new Restore());
          addOperator(new SetMatrix());
          imagesData = new ArrayList&lt;Object[]&gt;();
      }
  
      @Override
      protected void processOperator(Operator operator, List&lt;COSBase&gt; operands) throws IOException {
          String operation = operator.getName();
          if ("Do".equals(operation)) {
              COSName objectName = (COSName) operands.get(0);
              // get the PDF object
              PDXObject xobject = getResources().getXObject(objectName);
              // check if the object is an image object
              if (xobject instanceof PDImageXObject) {
                  Object[] imageData = new Object[3];
                  PDImageXObject image = (PDImageXObject) xobject;
  
                  Matrix ctmNew = getGraphicsState().getCurrentTransformationMatrix();
  
                  // position of image in the pdf in terms of user space units
                  System.out.println("position in PDF = " + ctmNew.getTranslateX() + ", " + ctmNew.getTranslateY()
                          + " in user space units");
  
                  imageData[0] = ctmNew.getTranslateX();// xPos
                  imageData[1] = ctmNew.getTranslateY();// yPos
  
                  imageData[2] = image;//Image
  
                  imagesData.add(imageData);
  
              } else if (xobject instanceof PDFormXObject) {
                  PDFormXObject form = (PDFormXObject) xobject;
                  showForm(form);
              }
          } else {
              super.processOperator(operator, operands);
          }
      }
  
      public ArrayList&lt;Object[]&gt; getImagesList(){
          return imagesData;
      }
  }
  </code></pre>
  
  <p>next is the implementation thereof</p>
  
  <pre><code>public class PDFManager{
  
      private PDFParser parser;
      private PDDocument pdDoc;
      private PDDocument retDoc;
      private COSDocument cosDoc;
      private PDPage page;
      private String filePath;
      private File file; 
  
      public PDDocument transferImage() throws IOException {
          this.pdDoc = null;
          this.cosDoc = null;
  
          file = new File(filePath);
          parser = new PDFParser(new RandomAccessFile(file, "r"));
          parser.parse();
          cosDoc = parser.getDocument();
          pdDoc = new PDDocument(cosDoc);
  
          //Get Image Data
          ImageStripper imageStripper = new ImageStripper();
          imageStripper.processPage(pdDoc.getPage(0));
          ArrayList&lt;Object []&gt; imageList = imageStripper.getImagesList();
  
          //Close Doc
          pdDoc.close();
          cosDoc.close();
  
          //Create new PDF Doc
          retDoc = new PDDocument();
          page = new PDPage(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth())); 
          retDoc.addPage(page);
  
          PDPageContentStream cs = new PDPageContentStream(retDoc, page, AppendMode.OVERWRITE, true);
  
          for(int pos = 0; pos &lt; imageList.size() ; pos++) {
              Object [] imageData = imageList.get(pos);
  
              float xPos = (float)imageData[0];
              float yPos = (float)imageData[1];
              PDImageXObject image = (PDImageXObject)imageData[2];
              cs.drawImage(image, xPos, yPos);
          }
  
          cs.close();
          return retDoc;
      }
  
      public static void main(String[] args) throws IOException {
  
          PDFManager pdfManager = new PDFManager();
  
          PDDocument doc =pdfManager.ToText("c:\\test\\test.pdf"); 
  
          doc.save("c:\\test\\test2.pdf");
          doc.close();
      }
  }
  </code></pre>
  
  <p>Now the problem comes in at the point where I am writing calling the <code>cs.drawImage</code>. All the code executes without any issue except when trying to save the new file... I get the exception <code>COSStream has been closed and cannot be read. Perhaps its enclosing PDDocument has been closed?</code></p>
  
  <p>I suspect that there is still metadata linking the image to the original Document it was extracted from as calling <code>PDImageXobject.createFromFile("c:\\test\\testImage.png", doc)</code> returns a new instance of <code>PDImageXObject</code> which writes perfectly. As the <code>PDDocument</code> that gets written to gets passed into the <code>PDImageXObject</code> I suspect it gets linked in some way or another.</p>
  
  <p>I can not save the image to a temp location as this is just testing for a POC.</p>
  
  <p>Any assistance would be appreciated</p>