.Net, ASP.NET, C#, CodeProject, iTextSharp, PDF, Programming, Software, VB.NET, Web Development, WebForms

iTextSharp – Insert an Image to a PDF in C#

iTextSharp PDF
Using iTextSharp to Generate a PDF

This article will review the basics of programmatically inserting and positioning an image in a PDF being generated using the iTextSharp library. I’ll show you the code for doing so in both C# and VB.NET.

Here are the main categories I’ll be covering, with links to the appropriate section:

  1. Adding your image programmatically while generating your PDF
  2. Adjusting your image scaling so it renders nicely in your PDF
  3. Positioning your image in your PDF
  4. Example code in C#
  5. Example code in VB.NET

If you are interested in working with the iTextSharp .NET libraries then have a look at some of the other articles covering iTextSharp I have written on the topic.

Adding your Image Programmatically while Generating your PDF


If you are including an image in an HTML page that you are exporting to PDF with iTextSharp, then you’ll quickly see that iTextSharp will not include the image from the traditional HTML <img src= markup unless you specify a full URL. Also you’ll discover that an image does not look and position the same in your PDF as it does in your HTML Web page. If you are interested in creating a good-looking document that’s tailored to the PDF format then I definitely suggest doing so in your code rather than in your HTML mark-up.

The basics of adding an image to your iTextSharp PDF document involves first reading your file into an iTextSharp image object ( iTextSharp.text.Image). In the example of adding a logo from the Images folder from the root of your Web site to your PDF, this is done as follows:

iTextSharp.text.Image addLogo = default(iTextSharp.text.Image);
addLogo = iTextSharp.text.Image.GetInstance(Server.MapPath("Images") + "/logo.gif");

As you can see this is quite straightforward. Next you will want to add your image to your PDF document. You can do so when you have instantiated and opened your document and before you read in your HTML page:

docWorkingDocument.Open();
docWorkingDocument.Add(addLogo);

This code will add the logo image to your PDF document header before your HTML is added. However you’ll note that the image doesn’t look quite the same as it did in your image editing software or in your Web browser. You’ll need to take a look at scaling the image so that it keeps the look you want it to have in your PDF document, which I cover in the next section.

A pointer to keep in mind is that it’s not very easy to separate your inserted image from your rendered document since the iTextSharp converter will want to add your document content flush with the bottom of your image. The simplest and most effective way to pad your image from your content is to add a few pixels of white-space to your image bottom in your favorite image editing software.

Adjusting Your Image Scaling to Render in Your PDF


iTextSharp supports an image resolution of 72 dpi, which is a less than the average image these days. Furthermore, if you compare the image size rendered in an HTML version of your page with the image size rendered in a PDF version generated by iTextSharp, then you will realize that you need to adjust the image size for rendering with PDF.

From personal experience, I’ve found that an image will appear 35% larger in iTextSharp than it appears in your image editor or in an HTML document, which also makes the image look pixelated and choppy. So when you are including your image for rendering in an iTextSharp generated PDF remember to use either the ScaleToFit or the ScalePercent method to declare the image size.

Using ScaleToFit you will want to manually calculate the new image dimensions to use. Thus an image that normally is 197 pixels wide x 57 pixels high needs to be reduced to 65% of that size to 128h x 37w using:

imageVariable.ScaleToFit(128, 37)

Alternately using the ScalePercent method you can directly specify that the image should be 65% of its original size without needing to manually calculate the reduced width and height. You use this method as follows:

imageVariable.ScalePercent(65f)

Positioning the iTextSharp Image in your PDF


The next issue that appears is how to properly position your new iTextSharp image in your PDF document. If you want the image to act as a header aligned at the top left corner of your document, then you can simply add the image to your document before you stream in your HTML page.

Alternately you can set the .Alignment attribute of your iTextSharp image. Alignment options are basic and range from the standard options:

  • .ALIGN_RIGHT
  • .ALIGN_LEFT
  • .ALIGN_CENTER
  • .ALIGN_MIDDLE
  • .ALIGN_TOP
  • .ALIGN_BOTTOM

If you want to be more specific with positioning your image element, then you can  can set the .SetAbsolutePosition(x-axis, y-axis) attribute of your iTextSharp image. Interestingly, iTextSharp considers the (0,0) baseline to be the bottom left corner of your PDF document (on the first page if you are later streaming in an HTML document). So when you are setting the absolute location of the document, you need to set it based on the x/y location of the bottom left corner of your image. For  example if you want to set your image to the top left corner of you first page with a 100px high image, you would set your position as:

addLogo.SetAbsolutePosition(0,myWorkingDocument.PageSize.Height - 100)

As you can see, the attributes PageSize.Height and PageSize.Width come in very handy here in calculating exactly where on your document your image will appear.

Example HTML Report with an Image in an iTextSharp PDF in C#


