add text just below or above every image in pdf

2019-06-10 06:11发布

问题:

 private static void InsertTextToPdf(string sourceFileName, string newFileName)
        {
            using (Stream pdfStream = new FileStream(sourceFileName, FileMode.Open))
            using (Stream newpdfStream = new FileStream(newFileName, FileMode.Create, FileAccess.ReadWrite))
            {
                PdfReader pdfReader = new PdfReader(pdfStream);
                PdfStamper pdfStamper = new PdfStamper(pdfReader, newpdfStream);
                PdfContentByte pdfContentByte = pdfStamper.GetOverContent(1);
                BaseFont baseFont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1250, BaseFont.NOT_EMBEDDED);
                pdfContentByte.SetColorFill(BaseColor.BLUE);
                pdfContentByte.SetFontAndSize(baseFont, 8);
                pdfContentByte.BeginText();
                pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "Kevin Cheng - A Hong Kong actor", 400, 600, 0);
                pdfContentByte.EndText();
                pdfStamper.Close();
            }
        }

This code is working fine to add text in a PDF , but i want to add the same text on below of every image in PDF.

I tried with merging the code of image extraction with text add but not able to see the same text multiple time , while able to see multiple image extraction. I added the text in same loop where extracting the image .

public static Dictionary<string, System.Drawing.Image> ExtractImages(string filename, string sourceFileName, string newFileName)
        {
            var images = new Dictionary<string, System.Drawing.Image>();
            Stream newpdfStream = new FileStream(newFileName, FileMode.Create, FileAccess.ReadWrite);

            using (var reader = new PdfReader(filename))
            {
                //
                PdfReader pdfReader = new PdfReader(reader);
                PdfStamper pdfStamper = new PdfStamper(pdfReader, newpdfStream);
                PdfContentByte pdfContentByte = pdfStamper.GetOverContent(1);
                var parser = new PdfReaderContentParser(reader);
                ImageRenderListener listener = null;
                for (var i = 1; i <= reader.NumberOfPages; i++)
                {
                    parser.ProcessContent(i, (listener = new ImageRenderListener()));
                    var index = 1;
                    if (listener.Images.Count > 0)
                    {
                        foreach (var pair in listener.Images)
                        {

                            images.Add(string.Format("{0}_Page_{1}_Image_{2}{3}",
                                System.IO.Path.GetFileNameWithoutExtension(filename), i.ToString("D4"), index.ToString("D4"), pair.Value), pair.Key);

                            index++;


                            {

                                BaseFont baseFont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1250, BaseFont.NOT_EMBEDDED);
                                pdfContentByte.SetColorFill(BaseColor.BLUE);
                                pdfContentByte.SetFontAndSize(baseFont, 8);
                                pdfContentByte.BeginText();
                                pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "Kevin Cheng - A Hong Kong actor", 400 + index * 10, 600, 0);
                                pdfContentByte.EndText();

                            }
                        }
                    }
                }
                pdfStamper.Close();
                return images;
            }
        }

回答1:

The IRenderListener implementation ImageRenderListener you try to use collects the images in a Dictionary<System.Drawing.Image, string> mapping images to the file extension matching their original type. In particular it completely ignores the image coordinates and, therefore, is not usable for your task to add text just below or above every image in pdf.

Instead you need an IRenderListener implementation which calculates the coordinates of the position atop an image; you can actually go a step further and even do the text adding in that listener, e.g. this implementation:

public class ImageEntitlingRenderListener : IRenderListener
{
    BaseFont baseFont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1250, BaseFont.NOT_EMBEDDED);
    PdfStamper pdfStamper = null;
    int page = 0;

    public ImageEntitlingRenderListener(PdfStamper pdfStamper, int page)
    {
        this.pdfStamper = pdfStamper;
        this.page = page;
    }

    public void RenderImage(ImageRenderInfo renderInfo)
    {
        Matrix ctm = renderInfo.GetImageCTM();
        float xCenter = ctm[Matrix.I31] + 0.5F * ctm[Matrix.I11];
        float yTop = ctm[Matrix.I32] + ctm[Matrix.I22];
        PdfContentByte pdfContentByte = pdfStamper.GetOverContent(page);
        pdfContentByte.SetColorFill(BaseColor.BLUE);
        pdfContentByte.SetFontAndSize(baseFont, 8);
        pdfContentByte.BeginText();
        pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "rahul", xCenter, yTop, 0);
        pdfContentByte.EndText();
    }

    public void BeginTextBlock() { }
    public void EndTextBlock() { }
    public void RenderText(TextRenderInfo renderInfo) { }
}

This render listener adds "rahul" atop each bitmap image in your PDF.

Beware: I kept the code simple by introducing some assumptions. In particular I assumed the images in the PDF to be rendered upright and no page rotation to be involved. A generic solution would have to consider the whole ctm and the page rotation when calculating xCenter, yTop, and the text rotation (here always 0).

You can use that render listener like this:

private static void InsertTextToPdf(string sourceFileName, string newFileName)
{
    using (Stream pdfStream = new FileStream(sourceFileName, FileMode.Open))
    using (Stream newpdfStream = new FileStream(newFileName, FileMode.Create, FileAccess.ReadWrite))
    {
        PdfReader pdfReader = new PdfReader(pdfStream);
        PdfStamper pdfStamper = new PdfStamper(pdfReader, newpdfStream);

        var parser = new PdfReaderContentParser(pdfReader);
        for (var i = 1; i <= pdfReader.NumberOfPages; i++)
        {
            parser.ProcessContent(i, (new ImageEntitlingRenderListener(pdfStamper, i)));
        }
        pdfStamper.Close();
        pdfReader.Close();
    }
}


标签: c# pdf itext