искать использованные ресурсы через страницу и удалять их - PullRequest
0 голосов
/ 29 марта 2019

Я использую эту технику , чтобы экспортировать acroform в новый файл pdf из другого источника pdf.

Результат pdf только с acroform вы можете скачать здесь

Я использовал онлайн-сайт pdfcompressor, чтобы сжать этот pdf (59Ko), и я сократил его на -64%.Этот веб-сайт, по-видимому, очищает все неиспользуемые вещи внутри ресурсов. Вот скриншот из PDFDebugger

screenshot from PDFDebugger

Мой вопрос: как я могу получить xobject или шрифт из ресурсов?[] и проверьте, используются ли они где-нибудь на странице, если не удалите его из Ресурсов [].

Если поиск в PDPage затруднен, если некоторые ресурсы используются или нет, как я могу просто удалить 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 , обсужденной здесь

update1

Вот текущий код, который я должен извлечь из формата pdf: // создать 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);

Этот результат: pdf без ресурсов

На этот раз форма без ресурсов - 73Ko, а мой оригинальный PDF - 75Ko.

1 Ответ

2 голосов
/ 29 марта 2019

Сокращение ресурсов ваших объектов страницы

Ну, я думаю, что ваша текущая задача намного проще, чем то, что вы просите в своем вопросе. Я истолковываю ваши

Я использую эту технику , чтобы экспортировать acroform в новый файл PDF из другого исходного файла PDF.

означает, что вы действительно просто хотите перенести поля и функции AcroForm из одного PDF-файла в другой и не заинтересованы в статическом содержимом страницы исходного файла.

Таким образом, ответ на вопрос, какие ресурсы вы фактически используете , прост: Нет ! Ресурсы страницы - это ресурсы, используемые в статическом контенте (в потоке контента страницы), который вас не интересует.

Таким образом, нет необходимости сначала копировать ресурсы страницы в новый документ, просто удалите строку

documentDest.getPage(pageIndex).setResources(page.getResources());

из кода в ссылочном ответе.


В качестве отступления: @Tilman уже заметил в комментарии к ответу, который вы использовали в качестве шаблона, что интересующие вас ресурсы - это "ресурсы по умолчанию для акроформы", а не ресурсы страницы . Таким образом, вы можете не только скопировать поля между PDAcroForm экземплярами:

acroFormDest.setFields(acroFormSrc.getFields());

, но также ресурсы по умолчанию, внешний вид по умолчанию и четырехугольник по умолчанию

acroFormDest.setDefaultAppearance(acroFormSrc.getDefaultAppearance());
acroFormDest.setDefaultResources(acroFormSrc.getDefaultResources());
acroFormDest.setQ(acroFormSrc.getQ());

Другие вопросы

Аннотации со ссылкой на неправильную страницу

На этот раз форма без ресурсов - 73Ko, а мой оригинальный PDF - 75Ko.

Если заглянуть немного глубже в ваш "form-without-resources.pdf", проблема становится понятной:

screen shot

Как видите, аннотации виджетов в вашем поле указывают на неправильную страницу!

Это значение P указано как

P толковый словарь (Не обязательно, за исключением случаев, указанных ниже; PDF 1.3; не используется в файлах FDF) Косвенная ссылка на объект страницы, с которым связана эта аннотация.

(ISO 32000-1, Таблица 164 - Записи, общие для всех словарей аннотаций)

Таким образом, вы устанавливаете аннотации вашей целевой страницы на аннотации исходной страницы, но эти аннотации в их значении 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 test testCopyLikeBeeImproved)

вы потеряете эти ссылки на старые данные.

...