2015-05-06 69 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脚本。