создать PDF-файл одной страницы из нескольких PDF-файлов, используя PDFBOX [дубликат]

Используйте thing[:]

>>> a = [1,2]
>>> b = a[:]
>>> a += [3]
>>> a
[1, 2, 3]
>>> b
[1, 2]
>>> 
4
задан Andreas 8 October 2014 в 13:09
поделиться

3 ответа

Возможно ли использовать pdfbox для включения других страниц PDF в качестве встроенных объектов на странице

Это должно быть возможно. Формат PDF позволяет использовать так называемые формы xobjects для использования в качестве таких внедренных объектов. Однако я не вижу явной реализации для этого, но процедура достаточно схожа с тем, что делают PageExtractor или PDFMergerUtility.

Доказательство концепции, полученное из PageExtractor с использованием текущего SNAPSHOT версии версии PDFBox 2.0.0:

PDDocument source = PDDocument.loadNonSeq(SOURCE, null);
List<PDPage> pages = source.getDocumentCatalog().getAllPages();

PDDocument target = new PDDocument();
PDPage page = new PDPage();
PDRectangle cropBox = page.findCropBox();
page.setResources(new PDResources());
target.addPage(page);

PDFormXObject xobject = importAsXObject(target, pages.get(0));
page.getResources().addXObject(xobject, "X");

PDPageContentStream content = new PDPageContentStream(target, page);
AffineTransform transform = new AffineTransform(0, 0.5, -0.5, 0, cropBox.getWidth(), 0);
content.drawXObject(xobject, transform);
transform = new AffineTransform(0.5, 0.5, -0.5, 0.5, 0.5 * cropBox.getWidth(), 0.2 * cropBox.getHeight());
content.drawXObject(xobject, transform);
content.close();

target.save(TARGET);
target.close();
source.close();

Этот код импортирует первую страницу исходного документа в целевой документ как объект XObject и дважды помещает его на страницу с различными преобразованиями масштабирования и вращения, например для этого источника

Source PDF, page 1 [/g0]

он создает это

Target PDF [/g1]

Помощник метод importAsXObject, фактически выполняющий импорт, определяется следующим образом:

PDFormXObject importAsXObject(PDDocument target, PDPage page) throws IOException
{
    final PDStream src = page.getContents();
    if (src != null)
    {
        final PDFormXObject xobject = new PDFormXObject(target);

        OutputStream os = xobject.getPDStream().createOutputStream();
        InputStream is = src.createInputStream();
        try
        {
            IOUtils.copy(is, os);
        }
        finally
        {
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(os);
        }

        xobject.setResources(page.findResources());
        xobject.setBBox(page.findCropBox());

        return xobject;
    }
    return null;
}

Как упоминалось выше, это только доказательство концепции, угловые случаи еще не приняты во внимание.

4
ответ дан mkl 21 August 2018 в 03:18
поделиться
  • 1
    Работает как шарм. Хотелось бы добавить, что для него требуется моментальный снимок 2.0.0 из репозитория. Пока не могу отредактировать ваш ответ. Благодарю. – Andreas 10 October 2014 в 15:11
  • 2
    Я добавил намек на использование 2.0.0. – mkl 10 October 2014 в 15:16
  • 3
    Вы можете добавить свое решение в документацию pdfbox. Для этого был отложенный запрос . Это может даже вызвать его реализацию ... – Andreas 13 October 2014 в 09:56

Чтобы обновить этот вопрос:

В файле org.apache.pdfbox.multipdf.LayerUtility уже есть вспомогательный класс.

Пример отображения наложения PDF страница в другой PDF: SuperimposePage .

Этот класс является частью примеров Apache PDFBox и примеров преобразований, как показано в @mkl.

3
ответ дан IvanRF 21 August 2018 в 03:18
поделиться

Так как mkl предположительно предлагается, PDFClown относится к библиотекам Java, которые обеспечивают явную поддержку для встраивания страниц (так называемые Form XObjects (см. PDF Reference 1.7, § 4.9) ).

Чтобы дать вам понять, как работает PDFClown, следующий код представляет собой эквивалент решения mbox в формате PDFBox (ПРИМЕЧАНИЕ: как было указано позже в mkl, его образец кода никоим образом не оптимизирован, поэтому это сравнение может не соответствовать фактическому статусу PDFBox - комментарии могут быть прояснены):

Document source = new File(SOURCE).getDocument();
Pages sourcePages = source.getPages();

Document target = new File().getDocument();
Page targetPage = new Page(target);
target.getPages().add(targetPage);

XObject xobject = sourcePages.get(0).toXObject(target);

PrimitiveComposer composer = new PrimitiveComposer(targetPage);
Dimension2D targetSize = targetPage.getSize();
Dimension2D sourceSize = xobject.getSize();
composer.showXObject(xobject, new Point2D.Double(targetSize.getWidth() * .5, targetSize.getHeight() * .35), new Dimension(sourceSize.getWidth() * .6, sourceSize.getHeight() * .6), XAlignmentEnum.Center, YAlignmentEnum.Middle, 45);
composer.showXObject(xobject, new Point2D.Double(targetSize.getWidth() * .35, targetSize.getHeight()), new Dimension(sourceSize.getWidth() * .4, sourceSize.getHeight() * .4), XAlignmentEnum.Left, YAlignmentEnum.Top, 90);
composer.flush();

target.getFile().save(TARGET, SerializationModeEnum.Standard);
source.getFile().close();

Сравнивая этот код с эквивалентом PDFBox, вы можете заметить некоторые существенные различия, которые показывают стиль стиля PDFClown. если какой-нибудь эксперт по PDFBox может проверить мои утверждения):

  • Преобразование страницы в формуXObject: PDFClown поддерживает выделенный метод (Page.toXObject ()), поэтому нет необходимости в дополнительном тяжелом подъеме, таком как вспомогательный метод importAsXObject ();
  • Управление ресурсами: PDFClown автоматически (и прозрачно) выделяет ресурсы страниц , поэтому нет необходимости явные вызовы, такие как page.getResources (). addXObject (xobject, "X");
  • Рисунок XObject: PDFClown поддерживает оба hi gh-уровень (явный масштаб, привязки для перевода и вращения) и методы низкоуровневого (аффинного преобразования) , чтобы разместить ваш FormXObject на странице, поэтому нет необходимости обязательно иметь дело с аффинными преобразованиями.

Все дело в том, что PDFClown имеет богатую архитектуру, состоящую из нескольких слоев абстракции : в соответствии с вашими требованиями вы можете выбрать наиболее подходящий стиль кодирования (либо вникать в низкоуровневые PDF- либо использовать удобную и элегантную модель высокого уровня). PDFClown позволяет вам настраивать каждый байт и решать сложные задачи с помощью смехотворно простого вызова метода по вашему желанию.

РАСКРЫТИЕ: Я являюсь ведущим разработчиком PDFClown.

1
ответ дан Stefano Chizzolini 21 August 2018 в 03:18
поделиться
  • 1
    Что касается сравнения: я не эксперт по PDFBox. Таким образом, возможно, некоторые недостатки в сравнении связаны с моим кодированием, а не из-за недостатков PDFBox. Например. что касается управления ресурсами, я думаю, что явное добавление ресурса не было строго необходимым. – mkl 11 October 2014 в 14:49
  • 2
    @mkl Спасибо за внимание: я обновил свой ответ, чтобы читатели не интерпретировали его как объективное сравнение. – Stefano Chizzolini 11 October 2014 в 16:16
  • 3
    @StefanoChizzolini Спасибо за добавление этой демонстрации. У этого действительно хороший API высокого уровня. – Andreas 13 October 2014 в 10:08
Другие вопросы по тегам:

Похожие вопросы: