ImageArticles.vb
'' 
'' このコードは、DioDocs for PDF のサンプルの一部として提供されています。
'' © MESCIUS inc. All rights reserved.
'' 
Imports System.IO
Imports System.Drawing
Imports System.Linq
Imports System.Collections.Generic
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Pdf.Articles
Imports GrapeCity.Documents.Imaging
Imports GrapeCity.Documents.Drawing

'' このサンプルは、PDF 文書に記事のスレッドを作成する方法を示します。
'' 記事のスレッドは、サポートしている PDF ビューアで順方向(前後)に移動できる
'' 一連の関連ページまたはページ領域です。
'' このサンプルでは、フォルダから多数の写真を読み込み、それらを1ページに1つずつ
'' ランダムな順序で描画します。
'' いくつかの写真は特定の主題(建物、アートなど)に(既知のファイル名で)関連付け
'' られており、各主題に関連するすべての画像を主題固有の記事スレッドに入れます
'' (既知の主題に関連付けられていない画像は 「その他」のスレッドに入れます。
'' さらに、縦横比(水平、垂直、正方形)ごとに3つのスレッドを作成し、各画像を適切な
'' アスペクト記事に追加します。
'' Acrobat で記事のスレッドをナビゲートする方法の詳細については、Navigating PDF pages の
'' 「Article threads」セクションを参照してください。
'' (本デモサイト内の PDF ビューアは、これに似た UI を提供します)。
Public Class ImageArticles
    '' 記事の名前です。
    Class ArticleNames
        Public Shared Landscape = "件名:風景"
        Public Shared Art = "件名:アート"
        Public Shared Flora = "件名:植物"
        Public Shared Buildings = "件名:建物"
        Public Shared Misc = "件名:その他"
        Public Shared AspectHorz = "アスペクト:水平"
        Public Shared AspectVert = "アスペクト:垂直"
        Public Shared AspectSquare = "アスペクト:正方形"
    End Class

    '' 既知の画像ファイル名を適切な主題に関連付けます。
    Shared _subjects As New Dictionary(Of String, String)() From
        {
            {"aurora.jpg", ArticleNames.Landscape},
            {"chairs.jpg", ArticleNames.Buildings},
            {"clouds.jpg", ArticleNames.Landscape},
            {"colosseum.jpg", ArticleNames.Art},
            {"deadwood.jpg", ArticleNames.Flora},
            {"door.jpg", ArticleNames.Buildings},
            {"ferns.jpg", ArticleNames.Flora},
            {"fiord.jpg", ArticleNames.Landscape},
            {"firth.jpg", ArticleNames.Landscape},
            {"lady.jpg", ArticleNames.Art},
            {"lavender.jpg", ArticleNames.Flora},
            {"maple.jpg", ArticleNames.Buildings},
            {"minerva.jpg", ArticleNames.Art},
            {"out.jpg", ArticleNames.Landscape},
            {"pines.jpg", ArticleNames.Flora},
            {"purples.jpg", ArticleNames.Flora},
            {"reds.jpg", ArticleNames.Flora},
            {"road.jpg", ArticleNames.Landscape},
            {"rome.jpg", ArticleNames.Art},
            {"roofs.jpg", ArticleNames.Buildings},
            {"sea.jpg", ArticleNames.Landscape},
            {"skye.jpg", ArticleNames.Landscape},
            {"tudor.jpg", ArticleNames.Buildings},
            {"windswept.jpg", ArticleNames.Flora}
        }
    '' このリストにない画像は 'misc'として扱われます。

    '' 画像情報を保持するクラス
    Class ImageInfo
        Public Name As String
        Public Image As IImage
        Public Subject As String
        Public Aspect As String
    End Class

    Function CreatePDF(ByVal stream As Stream) As Integer
        '' 画像とその関連情報を読み込みます。
        Dim imageInfos = New List(Of ImageInfo)
        For Each fname In Directory.GetFiles(Path.Combine("Resources", "Images"), "*", SearchOption.AllDirectories)
            Dim image = Util.ImageFromFile(fname)
            Dim aspect As String
            If image.Width > image.Height Then
                aspect = ArticleNames.AspectHorz
            ElseIf image.Width < image.Height Then
                aspect = ArticleNames.AspectVert
            Else
                aspect = ArticleNames.AspectSquare
            End If
            Dim name = Path.GetFileName(fname)
            Dim subject As String = Nothing
            _subjects.TryGetValue(name, subject)
            If String.IsNullOrEmpty(subject) Then
                subject = ArticleNames.Misc
            End If
            imageInfos.Add(New ImageInfo() With {
                .Name = name,
                .Image = image,
                .Subject = subject,
                .Aspect = aspect
                })
        Next
        '' PDF内の画像をランダムに並べ替えます。
        imageInfos.Shuffle()

        '' キーは(ArticleNames からの)記事のスレッド名、
        '' 値は PDF に追加される ArticleThread オブジェクトです。
        Dim articles = New Dictionary(Of String, ArticleThread)()
        For Each subject In _subjects.Values.Distinct()
            articles.Add(subject,
                         New ArticleThread() With {
                            .Info = New DocumentInfo() With {.Title = subject}
                         })
        Next
        articles.Add(ArticleNames.Misc,
                     New ArticleThread() With {.Info = New DocumentInfo() With {.Title = ArticleNames.Misc}})
        Dim horizontals = New ArticleThread() With {.Info = New DocumentInfo() With {.Title = ArticleNames.AspectHorz}}
        Dim verticals = New ArticleThread() With {.Info = New DocumentInfo() With {.Title = ArticleNames.AspectVert}}
        Dim squares = New ArticleThread() With {.Info = New DocumentInfo() With {.Title = ArticleNames.AspectSquare}}

        '' ドキュメントを生成します。
        Dim doc = New GcPdfDocument()

        '' PDF と記事のスレッドに画像を(ページごとに1つ)追加します。
        Dim ia = New ImageAlign(ImageAlignHorz.Center, ImageAlignVert.Top, True, True, True, False, False)
        For i = 0 To imageInfos.Count - 1
            Dim page = doc.NewPage()
            Dim ii = imageInfos(i)
            Dim rc = New RectangleF(72, 72, doc.PageSize.Width - 144, doc.PageSize.Height - 144)
            '' スレッド内のページ領域を正確に指定するために実際の画像境界を取得します。
            Dim imageBounds As RectangleF() = Nothing
            page.Graphics.DrawImage(ii.Image, rc, Nothing, ia, imageBounds)
            Dim bounds = imageBounds(0)
            '' 適切な件名とアスペクトのスレッドに画像を追加します。
            articles(ii.Subject).Beads.Add(New ArticleBead() With {.Page = page, .Bounds = bounds})
            If (ii.Aspect = ArticleNames.AspectHorz) Then
                horizontals.Beads.Add(New ArticleBead() With {.Page = page, .Bounds = bounds})
            ElseIf (ii.Aspect = ArticleNames.AspectVert) Then
                verticals.Beads.Add(New ArticleBead() With {.Page = page, .Bounds = bounds})
            Else
                squares.Beads.Add(New ArticleBead() With {.Page = page, .Bounds = bounds})
            End If
        Next
        '' 件名とアスペクトの記事のスレッドを PDF に追加します。
        For Each article In articles.Select(Function(a_) a_.Value)
            doc.ArticleThreads.Add(article)
        Next
        doc.ArticleThreads.Add(horizontals)
        doc.ArticleThreads.Add(verticals)
        doc.ArticleThreads.Add(squares)

        '' PDF ドキュメントを保存します。
        doc.Save(stream)
        Return doc.Pages.Count
    End Function
End Class