操纵PDF对象

时间:2015-05-06 14:00:39

标签: c# pdf pdf-generation itextsharp pdfsharp

我正在尝试操作PDF,它充当模板。我正在尝试的是取代占位符'在PDF模板中包含我的数据。因此,有人在var object = Pdf.GetObjectById("company_logo"); object.SetValue(myImage); object.SetPosition(x, y); 中制作了一个PDF模板,并添加了一个名为" company_logo"的空图像。我的应用程序看到一个名为" company_logo"的图像占位符它在那里添加了公司徽标。

我可以使用iTextSharp库浏览AcroFields并在文本字段中设置文本(例如),但AcroFields不会列出图像占位符。我觉得AcroFields不是我想要的。

那么如何从PDF中获取所有对象的列表(或树)并读取它们的属性(如位置,大小,内容等)。

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

一些伪代码让我自己更清楚

$timeout(function() {
        $scope.local = {selectedItem : 1}
    }, 2000);

2 个答案:

答案 0 :(得分:1)

从您的伪代码示例中,我们了解您要替换包含图像的对象的流。有几个例子说明如何做到这一点。

例如,在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);

我们正在操作的对象是用作Image XObjects的流。拥有Image XObjects的优点是可以重用它们。例如:如果每个页面上都有相同的徽标,那么您只想将该图像的字节存储一次,并多次重复使用相同的徽标。这意味着具有图像字节的对象对其位置一无所知。位置在内容流中确定。这取决于CTM。

答案 1 :(得分:0)

您是否看过scribus脚本功能? 既然您在scribus中创建了一个模板,您也可以编写一个简短的python脚本,用您的最终数据替换占位符并导出最终的PDF。

自scribus 1.5以来,也可以从commandline调用python脚本。