An application I was recently working on received PDF files from a webservice which it then needed to store in a database. I wanted the ability to display previews of these documents within the application. While there are a number of solutions for creating PDF files from C#, options for viewing a PDF within your application is much more limited, unless you purchase expensive commercial products, or use COM interop to embed Acrobat Reader into your application.
This article describes an alternate solution, in which the pages in a PDF are converted into images using GhostScript, from where you can then display them in your application.
In order to avoid huge walls of text, this article has been split into two parts, the first dealing with the actual conversion of a PDF, and the second demonstrates how to extend the ImageBox control to display the images.
Caveat emptor
Before we start, some quick points.
- The method I'm about to demonstrate converts into page of the PDF into an image. This means that it is very suitable for viewing, but interactive elements such as forms, hyperlinks and even good old text selection are not available.
- GhostScript has a number of licenses associated with it but I can't find any information of the pricing of commercial licenses.
- The GhostScript API Integration library used by this project isn't complete and I'm not going to go into the bells and whistles of how it works in this pair of articles - once I've completed the outstanding functionality I'll create a new article for it.
Getting Started
You can download the two libraries used in this article from the links below, these are:
Cyotek.GhostScript- core library providing GhostScript integration supportCyotek.GhostScript.PdfConversion- support library for converting a PDF document into images
Please note that the native GhostScript DLL is not included in these downloads, you will need to obtain that from the GhostScript project page.
Using the GhostScriptAPI class
As mentioned above, the core GhostScript library isn't complete yet, so I'll just give a description of the basic functionality required by the conversion library.
The GhostScriptAPI class handles all communication with GhostScript. When you create an instance of the class, it automatically calls gsapi_new_instance in the native GhostScript DLL. When the class is disposed, it will automatically release any handles and calls the native gsapi_exit and gsapi_delete_instance methods.
In order to actually call GhostScript, you call the Execute method, passing in either a string array of all the arguments to pass to GhostScript, or a typed dictionary of commands and values. The GhostScriptCommand enum contains most of the commands supported by GhostScript, which may be a preferable approach rather than trying to remember the parameter names themselves.
Defining conversion settings
The Pdf2ImageSettings class allows you to customize various properties of the output image. The following properties are available:
AntiAliasMode- specifies the antialiasing level between Low, Medium and High. This internally will set thedTextAlphaBitsanddGraphicsAlphaBitsGhostScript switches to appropriate values.Dpi- dots per inch. Internally sets therswitch. This property is not used if a paper size is set.GridFitMode- controls the text readability mode. Internally sets thedGridFitTTswitch.ImageFormat- specifies the output image format. Internally sets thesDEVICEswitch.PaperSize- specifies a paper size from one of the standard sizes supported by GhostScript.TrimMode- specifies how the image should be sized. Your milage may vary if you try and use the paper size option. Internally sets either thedFIXEDMEDIAandsPAPERSIZEor thedUseCropBoxor thedUseTrimBoxswitches.
Typical settings could look like this:
Pdf2ImageSettings settings;
settings = new Pdf2ImageSettings();
settings.AntiAliasMode = AntiAliasMode.High;
settings.Dpi = 300;
settings.GridFitMode = GridFitMode.Topological;
settings.ImageFormat = ImageFormat.Png24;
settings.TrimMode = PdfTrimMode.CropBox;
Converting the PDF
To convert a PDF file into a series of images, use the Pdf2Image class. The following properties and methods are offered:
ConvertPdfPageToImage- converts a given page in the PDF into an image which is saved to diskGetImage- converts a page in the PDF into an image and returns the imageGetImages- converts a range of pages into the PDF into images and returns an image arrayPageCount- returns the number of pages in the source PDFPdfFilename- returns or sets the filename of the PDF document to convertPdfPassword- returns or sets the password of the PDF document to convertSettings- returns or sets the settings object described above
A typical example to convert the first image in a PDF document:
Bitmap firstPage = new Pdf2Image("sample.pdf").GetImage();
The inner workings
Most of the code in the class is taken up with the GetConversionArguments method. This method looks at the various properties of the conversion such as output format, quality, etc, and returns the appropriate commands to pass to GhostScript:
protected virtual IDictionary<GhostScriptCommand, object> GetConversionArguments(string pdfFileName, string outputImageFileName, int pageNumber, string password, Pdf2ImageSettings settings)
{
IDictionary<GhostScriptCommand, object> arguments;
arguments = new Dictionary<GhostScriptCommand, object>();
// basic GhostScript setup
arguments.Add(GhostScriptCommand.Silent, null);
arguments.Add(GhostScriptCommand.Safer, null);
arguments.Add(GhostScriptCommand.Batch, null);
arguments.Add(GhostScriptCommand.NoPause, null);
// specify the output
arguments.Add(GhostScriptCommand.Device, GhostScriptAPI.GetDeviceName(settings.ImageFormat));
arguments.Add(GhostScriptCommand.OutputFile, outputImageFileName);
// page numbers
arguments.Add(GhostScriptCommand.FirstPage, pageNumber);
arguments.Add(GhostScriptCommand.LastPage, pageNumber);
// graphics options
arguments.Add(GhostScriptCommand.UseCIEColor, null);
if (settings.AntiAliasMode != AntiAliasMode.None)
{
arguments.Add(GhostScriptCommand.TextAlphaBits, settings.AntiAliasMode);
arguments.Add(GhostScriptCommand.GraphicsAlphaBits, settings.AntiAliasMode);
}
arguments.Add(GhostScriptCommand.GridToFitTT, settings.GridFitMode);
// image size
if (settings.TrimMode != PdfTrimMode.PaperSize)
arguments.Add(GhostScriptCommand.Resolution, settings.Dpi.ToString());
switch (settings.TrimMode)
{
case PdfTrimMode.PaperSize:
if (settings.PaperSize != PaperSize.Default)
{
arguments.Add(GhostScriptCommand.FixedMedia, true);
arguments.Add(GhostScriptCommand.PaperSize, settings.PaperSize);
}
break;
case PdfTrimMode.TrimBox:
arguments.Add(GhostScriptCommand.UseTrimBox, true);
break;
case PdfTrimMode.CropBox:
arguments.Add(GhostScriptCommand.UseCropBox, true);
break;
}
// pdf password
if (!string.IsNullOrEmpty(password))
arguments.Add(GhostScriptCommand.PDFPassword, password);
// pdf filename
arguments.Add(GhostScriptCommand.InputFile, pdfFileName);
return arguments;
}
As you can see from the method above, the commands are being returned as a strongly typed dictionary - the GhostScriptAPI class will convert these into the correct GhostScript commands, but the enum is much easier to work with from your code! The following is an example of the typical GhostScript commands to convert a single page in a PDF document:
-q -dSAFER -dBATCH -dNOPAUSE -sDEVICE=png16m -sOutputFile=tmp78BC.tmp -dFirstPage=1 -dLastPage=1 -dUseCIEColor -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -dGridFitTT=2 -r150 -dUseCropBox=true sample.pdf
The next step is to call GhostScript and convert the PDF which is done using the ConvertPdfPageToImage method:
public void ConvertPdfPageToImage(string outputFileName, int pageNumber)
{
if (pageNumber < 1 || pageNumber > this.PageCount)
throw new ArgumentException("Page number is out of bounds", "pageNumber");
using (GhostScriptAPI api = new GhostScriptAPI())
api.Execute(this.GetConversionArguments(this._pdfFileName, outputFileName, pageNumber, this.PdfPassword, this.Settings));
}
As you can see, this is a very simple call - create an instance of the GhostScriptAPI class and then pass in the list of parameters to execute. The GhostScriptAPI class takes care of everything else.
Once the file is saved to disk, you can then load it into a Bitmap or Image object for use in your application. Don't forget to delete the file when you are finished with it!
Alternatively, the GetImage method will convert the file and return the bitmap image for you, automatically deleting the temporary file. This saves you from having to worry about providing and deleting the output file, but it does mean you are responsible for disposing of the returned bitmap.
public Bitmap GetImage(int pageNumber)
{
Bitmap result;
string workFile;
if (pageNumber < 1 || pageNumber > this.PageCount)
throw new ArgumentException("Page number is out of bounds", "pageNumber");
workFile = Path.GetTempFileName();
try
{
this.ConvertPdfPageToImage(workFile, pageNumber);
using (FileStream stream = new FileStream(workFile, FileMode.Open, FileAccess.Read))
result = new Bitmap(stream);
}
finally
{
File.Delete(workFile);
}
return result;
}
You could also convert a range of pages at once using the GetImages method:
public Bitmap[] GetImages(int startPage, int lastPage)
{
List<Bitmap> results;
if (startPage < 1 || startPage > this.PageCount)
throw new ArgumentException("Start page number is out of bounds", "startPage");
if (lastPage < 1 || lastPage > this.PageCount)
throw new ArgumentException("Last page number is out of bounds", "lastPage");
else if (lastPage < startPage)
throw new ArgumentException("Last page cannot be less than start page", "lastPage");
results = new List<Bitmap>();
for (int i = startPage; i <= lastPage; i++)
results.Add(this.GetImage(i));
return results.ToArray();
}
In conclusion
The above methods provide a simple way of providing basic PDF viewing in your applications. In the next part of this series, we describe how to extend the ImageBox component to support conversion and navigation.
Downloads:
- Cyotek.GhostScript.zip
(11.68 KB | 04 September 2011 )
Work in progress class library for providing GhostScript integration in a .NET application.
- Cyotek.GhostScript.PdfConversion.zip
(5.43 KB | 04 September 2011 )
Class library for converting PDF files into images using GhostScript. Also requires the Cyotek.GhostScript assembly.

