2015-05-06 98 views
0

我試圖操作PDF,它用作模板。我正在嘗試用我的數據替換PDF模板中的「佔位符」。例如,有人在Scribus中製作PDF模板,並添加一個名稱爲「company_logo」的空圖像。我的應用程序會看到名爲「company_logo」的圖像佔位符,並在其中添加公司徽標。操作PDF對象

我可以使用iTextSharp庫瀏覽AcroFields並在文本字段中設置文本(例如),但AcroFields不會列出圖像佔位符。我覺得AcroFields不是我正在尋找的。

那麼如何從PDF中獲取所有對象的列表(或樹)並讀取其屬性(如位置,大小,內容等)。

P.S.我不一定需要使用iTextSharp,任何其他PDF庫也可以。最好免費。

有點僞代碼,以使自己更清楚

var object = Pdf.GetObjectById("company_logo"); 
object.SetValue(myImage); 
object.SetPosition(x, y); 
+0

首先,iTextSharp不是免費的,它是開源的,它有一個非常大的差異。其次,你是正確的,'AcroFields'不是你應該走下去的道路。第三,如果您將PDF視爲模板,您會遇到一些麻煩。這一切都說,通過[這裏的答案](http://stackoverflow.com/a/8751517/231316)閱讀從哪裏開始的(不完整)示例 –

+0

您的僞代碼揭示了對PDF缺乏理解:位置的圖像**從未存儲在圖像**中。如果是這樣,那意味着你不能重用Image XObject。這1分鐘的視頻解釋了免費/開源軟件何時可以免費使用*以及何時需要商業許可證:https://www.youtube.com/watch?v = QHF3xcWnSD4 –

+0

PDF文件中的圖像不需要必須有名稱或ID。你能解釋Scribus如何將這些名稱注入PDF中嗎? – mkl

回答

0

從你的僞代碼示例中,我們明白,要替換包含圖像對象的流。有幾個例子說明如何做到這一點。

例如,在SpecialID示例中,我們創建了一個PDF,其中我們用特殊ID標記了特定圖像。在ResizeImage例子中,我們跟蹤基於該特殊的ID形象,我們在更換流:

object = reader.getPdfObject(i); 
if (object == null || !object.isStream()) 
    continue; 
stream = (PRStream)object; 
if (value.equals(stream.get(key))) { 
    PdfImageObject image = new PdfImageObject(stream); 
    BufferedImage bi = image.getBufferedImage(); 
    if (bi == null) continue; 
    int width = (int)(bi.getWidth() * FACTOR); 
    int height = (int)(bi.getHeight() * FACTOR); 
    BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
    AffineTransform at = AffineTransform.getScaleInstance(FACTOR, FACTOR); 
    Graphics2D g = img.createGraphics(); 
    g.drawRenderedImage(bi, at); 
    ByteArrayOutputStream imgBytes = new ByteArrayOutputStream(); 
    ImageIO.write(img, "JPG", imgBytes); 
    stream.clear(); 
    stream.setData(imgBytes.toByteArray(), false, PRStream.NO_COMPRESSION); 
    stream.put(PdfName.TYPE, PdfName.XOBJECT); 
    stream.put(PdfName.SUBTYPE, PdfName.IMAGE); 
    stream.put(key, value); 
    stream.put(PdfName.FILTER, PdfName.DCTDECODE); 
    stream.put(PdfName.WIDTH, new PdfNumber(width)); 
    stream.put(PdfName.HEIGHT, new PdfNumber(height)); 
    stream.put(PdfName.BITSPERCOMPONENT, new PdfNumber(8)); 
    stream.put(PdfName.COLORSPACE, PdfName.DEVICERGB); 
} 

你會發現在這本書The Best iText Questions on StackOverflow,我回答以下問題又如:PDF Convert to Black And White PNGs

我寫的在ReplaceImage例子來說明如何更換圖像:

public static void replaceStream(PRStream orig, PdfStream stream) throws IOException { 
    orig.clear(); 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    stream.writeContent(baos); 
    orig.setData(baos.toByteArray(), false); 
    for (PdfName name : stream.getKeys()) { 
     orig.put(name, stream.get(name)); 
    } 
} 

正如你所看到的,這不是微不足道的話說:

var object = Pdf.GetObjectById("company_logo"); 
object.SetValue(myImage); 

正如我在評論解釋說,這是沒有意義的:

object.SetPosition(x, y); 

我們操縱的對象是作爲圖像XObject的流。擁有Image XObjects的優點是可以重複使用它們。例如:如果您在每個頁面上都有相同的徽標,那麼您只需要將該圖像的字節存儲一次,並多次重複使用相同的徽標。這意味着具有圖像字節的對象不知道其位置。該位置在內容流中確定。這取決於CTM。

0

您是否看過scribus腳本功能? 由於您在scribus中創建了一個模板您還可以編寫一個簡短的python腳本,用您的最終數據替換佔位符並導出最終的PDF。

由於scribus 1.5還可以從commandline調用python腳本。