Замените несколько разных изображений на одной странице шаблона PDF с помощью itext (itextsharp) - PullRequest
2 голосов
/ 29 ноября 2010

У нас есть приложение ASP.NET, которое пользователи используют для создания определенных отчетов. До сих пор у нас был один шаблон PDF с одним изображением, и мы просто заменили это изображение на наше сгенерированное программным способом (график).
Для этого мы использовали код с этого сайта: http://blog.rubypdf.com/2007/12/12/how-to-replace-images-in-a-pdf/

Проблема теперь в том, что у нас есть два разных изображения на одной странице PDF, и код по ссылке выше выбирает оба изображения на одной странице и заменяет их все сразу нашим сгенерированным изображением.

Кто-нибудь знает, как заменить несколько разных изображений на одной странице с помощью itext?

Спасибо

Ответы [ 2 ]

8 голосов
/ 30 ноября 2010

Тьфу. Во-первых, позвольте мне переписать некоторые из этих источников.

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();
  ...
}
2 голосов
/ 31 июля 2012

Просто обратите внимание, что иногда изображение будет вложено в форму, поэтому имеет смысл создать функцию, которая будет вызываться рекурсивно.Как то так:

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