iTextSharp - Working with images

The seventh article in my iTextSharp series looks at working with images. This article builds on the previous six which are listed below.

Create PDFs in ASP.NET - getting started with iTextSharp
iTextSharp - Working with Fonts
iTextSharp - Adding Text with Chunks, Phrases and Paragraphs
Lists with iTextSharp
iTextSharp - Links and Bookmarks
iTextSharp - Introducing Tables

iTextSharp supports all the main image types: jpg, tif, gif, bmp, png and wmf. There are a number of ways to create images with iTextSharp using the Image.GetInstance() method. Probably the most used option will be to pass a filesystem path and file name into the method:

 

string pdfpath = Server.MapPath("PDFs");

string imagepath = Server.MapPath("Images");

Document doc = new Document();

try

{

  PdfWriter.GetInstance(doc, new FileStream(pdfpath + "/Images.pdf", FileMode.Create));

  doc.Open();

 

  doc.Add(new Paragraph("GIF"));

  Image gif = Image.GetInstance(imagepath + "/mikesdotnetting.gif");

  doc.Add(gif);

}

catch (Exception ex)

{

  //Log error;

}

finally

{

  doc.Close();

}

 

Alternative constructors that you may use include passing a URL or a System.Drawing.Image object (as opposed to an iTextSharp.text.Image). Note - the following snippet that System.Drawing.Image.FromStream() method shows the use of namespace aliasing again (sd.Image.FromStream(fs)), as was highlighted in the article Lists with iTextSharp to avoid clashes with the two different types of Image object:

 

doc.Add(new Paragraph("JPG"));

string url = "http://localhost:1805/PDF/Images/mikesdotnetting.jpg";

Image jpg = Image.GetInstance(new Uri(url));

doc.Add(jpg);

doc.Add(new Paragraph("PNG"));

using (FileStream fs = new FileStream(imagepath + "/mikesdotnetting.png", FileMode.Open))

{

  Image png = Image.GetInstance(sd.Image.FromStream(fs),ImageFormat.Png);

  doc.Add(png);

}

 

It's difficult to tell from the images I have provided so far, but the resolution of the resulting images in the PDF file is not that great. By default, images are embedded at 72 dpi (Dots Per Inch) which coincidentally, matches the number of points in an inch. If this file was being prepared for printing, the final job would be a bit nasty. Generally, commercial printers require that colour images for printing have a resolution of 300 dpi. To achieve this, you can scale the image to 24%. What you are actually trying to do is squeeze 300 pixels into the space that 72 normally occupies. 72/300 * 100 = 24%. The image stays the same in terms of file size but occupies less space in the document.

 

doc.Add(new Paragraph("TIF Scaled to 300dpi"));

Image tif = Image.GetInstance(imagepath + "/mikesdotnetting.tif");

tif.ScalePercent(24f);

doc.Add(tif);

 

Now, I have a large tif file that I want to use as a logo on an A4 letterhead. It measures 300 x 890 pixels. So at the default 72 dpi, it will measure 4.17 inches wide by12.36 inches deep. Increasing the resolution to 300 dpi will reduce the width to 1 inch, and the depth to 2.97 inches (72 points by 213.6 points). That part is fine. We can do that using the code above. Now I want to place the 300 dpi image in a particular position on the page. I have in mind the top right hand corner. The SetAbsolutePosition() method will do this, but I need to get a calculator out.

SetAbsolutePosition() accepts 2 floats as parameters. The first represents the co-ordinate along the X-axis, which starts at the left hand edge of the document and finishes at the right hand edge of the document. The second represents the Y-axis co-ordinate which starts from the bottom of the document and goes to the top. An A4 document is 595 points wide and 842 pixels high with a 36 point margin all around by default.

