PDFBox - «saveIncremental» после вставки второго изображения не работает - PullRequest
0 голосов
/ 07 мая 2019

У меня проблемы с PDFBox.У меня есть пустая страница в PDF, и я хочу вставить в нее изображения.Поскольку я также работаю с подписанными PDF-файлами, все изменения должны быть сохранены как «saveIncremental».

Когда я вставляю только одно изображение, все в порядке (изображение вставлено).Когда я пытаюсь вставить другое изображение в этот PDF-файл, оно не было вставлено, и при открытии в Adobe Acrobat Reader появляется сообщение «На этой странице существует ошибка. Adobe может отображать страницу неправильно ...».

Странная вещь - когда PDF - это не только пустая страница, но, например, пустая страница с изображением, все в порядке (первое и второе изображения были вставлены правильно с помощью saveIncremental).

Код вставки и сохранения изображения:

PDImageXObject pdImage = PDImageXObject.createFromFile(tmpSig.getFileName(), doc);
PDPageContentStream contentStream = new PDPageContentStream(doc, tmpPage, PDPageContentStream.AppendMode.APPEND, true, true);
contentStream.drawImage(pdImage, finalX, (finalPageHeight - finalY - finalHeight), finalWidth, finalHeight);
contentStream.close();

// update before save
tmpPage.getCOSObject().setNeedToBeUpdated(true);
tmpPage.getResources().getCOSObject().setNeedToBeUpdated(true);
doc.getDocumentCatalog().getPages().getCOSObject().setNeedToBeUpdated(true);
doc.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);

// save
doc.saveIncremental(new FileOutputStream(pdfFile));

Все файлы доступны здесь

Используя PDFBox версии 2.0.7, но я также попробовал новейшую (2.0.15), но это не помогло.

Спасибо за все идеи!


РЕДАКТИРОВАТЬ: я пытался обновить XObject и ресурсы, как это (добавил этот код под комментарием "обновить до сохранения"):

pdImage.getCOSObject().setNeedToBeUpdated(true);
PDResources pdResources = tmpPage.getResources();
for (COSName name : pdResources.getXObjectNames()) {
    pdResources.getXObject(name).getCOSObject().setNeedToBeUpdated(true);
}

Проблема все еще остается, ничего не изменилось ...

1 Ответ

1 голос
/ 08 мая 2019

В дополнение к словарям, которые вы уже отметили как обновленные

tmpPage.getCOSObject().setNeedToBeUpdated(true);
tmpPage.getResources().getCOSObject().setNeedToBeUpdated(true);
doc.getDocumentCatalog().getPages().getCOSObject().setNeedToBeUpdated(true);
doc.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);

также пометьте запись XObject в словаре ресурсов как обновленную:

tmpPage.getResources().getCOSObject().getCOSDictionary(COSName.XOBJECT).setNeedToBeUpdated(true);

Вы задаетесь вопросом, почему вам не нужно было делать это при добавлении первого изображения?

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

Вы задаетесь вопросом, почему вам не нужно было делать это при добавлении в файл, в котором уже были изображения?

В этом другом файле запись XObject в словаре ресурсов является прямым объектом, т. Е. Немедленно содержится в словаре ресурсов.

4 0 obj
<<
  /Type /Page
  /Resources <<
    /ProcSets [/PDF /Text /ImageB /ImageC /ImageI]
    /ExtGState <</G3 5 0 R /gs2 6 0 R /gs3 7 0 R>>
    /XObject <</Im1 8 0 R /Im2 9 0 R>>
  >>
  /MediaBox [0 0 611.03998 864.95996]
  /Contents [10 0 R 11 0 R 12 0 R 13 0 R 14 0 R]
  /StructParents 0
  /Parent 2 0 R
>> 
endobj

Таким образом, всякий раз, когда пишется новая копия словаря ресурсов, неявно записывается и новая копия записи XObject .

В файле, в котором PDFBox создал запись XObject в словаре ресурсов, PDFBox создал ее как косвенный объект, т. Е. В словаре ресурсов XObject отображается только на ссылка на номер объекта, а в объекте с этим номером можно найти фактический словарь записей.

2 0 obj
<<
  /Type /Page
  /Resources <<
    /ProcSets [/PDF /Text /ImageB /ImageC /ImageI]
    /ExtGState <</G3 3 0 R>>
    /XObject 7 0 R
  >>
  /MediaBox [0 0 611.03998 864.95996]
  /Contents [8 0 R 4 0 R 9 0 R]
  /StructParents 0
  /Parent 5 0 R
>>
endobj
7 0 obj
<<
  /Im1 10 0 R
>> 
endobj

Поэтому, когда пишется новая копия словаря ресурсов, в этом случае не создается неявная новая копия словаря записей XObject .


Кстати, ваш текущий подход не поможет вам с вашей задачей

Поскольку я также работаю с подписанными PDF-файлами, все изменения должны быть сохранены как «saveIncremental».

Добавление изображений к содержимому страницы недопустимо для изменения подписанного PDF, поэтому Adobe Reader по-прежнему будет указывать, что ваша подпись недействительна. Чтобы получить сводку разрешенных и запрещенных изменений после подписания, просмотрите этот ответ и документы, на которые имеются ссылки.

Вместо этого попробуйте добавить изображения в аннотации.

...