This example consists of two pages. The main page  is called TestGenPdf.aspx and this page will call an example page called TestReport.aspx. The PDF-generation logic for this example is contained in the example page  TestGenPdf.aspx.

Please note when setting up this example, that you should add a logo image to an Images folder located at the root of your Web site. Also note that you should create a folder called Reports at the root of your Web site into which the generated PDF documents can be written. The Reports folder should have sufficient permissions for the ASP.NET worker process to write a file to it.

Also, just to note: you’ll need to download and reference the iTextSharp library for this example.

TestGenPdf.aspx in C#

<%@ Page Language="C#" %>
<%@ Import Namespace="iTextSharp.tool.xml" %>
<%@ Import Namespace="iTextSharp.text.pdf" %>
<%@ Import Namespace="System.IO" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
 protected void Button1_Click(object sender, System.EventArgs e)
 {
 string strHtml = null;
 MemoryStream memStream = new MemoryStream();
 StringWriter strWriter = new StringWriter();
 Server.Execute("TestReport.aspx", strWriter);
 strHtml = strWriter.ToString();
 strWriter.Close();
 strWriter.Dispose();
 iTextSharp.text.Image addLogo = default(iTextSharp.text.Image);
 addLogo = iTextSharp.text.Image.GetInstance(Server.MapPath("Images") + "/logo.gif");
 string strFileShortName = "test" + DateTime.Now.Ticks + ".pdf";
 string strFileName = HttpContext.Current.Server.MapPath("reports\\" + strFileShortName);
 iTextSharp.text.Document docWorkingDocument = new iTextSharp.text.Document(iTextSharp.text.PageSize.A4.Rotate(), 1, 1, 0, 0);
 StringReader srdDocToString = null;
 try
 {
 PdfWriter pdfWrite = default(PdfWriter);
 pdfWrite = PdfWriter.GetInstance(docWorkingDocument, new FileStream(strFileName, FileMode.Create));
 srdDocToString = new StringReader(strHtml);
 docWorkingDocument.Open();
 addLogo.ScaleToFit(128, 37);
 addLogo.Alignment = iTextSharp.text.Image.ALIGN_RIGHT;
 // addLogo.SetAbsolutePosition(0, docWorkingDocument.PageSize.Height - 100)
 docWorkingDocument.Add(addLogo);
 XMLWorkerHelper.GetInstance().ParseXHtml(pdfWrite, docWorkingDocument, srdDocToString);
 }
 catch (Exception ex)
 {
 Response.Write(ex.Message);
 }
 finally
 {
 if ((docWorkingDocument != null))
 {
 docWorkingDocument.Close();
 docWorkingDocument.Dispose();
 }
 if ((srdDocToString != null))
 {
 srdDocToString.Close();
 srdDocToString.Dispose();
 }
 }
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "myscript", "window.open('reports/" + strFileShortName + "','_blank','location=0,menubar=0,status=0,titlebar=0,toolbar=0');", true);
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
 <title></title>
</head>
<body>
 <form id="form1" runat="server">
 <div>
 <asp:Button ID="Button1" runat="server" Text="Generate PDF" OnClick="Button1_Click" />
 </div>
 </form>
</body>
</html>

TestReport.aspx in C#

<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
 Dim m_testData As New Hashtable()
 Protected Sub Page_Load(sender As Object, e As System.EventArgs)
 m_testData.Add("test_1_id", "test_1_value")
 m_testData.Add("test_2_id", "test_2_value")
 m_testData.Add("test_3_id", "test_3_value")
 m_testData.Add("test_4_id", "test_4_value")
 GridView1.DataSource = m_testData
 GridView1.DataBind()
 End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
 <title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
 <Columns>
 <asp:TemplateField HeaderText="key">
 <EditItemTemplate>
 <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("key") %>'></asp:TextBox>
 </EditItemTemplate>
 <ItemTemplate>
 <asp:Label ID="Label1" runat="server" Text='<%# Bind("key") %>'></asp:Label>
 </ItemTemplate>
 </asp:TemplateField>
 <asp:TemplateField HeaderText="value">
 <EditItemTemplate>
 <asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("value") %>'></asp:TextBox>
 </EditItemTemplate>
 <ItemTemplate>
 <asp:Label ID="Label2" runat="server" Text='<%# Bind("value") %>'></asp:Label>
 </ItemTemplate>
 </asp:TemplateField>
 </Columns>
</asp:GridView>
</form>
</body>
</html>

Example HTML Report with an Image in an iTextSharp PDF in VB.NET


The example below is the VB.NET version of the C# example I have provided above. When setting this example up, please consider the same setup explanation:

This example consists of two pages. The main page  is called TestGenPdf.aspx and this page will call an example page called TestReport.aspx. The PDF-generation logic for this example is contained in the example page  TestGenPdf.aspx.

When setting up this example, that you should add a logo image to an Images folder located at the root of your Web site. Also note that you should create a folder called Reports at the root of your Web site into which the generated PDF documents can be written. The Reports folder should have sufficient permissions for the ASP.NET worker process to write a file to it.

