简体   繁体   中英

Insert PDF in PDF (NOT merging files)

I'd like to insert a PDF page in another PDF page scaled. I'd like to use iTextSharp for this.

I have a vector drawing which can be exported as a single page PDF file. I would like to add this file into a page of other PDF document just like I would add an image to a PDF document.

Is this possible?

The purpose of this is to retain the ability to zoom in without losing quality.

It is very hard to reproduce the vector drawing using PDF vectors because it is an extremely complex drawing.

Exporting the vector drawing as high resolution image is not an option since I have to use a lot of them in a single PDF document. The final PDF would be very large and its writing too slow.

This is relatively easy to do although there's a couple of ways to go about it. If you're creating a new document that has the other documents inside of it and nothing else then the easiest thing to use is probably the PdfWriter.GetImportedPage(PdfReader, Int) . This will give you a PdfImportedPage (which inherits from PdfTemplate ). Once you have that you can add it to your new document by using PdfWriter.DirectContent.AddTemplate(PdfImportedPage, Matrix) .

There's a couple of overloads to AddTemplate() but the easiest one (at least for me) is the one that takes a System.Drawing.Drawing2D.Matrix . If you use this you can easily scale and translate (change x,y) without having to think in "matrix" terms.

Below is sample code that shows this off. It targets iTextSharp 5.4.0 although it should work pretty much the same with 4.1.6 if you remove the using statements. It first creates a sample PDF with 12 pages with random background colors. Then it creates a second document and adds each page from the first PDF scaled by 50% so that 4 old pages fit onto 1 new page. See the code comments for further details. This code assumes that all pages are the same size, you might need to perform further calculations if your situation differs.

//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();
            }
        }
    }
}

In addition; while i was trying to add a rotated pdf to a rotated pdf, i got some rotation problems. Kind of confusing but you should check the "PdfImportedPage.Rotation" of the page which is gonna be added to pdf.

PdfImportedPage page;//page = writer.GetImportedPage(PdfReader reader, int pageNum);
PdfContentByte pcb;//pcb = PdfWriter.DirectContentUnder;

//create matrix to use for rotating imported page    
Matrix matrix = new Matrix(a, b, c, d, e, f);
matrix.Rotate(-(page.Rotation));
if (page.Rotation != 0)
   pcb.AddTemplate(page, matrix, true);
else
   pcb.AddTemplate(page, a, b, c, d, e, f, true);

code looks like silly but i want to get your attention on "matrix.Rotate(negative rotation of imported page)"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM