【问题标题】:Insert PDF in PDF (NOT merging files)在 PDF 中插入 PDF(不合并文件)
【发布时间】:2013-04-09 10:12:33
【问题描述】:

我想在另一个缩放的 PDF 页面中插入一个 PDF 页面。我想为此使用 iTextSharp。

我有一个可以导出为单页 PDF 文件的矢量图。我想将此文件添加到其他 PDF 文档的页面中,就像我将图像添加到 PDF 文档一样。

这可能吗?

这样做的目的是保留放大而不损失质量的能力。

使用 PDF 矢量再现矢量绘图非常困难,因为它是一个极其复杂的绘图。

将矢量绘图导出为高分辨率图像不是一种选择,因为我必须在单个 PDF 文档中使用大量矢量绘图。最终的 PDF 会非常大,而且写入速度也很慢。

【问题讨论】:

    标签: pdf itextsharp


    【解决方案1】:

    虽然有几种方法可以做到这一点,但这相对容易做到。如果您正在创建一个新文档,其中包含其他文档而没有其他文档,那么最容易使用的可能是PdfWriter.GetImportedPage(PdfReader, Int)。这会给你一个PdfImportedPage(继承自PdfTemplate)。完成后,您可以使用 PdfWriter.DirectContent.AddTemplate(PdfImportedPage, Matrix) 将其添加到新文档中。

    AddTemplate() 有几个重载,但最简单的一个(至少对我而言)是采用 System.Drawing.Drawing2D.Matrix 的重载。如果您使用它,您可以轻松缩放和转换(更改 x,y),而无需考虑“矩阵”术语。

    下面是展示这一点的示例代码。它以 iTextSharp 5.4.0 为目标,但如果删除 using 语句,它应该与 4.1.6 几乎相同。它首先创建一个包含 12 页随机背景颜色的示例 PDF。然后它会创建第二个文档,并将第一个 PDF 中的每一页都按 50% 比例添加,以便 4 个旧页面适合 1 个新页面。有关详细信息,请参阅代码 cmets。此代码假定所有页面的大小相同,如果您的情况不同,您可能需要执行进一步的计算。

    //Test files that we'll be creating
    var file1 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "File1.pdf");
    var file2 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "File2.pdf");
    
    //For test purposes we'll fill the pages with a random background color
    var R = new Random();
    
    //Standard PDF creation, nothing special here
    using (var fs = new FileStream(file1, FileMode.Create, FileAccess.Write, FileShare.None)) {
        using (var doc = new Document()) {
            using (var writer = PdfWriter.GetInstance(doc, fs)) {
                doc.Open();
    
                //Create 12 pages with text on each one
                for (int i = 1; i <= 12; i++) {
                    doc.NewPage();
    
                    //For test purposes fill the page with a random background color
                    var cb = writer.DirectContentUnder;
                    cb.SaveState();
                    cb.SetColorFill(new BaseColor(R.Next(0, 256), R.Next(0, 256), R.Next(0, 256)));
                    cb.Rectangle(0, 0, doc.PageSize.Width, doc.PageSize.Height);
                    cb.Fill();
                    cb.RestoreState();
    
                    //Add some text to the page
                    doc.Add(new Paragraph("This is page " + i.ToString()));
                }
                doc.Close();
            }
        }
    }
    
    //Create our combined file
    using (var fs = new FileStream(file2, FileMode.Create, FileAccess.Write, FileShare.None)) {
        using (var doc = new Document()) {
            using (var writer = PdfWriter.GetInstance(doc, fs)) {
    
                //Bind a reader to the file that we created above
                using (var reader = new PdfReader(file1)) {
                    doc.Open();
    
                    //Get the number of pages in the original file
                    int pageCount = reader.NumberOfPages;
    
                    //Loop through each page
                    for (int i = 0; i < pageCount; i++) {
                        //We're putting four original pages on one new page so add a new page every four pages
                        if (i % 4 == 0) {
                            doc.NewPage();
                        }
    
                        //Get a page from the reader (remember that PdfReader pages are one-based)
                        var imp = writer.GetImportedPage(reader, (i + 1));
                        //A transform matrix is an easier way of dealing with changing dimension and coordinates on an rectangle
                        var tm = new System.Drawing.Drawing2D.Matrix();
    
                        //Scale the image by half
                        tm.Scale(0.5f, 0.5f);
    
                        //PDF coordinates put 0,0 in the bottom left corner.
                        if (i % 4 == 0) {
                            tm.Translate(0, doc.PageSize.Height);                   //The first item on the page needs to be moved up "one square"
                        } else if (i % 4 == 1) {
                            tm.Translate(doc.PageSize.Width, doc.PageSize.Height);  //The second needs to be moved up and over
                        } else if (i % 4 == 2) {
                                                                                    //Nothing needs to be done for the third
                        } else if (i % 4 == 3) {
                            tm.Translate(doc.PageSize.Width, 0);                    //The fourth needs to be moved over
                        }
    
                        //Add our imported page using the matrix that we set above
                        writer.DirectContent.AddTemplate(imp,tm);
    
                    }
    
                    doc.Close();
                }
            }
        }
    }
    

    【讨论】:

    • 对。这是使用PdfWriter 而不是Pdf*Copy* 类之一将一个文档中的页面导入另一个文档的用例之一,参见。回复How to merge multiple pdf files (generated in run time)?
    • @Chris Hass。感谢您的精彩重播,我也阅读了您在其他问题中的回复,我发现它们对这一点很有帮助。再次感谢。
    • 另外,为了明确以防其他人在将来阅读此内容,上面的代码适用于基本的简单 PDF。如果有任何表单字段、注释、书签等(基本上除了文本、行和图像之外的任何内容),请务必阅读 @mkl 的链接以了解执行此操作的替代方法。
    猜你喜欢
    • 1970-01-01
    • 2013-09-24
    • 2011-03-27
    • 2011-02-13
    • 1970-01-01
    • 2013-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多