Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iTextSharp - PDF - Resize Document to Accommodate a Large Image

I'm using iTextSharp to convert large images to PDF documents.

This works, but the images appear cropped, because they exceed boundaries of the generated document.

So the question is - how to make the document same size as the image being inserted into it?

I'm using the following code:

  Document doc = new Document(PageSize.LETTER.Rotate());
  try
  {
     PdfWriter.GetInstance(doc, new FileStream(saveFileDialog1.FileName,FileMode.Create));
     doc.Open();
     doc.Add(new Paragraph());
     iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(imagePath);
     doc.Add(img);
   }
   catch
   {
      // add some code here incase you have an exception
   }
   finally
   {
      //Free the instance of the created doc as well
      doc.Close();
   }
like image 884
SharpAffair Avatar asked Jan 18 '23 21:01

SharpAffair


2 Answers

The Document object in iText and iTextSharp is an abstraction that takes care of various spacings, paddings and margins for you automatically. Unfortunately for you, this also means that when you call doc.Add() it takes into account existing margins of the document. (Also, if you happen to add anything else the image will be added relative to that, too.)

One solution would be to just remove the margins:

doc.SetMargins(0, 0, 0, 0);

Instead, it's easier to add the image directly to the PdfWriter object which you get from calling PdfWriter.GetInstance(). You're currently throwing away and not storing that object but you can easily change your line to:

PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream(saveFileDialog1.FileName,FileMode.Create));

Then you can access the DirectContent property of the PdfWriter and call its AddImage() method:

writer.DirectContent.AddImage(img);

Before doing this you must also absolutely position the image by calling:

img.SetAbsolutePosition(0, 0);

Below is a full working C# 2010 WinForms app targeting iTextSharp 5.1.1.0 that shows the DirectContent method above. It dynamically creates two images of different sizes with two red arrows stretching across both vertically and horizontally. Your code would obviously just use standard image loading and could thus omit a lot of this but I wanted to deliver a full working example. See the notes in the code for more details.

using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e) {
            //File to write out
            string outputFilename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Images.pdf");

            //Standard PDF creation
            using (FileStream fs = new FileStream(outputFilename, FileMode.Create, FileAccess.Write, FileShare.None)) {
                //NOTE, we are not setting a document size here at all, we'll do that later
                using (Document doc = new Document()) {
                    using (PdfWriter writer = PdfWriter.GetInstance(doc, fs)) {
                        doc.Open();

                        //Create a simple bitmap with two red arrows stretching across it
                        using (Bitmap b1 = new Bitmap(100, 400)) {
                            using (Graphics g1 = Graphics.FromImage(b1)) {
                                using(Pen p1 = new Pen(Color.Red,10)){
                                    p1.StartCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
                                    p1.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
                                    g1.DrawLine(p1, 0, b1.Height / 2, b1.Width, b1.Height / 2);
                                    g1.DrawLine(p1, b1.Width / 2, 0, b1.Width / 2, b1.Height);

                                    //Create an iTextSharp image from the bitmap (we need to specify a background color, I think it has to do with transparency)
                                    iTextSharp.text.Image img1 = iTextSharp.text.Image.GetInstance(b1, BaseColor.WHITE);
                                    //Absolutely position the image
                                    img1.SetAbsolutePosition(0, 0);
                                    //Change the page size for the next page added to match the source image
                                    doc.SetPageSize(new iTextSharp.text.Rectangle(0, 0, b1.Width, b1.Height, 0));
                                    //Add a new page
                                    doc.NewPage();
                                    //Add the image directly to the writer
                                    writer.DirectContent.AddImage(img1);
                                }
                            }
                        }

                        //Repeat the above but with a larger and wider image
                        using (Bitmap b2 = new Bitmap(4000, 1000)) {
                            using (Graphics g2 = Graphics.FromImage(b2)) {
                                using (Pen p2 = new Pen(Color.Red, 10)) {
                                    p2.StartCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
                                    p2.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
                                    g2.DrawLine(p2, 0, b2.Height / 2, b2.Width, b2.Height / 2);
                                    g2.DrawLine(p2, b2.Width / 2, 0, b2.Width / 2, b2.Height);
                                    iTextSharp.text.Image img2 = iTextSharp.text.Image.GetInstance(b2, BaseColor.WHITE);
                                    img2.SetAbsolutePosition(0, 0);
                                    doc.SetPageSize(new iTextSharp.text.Rectangle(0, 0, b2.Width, b2.Height, 0));
                                    doc.NewPage();
                                    writer.DirectContent.AddImage(img2);
                                }
                            }
                        }


                        doc.Close();
                    }
                }
            }
            this.Close();
        }
    }
}
like image 132
Chris Haas Avatar answered Jan 31 '23 05:01

Chris Haas


Try something like this to correct your issue

foreach (var image in images)
{
    iTextSharp.text.Image pic = iTextSharp.text.Image.GetInstance(image, System.Drawing.Imaging.ImageFormat.Jpeg);

    if (pic.Height > pic.Width)
    {
        //Maximum height is 800 pixels.
        float percentage = 0.0f;
        percentage = 700 / pic.Height;
        pic.ScalePercent(percentage * 100);
    }
    else
    {
        //Maximum width is 600 pixels.
        float percentage = 0.0f;
        percentage = 540 / pic.Width;
        pic.ScalePercent(percentage * 100);
    }

    pic.Border = iTextSharp.text.Rectangle.BOX;
    pic.BorderColor = iTextSharp.text.BaseColor.BLACK;
    pic.BorderWidth = 3f;
    document.Add(pic);
    document.NewPage();
}
like image 44
MethodMan Avatar answered Jan 31 '23 07:01

MethodMan