Этот вопрос, по сути, касается плотного объединения нескольких страниц PDF из одного или нескольких файлов PDF.
Обычно методы объединения PDF-файлов объединяются только на основе страниц, то есть они берут страницы издокументы для объединения и создания нового документа со всеми этими страницами.Часто более плотное объединение (размещение содержимого нескольких страниц на одной странице результатов) не представляется возможным из-за верхних и нижних колонтитулов, фоновой графики и других артефактов, которые должны были бы распознаваться и игнорироваться в этом контексте.Для таких страниц, как ваша, возможно плотное объединение, просто пока не предоставляемое в качестве одного служебного метода.
Можно реализовать такой класс утилит, например:
public class PdfDenseMergeTool {
public PdfDenseMergeTool(PDRectangle size, float top, float bottom, float gap)
{
this.pageSize = size;
this.topMargin = top;
this.bottomMargin = bottom;
this.gap = gap;
}
public void merge(OutputStream outputStream, Iterable<PDDocument> inputs) throws IOException
{
try
{
openDocument();
for (PDDocument input: inputs)
{
merge(input);
}
if (currentContents != null) {
currentContents.close();
currentContents = null;
}
document.save(outputStream);
}
finally
{
closeDocument();
}
}
void openDocument() throws IOException
{
document = new PDDocument();
newPage();
}
void closeDocument() throws IOException
{
try
{
if (currentContents != null) {
currentContents.close();
currentContents = null;
}
document.close();
}
finally
{
this.document = null;
this.yPosition = 0;
}
}
void newPage() throws IOException
{
if (currentContents != null) {
currentContents.close();
currentContents = null;
}
currentPage = new PDPage(pageSize);
document.addPage(currentPage);
yPosition = pageSize.getUpperRightY() - topMargin + gap;
currentContents = new PDPageContentStream(document, currentPage);
}
void merge(PDDocument input) throws IOException
{
for (PDPage page : input.getPages())
{
merge(input, page);
}
}
void merge(PDDocument sourceDoc, PDPage page) throws IOException
{
PDRectangle pageSizeToImport = page.getCropBox();
BoundingBoxFinder boundingBoxFinder = new BoundingBoxFinder(page);
boundingBoxFinder.processPage(page);
Rectangle2D boundingBoxToImport = boundingBoxFinder.getBoundingBox();
double heightToImport = boundingBoxToImport.getHeight();
float maxHeight = pageSize.getHeight() - topMargin - bottomMargin;
if (heightToImport > maxHeight)
{
throw new IllegalArgumentException(String.format("Page %s content too large; height: %s, limit: %s.", page, heightToImport, maxHeight));
}
if (gap + heightToImport > yPosition - (pageSize.getLowerLeftY() + bottomMargin))
{
newPage();
}
yPosition -= heightToImport + gap;
LayerUtility layerUtility = new LayerUtility(document);
PDFormXObject form = layerUtility.importPageAsForm(sourceDoc, page);
currentContents.saveGraphicsState();
Matrix matrix = Matrix.getTranslateInstance(0, (float)(yPosition - (boundingBoxToImport.getMinY() - pageSizeToImport.getLowerLeftY())));
currentContents.transform(matrix);
currentContents.drawForm(form);
currentContents.restoreGraphicsState();
}
PDDocument document = null;
PDPage currentPage = null;
PDPageContentStream currentContents = null;
float yPosition = 0;
final PDRectangle pageSize;
final float topMargin;
final float bottomMargin;
final float gap;
}
( PdfDenseMergeTool служебный класс)
Используется класс BoundingBoxFinder
из этого ответа на старый вопрос .
Вы можетеиспользуйте PdfDenseMergeTool
следующим образом:
PDDocument document1 = ...;
PDDocument document2 = ...;
PDDocument document3 = ...;
PDDocument document4 = ...;
PDDocument document5 = ...;
PdfDenseMergeTool tool = new PdfDenseMergeTool(PDRectangle.A4, 30, 30, 10);
tool.merge(new FileOutputStream("Merge with Text.pdf"),
Arrays.asList(document1, document2, document3, document4, document5,
document1, document2, document3, document4, document5,
document1, document2, document3, document4, document5));
Чтобы объединить пять исходных документов три раза подряд.
В случае моих тестовых документов (каждый исходный документ содержит три строки текста) Я получаю этот результат:
Страница 1:
![result page 1](https://i.stack.imgur.com/tXcxt.png)
Страница 2:
![result page 2](https://i.stack.imgur.com/zSgDZ.png)
Этот служебный класс по существу является портом PdfDenseMergeTool
для iText в этот ответ .
Он был протестирован с текущимPDFBox 3.0.0 ветка разработки SNAPSHOT.