Click here to Skip to main content
13,357,610 members (64,885 online)
Click here to Skip to main content
Add your own
alternative version


478 bookmarked
Posted 19 Jun 2009

PDF Viewer Control Without Acrobat Reader Installed

, 6 Oct 2009
Rate this:
Please Sign up or sign in to vote.
PDF document viewer control that does not require any Acrobat product to be installed


This article discusses how to create a .NET PDF Viewer control that is not dependent on Acrobat software being installed.

Fundamental Concepts

The basic steps that need to take place in order to view a PDF document:

  1. Get a page count of the PDF document that needs to be viewed to define your page number boundaries (iTextSharp or PDFLibNET)
  2. Convert the PDF document (specific page on demand) to a raster image format (GhostScript API or PDFLibNET)
  3. --(Deprecated) Extract only the current frame to be viewed from the raster image (FreeImage.Net)
  4. Convert the current frame to be viewed into a System.Image
  5. Display the current frame in a PictureBox control

Several utility classes were created or added from others which expose functionality needed from the various helper libraries.

  • GhostScriptLib.vb (contains methods to convert PDF to TIFF for Viewing and Printing)
  • AFPDFLibUtil.vb (contains methods to convert PDF to System.Image for Viewing and Printing as well as methods to create a Bookmark TreeView)
  • iTextSharpUtil.vb (contains methods for getting PDF page count, converting images to searchable PDF and for extracting PDF bookmarks into TreeNodes)
  • PrinterUtil.vb (contains methods for sending images to printers)
  • ImageUtil.vb (contains methods for image manipulation such as resize, rotation, conversion, etc.)
  • TesseractOCR.vb (contains methods for Optical Character Recognition from images)
  • PDFViewer.vb (contains the Viewer user control)

I was tempted to move every function over to PDFLibNet (XPDF) which is faster, but after a lot of testing, I decided to use Ghostscript and PDFLibNET. Ghostscript is used for printing, "PDF to image" conversion, and as a secondary renderer in case of XPDF incompatibility. PDFLibNET is used for quick PDF to screen rendering, searching, and bookmarks.

Using the Code

This project consists of 7 DLLs that must all be in the same directory:

  • FreeImage.dll
  • FreeImageNET.dll
  • gsdll32.dll
  • itextsharp.dll
  • PDFLibNET.dll
  • tessnet2_32.dll
  • PDFView.dll

Due to file size restrictions, I could not include the Ghostscript 8.64 DLL (gsdll32.dll) in the source code. Please download the Win32 Ghostscript 8.64 package from and place the file "gsdll32.dll" into the \PDFView\lib directory where the other DLLs already exist.

To place a PDF control on form:

Dim PDFFileName As String = "MyPDF.pdf"

Dim PDFViewer As New PDFView.PDFViewer
' Specify whether you want to see bookmarks in the control
' Bookmarks are enabled by default
' PDFViewer.AllowBookmarks = False 'Disable bookmarks

' Get the page count of the PDF document if you want to
' conditionally set properties of the PDFViewer control
' Dim PageCount As Integer = PDFViewer.PageCount(PDFFileName)

' To use Ghostscript, UseXPDF = False
' Ghostscript is slower, but is more compatible and has higher quality rendering
' To use XPDF, UseXPDF = True
' XPDF is quite a bit faster than Ghostscript since there is no file i/o involved
' PdfViewer1.UseXPDF = False 'Disables use of XPDF and associated features

' PDFViewer displays the file as soon as the FileName property is set
' File can be a PDF or a TIFF
PDFViewer.FileName = OpenFileDialog1.FileName

PDFViewer.Dock = DockStyle.Fill 'Autosize the viewer control


The essential part of this solution is extracting the current frame to be viewed from a multi-frame (or single frame) image. At first I used System.Drawing to implement it. I found this to be slower than other C++ solutions that use DIBs (Device Independent Bitmaps) to perform graphic conversions.

Public Shared Function GetFrameFromTiff_
	(ByVal Filename As String, ByVal FrameNumber As Integer) As Image
    Dim fs As FileStream = File.Open(Filename, FileMode.Open, FileAccess.Read)
    Dim bm As System.Drawing.Bitmap = _
	CType(System.Drawing.Bitmap.FromStream(fs), System.Drawing.Bitmap)
    bm.SelectActiveFrame(FrameDimension.Page, FrameNumber)
    Dim temp As New System.Drawing.Bitmap(bm.Width, bm.Height)
    Dim g As Graphics = Graphics.FromImage(temp)
    g.InterpolationMode = InterpolationMode.NearestNeighbor
    g.DrawImage(bm, 0, 0, bm.Width, bm.Height)
    GetFrameFromTiff = temp
End Function

I then tried implementing FreeImage with a .NET wrapper which gave it a little speed boost. FreeImage also has a ton of image conversion functions which may come in handy if you wanted to extend this into an editor.

