java - 删除图像后 PDFBox 错误 - 此页面存在错误。Acrobat 可能无法正确显示页面
问题描述
我正在使用 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();
}
}
请帮我解决这个问题。 此外,期待其他代码审查评论关于正确执行此操作所需的更改。:)
解决方案
根据@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();
}
}
推荐阅读
- python-3.x - 如何在 python 3 中创建具有特定内容的模拟文件
- excel - 自动过滤可见细胞的 VLOOKUP
- arrays - Excel Match Multiple Criteria Lookup Array:从列表中查找包含所有值的列,并返回列在数组中的位置
- web-scraping - scrapy文件管道下载文件并覆盖它
- javascript - 如何将 Array.prototype.filter 与对象一起使用
- amazon-web-services - 推动放大环境后的 grequests 问题
- reactjs - 在 React 上刷新后保持在同一个 TabPanel 上
- typescript - 在 TypeScript 中使用 MemoryDescriptor(用于 new WebAssembly.Memory())
- python - 如何保存 AzureML Pipelines 的输出
- python - 当键指向数组时遍历字典键?