The actual co-ordinate that needs to be passed in is the bottom left of the image position. This image will butt right up to the right-hand margin. The image is 72 points wide (1 inch) + the margin at 36 points (total 108 points) from the right hand edge of the document, or 595 - 108 = 487 points along the X-axis. The Y-axis co-ordinate is the height of the image + the margin away from the top of the document, or 842 - (213.6 + 36) = 592.4 points from the bottom. Cripes. I don't really want to have to remember all the various sizes of different documents and do these calculations every time I want to set the absolute position of an element. And fortunately, I don't have to. I can use the Document.PageSize object to do the work for me.

 

Image tif = Image.GetInstance(imagepath + "/verticallogo.tif");

tif.ScalePercent(24f);

tif.SetAbsolutePosition(doc.PageSize.Width - 36f - 72f,
      doc.PageSize.Height - 36f - 216.6f);

doc.Add(tif);

 

doc.PageSize.Width gives me the width in points of the document, and I just remove the margin (36 points) and the width of the image (72 points) for the X-axis co-ordinate, and the margin and height of the image from the total height of the document for the Y-axis co-ordinate.

Got my company logo in :-)

Another scenario that might need to be catered for is to fit a user-supplied image into a fixed size box somewhere on a form. I've pinched the Sunset image that I found in the Sample Images folder in My Pictures that comes as part of the default install of WindowsXP to illustrate how to use the ScaleToFit() method to achieve this. The following code takes an image of 800 x 600 and forces it to resize, maintaining its aspect ratio, into a rectangle measuring 250 points square.

 

Image jpg = Image.GetInstance(imagepath + "/Sunset.jpg");

jpg.ScaleToFit(250f, 250f);

jpg.Border = Rectangle.BOX;

jpg.BorderColor = Color.YELLOW;

jpg.BorderWidth = 5f;

doc.Add(jpg);

doc.Add(new Paragraph("Original Width: " + jpg.Width.ToString()));

doc.Add(new Paragraph("Original Height " + jpg.Height.ToString()));

doc.Add(new Paragraph("Scaled Width: " + jpg.ScaledWidth.ToString()));

doc.Add(new Paragraph("Scaled Height " + jpg.ScaledHeight.ToString()));

float Resolution = jpg.Width / jpg.ScaledWidth * 72f;

doc.Add(new Paragraph("Resolution: " + Resolution));

 

I have also taken the opportunity to add a yellow border to the embedded image, which is 5 points wide, and then shown the original dimensions, followed by the scaled dimensions, and the resulting resolution of the image. And here's the result:

If you use SetAbsolutePosition() you end up with the same effect as if you had set the Alignment property of the image to Image.UNDERLYING, in that text added to the document will run over the top of it. Unless you want to achieve this kind of watermark effect, you need to use Image.TEXTWRAP instead.

 

Image jpg = Image.GetInstance(imagepath + "/Sunset.jpg");

Paragraph paragraph = new Paragraph(@"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Suspendisse blandit blandit turpis. Nam in lectus ut dolor consectetuer bibendum. Morbi neque ipsum, laoreet id; dignissim et, viverra id, mauris. Nulla mauris elit, consectetuer sit amet, accumsan eget, congue ac, libero. Vivamus suscipit. Nunc dignissim consectetuer lectus. Fusce elit nisi; commodo non, facilisis quis, hendrerit eu, dolor? Suspendisse eleifend nisi ut magna. Phasellus id lectus! Vivamus laoreet enim et dolor. Integer arcu mauris, ultricies vel, porta quis, venenatis at, libero. Donec nibh est, adipiscing et, ullamcorper vitae, placerat at, diam. Integer ac turpis vel ligula rutrum auctor! Morbi egestas erat sit amet diam. Ut ut ipsum? Aliquam non sem. Nulla risus eros, mollis quis, blandit ut; luctus eget, urna. Vestibulum vestibulum dapibus erat. Proin egestas leo a metus?");

paragraph.Alignment = Element.ALIGN_JUSTIFIED;

jpg.ScaleToFit(250f, 250f);

jpg.Alignment = Image.TEXTWRAP | Image.ALIGN_RIGHT;