Public Shared Function GetFrameFromTiff2_
	(ByVal Filename As String, ByVal FrameNumber As Integer) As Image
    dib = FreeImage.OpenMultiBitmapEx(Filename)
    Dim page As FIBITMAP = New FIBITMAP()
    page = FreeImage.LockPage(dib, FrameNumber)
    GetFrameFromTiff2 = FreeImage.GetBitmap(page)
End Function

I ended up implementing PDFLibNET which gave it a substantial speed boost since the amount of File I/O operations were reduced. Another streamlined routine for extracting one page from a PDF was added to the Ghostscript utility class as well.


Public Shared Sub DrawImageFromPDF(ByRef pdfDoc As AFPDFLibNET.AFPDFDoc,
    ByVal PageNumber As Integer, ByRef oPictureBox As PictureBox)
        If pdfDoc IsNot Nothing Then
            pdfDoc.CurrentPage = PageNumber
            pdfDoc.CurrentX = 0
            pdfDoc.CurrentY = 0
            pdfDoc.RenderDPI = RENDER_DPI
            oPictureBox.Image = Render(pdfDoc)
        End If
    End Sub

    Public Shared Function Render(ByRef pdfDoc As AFPDFLibNET.AFPDFDoc) As Bitmap
        If pdfDoc IsNot Nothing Then
            Dim backbuffer As New Bitmap(pdfDoc.PageWidth, pdfDoc.PageHeight)
            Dim g As Graphics = Graphics.FromImage(backbuffer)
            Using g
                Dim lhdc As Integer = g.GetHdc().ToInt32()
            End Using
            Return backbuffer
        End If
        Return Nothing
    End Function


Public Shared Function GetPageFromPDF(ByVal filename As String,
    ByVal PageNumber As Integer, Optional ByVal ToPrinter As Boolean = False) As Image
            Dim converter As New ConvertPDF.PDFConvert
            Dim Converted As Boolean = False
            converter.RenderingThreads = Environment.ProcessorCount
            converter.OutputToMultipleFile = False
            If PageNumber > 0 Then
                converter.FirstPageToConvert = PageNumber
                converter.LastPageToConvert = PageNumber
                GetPageFromPDF = Nothing
                Exit Function
            End If
            converter.FitPage = False
            converter.JPEGQuality = 70
            If ToPrinter = True Then 'Settings for decent print quality
                converter.TextAlphaBit = -1
                converter.GraphicsAlphaBit = -1
                converter.ResolutionX = PRINT_DPI
                converter.ResolutionY = PRINT_DPI
            Else 'Settings for screen resolution
                converter.TextAlphaBit = 4
                converter.GraphicsAlphaBit = 4
                converter.ResolutionX = VIEW_DPI
                converter.ResolutionY = VIEW_DPI
            End If
            converter.OutputFormat = COLOR_PNG_RGB
            Dim input As System.IO.FileInfo = New FileInfo(filename)
            Dim output As String = System.IO.Path.GetTempPath & Now.Ticks & ".png"

            Converted = converter.Convert(input.FullName, output)
            If Converted Then
                GetPageFromPDF = New Bitmap(output)
                GetPageFromPDF = Nothing
            End If
        End Function

In the PDFViewer code, a page number is specified and:

  • The page is loaded from the PDF file and converted to a System.Image object.
  • The PictureBox is updated with the image.
Private Function ShowImageFromFile(ByVal sFileName As String,
    ByVal iFrameNumber As Integer, ByRef oPictureBox As PictureBox,
    Optional ByVal XPDFDPI As Integer = 0) As Image
        If mUseXPDF Then 'Use AFPDFLib (XPDF)
            If ImageUtil.IsPDF(sFileName) Then
                If XPDFDPI > 0 Then
                    AFPDFLibUtil.DrawImageFromPDF(mPDFDoc, iFrameNumber + 1,
                    oPictureBox, XPDFDPI)
                    AFPDFLibUtil.DrawImageFromPDF(mPDFDoc, iFrameNumber + 1, oPictureBox)
                End If
            End If
        Else 'Use Ghostscript if PDF or use System.Drawing if TIFF
            If ImageUtil.IsPDF(sFileName) Then 'convert one frame to a tiff for viewing
                oPictureBox.Image = ConvertPDF.PDFConvert.GetPageFromPDF(sFileName,
                iFrameNumber + 1)
            ElseIf ImageUtil.IsTiff(sFileName) Then
                oPictureBox.Image = ImageUtil.GetFrameFromTiff(sFileName, iFrameNumber)
            End If
        End If
        Return oPictureBox.Image
    End Function

Points of Interest

