如何在java中拆分PDF页面?

时间:2017-09-28 10:22:23

标签: java pdf split itext

如果PDF文件包含任何纸张尺寸的页面(A0,A1,自定义等),如何将页面拆分为不同的页面,每个页面都相同,例如A4,并将其保存到新的PDF文档中在java?我尝试使用iText库,但没有成功。

Original PDF Page

A4 sized split

Final PDF file with A4 pages

1 个答案:

答案 0 :(得分:1)

此任务类似于this answer中实施的任务,拆分不仅仅是在一个维度而是在二维中。

因此,可以使用那里使用的AbstractPdfPageSplittingTool来实现可能的解决方案。

所以,我们再次有一个抽象的分裂器类

public abstract class Abstract2DPdfPageSplittingTool {
    public void split(OutputStream outputStream, PdfReader... inputs) throws DocumentException, IOException {
        try {
            initDocument(outputStream);
            for (PdfReader reader : inputs) {
                split(reader);
            }
        } finally {
            closeDocument();
        }
    }

    void initDocument(OutputStream outputStream) throws DocumentException {
        final Document document = new Document(PageSize.A4);
        final PdfWriter writer = PdfWriter.getInstance(document, outputStream);
        this.document = document;
        this.writer = writer;
    }

    void closeDocument() {
        try {
            document.close();
        } finally {
            this.document = null;
            this.writer = null;
        }
    }

    void newPage(Rectangle pageSize) {
        document.setPageSize(pageSize);
        if (!document.isOpen())
            document.open();
        else
            document.newPage();
    }

    void split(PdfReader reader) throws IOException {
        for (int page = 1; page <= reader.getNumberOfPages(); page++) {
            split(reader, page);
        }
    }

    void split(PdfReader reader, int page) throws IOException
    {
        PdfImportedPage importedPage = writer.getImportedPage(reader, page);

        Rectangle pageSizeToImport = reader.getPageSize(page);
        Iterable<Rectangle> rectangles = determineSplitRectangles(reader, page);

        for (Rectangle rectangle : rectangles) {
            newPage(rectangle);
            PdfContentByte directContent = writer.getDirectContent();
            directContent.saveState();
            directContent.rectangle(rectangle.getLeft(), rectangle.getBottom(), rectangle.getWidth(), rectangle.getHeight());
            directContent.clip();
            directContent.newPath();

            writer.getDirectContent().addTemplate(importedPage, -pageSizeToImport.getLeft(), -pageSizeToImport.getBottom());

            directContent.restoreState();
        }
    }

    protected abstract Iterable<Rectangle> determineSplitRectangles(PdfReader reader, int page);

    Document document = null;
    PdfWriter writer = null;
}

Abstract2DPdfPageSplittingTool.java

此实用程序允许将每个源页面拆分为一组自定义结果页面,每个结果页面可以表示源页面的任意矩形(边缘平行于相应的页面边缘)。

您可以使用这样的工具沿A4单元网格分割页面:

Abstract2DPdfPageSplittingTool tool = new Abstract2DPdfPageSplittingTool() {
    @Override
    protected Iterable<Rectangle> determineSplitRectangles(PdfReader reader, int page) {
        Rectangle targetSize = PageSize.A4;
        List<Rectangle> rectangles = new ArrayList<>();
        Rectangle pageSize = reader.getPageSize(page);
        for (float y = pageSize.getTop(); y > pageSize.getBottom() + 5; y-=targetSize.getHeight()) {
            for (float x = pageSize.getLeft(); x < pageSize.getRight() - 5; x+=targetSize.getWidth()) {
                rectangles.add(new Rectangle(x, y - targetSize.getHeight(), x + targetSize.getWidth(), y));
            }
        }
        return rectangles;
    }
};
tool.split(RESULT_OUTPUT_STREAM, new PdfReader(SOURCE_PDF));

(基于SplitPages测试testSplitDocumentA6

由于纸张尺寸规格存在一定的容差,我会删除Rectangles,它只包含左侧或顶部原始文档中的一个非常小的带,以防止出现空结果页,假设这些波段完全包含在原始页边距中。如果您不想要,请删除(或更改)示例+ 5循环中的- 5determineSplitRectangles