Convert a PDF into a series of images using C# and GhostScript
Thank you for submitting this cool story - Trackback from DotNetShoutout
# 04/09/2011 16:55 | DotNetShoutout
Convert a PDF into a series of images using C# and GhostScript
You've been kicked (a good thing) - Trackback from DotNetKicks.com
# 04/09/2011 16:55 | DotNetKicks.com
Thank you for this. Please change for support of other languages/codepages, i.e. german Umlaute. Thanks
# 07/09/2011 17:07 | MichaW | Reply
Hello,
Thanks for the comment - could you clarify what were having a problem with so I can look into it further?
Regards;
Richard Moss
# 07/09/2011 20:58 | Richard Moss | Reply
Thank you very much. You made my day dude.
# 29/09/2011 11:26 | Muhammad | Reply
Hi,
I used your library into sharepoint 2010 workflow on server on 64 bit and I get this error:
Unable to load DLL 'gsdll32.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)?
Why? On the server I installed ghostscript x64 and x86...
# 01/11/2011 00:56 | Lorena | Reply
Hello,
While I haven't tested this in SharePoint, or indeed on a server full stop, the most likely cause is gsdll32.dll isn't in your path - either copy it to the folder where your assemblies are deployed, or into a folder which is part of your path, such as \Windows\SysWOW64
Hope this helps;
Richard Moss
# 01/11/2011 16:41 | Richard Moss | Reply
Hi,
I am getting the following error when i load a pdf file into Picturebox "Failed to process GhostScript command."
Please help me ...
# 31/03/2012 05:26 | chandrasekhar | Reply
This error is thrown when Ghostscript cannot perform the action was requested of it. There could be any number of causes, with such limited information I have no way of knowing. Check the the exception object for the Ghostscript result code and the arguments provided.
# 31/03/2012 15:29 | Richard Moss | Reply
Hi
How to convert pdf to bmp images in c# . Any examples for converting of pdf to bmp images?
Please help me
# 04/04/2012 11:00 | chandrasekhar | Reply
That's exactly what this article does; converts a PDF into a series of images. To save them into bitmaps, call the `Save` method of one of the images passing in the `ImageFormat.Bmp` format.
# 04/04/2012 16:33 | Richard Moss | Reply
Hi. I am getting this error when i try to convert pdf2image(.GetImage()).
The Error is "Unable to find an entry point named 'gsapi_new_instance' in DLL 'gsdll32.dll'.".
Note : Web Application bin dir have gsdll32.dll and i am not installed ghostscript.exe.
How can i get it?
# 05/04/2012 09:05 | Rafi | Reply
As I've already noted to another commenter, I haven't tested this on a server environment or in a web application and so I can't assist on deployment issues. The error would indicate that while a DLL is present and loaded, it doesn't actually contain the function that is being requested of it. That would most likely indicate the wrong version of Ghostscript being loaded or perhaps a custom build that doesn't export the function. Or it could be an error in the C# function declaration. Sorry for not being specific, but there's no single cause.
# 06/04/2012 10:54 | Richard Moss | Reply
Is this dll will work against IIS 7.5 and 64 bit OS/Windows 7?
# 10/05/2012 15:55 | AmityRooso | Reply
Hello,
It should work if your application is 32bit as it's calling the 32bit version of Ghostscript (I haven't looked to see if there's a 64bit version of the library - if there is just replace the calls). As long as the correct DLL's are in your path, then it should work fine. But as I've noted multiple times above, I haven't tested this in a server environment at this point in time so I can't say for definite.
Regards;
Richard Moss
# 10/05/2012 16:34 | Richard Moss | Reply
You can solve this issue with following steps(If you are using Windows 7(64 bit) OS and IIS7 or above manager )
Pdf2Image should work with this settings
1)Visual Studio 2008 Project Properties :
Go Build->Configuration Manager...
Change 'AnyCPU' to x86
Click OK
2) IIS7 or above manager:
Application Pool and select “Advanced Settings…”
Change the “Enable 32-bit Applications” to True
Click OK
# 14/05/2012 09:36 | Rafi | Reply
Thanks for the information, hopefully this will help others!
IIS6 can also be set to run in 32bit mode, although it's a little more complicated than 7.
# 14/05/2012 16:35 | Richard Moss | Reply