jpg.IndentationLeft = 9f;

jpg.SpacingAfter = 9f;

jpg.BorderWidthTop = 36f;

jpg.BorderColorTop = Color.WHITE;

doc.Add(jpg);

doc.Add(paragraph);

 

In this instance, I added a white border to the image to align it with the top of the text, and a bit of padding to the left and bottom of the image to stop the text running right up to its edge. Left and Right padding can be added using the IndentationLeft and IndentationRight properties, while SpacingBefore and SpacingAfter is used to pad the top and bottom. You may ask why I didn't use SapcingBefore instead of adding a white border, and that's a good question. The fact is that whatever I set the value to for SpacingBefore, it seemed to have no effect whatsover in this instance. I have no idea why this should be, but if anyone does, I'll be pleased to hear from them.

One final thing with images - you can rotate them if you need to. One way to do this is to set the Rotation property, which takes a float. The float value represents an angle measured in Radians. If you did more Mathematics than I did at school, you may be comfortable with this, but if you are like me and ask "What??", you can either read this article on Radians and work out that a quarter turn (90°) is Pi / 2, or simply set the RotationDegrees property instead. Rotation by default is anti-clockwise. The following are equally valid and equivalent:

 

jpg.Rotation = (float)Math.PI / 2;

jpg.RotationDegrees = 90f;

 

 

Date Posted: Friday, November 7, 2008 11:00 PM
Last Updated: Wednesday, June 20, 2012 4:34 PM
Posted by: Mikesdotnetting
Total Views to date: 296932

31 Comments

Thursday, June 4, 2009 7:41 PM - dsoltesz

Is there a way to convert a pdf to image?

Thursday, July 23, 2009 2:43 PM - Oliver Kanani

Thank you for this guide !

My previous boring PDF pages have now come alive !

Wednesday, September 23, 2009 1:29 PM - Steven Bey

Mike

I have a task to create a PDF that contains several graphs. Each graph has a title but, at the moment, if the graph is too big for the remaining space on the page, it moves to the next page and my client (as well as myself) isn't happy with it. I've spent hours searching and trying different solutions, without success, but I keep coming across your tutorials, which I think are of extremely high quality (unlike many other sites, including the main iTextSharp site). So, I was wondering if you have any idea how to get this right?

Many thanks

Steve

Wednesday, September 23, 2009 3:10 PM - Mike

@Steve

It's difficult to provide sensible suggestions without more detail. You say graphs, but you have posted your comment against the "images" article. Are they in fact images? What are you using to generate the graphs? You can resize images prior to adding them to a Document object, which would be the first thing I think of.

Friday, September 25, 2009 5:25 PM - jonny

I was wondering if you can insert an image from sql using a query string

Friday, September 25, 2009 11:52 PM - Mike

@jonny

Yes you can. If you Google, there are loads of examples of getting an image out of a database using C# or VB. Assuming you get it out as a Stream, you just use the Image.GetInstance() overload that accepts a stream and plug the result into your Document.

Thursday, November 19, 2009 5:32 AM - Abhijit Aradhye

This article is really awesome .
i really get help from it n solve my problem.

i have another problem
i want to add water mark image in pdf?
will u please help m?

Tuesday, December 1, 2009 7:37 AM - Deepak C

Hi Mike,
Great article. However, I was just wondering if there is a way to convert a pdf page into an TIFF image and save it to disk. I tried walking through iTextSharp API, but couldn't find a solution.
Please let me know, if there is a way to do this using this API.

Thanks in advance for your help.

Tuesday, December 1, 2009 9:12 PM - Mike

@Deepak C

No - iTextSharp doesn't provide this functionality. I can't think why they would. PDF is a better storage format than TIFF, and if you want a readonly PDF, iTextSharp lets you prevent copying, editing, extraction etc, and you can password protect the file too.

Saturday, December 5, 2009 6:36 AM - omm

