Spire.PDF is a professional PDF library applied to creating, writing, editing, handling and reading PDF files without any external dependencies. Get free and professional technical support for Spire.PDF for .NET, Java, Android, C++, Python.

Mon Mar 26, 2018 4:02 pm

I've a requirement to take existing PDF documents, generated by a third-party system, and update them to include company letterhead. The letterheads I'll be provided with are PDFs - one for the first page and one to be applied on all other pages.

I'm evaluating Spire.PDF to see if it can fulfil the requirement and have seen plenty of samples online showing to apply background image, but have been unable to find a way of doing this with PDFs.

I'd be grateful if anyone can shed some light on this.

PeterCozens
 
Posts: 4
Joined: Thu Mar 15, 2018 3:26 pm

Tue Mar 27, 2018 2:54 am

Hello,

Thanks for your post. As for your case, you could first convert the PDFs with letterheads to images and then set the background image to another PDF file. Please refer to the below code snippet to accomplish it.
Code: Select all
            PdfDocument doc = new PdfDocument();
            doc.LoadFromFile(@"letterhead1.pdf");     
            Image image1 = doc.SaveAsImage(0);

            doc.LoadFromFile(@"letterhead2.pdf");
            Image image2 = doc.SaveAsImage(0);

            doc.LoadFromFile(@"test.pdf");
            for (int i = 0; i < doc.Pages.Count; i++)
            {
                if (i == 0)
                {
                    doc.Pages[i].BackgroundImage = image1;
                }
                else
                {
                    doc.Pages[i].BackgroundImage = image2;                   
                }               
            }
            doc.SaveToFile("result.pdf", FileFormat.PDF);
            doc.Close();


Best regards,
Simon
E-iceblue support team
User avatar

Simon.yang
 
Posts: 620
Joined: Wed Jan 11, 2017 2:03 am

Tue Mar 27, 2018 10:49 am

Hi Simon,

thanks for the prompt reply. I've implemented your code and it does indeed apply the PDFs in the background. I noticed, however, that the backgrounds were partially opaque and rather pixelated.

A little research on the forums threw up an article to solve the transparency issue. Unfortunately this forum won't let me post the URL to it (WHY????), so if anyone wants to see it, replace the underscores in the following with dots: https://www_e-iceblue_com/forum/transpa ... 46-15_html

Sorting out the quality of the background image was as simple as modifying the parameters for the save method.

My updated C# code is as follows:

Code: Select all
public static void ApplyBackgrounds(string sourcePdfPath, string firstPagePdfPath, string otherPagePdfPath, string outputPdfPath)
{
    var first = LoadPdfAsImage(firstPagePdfPath, 300);
    var other = LoadPdfAsImage(otherPagePdfPath, 300);
         
    using (var pdf = new PdfDocument(sourcePdfPath))
    {
        for (var i = 0; i < pdf.Pages.Count; i++)
        {
            var page = pdf.Pages[i];
            page.DefaultLayerIndex = -1;           
            page.BackgroundImage = i == 0 ? first : other;
            page.BackgroudOpacity = 1.0f;
        }

        pdf.SaveToFile(outputPdfPath, FileFormat.PDF);
    }
}

private static System.Drawing.Image LoadPdfAsImage(string pdfPath, int dpi)
{
    using (var doc = new PdfDocument(pdfPath))
        return doc.SaveAsImage(0,PdfImageType.Metafile, dpi, dpi);
}


The only downside with this apprach is that it significantly increases the size of the generated PDF. In my test case the three PDFs that go into the final result are less than 200k in total, yet the generated output is 1.2MB. I presume that this is because I'm placing a 300dpi image on each page, rather than the text elements from the letterhead templates. (NOTE: I've selected 300pdi as the minimum acceptable print resolution for the background - any less does not print sharply enough)

As an alternative approach, is there any way to enumerate the elements in the letterhead PDFs and apply them to a PdfTemplate on each page of the source PDF? In addition to reducing the output file size, this will also make the text in the letterhead (such as the address, contact email, etc) selectable for copy & paste.

PeterCozens
 
Posts: 4
Joined: Thu Mar 15, 2018 3:26 pm

Wed Mar 28, 2018 8:58 am

Hello,

Thanks for you reply.
As for the limitation to post URL, that's because your account is new. If you post more in the future, you will be allowed to post URL.
Regarding the increasing size of the generated PDF, yes, the higher DPI of the background image will result in bigger size of the result PDF. Please try to use pdf.FileInfo.IncrementalUpdate = false before saving which will help to reduce the size.
I think there is an alternative approach as your description that we can extract text from the letterheads PDFs and then draw the text to the source Pdf file. It will help a lot to reduce the file size and the drawing text are also selectable.
Please share us with your input PDFs and expected result file for further investigation. If it's reachable, we will provide a demo for you. You could zip them and attach here or send to [email protected].

Best regards,
Simon
E-iceblue support team
Last edited by Simon.yang on Thu Mar 29, 2018 1:09 am, edited 1 time in total.
User avatar

Simon.yang
 
Posts: 620
Joined: Wed Jan 11, 2017 2:03 am

