«Переразделать» PDF с помощью iText - PullRequest
0 голосов
/ 17 сентября 2018

Отказ от ответственности:

Я использую iText 5. Я знаю, что это обычно осуждается (вместо использования iText 7), но я работаю со значительным устаревшим кодом, который использует iText 5, и обновление не попадает под мой контроль.

Требования:

  • В качестве входных данных принимается «простой» PDF / A (только текст, они генерируются из RTF), а также значение с плавающей запятой, соответствующее требуемой длине первой страницы в дюймах.
  • PDF / A должен выводиться так же, как входной PDF, за исключением того, что он разбит на страницы следующим образом: длина первой страницы = входное значение; каждая последующая (не первая или последняя) страница будет заполнять стандартную длину страницы; последняя страница будет усечена на постоянное количество точек ниже содержимого, ближайшего к нижней части страницы. Обратите внимание, что ширина входа и выхода будет одинаковой и постоянной.

Ход / Подход:

Я расширил SimpleTextExtractionStrategy, чтобы сгенерировать XML, содержащий информацию о шрифте (размер и семейство, жирный или курсив и т. Д.), А также информацию о местоположении (относительно абсолютной системы координат, где начало координат находится в верхнем левом углу первая страница входного PDF) для каждого «диапазона» текста, извлеченного из входного PDF.

Затем я генерирую новый PDF-файл постранично (где каждая страница имеет желаемую длину в соответствии с требованиями, изложенными выше), фильтрует извлеченную информацию XML с помощью LINQ на основе границ каждой новой страницы и добавляет соответствующий форматированный текст в соответствующее местоположение, используя ColumnText.ShowTextAligned(...).

Проблема:

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

Этот набор требований должен также включать PDF-файлы с таблицами. Первоначально я планировал реализовать другой модуль, который придерживается того же интерфейса для таблиц PDF, так как они генерируются и используются отдельно от PDF, генерируемых из RTF, а в iText встроена относительно мощная функциональность таблиц.

Две проблемы, о которых говорилось выше, в сочетании с тем фактом, что мой описанный подход был рожден попыткой повторного использования существующего кода, заставляет меня полагать, что совершенно иной подход может быть необходим или, по крайней мере, намного лучше. Мне кажется, что должен быть способ захвата байтовой информации контента и ее обрезки по мере необходимости для «повторной разбивки на страницы» входного PDF, беспокоясь только о перемещении контента, который падает вдоль границы страницы.

По сути, я ищу (основанные на iText) рекомендации для лучшего подхода. Ответы типа псевдокода или просто рекомендации для классов / интерфейсов, которые могут помочь, являются приемлемыми. Хотя было бы неплохо обрабатывать текст и таблицы вместе, любой совет, относящийся к одному или другому, также был бы оценен. Я просмотрел большую часть доступной документации на веб-сайте iText и другие SO вопросы, но не нашел именно то, что я ищу.

Обратите внимание, что в этот вопрос не включен код, поскольку я ищу высокоуровневый подход, который полностью отличается от того, что я пробовал.

Edit:

Я не замечал этого раньше, но способ повторного использования шрифтов (аналогично this ) привел к неожиданному (но задокументированному) поведению. Похоже, мне нужно будет избегать извлечения информации для разбивки на текстовые уровни, так как будет трудно обеспечить непрерывность шрифтов между вводом и выводом.

1 Ответ

0 голосов
/ 02 ноября 2018

Я решил эту проблему некоторое время назад, но решил опубликовать свое решение.Я уверен, что это не самое эффективное решение, но оно хорошо работает для моих целей.Обратите внимание, что это приведет к повторной разбивке на PDF-файл, как описано в вопросе, содержащем только текст .Таблицы PDF обрабатываются отдельно.

Основной процесс заключается в следующем:

  1. Использование пользовательского TextExtractionStrategy для извлечения XML, содержащего информацию о линиях подъема и спуска для всего текста во входном PDF.а также на какой странице он изначально отображается.
  2. С учетом требований к длине страницы, как описано в вопросе (первая страница = входное значение, последующая = стандартная длина, последняя страница = подходящее содержимое) и информация XML относительнопозиции текста, определить, какой контент поместится на каждой странице выходного PDF.Создайте карту, где каждая входная страница должна быть обрезана (сверху и снизу, обратите внимание, что каждая входная страница может быть обрезана более одного раза), а также карту, из которой обрезанные страницы нужно будет «объединить» вместе вокончательный вывод.
  3. Скопируйте входной PDF-файл постранично в промежуточный временный PDF-файл (используя PdfCopier).Если входная страница должна быть обрезана более одного раза (например: первые 2 дюйма входной страницы 1 = выходные данные страницы 1, следующие 6 дюймов входной страницы 1 = выходные данные страницы 2, последние 0,5 дюйма входной страницы 1 = верхняя часть вывода страницы 3), убедитесь, что оно скопировано соответствующее количество раз (1 раз на обрезку).
  4. Обрежьте каждую страницу промежуточного скопированного PDF соответствующим образом.Это делается путем изменения MediaBox и / или CropBox.
  5. Объедините соответствующие обрезанные страницы вместе в страницы конечного PDF.Я использовал PdfWriter, чтобы сначала создать новую страницу соответствующей высоты, а затем добавить каждую подходящую обрезанную страницу в соответствующую позицию в байтовом содержимом выходной страницы PDF, используя contentByte.AddTemplate(inputCroppedPage, 0, bottomOfLastAddedCroppedPage).

Для всехкому удалось все это прочитать и понять, поздравляю.Для всех, пожалуйста, дайте мне знать, что вы, если вы в замешательстве.Описанное выше решение немного искажено и сложно выразить словами.Хотя здесь слишком много кода для публикации (и я не имею права делиться кодом на GitHub или аналогичном), я был бы рад ответить на любые вопросы, которые помогут кому-то другому реализовать нечто подобное.

TextExtractionStrategy, упомянутый в шаге 1, был вдохновлен этим ответом .По сути, я использовал System.Xml.Linq для создания XML-документа, а не для конкатенации строк для формирования HTML, и я игнорировал любую информацию о шрифте, сохраняя только информацию о том, где находится текст на странице (вы увидите, что эта информация доступна всвязанный ответ, просто не записан в окончательный HTML).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...