2014-10-08 81 views
4

我使用不同的工具(如處理來創建矢量圖)。這些地塊被寫成單頁或多頁PDF文件。我想用pdfbox將這些地塊包含在一個報告中,就像pdf一樣。如何使用pdfbox在另一個PDPage中插入PDPage

我目前的工作流程包括以下PDF文件與下面的僞代碼

PDDocument inFile = PDDocument.load(file); 
PDPage firstPage = (PDPage) inFile.getDocumentCatalog().getAllPages().get(0); 
BufferedImage image = firstPage.convertToImage(BufferedImage.TYPE_INT_RGB, 300); 
PDXObjectImage ximage = new PDPixelMap(document, image); 

PDPageContentStream contentStream = new PDPageContentStream(document, page); 
contentStream.drawXObject(ximage, 0, 0, ximage.getWidth(), ximage.getHeight()); 
contentStream.close(); 

雖然這個作品它失去的矢量文件格式的優點的圖像,espectially文件/文件尺寸與印刷qualitity。

是否可以使用pdfbox在頁面中包含其他pdf頁面作爲嵌入對象(不作爲單獨頁面添加)?我可以使用PDStream?我更喜歡像pdflatex這樣的解決方案能夠將pdf數字嵌入到新的pdf文檔中。

您可以推薦哪些其他Java庫來完成該任務?

+1

*是否有可能使用pdfbox在頁面中包含其他pdf頁面作爲嵌入對象* - 應該可以。 PDF格式允許使用所謂的*表單xobjects *來充當這樣的嵌入對象。儘管如此,我沒有看到明確的實現,但該過程與'PDFMergerUtility'的功能相似。 *您可以推薦哪些其他Java庫來完成這項任務?* - 任何通用庫都應該能夠做到這一點,iText和PdfClown都有明確的支持。 – mkl 2014-10-08 13:05:51

+0

@mkl對,它應該是一個相當普遍的任務。看着「PDFMergerUtility」,它將pdf添加爲單獨的頁面。由於其最新版本的許可證更改,iText不是一種選擇。雖然會看看PdfClown。感謝您指出它。 – Andreas 2014-10-09 13:25:40

回答

4

是否有可能使用PDFBOX包括其它PDF頁面嵌入對象頁

內應該有可能。 PDF格式允許使用所謂的表單xobjects來充當這樣的嵌入對象。雖然我沒有看到明確的實施方案,但程序與PageExtractorPDFMergerUtility相似。

使用的PDFBox的2.0.0開發版本當前快照概念的樣張,從PageExtractor得出:

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(); 

此代碼導入源文檔的第一頁到目標文檔作爲X對象,並把它兩次到不同的縮放和旋轉轉換的頁面上,例如對於這個源

Source PDF, page 1

它創建這個

Target PDF

的輔助方法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; 
} 

如上所述,這僅是一個概念證明,角落案件尚未被考慮在內。

+0

工程就像一個魅力。想補充一點,它需要2.0。來自存儲庫的0快照。儘管如此,仍然無法編輯您的答案。謝謝。 – Andreas 2014-10-10 14:11:05

+0

我添加了2.0.0使用提示。 – mkl 2014-10-10 14:16:18

+1

您可能想要將您的解決方案添加到pdfbox文檔中。無論如何,已有[推遲請求](https://issues.apache.org/jira/browse/PDFBOX-2197)。這甚至可能會觸發它的執行... – Andreas 2014-10-13 08:56:59

1

由於MKL適當建議,PDFClown是提供嵌入頁明確支持的Java庫中(所謂的格式XObject對象(見PDF參考1.7,第4.9))。

爲了讓您領略一下PDFClown的工作方式,下面的代碼表示mkl的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的專家可以驗證我的斷言):

  • Page-to-FormXObject轉換PDFClown本身支持專用方法(Page.toXObject()),因此不需要額外的繁重工作,例如helper方法importAsXObject();
  • 資源管理PDFClown自動(且透明)分配頁面資源,所以沒有必要顯式調用,如page.getResources()addXObject(X對象, 「X」)。
  • X對象繪製PDFClown同時支持高層次的(明確的尺度,平移和旋轉錨)和低級(仿射變換)方法您FormXObject放置到頁面,所以沒有必要一定與處理仿射變換。

整個的一點是,PDFClown功能由多個抽象層豐富的架構:根據您的要求,您可以選擇最合適的編碼風格(或者深入到PDF的底層基礎結構或利用其便捷優雅的高級模型)。 PDFClown可以讓你調整每一個字節,並根據你的意願用一個可笑的簡單方法調用來解決複雜的任務。

披露:我是PDFClown的首席開發人員。

+0

關於比較:我不是PDFBox專家。因此,比較中的一些缺點可能是由於我的編碼,而不是由於PDFBox的缺陷。例如。關於資源管理,我認爲我明確地增加資源並不是絕對必要的。 – mkl 2014-10-11 13:49:23

+0

@mkl感謝您的提示:我更新了答案,以確保讀者不會將其解釋爲客觀比較。 – 2014-10-11 15:16:38

+0

@StefanoChizzolini感謝您加入此演示。它確實有一個很好的高級API。 – Andreas 2014-10-13 09:08:11

2

要更新這個問題:

目前已經在org.apache.pdfbox.multipdf.LayerUtility一個輔助類做進口。

例子來說明疊加PDF頁面到另一個PDF:SuperimposePage

此課程是Apache PDFBox Examples的一部分,並且已向其添加了@mkl所示的樣本轉換。

相關問題