Wed Mar 28, 2018 10:34 am

Thanks Simon - I've just sent an email with the PDFs and sample project to your support address.

I'm looking forward to seeing what you can come up with.

PeterCozens
 
Posts: 4
Joined: Thu Mar 15, 2018 3:26 pm

Thu Mar 29, 2018 10:31 am

Hello,

I have received your email. Once I finish the demo, I will let you know.

Best regards,
Simon
E-iceblue support team
User avatar

Simon.yang
 
Posts: 620
Joined: Wed Jan 11, 2017 2:03 am

Fri Mar 30, 2018 2:21 am

Hello,

We find that there is another approach to fulfill your requirement which is simple and convenient. Also the result Pdf size is very closed to the source Pdf. We could create templates from the template Pdf file directly and then draw them to the invoice file. Please refer to the below code snippet and have a try.
Code: Select all
            //Load 3 documents from disk
            PdfDocument doc1 = new PdfDocument();
            doc1.LoadFromFile(@"TestData\first page template.pdf");

            PdfDocument doc2 = new PdfDocument();
            doc2.LoadFromFile(@"TestData\other page template.pdf");

            PdfDocument doc3 = new PdfDocument();
            doc3.LoadFromFile(@"TestData\sample invoice.pdf");

            //Create page templates
            PdfTemplate template1 = doc1.Pages[0].CreateTemplate();
            PdfTemplate template2 = doc2.Pages[0].CreateTemplate();

            //apply the templates and save it to the output path
            for (int i = 0; i < doc3.Pages.Count; i++)
            {
                doc3.Pages[i].Canvas.SetTransparency(0.25f, 0.25f, PdfBlendMode.Overlay);
                doc3.Pages[i].Canvas.DrawTemplate(i==0?template1:template2, PointF.Empty);
            }

            //Save the document
            doc3.SaveToFile(@"TestData\Overlay.pdf");
            doc1.Close();
            doc2.Close();
            doc3.Close();


Best regards,
Simon
E-iceblue support team
User avatar

Simon.yang
 
Posts: 620
Joined: Wed Jan 11, 2017 2:03 am

Mon Apr 02, 2018 8:38 am

Hello,

Greeting from E-iceblue.
How is the issue going?
Is the solution helpful to you?
Your feedback will be greatly appreciated.

Best regards,
Simon
E-iceblue support team
User avatar

Simon.yang
 
Posts: 620
Joined: Wed Jan 11, 2017 2:03 am

Tue Apr 03, 2018 10:49 am

Absolutely brilliant! Thanks very much for the updated sample code - it does exactly what I want. The generated PDFs are much smaller than the earlier sample code using images and since the background is text it will copy & paste just fine.

My final proof-of-concept code is as follows:

Code: Select all
var location = new Uri(Assembly.GetEntryAssembly().GetName().CodeBase).LocalPath;
var folder = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(location), @"..\..\TestData"));

// Determine the full paths to all the PDFs

var invoicePath = Path.Combine(folder, "sample invoice.pdf");
var firstPagePath = Path.Combine(folder, "first page template.pdf");
var otherPagePath = Path.Combine(folder, "other page template.pdf");
var outputPath = Path.Combine(folder, "output.pdf");

// Ensure that the output file does not already exist

if (File.Exists(outputPath))
    File.Delete(outputPath);

// Load the invoice and templates

using (var pdf = new PdfDocument(invoicePath))
using (var firstPagePdf = new PdfDocument(firstPagePath))
using (var otherPagePdf = new PdfDocument(otherPagePath))
{
    var firstPageTemplate = firstPagePdf.Pages[0].CreateTemplate();
    var otherPageTemplate = otherPagePdf.Pages[0].CreateTemplate();

    // Apply the templates to the invoice

    for (var i = 0; i < pdf.Pages.Count; i++)
    {
        var page = pdf.Pages[i];
        page.Canvas.SetTransparency(0.25f, 0.25f, PdfBlendMode.Overlay);
        page.Canvas.DrawTemplate(i == 0 ? firstPageTemplate : otherPageTemplate, PointF.Empty);
    }

    pdf.SaveToFile(outputPath, FileFormat.PDF);
}


This achieves exactly what I want, clearing the way for me to get some Spire.PDF licences and using this in production. Thanks for all your help.

As a side note, I've come across some minor anomolies with the output when viewing it in Foxit PDF viewer, but my testing indicates that the problems are down to the viewer, not the generated PDF.

PeterCozens
 
Posts: 4
Joined: Thu Mar 15, 2018 3:26 pm

Wed Apr 04, 2018 2:31 am

Hello,

Thanks for your feedback.
I noticed the issue when using a Foxit Reader. Just as you said, the issue is caused by the Foxit Reader. As Spire.Pdf follows the rules of Adobe, I am afraid you need to use a Adobe Reader to view it which doesn't have the background issue.
On the other hand, our sales will send you the detail to help you choose a license that is suitable for you.

Best regards,
Simon
E-iceblue support team
User avatar

Simon.yang
 
Posts: 620
Joined: Wed Jan 11, 2017 2:03 am

Return to Spire.PDF