This very useful for me, who was in need to convert the text into image and then scale them exactly to the size of the text placed in the PDF. also thanking for that DPI-Pixels calculation.

Monday, December 7, 2009 12:07 PM - Marina

This article is realy usefull.
But I have some more questions.
1. I plan to use iText library to create pdf file and insert image into it. As far as i can see this library changes a filter for the image using some internal algorithm. How can I insert image using /DCTDecode filter?
2. I also need extract images from pdf file. If filter is /DCTDecode all works fine. But how to extact image with /FlateDecode filter?

Friday, May 7, 2010 4:16 PM - Geoffrey

Wow, Mike...I appreciate you taking the time to blog about obscure, helpful information like this. I fumbled my way through some less-helpful iTextSharp tutorials a while back to achieve the necessary, but your tutorials show so many different possibilities that my website will definitely start looking more professional. Thanks and please keep them coming!

Thursday, September 9, 2010 10:56 AM - Marisha

does itextsharp have anything to generate graphs? I want to generate graphs based on the dyanamic data coming from the database and treat them as an image in the pdf file. Is there a way to do it?

Thursday, September 9, 2010 2:08 PM - Mike

@Marisha

iTextSharp doesn't have anything for charting, but you can use the Microsoft Charting controls and generate images which can be embedded in PDFs. I've done an article on how to do this in MVC, but the code can easily be transfered to Web Forms:
http://www.mikesdotnetting.com/Article/115/Microsoft-Chart-Controls-to-PDF-with-iTextSharp-and-ASP.NET-MVC

Monday, September 20, 2010 5:27 PM - Reyaz

Thanks for the artilce, Really nice and well explained.

I was trying to run the code on godaddy server and i am getting the error " System.Security.SecurityException: That assembly does not allow partially trusted callers."

Any idea on how to set the securtiy to allow the script?

Thanks in advance

Monday, September 20, 2010 9:05 PM - Mike

@Reyaz,

The iTextsharp assembly is not marked with the AllowPartiallyTrustedCallers attribute. I suspect that GoDaddy are unlikely to add the dll to an exceptions list, so the best thing you can do is to download the source code, modify the AssemblyInfo.cs file to add the partially trusted callers attribute.
[assembly: AllowPartiallyTrustedCallers()]

and then build the project. The resulting dll should be ok for use in medium trust, which is what I believe GoDaddy support.

Wednesday, September 29, 2010 4:46 PM - Clark Harper

How would you position text over an image -- so that the image appears to be the background?

This is a fantastic set of articles. Thanks so much.

Wednesday, October 6, 2010 11:10 AM - Jason

Thanx so much for this example ive been looking for something like this for about an hour and yours is perfect!

thanx so much, happy coding

Friday, October 15, 2010 11:56 AM - Jonathan

Hi

Examples are great
Can you overlay images on top of each other ?
i have tableCell.Image = imagePdf
i need to overlay another image on top of the same table cell ?

Jon

Saturday, October 16, 2010 8:33 AM - Mike

@Jonathon

I've never tried, but I suspect you could use positioning to do this: http://www.mikesdotnetting.com/Article/89/iTextSharp-Page-Layout-with-Columns

Saturday, October 16, 2010 9:09 PM - Richard

Hi Mike,

First of all, great series of articles, particularly considering the lack of iTextSharp documentation out there.

I just wonder if you can help me out with something. I am trying to programatically determine if a PDF file contains Bitmap images but not sure if this is possible with iTextSharp.

Any ideas would be appreciated.

Many thanks,
Richard

Sunday, October 17, 2010 7:09 PM - Mike

@Richard

I don't know of any way to do that. As far as the PDF is concerned, it's all just "content".

Wednesday, October 27, 2010 8:31 AM - SP

Hi Mike,

I need to create image from a PDF page to show a kind of preview. Is there any way to render a PDF page as a bitmap. Once I get it in a bitmap I can save it to a file.

Friday, January 28, 2011 4:50 PM - alex

