''' <summary>
''' Merges several documents (PDF, TIFF, PNG, DOCX, XLSX, ...) to single PDF document.
''' </summary>
''' <param name="outputFilename">The output PDF filename.</param>
''' <param name="inputFilenames">The filenames of input documents.</param>
Public Shared Sub MergeDocuments(outputFilename As String, ParamArray inputFilenames As String())
If inputFilenames Is Nothing OrElse inputFilenames.Length < 1 Then
Throw New System.ArgumentOutOfRangeException("inputFilenames")
End If
' define style of index page
Dim indexPageFontName As String = "Arial"
Dim indexPageFontSize As Single = 14
Dim indexPagePadding As New System.Drawing.PointF(indexPageFontSize * 2, indexPageFontSize * 4)
Dim indexPageLineSpacing As Single = indexPageFontSize * 0.8F
Dim linkFontColor As System.Drawing.Color = System.Drawing.Color.Blue
Dim titleFontColor As System.Drawing.Color = System.Drawing.Color.Black
' create output PDF document
Using document As New Vintasoft.Imaging.Pdf.PdfDocument(outputFilename, Vintasoft.Imaging.Pdf.PdfFormat.Pdf_17)
' create bookmark collection
document.Bookmarks = New Vintasoft.Imaging.Pdf.Tree.PdfBookmarkCollection(document)
' create index page
Dim indexPage As New Vintasoft.Imaging.Pdf.Tree.PdfPage(document, Vintasoft.Imaging.PaperSizeKind.A4)
' add index page to PDF document
document.Pages.Add(indexPage)
' create annotation collection for index page
indexPage.Annotations = New Vintasoft.Imaging.Pdf.Tree.Annotations.PdfAnnotationList(document)
' create font and text brush
Dim font As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont
Dim fontProgramSearchResult As Vintasoft.Imaging.Fonts.FontProgramSearchResult = document.FontProgramsController.GetTrueTypeFontProgram(New Vintasoft.Imaging.Fonts.FontInfo(indexPageFontName))
Using fontProgramStream As System.IO.Stream = fontProgramSearchResult.FontProgramStream
font = document.FontManager.CreateCIDFontFromTrueTypeFont(fontProgramStream)
End Using
Dim fontBrush As New Vintasoft.Imaging.Pdf.Drawing.PdfBrush(linkFontColor)
' open PdfGraphics on index page
Using indexGraphics As Vintasoft.Imaging.Pdf.Drawing.PdfGraphics = indexPage.GetGraphics()
' start location in index page
Dim indexPageTextLocation As System.Drawing.PointF = indexPage.MediaBox.Location
indexPageTextLocation.X += indexPagePadding.X
indexPageTextLocation.Y += indexPage.MediaBox.Height - indexPagePadding.Y - indexPageFontSize * 2
' draw index title
Dim titleRect As New System.Drawing.RectangleF(indexPageTextLocation.X, indexPageTextLocation.Y, indexPage.MediaBox.Width - indexPageTextLocation.X * 2, indexPageFontSize * 2 * 2)
indexGraphics.DrawString("Example: Create PDF document from several documents.", font, indexPageFontSize * 2, New Vintasoft.Imaging.Pdf.Drawing.PdfBrush(titleFontColor), titleRect, Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Center, _
True)
indexPageTextLocation.Y -= indexPageLineSpacing * 4
' location of page number
Dim indexPageNumberLocationX As Single = indexPage.MediaBox.X + indexPage.MediaBox.Width - indexPagePadding.X
' for each input file
For Each inputFilename As String In inputFilenames
Dim firstPageIndex As Integer = document.Pages.Count
' create bookmark
Dim fileBookmark As New Vintasoft.Imaging.Pdf.Tree.PdfBookmark(document, System.IO.Path.GetFileName(inputFilename))
fileBookmark.Destination = New Vintasoft.Imaging.Pdf.Tree.PdfDestinationFit(document, firstPageIndex)
document.Bookmarks.Add(fileBookmark)
' if input image file is PDF document
If System.IO.Path.GetExtension(inputFilename).ToUpper() = ".PDF" Then
' open input PDF document
Using inputDoc As New Vintasoft.Imaging.Pdf.PdfDocument(inputFilename)
' add pages from input PDF document to the output document, also add bookmark tree from input PDF document to the 'fileBookmark'
document.AddDocument(inputDoc, fileBookmark.ChildBookmarks)
End Using
Else
' add images from input image file to the output document
Dim images As New Vintasoft.Imaging.ImageCollection()
images.Add(inputFilename)
' if input file is vector document (DOCX, XLSX, ...)
If images(0).IsVectorImage Then
' create temp stream
Using tempStream As New System.IO.MemoryStream()
' create PDF encoder
Using encoder As New Vintasoft.Imaging.Codecs.Encoders.PdfEncoder()
' convert input file to temporary PDF document
images.SaveSync(tempStream, encoder)
' add pages from temp PDF document to the output document
Using tempDoc As New Vintasoft.Imaging.Pdf.PdfDocument(tempStream)
document.AddDocument(tempDoc, fileBookmark.ChildBookmarks)
End Using
End Using
End Using
Else
' encode input file as image-only PDF pages
For Each image As Vintasoft.Imaging.VintasoftImage In images
AddImageToPdfDocument(document, image)
Next
End If
images.ClearAndDisposeItems()
End If
' if 'fileBookmark' does not have children bookmarks AND added document is multipage document, i.e.
' input document is PDF document without bookmarks OR input document is NOT PDF document
If fileBookmark.ChildBookmarks.Count = 0 AndAlso (document.Pages.Count - firstPageIndex) > 1 Then
' for each page in input document
For i As Integer = firstPageIndex To document.Pages.Count - 1
' create bookmark for page
Dim pageBookmark As New Vintasoft.Imaging.Pdf.Tree.PdfBookmark(document, String.Format("Page {0}", i - firstPageIndex + 1))
' set destination for page bookmark
pageBookmark.Destination = New Vintasoft.Imaging.Pdf.Tree.PdfDestinationFit(document, i)
' add page bookmark to the file bookmark
fileBookmark.ChildBookmarks.Add(pageBookmark)
Next
End If
' draw link text on index page
Dim indexRect As System.Drawing.RectangleF = DrawIndexString(indexGraphics, System.IO.Path.GetFileName(inputFilename), font, indexPageFontSize, fontBrush, indexPageTextLocation, _
firstPageIndex + 1, indexPageNumberLocationX)
' add link annotation on link text
Dim linkAnnotation As New Vintasoft.Imaging.Pdf.Tree.Annotations.PdfLinkAnnotation(document.Pages(firstPageIndex), fileBookmark.Destination)
linkAnnotation.Rectangle = indexRect
linkAnnotation.HighlightingMode = Vintasoft.Imaging.Pdf.Tree.Annotations.PdfAnnotationHighlightingMode.Invert
indexPage.Annotations.Add(linkAnnotation)
' move to next link
indexPageTextLocation.Y -= indexRect.Height + indexPageLineSpacing
Next
End Using
' subset font that is used for text drawing
document.FontManager.PackFont(font)
' save chages in the output document
document.SaveChanges()
End Using
End Sub
''' <summary>
''' Draws the index string.
''' </summary>
''' <param name="graphics">The graphics.</param>
''' <param name="text">The text.</param>
''' <param name="font">The font.</param>
''' <param name="fontSize">Size of the font.</param>
''' <param name="brush">The brush.</param>
''' <param name="textLocation">The text location.</param>
''' <param name="pageNumber">The page number.</param>
''' <param name="pageNumberLocationX">The page number location at X-axis.</param>
''' <returns>Rectangle, where text was drawn.</returns>
Private Shared Function DrawIndexString(graphics As Vintasoft.Imaging.Pdf.Drawing.PdfGraphics, text As String, font As Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont, fontSize As Single, brush As Vintasoft.Imaging.Pdf.Drawing.PdfBrush, textLocation As System.Drawing.PointF, _
pageNumber As Integer, pageNumberLocationX As Single) As System.Drawing.RectangleF
' draw text
Dim width As Single, height As Single
graphics.DrawString(text, font, fontSize, brush, textLocation)
graphics.MeasureString(text, font, fontSize, width, height)
' draw dots
Dim lineWidth As Single = 1
Dim pageNumberLocation As New System.Drawing.PointF(pageNumberLocationX, textLocation.Y)
Using pen As New Vintasoft.Imaging.Pdf.Drawing.PdfPen(brush.Color, lineWidth)
pen.DashPattern = New Single() {lineWidth, lineWidth * 2}
graphics.DrawLine(pen, New System.Drawing.PointF(textLocation.X + width, textLocation.Y), pageNumberLocation)
End Using
' draw page number
graphics.DrawString(pageNumber.ToString(), font, fontSize, brush, pageNumberLocation)
graphics.MeasureString(pageNumber.ToString(), font, fontSize, width, height)
Return New System.Drawing.RectangleF(textLocation.X, textLocation.Y, pageNumberLocation.X - textLocation.X + width, height)
End Function
''' <summary>
''' Adds the image to PDF document.
''' </summary>
''' <param name="document">The document.</param>
''' <param name="image">The image.</param>
Private Shared Sub AddImageToPdfDocument(document As Vintasoft.Imaging.Pdf.PdfDocument, image As Vintasoft.Imaging.VintasoftImage)
' select compression
Dim compression As Vintasoft.Imaging.Pdf.PdfCompression
Dim compressionSettings As Vintasoft.Imaging.Pdf.PdfCompressionSettings
If image.BitsPerPixel = 1 Then
compression = Vintasoft.Imaging.Pdf.PdfCompression.CcittFax
ElseIf image.PixelFormat = Vintasoft.Imaging.PixelFormat.Indexed8 Then
compression = Vintasoft.Imaging.Pdf.PdfCompression.Zip
Else
compression = Vintasoft.Imaging.Pdf.PdfCompression.Jpeg
End If
' create compression settings
compressionSettings = New Vintasoft.Imaging.Pdf.PdfCompressionSettings()
compressionSettings.JpegQuality = 75
' add page
document.Pages.Add(image, compression, compressionSettings)
End Sub