【问题标题】:Replace multiple different images on one PDF template page with itext (itextsharp)用 itext (itextsharp) 替换一个 PDF 模板页面上的多个不同图像
【发布时间】:2011-05-17 04:01:33
【问题描述】:

我们有一个 ASP.NET 应用程序,用户可以使用它来生成某些报告。到目前为止,我们有一个 PDF 模板,上面有一张图片,我们只需用我们以编程方式生成的图片(图表)替换该图片。
我们为此使用了该站点的代码:http://blog.rubypdf.com/2007/12/12/how-to-replace-images-in-a-pdf/

现在的问题是我们在一个 PDF 页面上有两个不同的图像,上面链接中的代码选择了一个页面上的两个图像,并一次将它们全部替换为我们生成的图像。

有人知道如何用 itext 替换一页上的多个不同图像吗?

谢谢

【问题讨论】:

    标签: asp.net image templates pdf itextsharp


    【解决方案1】:

    呃。首先,让我重写一些源代码。

    PdfReader pdf = new PdfReader("in.pdf");
    PdfStamper stp = new PdfStamper(pdf, new FileOutputStream("c:\\out.pdf"));
    PdfWriter writer = stp.getWriter();
    Image img = Image.getInstance("image.png");
    PdfDictionary pg = pdf.getPageN(1);
    PdfDictionary res = pg.getAsDict.get(PdfName.RESOURCES);
    PdfDictionary xobj = res.getAsDict(PdfName.XOBJECT);
    if (xobj != null) {
      for (Iterator<PdfName> it = xobj.getKeys().iterator(); it.hasNext(); ) {
        PdfObject obj = xobj.get(it.next());
        if (obj.isIndirect()) {
          PdfDictionary tg = (PdfDictionary)PdfReader.getPdfObject(obj);
          PdfName type = tg.getAsName(PdfName.SUBTYPE));
          if (PdfName.IMAGE.equals(type)) {
            PdfReader.killIndirect(obj);
            Image maskImage = img.getImageMask();
            if (maskImage != null)
              writer.addDirectImageSimple(maskImage);
            writer.addDirectImageSimple(img, (PRIndirectReference)obj);
            break;
          }
        }
      }
    }
    

    哇。 getAs 函数可以为您节省大量的关节油并使您的代码更清晰。

    现在。您需要能够区分各种图像。如果您愿意对事物进行硬编码,则可以找出资源名称并走这条路:

    String imageResName[] = {"Img1", "Img2" ... };
    Image img[] = {Image.getInstance("foo.png"), Image.getInstance("bar.png"), ... };
    for (int i = 0; i < imageResName.length; ++i) {
      PdfName curKey = new PdfName(imageResName[i]);
      PdfIndirectReference ref = xobj.getAsIndirect(curKey);
      PdfReader.killIndirect( ref );
      Image maskImage = img[i].getImageMask();
      if (maskImage != null) {
        writer.addDirectImageSimple(maskImage);
      }
      writer.addDirectImageSimple(img[i], (PRIndirectReference)ref);
    }
    

    如果您不愿意使用硬编码的资源名称(没有人会责怪您,恰恰相反,尤其是当它们出现的顺序(以及最后的数字)取决于它们在哈希图中的顺序时) ... [颤抖]),您也许可以根据图像的宽度和高度进行区分。

    //keep the original for loop, stepping through resource names
    if (PdfName.IMAGE.equals(type)) {
      float width = tg.getAsNumber(PdfName.WIDTH).floatValue();
      float height = tg.getAsNumber(PdfName.HEIGHT).floatValue();
    
      Image img = getImageFromDimensions(width, height);
    
      Image maskImage = img.getImageMask();
      ...
    }
    

    【讨论】:

    • 非常感谢!您似乎对 itext 有丰富的知识,能否请您指出一些可以提高我们在 itext 上的技能的材料?谢谢。
    • 我从... 06 年就开始使用 iText?我已经成为提交者大约两年了。总的来说,我使用 PDF 软件已经有 10 多年了,差不多 14 年了。两种改进方法:阅读本书(《iText in Action》第 2 版,原作者撰写),阅读源代码。对教皇的强烈奉献。阅读PDF specification。牢记“语法”部分,并知道在哪里查找其他所有内容。
    • 有没有办法抓取acrobat中定义的结构标签或元素名称?
    • 这段代码是用Java写的吗?我在 C# 中尝试过,它充满了编译错误。
    • 是的,我是 Java 母语人士。它可以很好地(令人震惊地)映射到 C#,以至于从一个到另一个的自动转换工作得相当好。奇怪的是,在 MS 向 Oracle 输掉了关于他们应用于 Java 的整个“拥抱和扩展”事情的法庭案件后不久,C# 就起飞了。
    【解决方案2】:

    请注意,有时图像会嵌套在表单中,因此创建一个递归调用的函数是明智的。 像这样的:

    public void StartHere()
    {
        PdfReader pdf = new PdfReader("in.pdf");
        PdfStamper stp = new PdfStamper(pdf, new FileOutputStream("c:\\out.pdf"));
        PdfWriter writer = stp.getWriter();
        Image img = Image.getInstance("image.png");
        PdfDictionary pg = pdf.getPageN(1);
        replaceImage(pg, writer,img);
    }
    
    private void replaceImage(PdfDictionary pg, PdfWriter writer,Image img)
    {
        PdfDictionary res = pg.getAsDict.get(PdfName.RESOURCES);
        PdfDictionary xobj = res.getAsDict(PdfName.XOBJECT);
        if (xobj != null) {
          for (Iterator<PdfName> it = xobj.getKeys().iterator(); it.hasNext(); ) {
            PdfObject obj = xobj.get(it.next());
            if (obj.isIndirect()) {
              PdfDictionary tg = (PdfDictionary)PdfReader.getPdfObject(obj);
              PdfName type = tg.getAsName(PdfName.SUBTYPE));
              if (PdfName.IMAGE.equals(type))
              {
                PdfReader.killIndirect(obj);
                Image maskImage = img.getImageMask();
                if (maskImage != null)
                  writer.addDirectImageSimple(maskImage);
                writer.addDirectImageSimple(img, (PRIndirectReference)obj);
                break;
              }
              else if(PdfName.FORM.equals(type))
              {
                  replaceImage(tg, writer,img);
              }
            }
          }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多