1

I have added an icon as Image object into PDF page with OpenPdf that is based on iText core. Here is my code

            // inout stream from file
            InputStream inputStream = new FileInputStream(file);

            // we create a reader for a certain document
            PdfReader reader = new PdfReader(inputStream);

            // we create a stamper that will copy the document to a new file
            PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(file));

            // adding content to each page
            PdfContentByte over;

            // get watermark icon
            Image img = Image.getInstance(PublicFunction.getByteFromDrawable(context, R.drawable.ic_chat_lawone_new));
            img.setAnnotation(new Annotation(0, 0, 0, 0, "https://github.com/LibrePDF/OpenPDF"));
            img.setAbsolutePosition(pointF.x, pointF.y);
            img.scaleAbsolute(50, 50);

            // get page file number count
            int pageNumbers = reader.getNumberOfPages();

            if (pageNumbers < pageIndex) {
                // closing PdfStamper will generate the new PDF file
                stamp.close();
                throw new PDFException("page index is out of pdf file page numbers", new Throwable());
            }

            // annotation added into target page
            over = stamp.getOverContent(pageIndex);
            if (over == null) {
                stamp.close();
                throw new PDFException("getUnderContent is null", new Throwable());
            }

            over.addImage(img);

            // closing PdfStamper will generate the new PDF file
            stamp.close();

            // close reader
            reader.close();

template of added icon into pdf page

now I need to delete or update the color of added image object on user click, I have the click function that returns MotionEvent, now I need to delete or update or replace added image object.

Any Idea?!

Hamid Reza
  • 624
  • 7
  • 23

1 Answers1

0

In your parallel OpenPDF issue 464 you posted additionally:

Here my progress

Now I can achieve the XObjects added into pdf file, and I can remove them from pdf page this way:

       // inout stream from file
       InputStream inputStream = new FileInputStream(file);

       // we create a reader for a certain document
       PdfReader pdfReader = new PdfReader(inputStream);

       // get page file number count
       int pageNumbers = pdfReader.getNumberOfPages();

       // we create a stamper that will copy the document to a new file

       PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileOutputStream(file));

       // get page
       PdfDictionary page = pdfReader.getPageN(currPage);
       PdfDictionary resources = page.getAsDict(PdfName.RESOURCES);

       // get page resources
       PdfArray annots = resources.getAsArray(PdfName.ANNOTS);
       PdfDictionary xobjects = resources.getAsDict(PdfName.XOBJECT);

      // remove Xobjects
      for (PdfName key : xobjects.getKeys()) {
               xobjects.remove(key);
      }

      // remove annots
      for (PdfObject element : annots.getElements()) {
               annots.remove(0);
      }

      // close pdf stamper
      pdfStamper.close();

     // close pdf reader
     pdfReader.close();

So the XObjects will remove from the screen, but still there is a problem!!!

When I remove them and try to add a new one, last deleted object appears and add into the pdf page! REALLY!!! :))

I think there should be another place that these objects should be removed from.

What happens here is that you indeed do remove the bitmap image resources from the page:

      for (PdfName key : xobjects.getKeys()) {
               xobjects.remove(key);
      }

but you don't remove the instructions for drawing these resources from the content stream. This has two consequences:

  1. Your PDF strictly speaking becomes invalid as a resource is referenced from the content stream which is not defined in the page resources. Depending on the viewer in question this might result in warning messages.
  2. If the PDF is further processed and some new XObject is added to the same page with the same resource name, the original image drawing instruction now again has a resource to draw and makes it appear at the original position once more.

This explains your observation:

When I remove them and try to add a new one, last deleted object appears and add into the pdf page! REALLY!!! :))

I assume you used the same source image in your test, so it looked like the original image appeared again at the original position when actually the new image appeared there.

Thus, instead of merely removing the image XObject, you have the choice of either

  • also removing the XObject drawing instruction from the content stream or
  • replacing the image XObject by an invisible XObject instead.

The former option in general is non-trivial, in particular if your PDF-tool-to-be also allows other changes of the page content. In case of iText 5 or iText 7 I'd propose using the PdfContentStreamEditor (see here) / PdfCanvasEditor (see here) class to find and remove Do operations from the page content streams but I have no OpenPDF version of that class yet.

What you can do quite easily, though, is replacing the image resources by form XObjects without any content:

PdfTemplate pdfTemplate = PdfTemplate.createTemplate(pdfStamper.getWriter(), 1, 1);

// replace Xobjects
for (PdfName key : xobjects.getKeys()) {
    xobjects.put(key, pdfTemplate.getIndirectReference());
}

(RemoveImage test testRemoveImageAddedLikeHamidReza)


Beware, replacing all XObjects by empty XObjects has an obvious disadvantage, it replaces all XObjects, not merely the ones your tool created before! Thus, if the original PDFs processed by your tool also drew XObjects in their immediate content streams, those XObjects also are rendered invisible. If you don't want that, you need some specific criteria to recognize the image XObjects you added and only replace them.

Furthermore, there are other problems afoot: Each time you process the OverContent of a page in a PdfStamper, the pre-existing content of that page is wrapped into a q / Q (save-graphics-state / restore-graphics-state) envelope to prevent changes of the graphics state in that previous content bleed through and mix up your OverContent additions. Thus, if you manipulate a file many times in your tool, the original page content may be wrapped in a fairly deep nesting of such envelopes. Unfortunately PDF readers may support only a limited nesting depth, e.g. ISO 32000-1 mentions a maximum depth of 28 envelopes.

Thus, if you still have the chance to overhaul your design, you should consider putting the images into annotation appearances instead of into the page content. After all, you already do generate annotations, currently merely to transport a link, so you could also generate annotations with appearances.

mkl
  • 90,588
  • 15
  • 125
  • 265
  • Thanks for your replay. I have some progress here but I still have tiny problems. I will update my issues. can I have your email address @mkl? – Hamid Reza Jan 11 '21 at 09:31
  • I prefer to discuss questions in this regard on stack overflow to also provide the answers to others with the same questions. In case of additional information you don't want available publicly (e.g. example PDFs not meant for public availability) the e-mail address in my stack overflow profile description can be used when agreed upon. – mkl Jan 11 '21 at 10:20