通过页面搜索使用的资源并删除它们
search used resources through page and remove them
我使用 this technique 从另一个源 pdf 将 acroform 导出到新的 pdf 文件。
只有你能用 acroform 得到的结果 pdf download here
我使用 pdfcompressor 在线网站压缩了这个 pdf(59Ko),我将它减少了 -64%。
这个网站似乎清理了资源中所有未使用的东西,这里是 PDFDebugger
的截图
我的问题是如何从 Resources[] 中获取 xobject 或字体,如果不从 Resources[] 中删除它们,如何检查它们是否在页面中的某处使用过。
如果在 PDPage 中搜索是否使用了某些资源很复杂,我如何简单地从 Resources[] 中删除 XObject 或 Font ?
虽然我无法在页面中搜索使用过的 xobject,但我只是尝试直接删除 COSObject 但它不起作用 ^^ :
for (PDPage page : document.getPages()) {
PDResources resources = page.getResources();
// all xobject form resources
for (COSName name : resources.getXObjectNames()) {
page.getCOSObject().removeItem(name); // NOT WORKS
}
// all font resources from pages
for (COSName name : resources.getFontNames()) {
if (resources.getFont(name) instanceof PDFont) {
page.getCOSObject().removeItem(name); // NOT WORKS
}
}
}
ps:@mkl 推荐后创建的问题
更新1
这是我必须从 pdf 中提取 acroform 的当前代码:
// 从原来的
创建 FORM
PDDocument documentSrc = PDDocument.load(new File("original.pdf"));;
PDAcroForm acroFormSrc = documentSrc.getDocumentCatalog().getAcroForm();
PDDocument documentDest = new PDDocument();
for (PDPage page : documentSrc.getPages()) {
PDPage destPage = new PDPage(PDRectangle.A4);
destPage.setMediaBox(page.getMediaBox());
destPage.setCropBox(page.getCropBox());
documentDest.addPage(destPage);
}
PDAcroForm acroFormDest = new PDAcroForm(documentDest);
acroFormDest.setCacheFields(true);
acroFormDest.setFields(acroFormSrc.getFields());
documentDest.getDocumentCatalog().setAcroForm(acroFormDest);
int pageIndex = 0;
for (PDPage page : documentSrc.getPages()) {
documentDest.getPage(pageIndex).setAnnotations(page.getAnnotations());
// after disabling this size increase
//documentDest.getPage(pageIndex).setResources(page.getResources());
pageIndex++;
}
acroFormDest.setDefaultAppearance(acroFormSrc.getDefaultAppearance());
acroFormDest.setDefaultResources(acroFormSrc.getDefaultResources());
acroFormDest.setQ(acroFormSrc.getQ());
// this is disabled because setResources is disabled above
//removeLinksInPages(documentDest);
//removeTextInDocument(documentDest);
这次没有资源的表格是73Ko,而我原来的pdf是75Ko。
减少您的 页面对象的资源
嗯,我认为你当前的任务比你在问题中要求的要简单得多。我解读你的
I use this technique to export acroform to new pdf file from another source pdf.
暗示您真的只想将 AcroForm 字段和功能从一个 PDF 转移到另一个 PDF,对原始文件的静态页面内容不感兴趣。
因此,您实际使用了哪些页面资源这个问题的答案很简单:None!页面资源是您不感兴趣的静态内容(页面内容流中)使用的资源。
因此,无需首先将页面资源复制到您的新文档中,只需删除行
documentDest.getPage(pageIndex).setResources(page.getResources());
来自参考答案中的代码。
顺便说一句:@Tilman 已经在对您用作模板的答案的评论中指出,感兴趣的资源是 "default resources of the acroform",而不是页面资源 .因此,您可能不仅要复制 PDAcroForm
个实例之间的字段:
acroFormDest.setFields(acroFormSrc.getFields());
还有默认资源、默认外观和默认四边形
acroFormDest.setDefaultAppearance(acroFormSrc.getDefaultAppearance());
acroFormDest.setDefaultResources(acroFormSrc.getDefaultResources());
acroFormDest.setQ(acroFormSrc.getQ());
其他问题
注释指向错误的页面
This time form-without-resources is 73Ko while my original pdf is 75Ko.
更深入地了解您的 "form-without-resources.pdf" 问题变得很清楚:
如您所见,您的字段小部件注释指向错误的页面!
即P值指定为
P
dictionary
(Optional except as noted below; PDF 1.3; not used in FDF files) An indirect reference to the page object with which this annotation is associated.
(ISO 32000-1, Table 164 – Entries common to all annotation dictionaries)
因此,您将目标页面的注释设置为源页面的注释,但 P 值中的那些注释仍然引用源页面。因此,您可以通过此引用将源页面及其所有资源拖到新文档中。因此,您的结果文件并不比您的源文件小一点也就不足为奇了。
如果您更改代码以更正 P 引用,例如像这样:
int pageIndex = 0;
for (PDPage page : documentSrc.getPages()) {
PDPage destPage = documentDest.getPage(pageIndex);
destPage.setAnnotations(page.getAnnotations());
for (PDAnnotation annotation : destPage.getAnnotations())
annotation.setPage(destPage);
// after disabling this size increase
//documentDest.getPage(pageIndex).setResources(page.getResources());
pageIndex++;
}
(CopyForm 测试 testCopyLikeBeeImproved
)
您将丢失这些对旧数据的引用。
我使用 this technique 从另一个源 pdf 将 acroform 导出到新的 pdf 文件。
只有你能用 acroform 得到的结果 pdf download here
我使用 pdfcompressor 在线网站压缩了这个 pdf(59Ko),我将它减少了 -64%。 这个网站似乎清理了资源中所有未使用的东西,这里是 PDFDebugger
的截图我的问题是如何从 Resources[] 中获取 xobject 或字体,如果不从 Resources[] 中删除它们,如何检查它们是否在页面中的某处使用过。
如果在 PDPage 中搜索是否使用了某些资源很复杂,我如何简单地从 Resources[] 中删除 XObject 或 Font ?
虽然我无法在页面中搜索使用过的 xobject,但我只是尝试直接删除 COSObject 但它不起作用 ^^ :
for (PDPage page : document.getPages()) {
PDResources resources = page.getResources();
// all xobject form resources
for (COSName name : resources.getXObjectNames()) {
page.getCOSObject().removeItem(name); // NOT WORKS
}
// all font resources from pages
for (COSName name : resources.getFontNames()) {
if (resources.getFont(name) instanceof PDFont) {
page.getCOSObject().removeItem(name); // NOT WORKS
}
}
}
ps:@mkl 推荐后创建的问题
更新1
这是我必须从 pdf 中提取 acroform 的当前代码: // 从原来的
创建 FORMPDDocument documentSrc = PDDocument.load(new File("original.pdf"));;
PDAcroForm acroFormSrc = documentSrc.getDocumentCatalog().getAcroForm();
PDDocument documentDest = new PDDocument();
for (PDPage page : documentSrc.getPages()) {
PDPage destPage = new PDPage(PDRectangle.A4);
destPage.setMediaBox(page.getMediaBox());
destPage.setCropBox(page.getCropBox());
documentDest.addPage(destPage);
}
PDAcroForm acroFormDest = new PDAcroForm(documentDest);
acroFormDest.setCacheFields(true);
acroFormDest.setFields(acroFormSrc.getFields());
documentDest.getDocumentCatalog().setAcroForm(acroFormDest);
int pageIndex = 0;
for (PDPage page : documentSrc.getPages()) {
documentDest.getPage(pageIndex).setAnnotations(page.getAnnotations());
// after disabling this size increase
//documentDest.getPage(pageIndex).setResources(page.getResources());
pageIndex++;
}
acroFormDest.setDefaultAppearance(acroFormSrc.getDefaultAppearance());
acroFormDest.setDefaultResources(acroFormSrc.getDefaultResources());
acroFormDest.setQ(acroFormSrc.getQ());
// this is disabled because setResources is disabled above
//removeLinksInPages(documentDest);
//removeTextInDocument(documentDest);
这次没有资源的表格是73Ko,而我原来的pdf是75Ko。
减少您的 页面对象的资源
嗯,我认为你当前的任务比你在问题中要求的要简单得多。我解读你的
I use this technique to export acroform to new pdf file from another source pdf.
暗示您真的只想将 AcroForm 字段和功能从一个 PDF 转移到另一个 PDF,对原始文件的静态页面内容不感兴趣。
因此,您实际使用了哪些页面资源这个问题的答案很简单:None!页面资源是您不感兴趣的静态内容(页面内容流中)使用的资源。
因此,无需首先将页面资源复制到您的新文档中,只需删除行
documentDest.getPage(pageIndex).setResources(page.getResources());
来自参考答案中的代码。
顺便说一句:@Tilman 已经在对您用作模板的答案的评论中指出,感兴趣的资源是 "default resources of the acroform",而不是页面资源 .因此,您可能不仅要复制 PDAcroForm
个实例之间的字段:
acroFormDest.setFields(acroFormSrc.getFields());
还有默认资源、默认外观和默认四边形
acroFormDest.setDefaultAppearance(acroFormSrc.getDefaultAppearance());
acroFormDest.setDefaultResources(acroFormSrc.getDefaultResources());
acroFormDest.setQ(acroFormSrc.getQ());
其他问题
注释指向错误的页面
This time form-without-resources is 73Ko while my original pdf is 75Ko.
更深入地了解您的 "form-without-resources.pdf" 问题变得很清楚:
如您所见,您的字段小部件注释指向错误的页面!
即P值指定为
P dictionary (Optional except as noted below; PDF 1.3; not used in FDF files) An indirect reference to the page object with which this annotation is associated.
(ISO 32000-1, Table 164 – Entries common to all annotation dictionaries)
因此,您将目标页面的注释设置为源页面的注释,但 P 值中的那些注释仍然引用源页面。因此,您可以通过此引用将源页面及其所有资源拖到新文档中。因此,您的结果文件并不比您的源文件小一点也就不足为奇了。
如果您更改代码以更正 P 引用,例如像这样:
int pageIndex = 0;
for (PDPage page : documentSrc.getPages()) {
PDPage destPage = documentDest.getPage(pageIndex);
destPage.setAnnotations(page.getAnnotations());
for (PDAnnotation annotation : destPage.getAnnotations())
annotation.setPage(destPage);
// after disabling this size increase
//documentDest.getPage(pageIndex).setResources(page.getResources());
pageIndex++;
}
(CopyForm 测试 testCopyLikeBeeImproved
)
您将丢失这些对旧数据的引用。