Replace multiple different images on one PDF template page with itext (itextsharp)

徘徊边缘 提交于 2019-12-30 07:25:11

问题


We have an ASP.NET application that users use to generate certain reports. So far we had one PDF template that had one image on it, and we would just replace that image with our programatically generated one (graph).
We have used code from this site for that:http://blog.rubypdf.com/2007/12/12/how-to-replace-images-in-a-pdf/

Problem now is that we have two different images on one PDF page, and the code from link above selects both images on one page and replaces them all at once with our generated image.

Does anyone have any idea how to replace multiple different images on one page with itext?

Thanks


回答1:


Ugh. First, let me rewrite some of that source.

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;
      }
    }
  }
}

Whew. the getAs functions can save you quite a bit of knuckle-grease and make your code much clearer.

Now. You need to be able to differentiate between the various images. If you're willing to hard-code things, you could find out what the resource names are and go that route:

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

If you're not willing to go with hardcoded resource names (and no one would fault you, quite the opposite, particularly when the order they appear (and thus the number on the end) depends on their order in a hash map... [shudder]), you may be able to differentiate based on image width and height.

//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();
  ...
}



回答2:


Just a note that sometimes the image will be nested in a form, so it is wise to make a function that will be called recursively. Something like this:

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


来源:https://stackoverflow.com/questions/4302056/replace-multiple-different-images-on-one-pdf-template-page-with-itext-itextshar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!