11

I've researched quite a bit but most answers I've found involve using iText which is only free for authors of open source software.

My question is how to utilise a free (preferably well maintained) PDF library to convert an image into PDF. More specifically I'm using Selenium to test a webpage and part of the requirements are for a screenshot of a results page to be saved in PDF format.

What I have at the moment:

        Screenshot screenshot = ((ITakesScreenshot)WebDriver).GetScreenshot();
        fileName =  filePath + fileName;

        screenshot.SaveAsFile($"{fileName}.png", ImageFormat.Png);

        // Convert to PDF and delete image
        // ?
Braiam
  • 1
  • 11
  • 47
  • 78
Ory Zaidenvorm
  • 896
  • 1
  • 6
  • 20

2 Answers2

30

I've come up with a way to do this using PDFSharp, hopefully will be useful for others as well.

        // Convert to PDF and delete image
        PdfHelper.Instance.SaveImageAsPdf($"{fileName}.png", $"{fileName}.pdf", 1000, true);

The new class:

using System.IO;
using PdfSharp.Drawing;
using PdfSharp.Pdf;  

public sealed class PdfHelper
{
    private PdfHelper()
    {
    }

    public static PdfHelper Instance { get; } = new PdfHelper();

    internal void SaveImageAsPdf(string imageFileName, string pdfFileName, int width = 600, bool deleteImage = false)
    {
        using (var document = new PdfDocument())
        {
            PdfPage page = document.AddPage();
            using (XImage img = XImage.FromFile(imageFileName))
            {
                // Calculate new height to keep image ratio
                var height = (int)(((double)width / (double)img.PixelWidth) * img.PixelHeight);

                // Change PDF Page size to match image
                page.Width = width;
                page.Height = height;

                XGraphics gfx = XGraphics.FromPdfPage(page);
                gfx.DrawImage(img, 0, 0, width, height);                
            }
            document.Save(pdfFileName);
        }

    if (deleteImage)            
        File.Delete(imageFileName);
    }
}
Ory Zaidenvorm
  • 896
  • 1
  • 6
  • 20
1

A quick and easy way is to build an HTML file and embed the images as base64 data. It would be more portable than a PDF and can be easily printed as PDF.

An example :

var driver = new FirefoxDriver();

// create new file
var file = File.CreateText(@"C:\temp\captures.html");
file.Write("<!DOCTYPE html><html><head></head><body width=\"600px\">");

// write image
file.Write("<img src=\"data:image/png;base64,");
file.Write(driver.GetScreenshot().AsBase64EncodedString);
file.Write("\">");

// close file
file.Write("</body></html>");
file.Close();

driver.Quit();
Florent B.
  • 41,537
  • 7
  • 86
  • 101
  • Very interesting approach, thanks. Doesn't seem that printing to PDF is that easy though? See https://stackoverflow.com/questions/564650/convert-html-to-pdf-in-net – Ory Zaidenvorm Mar 21 '16 at 00:57
  • My point was to actually drop the PDF for the HTML format. I used to create PDF of screenshots (with PDFSharp and then my own implementation) but switch to html since it is more flexible and faster when to come to create the file. – Florent B. Mar 21 '16 at 01:39
  • Yes I agree, however in this case the client's requirement is that it is saved as PDF :-) – Ory Zaidenvorm Mar 22 '16 at 01:13
  • This is a great workaround for PDF conversion libraries hosted on non-Windows platforms that use System.Drawing to handle image conversion - which is only supported on Windows. Instead you can use an HTML to PDF conversion with the HTML containing the embedded image. – John Trenwith Jun 22 '22 at 22:03