iTextSharp - PDF - 调整文档大小以适应大图像

4

我正在使用iTextSharp将大型图像转换为PDF文档。

虽然可以完成转换,但是由于图像超出了生成的文档边界,因此图像会被裁剪。

那么问题来了——如何使生成的文档大小与插入其中的图像大小相同?

我正在使用以下代码:

  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();
   }
3个回答

4
尝试类似以下内容来解决你的问题:
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();
}

1
这是一篇你可以尝试的文章。我不确定你是否已经尝试过,但看看这个链接吧,因为那应该是有效的:http://www.mikesdotnetting.com/Article/87/iTextSharp-Working-with-images - MethodMan

4
在iText和iTextSharp中,Document对象是一个抽象的概念,可以自动处理各种间距、填充和边距。但不幸的是,这也意味着当您调用doc.Add()时,它会考虑文档中现有的边距。(此外,如果您添加了其他任何内容,图像也将相对于该内容添加。) 一种解决方案是只需去除边距:
doc.SetMargins(0, 0, 0, 0);

相反,直接将图像添加到通过调用PdfWriter.GetInstance()获得的PdfWriter对象中更容易。您目前正在丢弃并未存储该对象,但您可以轻松更改行:

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

然后您可以访问的DirectContent属性,并调用其AddImage()方法:

writer.DirectContent.AddImage(img);

在执行这个操作之前,您必须通过调用绝对定位来定位图片:
img.SetAbsolutePosition(0, 0);

以下是一个完整的工作中的C# 2010 WinForms应用程序,针对iTextSharp 5.1.1.0,显示了上面的DirectContent方法。它动态地创建了两个不同大小的图像,其中有两个红色箭头在垂直和水平方向上延伸。您的代码显然只需要使用标准的图像加载,因此可以省略很多内容,但我想提供一个完整的工作示例。有关更多详细信息,请参见代码中的注释。
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();
        }
    }
}

谢谢 - 这比原来的解决方案好多了。你有没有想法这种方法可以处理的最大图像尺寸是多少? - SharpAffair
根据PDF规范(附录C第2节),符合1.6标准的PDF的最小尺寸为3x3,最大尺寸为14,400x14,4000。请注意,这些尺寸以“默认用户空间单位”表示,如果您不更改,则为1/72英寸。通常最好将单位视为像素。如果您想了解有关“用户空间”和“单位”的更多信息,请参见此帖子:https://dev59.com/imsy5IYBdhLWcg3w6iJZ#8245450 - Chris Haas
乍一看,似乎完美无缺。你的帖子非常有帮助!谢谢! - SharpAffair

1

你没有说明你是要向文档中添加一张图片还是多张图片。但无论哪种情况,更改Document.PageSize都有点棘手。你可以通过调用Document.SetPageSize()随时更改页面大小,但这个调用仅对下一页生效

换句话说,就像这样:

<%@ 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; } }
}

上面的工作示例是在Web环境(.ashx HTTP处理程序)中的,因此您需要用代码段中的FileStream替换上面的Response.OutputStream。显然,您还需要替换文件路径。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接