Click here to Skip to main content
13,087,797 members (82,017 online)
Click here to Skip to main content
Articles » Multimedia » GDI+ » General » Downloads


297 bookmarked
Posted 18 Jan 2004

Generate Thumbnail Images from PDF Documents

, 11 May 2004
This article presents VB.NET code to create thumbnail images from a directory of Adobe Acrobat PDF documents using the .NET Framework.
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Drawing.Graphics
Imports System.Configuration

Module PDFThumbnail

#Region "Comments on Adobe Acrobat SDK"
    ' This application uses the Adobe Acrobat COM objects
    ' to read a Adobe Acrobat PDF documents

    ' It then renders the first page to the clipboard
    ' and then copies the image from the clipboard
    ' to a bitmap which is then scaled

    ' The full Adobe Acrobat (not the free reader) and the 
    ' SDK must be installed on the machine to run this application

    ' Although the Adobe Acrobat API seems to have functions
    ' to bitblt directly to an offscreen bitmap these do not
    ' work on Windows NT/2000. They are legacy APIs from Win16
    ' days and because Acrobat reader (even the ActiveX control)
    ' runs Acrobat.exe as a separate process Device Contexts
    ' cannot be shared simply like this. You can't pass around
    ' Device Contexts as these a process specific.
    ' It would seems that the Adobe Acrobat API is badly
    ' written and documented (refer to the Adobe Acrobat SDK)
    ' from many posts to newsgroups. They do not make it easy
    ' to generate images of the pages, and their objects
    ' seem to be incorrectly documented, for example
    ' the PDFRect object IDispatch has x, y properties but
    ' the actual version needed to pass to CopyClipboard has
    ' left, right, top, bottom!

    ' Also do not get confused between thumbnails in a PDF document
    ' and the thumbnails we generate as .png files

#End Region

    Sub Main()

        ' Acrobat objects
        Dim pdfDoc As Acrobat.CAcroPDDoc
        Dim pdfPage As Acrobat.CAcroPDPage
        Dim pdfRect As Acrobat.CAcroRect
        Dim pdfRectTemp As Object

        Dim appSettings As AppSettingsReader = New AppSettingsReader

        Dim pdfInputPath As String
        Dim pngOutputPath As String

        With appSettings
            pdfInputPath = .GetValue("pdfInputPath", GetType(String))
            pngOutputPath = .GetValue("pngOutputPath", GetType(String))
        End With

        Dim templatePortraitFile As String = Application.StartupPath & "\pdftemplate_portrait.gif"
        Dim templateLandscapeFile As String = Application.StartupPath & "\pdftemplate_landscape.gif"


            ' Get list of files to process from the input path
            ' Could change to read list from database instead
            Dim files() As String = Directory.GetFiles(pdfInputPath, "*.pdf")

            Dim n As Integer

            For n = 0 To files.Length - 1

                Dim inputFile As String = files(n)
                Dim outputFile As String = files(n).ToString.Replace(".pdf", ".png")

                Dim pageCount As Integer
                Dim ret As Integer

                ' Could skip if thumbnail already exists in output path
                ''Dim fi As New FileInfo(inputFile)
                ''If Not fi.Exists() Then
                ''End If

                ' Create the document (Can only create the AcroExch.PDDoc object using late-binding)
                pdfDoc = CreateObject("AcroExch.PDDoc")

                ' Open the document
                ret = pdfDoc.Open(inputFile)

                If ret = False Then
                    Throw New FileNotFoundException
                End If

                ' Get the number of pages
                pageCount = pdfDoc.GetNumPages()

                ' Get the first page
                pdfPage = pdfDoc.AcquirePage(0)

                ' Get the size of the page
                ' This is really strange bug/documentation problem
                ' The PDFRect you get back from GetSize has properties
                ' x and y, but the PDFRect you have to supply CopyToClipboard
                ' has left, right, top, bottom
                pdfRectTemp = pdfPage.GetSize

                ' Create PDFRect to hold dimensions of the page
                pdfRect = CreateObject("AcroExch.Rect")

                pdfRect.Left = 0
                pdfRect.right = pdfRectTemp.x
                pdfRect.Top = 0
                pdfRect.bottom = pdfRectTemp.y

                ' Render to clipboard, scaled by 100 percent (ie. original size)
                ' Even though we want a smaller image, better for us to scale in .NET
                ' than Acrobat as it would greek out small text
                ' see

                Call pdfPage.CopyToClipboard(pdfRect, 0, 0, 100)

                Dim clipboardData As IDataObject = Clipboard.GetDataObject()

                If (clipboardData.GetDataPresent(DataFormats.Bitmap)) Then

                    Dim pdfBitmap As Bitmap = clipboardData.GetData(DataFormats.Bitmap)

                    ' Size of generated thumbnail in pixels
                    Dim thumbnailWidth As Integer = 38
                    Dim thumbnailHeight As Integer = 52

                    Dim templateFile As String

                    ' Switch between portrait and landscape
                    If (pdfRectTemp.x < pdfRectTemp.y) Then
                        templateFile = templatePortraitFile
                        templateFile = templateLandscapeFile
                        ' Swap width and height (little trick not using third temp variable)
                        thumbnailWidth = thumbnailWidth Xor thumbnailHeight
                        thumbnailHeight = thumbnailWidth Xor thumbnailHeight
                        thumbnailWidth = thumbnailWidth Xor thumbnailHeight
                    End If

                    ' Load the template graphic
                    Dim templateBitmap As Bitmap = New Bitmap(templateFile)
                    Dim templateImage As Image = Image.FromFile(templateFile)

                    ' Render to small image using the bitmap class
                    Dim pdfImage As Image = pdfBitmap.GetThumbnailImage(thumbnailWidth, _
                                                                        thumbnailHeight, _
                                                                        Nothing, Nothing)

                    ' Create new blank bitmap (+ 7 for template border)
                    Dim thumbnailBitmap As Bitmap = New Bitmap(thumbnailWidth + 7, _
                                                               thumbnailHeight + 7, _

                    ' To overlayout the template with the image, we need to set the transparency

                    Dim thumbnailGraphics As Graphics = Graphics.FromImage(thumbnailBitmap)

                    ' Draw rendered pdf image to new blank bitmap
                    thumbnailGraphics.DrawImage(pdfImage, 2, 2, thumbnailWidth, thumbnailHeight)

                    ' Draw template outline over the bitmap (pdf with show through the transparent area)
                    thumbnailGraphics.DrawImage(templateImage, 0, 0)

                    ' Save as .png file
                    thumbnailBitmap.Save(outputFile, Imaging.ImageFormat.Png)

                    Console.WriteLine("Generated thumbnail... {0}", outputFile)



                End If

            Next n

        Catch ex As Exception


        End Try

    End Sub

End Module

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Jonathan Hodgson
Web Developer
United Kingdom United Kingdom
Jonathan Hodgson works as Software Developer in London, UK.

He started programming in the '80s on a trusty 48k Spectrum before moving to PC development in the early 90s. During the working week most of his time is spent involved in application development both Windows and Web-based; .NET, C#, ASP.NET, SQL Server.

He is a Microsoft Certified Software Developer (MCSD) and MCP for developing web applications using ASP.NET in C# and is always looking for new projects and challenges to work on.

You may also be interested in...

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170813.1 | Last Updated 12 May 2004
Article Copyright 2004 by Jonathan Hodgson
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid