Bhailu
Bhailu

Reputation: 45

PDFBox Error After Deleting Image - An error exists on this page. Acrobat may not display the page correctly

I am using the pdfbox library 2.0 version. I have to remove the selected image from the page and add another image. It works properly. But when I open that file it shows a warning message: An error exists on this page. Acrobat may not display the page correctly. and the screenshot is as below:

Error Image

Herewith sharing the code to delete an image and add other image:(EDITTED with Fix)

public static void removeImages(String pdfFile) throws Exception {
        PDDocument document = PDDocument.load(new File(pdfFile));

        for (PDPage page : document.getPages()) {
            PDResources pdResources = page.getResources();
            String[] qrCodeCosName = new String[1];

            pdResources.getXObjectNames().forEach(propertyName -> {
                if (!pdResources.isImageXObject(propertyName)) {
                    return;
                }
                PDXObject o;
                try {
                    o = pdResources.getXObject(propertyName);
                    if (o instanceof PDImageXObject) {
                        PDImageXObject pdImageXObject = (PDImageXObject) o;
                        if (pdImageXObject.getMetadata() != null) {
                            // TO REMOVE FROM RESOURCE
                            ((COSDictionary) pdResources.getCOSObject().getDictionaryObject(COSName.XOBJECT))
                                    .removeItem(propertyName);
                            qrCodeCosName[0] = propertyName.getName();
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });

            PDFStreamParser parser = new PDFStreamParser(page);
            parser.parse();
            List<Object> tokens = parser.getTokens();
            System.out.println("Original tokens size" + tokens.size());
            List<Object> newTokens = new ArrayList<Object>();

            for (int j = 0; j < tokens.size(); j++) {
                Object token = tokens.get(j);

                if (token instanceof Operator) {
                    Operator op = (Operator) token;

                    // find image - remove it
                    if (op.getName().equals("Do")) {
                        COSName cosName = (COSName) tokens.get(j - 1);
                        if (cosName.getName().equals(qrCodeCosName[0])) {
                            newTokens.remove(newTokens.size() - 1);
                            continue;
                        }
                    }
                    newTokens.add(token);
                }

                System.out.println("tokens size" + newTokens.size());
                PDStream newContents = new PDStream(document);
                OutputStream out = newContents.createOutputStream();
                ContentStreamWriter writer = new ContentStreamWriter(out);
                writer.writeTokens(newTokens);
                out.close();
                page.setContents(newContents);

                // ADD OTHER IMAGE
                PDImageXObject pdImage = PDImageXObject.createFromFile("D:\\copy\\ind.png", document);

                PDPageContentStream contents = new PDPageContentStream(document, page,
                        PDPageContentStream.AppendMode.PREPEND, true, true);

                contents.saveGraphicsState();
                // Drawing the image in the PDF document
                contents.drawImage(pdImage, 0, 0, 50, 30);
                contents.restoreGraphicsState();

                System.out.println("Image inserted Successfully.");

                // Closing the PDPageContentStream object
                contents.close();

            }

            document.save("RemoveImage.pdf");
            document.close();
        }
    }

Kindly help me with this. Also, looking forward for other code review comments about required changes to make this operation properly. :)

Upvotes: 2

Views: 247

Answers (1)

Bhailu
Bhailu

Reputation: 45

As per @Tilman Hausherr suggestion below code works for me:

public static void removeImages(String pdfFile) throws Exception {
        PDDocument document = PDDocument.load(new File(pdfFile));

        for (PDPage page : document.getPages()) {
            PDResources pdResources = page.getResources();
            String[] qrCodeCosName = new String[1];

            pdResources.getXObjectNames().forEach(propertyName -> {
                if (!pdResources.isImageXObject(propertyName)) {
                    return;
                }
                PDXObject o;
                try {
                    o = pdResources.getXObject(propertyName);
                    if (o instanceof PDImageXObject) {
                        PDImageXObject pdImageXObject = (PDImageXObject) o;
                        if (pdImageXObject.getMetadata() != null) {
                            // TO REMOVE FROM RESOURCE
                            ((COSDictionary) pdResources.getCOSObject().getDictionaryObject(COSName.XOBJECT))
                                    .removeItem(propertyName);
                            qrCodeCosName[0] = propertyName.getName();
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });

            PDFStreamParser parser = new PDFStreamParser(page);
            parser.parse();
            List<Object> tokens = parser.getTokens();
            System.out.println("Original tokens size" + tokens.size());
            List<Object> newTokens = new ArrayList<Object>();

            for (int j = 0; j < tokens.size(); j++) {
                Object token = tokens.get(j);

                if (token instanceof Operator) {
                    Operator op = (Operator) token;

                    // find image - remove it
                    if (op.getName().equals("Do")) {
                        COSName cosName = (COSName) tokens.get(j - 1);
                        if (cosName.getName().equals(qrCodeCosName[0])) {
                            newTokens.remove(newTokens.size() - 1);
                            continue;
                        }
                    }
                    newTokens.add(token);
                }

                System.out.println("tokens size" + newTokens.size());
                PDStream newContents = new PDStream(document);
                OutputStream out = newContents.createOutputStream();
                ContentStreamWriter writer = new ContentStreamWriter(out);
                writer.writeTokens(newTokens);
                out.close();
                page.setContents(newContents);

                // ADD OTHER IMAGE
                PDImageXObject pdImage = PDImageXObject.createFromFile("D:\\copy\\ind.png", document);

                PDPageContentStream contents = new PDPageContentStream(document, page,
                        PDPageContentStream.AppendMode.PREPEND, true, true);

                contents.saveGraphicsState();
                // Drawing the image in the PDF document
                contents.drawImage(pdImage, 0, 0, 50, 30);
                contents.restoreGraphicsState();

                System.out.println("Image inserted Successfully.");

                // Closing the PDPageContentStream object
                contents.close();

            }

            document.save("RemoveImage.pdf");
            document.close();
        }
    }

Upvotes: 1

Related Questions