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