This project was made possible due to various open source libraries that others were kind enough to distribute freely. I would like to thank all of the Ghostscript, FreeImage.NET, iTextSharp, TessNet, and AFPDFLib (PDFLibNet) developers for their efforts.


  • 19th June, 2009: 1.0 Initial release
  • 22nd June, 2009: Updated source code to correctly scale printed pages to the Printable Page Area of the printer that is selected
  • 7th July, 2009: Updated source code to use AFPDFLib(XPDF) or Ghostscript for PDF rendering
  • 15th July, 2009: Updated source code to use PDFLibNet(XPDF ver 3.02pl3) and added search/export options
  • 22nd July, 2009: Added "Image to PDF" import, password prompt for encrypted PDF files, fallback rendering to Ghostscript if XPDF fails, latest version of PDFLibNet with various bug fixes applied, and LZW compression for "PDF to TIFF" export
  • 20th August, 2009: Major changes:
    • Added the ability to convert images into a searchable PDF (OCR is English only for now)
    • Added the ability to export a PDF to an HTML Image Viewer
    • Pages are only rendered at the DPI needed to fill the Viewer window (good speed increase)
    • Rotated page settings are kept while viewing the document
    • Added the ability to convert images into an encrypted PDF
    • Changed bookmark tree generation to use recursion
    • Multiple bug fixes (see SVN log on the repository)
  • 5th October, 2009
    • Fixed problem with incorrect configuration error with PDFLibNet.dll
    • Removed dependencies on FreeImage


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Ron Schuler
Software Developer
United States United States
No Biography provided

You may also be interested in...


Comments and Discussions

QuestionOpening a password-protected file. Pin
Ahmed M. Gamil5-Nov-13 22:02
professionalAhmed M. Gamil5-Nov-13 22:02 
QuestionFile is used by another process Pin
chanBOB4-Nov-13 23:59
memberchanBOB4-Nov-13 23:59 
QuestionWarning in Visual basic ver. 12 Pin
Member 103795334-Nov-13 8:10
memberMember 103795334-Nov-13 8:10 
GeneralMy vote of 5 Pin
Mr. Xie.G.Gang4-Sep-13 6:39
memberMr. Xie.G.Gang4-Sep-13 6:39 
GeneralMy vote of 5 Pin
RaviJJain25-Aug-13 20:48
memberRaviJJain25-Aug-13 20:48 
GeneralMy vote of 5 Pin
Ronald Meran20-Aug-13 18:57
memberRonald Meran20-Aug-13 18:57 
QuestionAuto Detect PDF Page Size and Full page Display. Pin
Member 237566727-Feb-13 17:29
memberMember 237566727-Feb-13 17:29 
QuestionCan you please help me to create pdf editor Pin
SMayur21-Jan-13 20:24
memberSMayur21-Jan-13 20:24 
You code help me a lot to create pdf viewer in but I want to go further I want to create pdf editor. So can you please provide me a way how to create pdf editor or some code samples?

I will be really graceful if you help me, thanks in advance.
Questionwill this work with website Pin
Farhan Ali10-Jan-13 5:42
memberFarhan Ali10-Jan-13 5:42 
AnswerRe: will this work with website Pin
GREG_DORIANcod14-Aug-15 13:57
memberGREG_DORIANcod14-Aug-15 13:57 
QuestionIt's not working! Pin
عماد أوز23-Dec-12 21:35
memberعماد أوز23-Dec-12 21:35 
AnswerRe: It's not working! Pin
JueSe18-Jan-13 4:20
memberJueSe18-Jan-13 4:20 
GeneralRe: It's not working! Pin
chrisflo270528-Oct-14 9:40
memberchrisflo270528-Oct-14 9:40 
GeneralRe: It's not working! Pin
guibirow1-Apr-15 14:53
memberguibirow1-Apr-15 14:53 
QuestionDoes this work with .NET 4 ? Pin
Member 945062424-Sep-12 7:41
memberMember 945062424-Sep-12 7:41 
QuestionContinuous Page Scrolling Pin
Waleed Ahmed Malik16-Aug-12 3:52
memberWaleed Ahmed Malik16-Aug-12 3:52 
GeneralMy vote of 5 Pin
Polinia1-Aug-12 4:04
memberPolinia1-Aug-12 4:04 
Question.NET FWK 4.0 support Pin
Tim Delmoitie9-Jul-12 5:26
memberTim Delmoitie9-Jul-12 5:26 
AnswerRe: .NET FWK 4.0 support Pin
Waleed Ahmed Malik16-Aug-12 1:58
memberWaleed Ahmed Malik16-Aug-12 1:58 
SuggestionMouse Wheel Pin
Lewis Darwin25-Jun-12 9:07
memberLewis Darwin25-Jun-12 9:07 
GeneralRe: Mouse Wheel Pin
sneharoopa3-Jul-12 3:39
membersneharoopa3-Jul-12 3:39 
GeneralRe: Mouse Wheel Pin
Tim Delmoitie9-Jul-12 5:15
memberTim Delmoitie9-Jul-12 5:15 
QuestionCan anyone convert its Code in C#? Pin
Vibs17-Jun-12 22:06
memberVibs17-Jun-12 22:06 
AnswerRe: Can anyone convert its Code in C#? Pin
k.sathishkumar30-Jul-12 9:04
memberk.sathishkumar30-Jul-12 9:04 
QuestionWhere I can download the .NET 4 version? Pin
OctavioCesar4-May-12 11:51
memberOctavioCesar4-May-12 11:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.180111.1 | Last Updated 6 Oct 2009
Article Copyright 2009 by Ron Schuler
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid