英文:
PDFBox Error After Deleting Image - An error exists on this page. Acrobat may not display the page correctly
问题
我正在使用pdfbox库的2.0版本。我必须从页面中删除所选图像并添加另一个图像。它可以正常运行。但是当我打开该文件时,会显示一个警告消息:***此页面存在错误。Acrobat可能无法正确显示页面***。如下是屏幕截图:
![错误图片][1]
下面是删除图像并添加其他图像的代码示例:(已编辑并修复)
```java
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) {
// 从资源中移除
((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("原始 tokens 大小:" + 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;
// 找到图像 - 删除它
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 大小:" + newTokens.size());
PDStream newContents = new PDStream(document);
OutputStream out = newContents.createOutputStream();
ContentStreamWriter writer = new ContentStreamWriter(out);
writer.writeTokens(newTokens);
out.close();
page.setContents(newContents);
// 添加其他图像
PDImageXObject pdImage = PDImageXObject.createFromFile("D:\\copy\\ind.png", document);
PDPageContentStream contents = new PDPageContentStream(document, page,
PDPageContentStream.AppendMode.PREPEND, true, true);
contents.saveGraphicsState();
// 在PDF文档中绘制图像
contents.drawImage(pdImage, 0, 0, 50, 30);
contents.restoreGraphicsState();
System.out.println("成功插入图像。");
// 关闭 PDPageContentStream 对象
contents.close();
}
document.save("RemoveImage.pdf");
document.close();
}
}
请帮忙解决这个问题。
同时,期待关于其他代码审查意见,以使此操作正常运行。
[1]: https://i.stack.imgur.com/VJaec.png
<details>
<summary>英文:</summary>
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][1]
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.** :)
[1]: https://i.stack.imgur.com/VJaec.png
</details>
# 答案1
**得分**: 1
根据@Tilman Hausherr的建议,以下代码适用于我:
```java
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();
}
}
英文:
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();
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论