ITextSharp - PDF - Resize Document to Fit Large Image

I use iTextSharp to convert large images to PDF documents.

This works, but the images are cropped because they exceed the borders of the generated document.

So the question is, how do you make a document the same size as the image you are inserting into it?

I am 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(); } 
+4
source share
3 answers

The Document object in iText and iTextSharp is an abstraction that automatically handles various distances, spacers, and fields. Unfortunately for you, this also means that when you call doc.Add() it takes into account the existing fields of the document. (Also, if you add anything else, an image will be added regarding this.)

One solution would be to simply remove the fields:

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

Instead, it’s easier to add the image directly to the PdfWriter object that you get from calling PdfWriter.GetInstance() . You are currently discarding and not saving this object, but you can easily change your line:

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

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

 writer.DirectContent.AddImage(img); 

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

 img.SetAbsolutePosition(0, 0); 

The following is a complete working C # 2010 WinForms application focused on iTextSharp 5.1.1.0, which shows the DirectContent method above. It dynamically creates two images of different sizes with two red arrows stretching both vertically and horizontally. Obviously, your code will simply use standard image loading and thus may skip this, but I would like to give a complete 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(); } } } 
+4
source

Try something similar to fix your problem.

 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(); } 
+3
source

You did not say whether you are adding one image to the document or several images. But in any case, changing Document.PageSize bit complicated. You can change the page size at any time by clicking Document.SetPageSize () , but the call ONLY acts on the NEXT page .

In other words, something like this:

 <%@ WebHandler Language="C#" Class="scaleDocToImageSize" %> using System; using System.Web; using iTextSharp.text; using iTextSharp.text.pdf; public class scaleDocToImageSize : IHttpHandler { public void ProcessRequest (HttpContext context) { HttpServerUtility Server = context.Server; HttpResponse Response = context.Response; Response.ContentType = "application/pdf"; string[] imagePaths = {"./Image15.png", "./Image19.png"}; using (Document document = new Document()) { PdfWriter.GetInstance(document, Response.OutputStream); document.Open(); document.Add(new Paragraph("Page 1")); foreach (string path in imagePaths) { string imagePath = Server.MapPath(path); Image img = Image.GetInstance(imagePath); var width = img.ScaledWidth + document.RightMargin + document.LeftMargin ; var height = img.ScaledHeight + document.TopMargin + document.BottomMargin ; Rectangle r = width > PageSize.A4.Width || height > PageSize.A4.Height ? new Rectangle(width, height) : PageSize.A4 ; /* * you __MUST__ call SetPageSize() __BEFORE__ calling NewPage() * AND __BEFORE__ adding the image to the document */ document.SetPageSize(r); document.NewPage(); document.Add(img); } } } public bool IsReusable { get { return false; } } } 

The working example is higher in a web environment (HTTP handler.), So you need to replace Response.OutputStream above with FileStream (from your code snippet). And obviously, you also need to replace the file paths.

0
source

Source: https://habr.com/ru/post/1389092/


All Articles