Also, just to note: don’t forget to  download and reference the iTextSharp library for this example to work.

TestGenPdf.aspx in VB.NET

<%@ Page Language="VB" %>
<%@ Import Namespace="iTextSharp.tool.xml" %>
<%@ Import Namespace="iTextSharp.text.pdf" %>
<%@ Import Namespace="System.IO" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
 Protected Sub Button1_Click(sender As Object, e As System.EventArgs)
 Dim strHtml As String
 Dim memStream As New MemoryStream()
 Dim strWriter As New StringWriter()
 Server.Execute("TestReport.aspx", strWriter)
 strHtml = strWriter.ToString()
 strWriter.Close()
 strWriter.Dispose()
 Dim addLogo As iTextSharp.text.Image
 addLogo = iTextSharp.text.Image.GetInstance(Server.MapPath("Images") & "/logo.gif")
 Dim strFileShortName As String = "test" & DateTime.Now.Ticks & ".pdf"
 Dim strFileName As String = HttpContext.Current.Server.MapPath("reports\" & strFileShortName)
 Dim docWorkingDocument As iTextSharp.text.Document = New iTextSharp.text.Document(iTextSharp.text.PageSize.A4.Rotate(), 1, 1, 0, 0)
 Dim srdDocToString As StringReader = Nothing
 Try
 Dim pdfWrite As PdfWriter
 pdfWrite = PdfWriter.GetInstance(docWorkingDocument, New FileStream(strFileName, FileMode.Create))
 srdDocToString = New StringReader(strHtml)
 docWorkingDocument.Open()
 addLogo.ScaleToFit(128, 37)
 addLogo.Alignment = iTextSharp.text.Image.ALIGN_RIGHT
 ' addLogo.SetAbsolutePosition(0, docWorkingDocument.PageSize.Height - 100)
 docWorkingDocument.Add(addLogo)
 XMLWorkerHelper.GetInstance().ParseXHtml(pdfWrite, docWorkingDocument, srdDocToString)
 Catch ex As Exception
 Response.Write(ex.Message)
 Finally
 If Not docWorkingDocument Is Nothing Then
 docWorkingDocument.Close()
 docWorkingDocument.Dispose()
 End If
 If Not srdDocToString Is Nothing Then
 srdDocToString.Close()
 srdDocToString.Dispose()
 End If
 End Try
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "myscript", "window.open('reports/" & strFileShortName & "','_blank','location=0,menubar=0,status=0,titlebar=0,toolbar=0');", True)
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
 <title></title>
</head>
<body>
 <form id="form1" runat="server">
 <div>
 <asp:Button ID="Button1" runat="server" Text="Generate PDF" OnClick="Button1_Click" />
 </div>
 </form>
</body>
</html>

TestReport.aspx in VB.NET

<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
 Dim m_testData As New Hashtable()
 Protected Sub Page_Load(sender As Object, e As System.EventArgs)
 m_testData.Add("test_1_id", "test_1_value")
 m_testData.Add("test_2_id", "test_2_value")
 m_testData.Add("test_3_id", "test_3_value")
 m_testData.Add("test_4_id", "test_4_value")
 GridView1.DataSource = m_testData
 GridView1.DataBind()
 End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
 <title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
 <Columns>
 <asp:TemplateField HeaderText="key">
 <EditItemTemplate>
 <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("key") %>'></asp:TextBox>
 </EditItemTemplate>
 <ItemTemplate>
 <asp:Label ID="Label1" runat="server" Text='<%# Bind("key") %>'></asp:Label>
 </ItemTemplate>
 </asp:TemplateField>
 <asp:TemplateField HeaderText="value">
 <EditItemTemplate>
 <asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("value") %>'></asp:TextBox>
 </EditItemTemplate>
 <ItemTemplate>
 <asp:Label ID="Label2" runat="server" Text='<%# Bind("value") %>'></asp:Label>
 </ItemTemplate>
 </asp:TemplateField>
 </Columns>
</asp:GridView>
</form>
</body>
</html>
Advertisements

6 thoughts on “iTextSharp – Insert an Image to a PDF in C#”

  1. Hi Justin, thanks for an excellent article.

    Do you maybe know if it’s possible to create a library of images in the PDF and then re-use the same image on multiple locations without the PDF actually storing multiple copies of the same PDF?

    My tests so far have shown that an additional copy of the image gets added every time even though I re-use the same identical PDF.

    1. Hi, thanks for your note. I am not aware of being able to refer to an image multiple times in a PDF without actually including a new physical copy. It’s a really great idea, though, since it would cut down on the high file sizes that PDFs can get to!

      1. Wow, I did not such a quick reply! But thanks for confirming what I suspected! It would be a really nice feature and I’d be willing to accept a reasonable royalty for the idea :D

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s