JPG to PDF Convertor in C#

Viewed 80420

I would like to convert from an image (like jpg or png) to PDF.

I've checked out ImageMagickNET, but it is far too complex for my needs.

What other .NET solutions or code are there for converting an image to a PDF?

10 Answers

You need Acrobat to be installed. Tested on Acrobat DC. This is a VB.net code. Due to that these objects are COM objects, you shall do a 'release object', not just a '=Nothing". You can convert this code here: https://converter.telerik.com/

Private Function ImageToPDF(ByVal FilePath As String, ByVal DestinationFolder As String) As String
    Const PDSaveCollectGarbage  As Integer = 32
    Const PDSaveLinearized      As Integer = 4
    Const PDSaveFull            As Integer = 1
    Dim PDFAVDoc                As Object = Nothing
    Dim PDFDoc                  As Object = Nothing

    Try
        'Check destination requirements
        If Not DestinationFolder.EndsWith("\") Then DestinationFolder += "\"
        If Not System.IO.Directory.Exists(DestinationFolder) Then Throw New Exception("Destination directory does not exist: " & DestinationFolder)
        Dim CreatedFile As String = DestinationFolder & System.IO.Path.GetFileNameWithoutExtension(FilePath) & ".pdf"
        'Avoid conflicts, therefore previous file there will be deleted
        If File.Exists(CreatedFile) Then File.Delete(CreatedFile)

        'Get PDF document
        PDFAVDoc = GetPDFAVDoc(FilePath)
        PDFDoc = PDFAVDoc.GetPDDoc

        If Not PDFDoc.Save(PDSaveCollectGarbage Or PDSaveLinearized Or PDSaveFull, CreatedFile) Then Throw New Exception("PDF file cannot be saved: " & PDFDoc.GetFileName())
        If Not PDFDoc.Close() Then Throw New Exception("PDF file could not be closed: " & PDFDoc.GetFileName())
        PDFAVDoc.Close(1)
        Return CreatedFile
    Catch Ex As Exception
        Throw Ex
    Finally
        System.Runtime.InteropServices.Marshal.ReleaseComObject(PDFDoc)
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(PDFDoc)
        PDFDoc = Nothing
        System.Runtime.InteropServices.Marshal.ReleaseComObject(PDFAVDoc)
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(PDFAVDoc)
        PDFAVDoc = Nothing
        GC.Collect()
        GC.WaitForPendingFinalizers()
        GC.Collect()
    End Try
End Function

If you want to do it in a cross-platform way, without any thirty part library, or paying any license, you can use this code. It takes an array of pictures (I think it only works only with jpg) with its sizes and return a pdf file, with one picture per page.

You have to create two files:

File Picture:

using System;
using System.Collections.Generic;
using System.Text;

namespace PDF
{
    public class Picture
    {
        private byte[] data;
        private int width;
        private int height;

        public byte[] Data { get => data; set => data = value; }
        public int Width { get => width; set => width = value; }
        public int Height { get => height; set => height = value; }
    }
}

File PDFExport:

using System;
using System.Collections.Generic;

namespace PDF
{
    public class PDFExport
    {
        private string company = "Your Company Here";

        public sbyte[] createFile(List<Picture> pictures)
        {
            int N = (pictures.Count + 1) * 3;
            string dateTimeStr = DateTime.Now.ToString("yyyyMMddhhmmss");

            string file1 =
            "%PDF-1.4\n";

            string file2 =
                "2 0 obj\n" +
                "<<\n" +
                "/Type /Pages\n" +
                getKids(pictures) +
                "/Count " + pictures.Count + "\n" +
                 ">>\n" +
                 "endobj\n" +
                "1 0 obj\n" +
                "<<\n" +
                "/Type /Catalog\n" +
                "/Pages 2 0 R\n" +
                "/PageMode /UseNone\n" +
                "/PageLayout /SinglePage\n" +
                 "/Metadata 7 0 R\n" +
                 ">>\n" +
                  "endobj\n" +
                N + " 0 obj\n" +
                "<<\n" +
                "/Creator(" + company + ")\n" +
                "/Producer(" + company + ")\n" +
                "/CreationDate (D:" + dateTimeStr + ")\n" +
                "/ModDate (D:" + dateTimeStr + ")\n" +
                ">>\n" +
                "endobj\n" +
                "xref\n" +
                "0 " + (N + 1) + "\n" +
                "0000000000 65535 f\n" +
                "0000224088 00000 n\n" +
                "0000224031 00000 n\n" +
                "0000000015 00000 n\n" +
                "0000222920 00000 n\n" +
                "0000222815 00000 n\n" +
                "0000224153 00000 n\n" +
                "0000223050 00000 n\n" +
                "trailer\n" +
                "<<\n" +
                "/Size " + (N + 1) + "\n" +
                 "/Root 1 0 R\n" +
                  "/Info 6 0 R\n" +
                   ">>\n" +
                   "startxref\n" +
                "0\n" +
                "%% EOF";

            sbyte[] part1 = file1.GetBytes();
            sbyte[] part2 = file2.GetBytes();

            List<sbyte[]> fileContents = new List<sbyte[]>();
            fileContents.Add(part1);
            for (int i = 0; i < pictures.Count; i++)
            {
                fileContents.Add(getPageFromImage(pictures[i], i));
            }
            fileContents.Add(part2);
            return getFileContent(fileContents);
        }

        private string getKids(List<Picture> pictures)
        {
            string kids = "/Kids[";
            for (int i = 0; i < pictures.Count; i++)
            {
                kids += (3 * (i + 1) + 1) + " 0 R ";
            }
            kids += "]\n";
            return kids;
        }

        private sbyte[] getPageFromImage(Picture picture, int P)
        {
            int N = (P + 1) * 3;
            string imageStart =
            N + " 0 obj\n" +
            "<<\n" +
            "/Type /XObject\n" +
            "/Subtype /Image\n" +
            "/Width " + picture.Width + "\n" +
             "/Height " + picture.Height + "\n" +
              "/BitsPerComponent 8\n" +
               "/ColorSpace /DeviceRGB\n" +
               "/Filter /DCTDecode\n" +
               "/Length " + picture.Data.Length + "\n" +
                ">>\n" +
                "stream\n";

            string dimentions = "q\n" +
            picture.Width + " 0 0 " + picture.Height + " 0 0 cm\n" +
            "/X0 Do\n" +
            "Q\n";

            string imageEnd =
                "\nendstream\n" +
                "endobj\n" +
                (N + 2) + " 0 obj\n" +
                "<<\n" +
                "/Filter []\n" +
                "/Length " + dimentions.Length + "\n" +
                ">>\n" +
                "stream\n";

            string page =
                "\nendstream\n" +
                "endobj\n" +
                (N + 1) + " 0 obj\n" +
                "<<\n" +
                "/Type /Page\n" +
                "/MediaBox[0 0 " + picture.Width + " " + picture.Height + "]\n" +
                "/Resources <<\n" +
                "/XObject <<\n" +
                "/X0 " + N + " 0 R\n" +
                ">>\n" +
                ">>\n" +
                "/Contents 5 0 R\n" +
                "/Parent 2 0 R\n" +
                ">>\n" +
                "endobj\n";

            List<sbyte[]> fileContents = new List<sbyte[]>();
            fileContents.Add(imageStart.GetBytes());
            fileContents.Add(byteArrayToSbyteArray(picture.Data));
            fileContents.Add(imageEnd.GetBytes());
            fileContents.Add(dimentions.GetBytes());
            fileContents.Add(page.GetBytes());
            return getFileContent(fileContents);
        }

        private sbyte[] byteArrayToSbyteArray(byte[] data)
        {
            sbyte[] data2 = new sbyte[data.Length];
            for (int i = 0; i < data2.Length; i++)
            {
                data2[i] = (sbyte)data[i];
            }
            return data2;
        }

        private sbyte[] getFileContent(List<sbyte[]> fileContents)
        {
            int fileSize = 0;
            foreach (sbyte[] content in fileContents)
            {
                fileSize += content.Length;
            }
            sbyte[] finaleFile = new sbyte[fileSize];
            int index = 0;
            foreach (sbyte[] content in fileContents)
            {
                for (int i = 0; i < content.Length; i++)
                {
                    finaleFile[index + i] = content[i];
                }
                index += content.Length;
            }
            return finaleFile;
        }
    }
}

You can use the code in this easy way

///////////////////////////////////////Export PDF//////////////////////////////////////

    private sbyte[] exportPDF(List<Picture> images)
    {
        if (imageBytesList.Count > 0)
        {
            PDFExport pdfExport = new PDFExport();
            sbyte[] fileData = pdfExport.createFile(images);
            return fileData;
        }
        return null;
    }

I use Sautinsoft, its very simple:

SautinSoft.PdfMetamorphosis p = new SautinSoft.PdfMetamorphosis();
p.Serial="xxx";
p.HtmlToPdfConvertStringToFile("<html><body><img src=\""+filename+"\"></img></body></html>","output.pdf");
Related