ImageLinks.vb
''
'' This code is part of GrapeCity Documents for PDF samples.
'' Copyright (c) GrapeCity, Inc. All rights reserved.
''
Imports System.IO
Imports System.Drawing
Imports System.Numerics
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Drawing
Imports GrapeCity.Documents.Pdf.Annotations
Imports GrapeCity.Documents.Pdf.Actions

'' This sample loads all images found in a directory, then renders each image
'' in the largest possible size on a separate page of the PDF.
'' Finally it inserts a TOC of image thumbnails linked to the large images
'' into the document.
'' See also SlidePages.
Public Class ImageLinks
    Private Class ImageInfo
        Public Property Name As String
        Public Property Image As Image
        Public Property PageIdx As Integer
    End Class

    Function CreatePDF(ByVal stream As Stream) As Integer
        Dim doc = New GcPdfDocument()
        Dim fnt = Font.FromFile(Path.Combine("Resources", "Fonts", "segoeui.ttf"))
        '' 1/4" page margins all around:
        Const margin = 36.0F

        '' Load all images from the Resources/Images folder:
        Dim imageInfos As New List(Of ImageInfo)
        For Each fname In Directory.GetFiles(Path.Combine("Resources", "Images"), "*", SearchOption.AllDirectories)
            imageInfos.Add(New ImageInfo() With {.Name = Path.GetFileName(fname), .Image = Util.ImageFromFile(fname)})
        Next
        imageInfos.Shuffle()
        '' Set up image alignment that would center images horizontally and align to top vertically:
        Dim ia = New ImageAlign(ImageAlignHorz.Center, ImageAlignVert.Top, True, True, True, False, False)
        '' Image rectangle for full-sized images - whole page:
        Dim rBig = New RectangleF(margin, margin, doc.PageSize.Width - margin * 2, doc.PageSize.Height - margin * 2)
        '' Render all images full-size, one image per page:
        For i = 0 To imageInfos.Count - 1
            Dim g = doc.NewPage().Graphics
            Dim ii = imageInfos(i)
            g.DrawImage(ii.Image, rBig, Nothing, ia)
            ii.PageIdx = i
        Next
        '' Insert page(s) with thumbnails into the beginning of the document as a 4x5 grid (see SlidePages):
        Const rows = 5
        Const cols = 4
        Dim gapx = 72.0F / 4, gapy = gapx
        Dim sWidth = (doc.PageSize.Width - margin * 2 + gapx) / cols
        Dim sHeight = (doc.PageSize.Height - margin * 2 + gapy) / rows
        If (sWidth > sHeight) Then
            gapx += sWidth - sHeight
            sWidth = sHeight
        Else
            gapy += sHeight - sWidth
            sHeight = sWidth
        End If
        Const sMargin = 72.0F / 6
        '' Center thumbnails vertically too:
        ia.AlignVert = ImageAlignVert.Center
        '' Text format for image captions:
        Dim tf = New TextFormat() With {.Font = fnt, .FontSize = sMargin * 0.65F}
        '' Insertion point:
        Dim ip = New PointF(margin, margin)
        Dim page = doc.Pages.Insert(0)
        For i = 0 To imageInfos.Count() - 1
            Dim ii = imageInfos(i)
            Dim rect = New RectangleF(ip, New SizeF(sWidth - gapx, sHeight - gapy))
            '' Add a link to the page where the full-sized image is (the page index
            '' will be updated when we know how many pages are in TOC, see below):
            page.Annotations.Add(New LinkAnnotation(rect, New DestinationFit(ii.PageIdx)))
            '' Draw thumbnail:
            Dim g = page.Graphics
            g.FillRectangle(rect, Color.LightGray)
            g.DrawRectangle(rect, Color.Black, 0.5F)
            rect.Inflate(-sMargin, -sMargin)
            Dim imageRect As RectangleF() = Nothing
            g.DrawImage(ii.Image, rect, Nothing, ia, imageRect)
            g.DrawRectangle(imageRect(0), Color.DarkGray, 1)
            '' Print image file name as caption in the bottom slide margin:
            g.DrawString(ii.Name, tf,
                New RectangleF(rect.X, rect.Bottom, rect.Width, sMargin),
                TextAlignment.Center, ParagraphAlignment.Near, False)
            ip.X += sWidth
            If (ip.X + sWidth > doc.PageSize.Width) Then
                ip.X = margin
                ip.Y += sHeight
                If (ip.Y + sHeight > doc.PageSize.Height) Then
                    page = doc.Pages.Insert(doc.Pages.IndexOf(page) + 1)
                    ip.Y = margin
                End If
            End If
        Next
        '' We now go through all TOC pages, updating page indices in links' destinations
        '' to account for the TOC pages inserted in the beginning of the document:
        Dim tocPages = doc.Pages.IndexOf(page) + 1
        For i = 0 To tocPages - 1
            For Each ann In doc.Pages(i).Annotations
                If TypeOf ann Is LinkAnnotation AndAlso TypeOf CType(ann, LinkAnnotation).Dest Is DestinationFit Then
                    Dim link = DirectCast(ann, LinkAnnotation)
                    Dim dest = DirectCast(CType(ann, LinkAnnotation).Dest, DestinationFit)
                    link.Dest = New DestinationFit(dest.PageIndex.Value + tocPages)
                End If
            Next
        Next
        ''
        '' Done:
        doc.Save(stream)
        imageInfos.ForEach(Sub(ii_) ii_.Image.Dispose())
        Return doc.Pages.Count
    End Function
End Class