Great article. I have one issue, the paragraphs are being added on top of the image instead of below. I follow the instructions on how to position the company logo but the text keeps appering on top of the image.

Wednesday, February 2, 2011 5:40 PM - elitsa

Great Article! I have 1 question. Can you set a z-index for the image and display it on top of the other, existing content of the page?

Saturday, February 26, 2011 10:05 AM - lsharma

Great article...

the code seems to work perfectly...but wht it also doing is that it is overwriting the content of the existing pdf file... say i have a pdf file a.pdf and i want to append the image on a certain location...how can i do that....

Friday, March 25, 2011 5:46 AM - umadevi

Great article. I have one issue, the paragraphs are being added on top of the image instead of below. I follow the instructions on how to position the company logo but the text keeps appering on top of the image

Friday, June 8, 2012 4:32 AM - Jignesh Rathod

I want you to know that your articles on iTextSharp have greatly helped my with my project. Thank you so much.

Monday, July 2, 2012 5:25 PM - Pat

I also just want to say thanks a million for this. It has helped allot.

Thanks again

Wednesday, January 23, 2013 9:22 AM - suresh

I wants to add watermark (string) on existing pdf which contains image. But watermark is added behind image. so i was unable to see watermark. Could you please tell me how can i bring watermark infront of image.

Wednesday, March 19, 2014 7:50 PM - Jose

Gracias este articulo ha solucionado un monton de cosas!!
Add your comment

If you have any comments to make about this article, please use this form to do so. Make sure that your comment relates specifically to the article above. More general comments can be posted through the form on the Contact page.

Please note, all comments are moderated, and some may not be published. The kind of things that will ensure your comment is deleted without ever seeing the light of day are as follows:

  • Not relevant to the article
  • Gratuitous links to your own site or product
  • Anything abusive or libellous
  • Spam
  • Anything in a language I don't understand including gibberish.

I do not pass email addresses on to spammers, so a valid one will assist me in responding to you personally if required.

Recent Comments

Gautam 11/20/2014 8:01 AM
In response to I'm Writing A Book On WebMatrix
Hello Mike, I read your book, loved it! However, I have a few request/suggestions: 1) an example...

Bret Dev 11/19/2014 8:39 PM
In response to The Difference Between @Helpers and @Functions In WebMatrix
Excellent post! One concern - where can you place global @Functions code within an MVC project to Is...

Rob Farquharson 11/19/2014 4:28 PM
In response to iTextSharp - Links and Bookmarks
How can I place text at an absolute position on the page? Also, how can I rotate text?...

Andy 11/17/2014 8:08 PM
In response to MVC 5 with EF 6 in Visual Basic - Sorting, Filtering and Paging
Hello I'm testing your sorting instructions above. This is great and I was able to get it to work...

Gautam 11/17/2014 5:51 PM
In response to WebMatrix - Database Helpers for IN Clauses
Hi Mike, I am very new to programming: In the above example if I want to use a delete button the...

donramon 11/17/2014 3:22 PM
In response to Entity Framework 6 Recipe - Alphabetical Paging In ASP.NET MVC
Congratulations on your new website look and the excellent articles. Thank you!...

Gautam 11/17/2014 11:26 AM
In response to Looking At The WebMatrix WebGrid
Hi Mike, I add the jquery script at the end of my html file.. when ajax attribute is added to the be...

Chet Ripley 11/15/2014 6:57 PM
In response to Adding A New Field
It appears the command is case sensitive. I had the same issue as Cameron. When I changed the to it...

Alvin 11/14/2014 12:49 PM
In response to Razor Web Pages E-Commerce - Adding A Shopping Cart To The Bakery Template Site
Great article Mike! When do you plan to extend the bakery shopping cart beyond this point?...

Gautam 11/14/2014 10:16 AM
In response to Web Pages - Efficient Paging Without The WebGrid
to get the count can we use only the below sql, why to join category and author table var sql =...