Ошибка PDFBox после удаления изображения — на этой странице существует ошибка. Acrobat может неправильно отображать страницу

#java #pdfbox

#java #pdfbox ( pdf-файл) #pdfbox

Вопрос:

Я использую библиотеку pdfbox версии 2.0. Я должен удалить выбранное изображение со страницы и добавить другое изображение. Он работает правильно. Но когда я открываю этот файл, он показывает предупреждающее сообщение: на этой странице существует ошибка. Acrobat может неправильно отображать страницу. и скриншот выглядит так, как показано ниже:

Изображение с ошибкой

При этом разделяем код для удаления изображения и добавления другого изображения: (ОТРЕДАКТИРОВАНО с исправлением)

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

Пожалуйста, помогите мне с этим.
Кроме того, с нетерпением ждем других комментариев по обзору кода о необходимых изменениях для правильного выполнения этой операции. 🙂

Комментарии:

1. Я думаю, что «if (token instanceof COSName)» неверно, вам нужно проверить «Do», который является оператором. Смотрите Пример RemoveAllText.

2. @Tilman Hausherr Да, это правильно. Но. тогда как это будет происходить, если потребуется удалить конкретное изображение. Я хотел сказать, что при циклическом просмотре всех токенов , как мы можем определить целевой объект PDImageXObject, подлежащий удалению.

3. Вам нужно сравнить имя с именем изображения. Это имя является предыдущим токеном.

4. @Tilman Hausherr Спасибо. Согласно вашему ответу, я узнал, что как мы можем получить имя ресурсов во время итерации по нему. Это решило мою проблему.

Ответ №1:

Согласно предложению @Tilman Hausherr, приведенный ниже код работает для меня:

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