//// This code is part of Document Solutions for PDF .NET demos.// Copyright (c) MESCIUS inc. All rights reserved.//usingSystem.IO;usingSystem.Drawing;usingSystem.Linq;usingSystem.Collections.Generic;usingGrapeCity.Documents.Pdf;usingGrapeCity.Documents.Pdf.Articles;usingGrapeCity.Documents.Drawing;usingDsPdfWeb.Demos.Common; namespaceDsPdfWeb.Demos{// This sample shows how to create article threads in a PDF document.// An article thread is a sequence of related pages or page areas that can be// navigated sequentially (forward or back) in a supporting PDF viewer.// In this sample we load a number of photos from a folder and render them// one per page in a random order.// Some photos are associated (via known file names) with a specific subject// (buildings, art, etc.), and we put all images associated with// each subject into a subject-specific article thread (images that are not// associated with any known subject are put in the 'Miscellaneous' thread).// In addition we create 3 threads for different aspect ratios (horizontal,// vertical and square), and add each image to the appropriate aspect article. // See section 'Article threads' in Navigating PDF pages// for details on how to navigate article threads in Acrobat// (our JavaScript PDF viewer provides a similar UI for this).publicclassImageArticles {// Article names:staticclassArticleNames {publicstaticstringLandscape => "Subject: landscape";publicstaticstringArt => "Subject: art";publicstaticstringFlora => "Subject: flora";publicstaticstringBuildings => "Subject: buildings";publicstaticstringMisc => "Subject: Miscellaneous";publicstaticstringAspectHorz => "Aspect: horizontal";publicstaticstringAspectVert => "Aspect: vertical";publicstaticstringAspectSquare => "Aspect: square"; } // Associate known image file names with appropriate subjects:staticreadonlyDictionary<string, string> _subjects = newDictionary<string, string>() { {"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 }, {"newfoundland.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 },// Images not in this list are 'misc'. }; // Class to hold image info:privateclassImageInfo {publicstringName;publicIImageImage;publicstringSubject;publicstringAspect; } publicintCreatePDF(Stream stream) {// Load images and their associated infos:var imageInfos = newList<ImageInfo>();foreach (var fname inDirectory.GetFiles(Path.Combine("Resources", "Images"), "*", SearchOption.AllDirectories)) {var image = Util.ImageFromFile(fname);var aspect = image.Width > image.Height ? ArticleNames.AspectHorz : (image.Width < image.Height ? ArticleNames.AspectVert : ArticleNames.AspectSquare);var name = Path.GetFileName(fname);_subjects.TryGetValue(name, outstring subject);if (string.IsNullOrEmpty(subject)) subject = ArticleNames.Misc; imageInfos.Add(newImageInfo() {Name = name,Image = image,Subject = subject,Aspect = aspect }); }// Randomize the order of images in the PDF: imageInfos.Shuffle(); // Keys are article thread names (from ArticleNames),// values are ArticleThread objects to be added to the PDF:var articles = newDictionary<string, ArticleThread>();foreach (var subject in_subjects.Values.Distinct()) articles.Add(subject,newArticleThread() {Info = newDocumentInfo() { Title = subject } }); articles.Add(ArticleNames.Misc,newArticleThread() {Info = newDocumentInfo() { Title = ArticleNames.Misc } });var horizontals = newArticleThread() {Info = newDocumentInfo() { Title = ArticleNames.AspectHorz } };var verticals = newArticleThread() {Info = newDocumentInfo() { Title = ArticleNames.AspectVert } };var squares = newArticleThread() {Info = newDocumentInfo() { Title = ArticleNames.AspectSquare } }; // Create the document:var doc = newGcPdfDocument(); // Add images (one per page) to the PDF and article threads:var ia = newImageAlign(ImageAlignHorz.Center, ImageAlignVert.Top, true, true, true, false, false);for (int i = 0; i < imageInfos.Count; ++i) {var page = doc.NewPage();var ii = imageInfos[i];var rc = newRectangleF(72, 72, doc.PageSize.Width - 144, doc.PageSize.Height - 144);// Note that we get the actual image bounds to precisely specify the page area in the thread: page.Graphics.DrawImage(ii.Image, rc, null, ia, outRectangleF[] imageBounds);var bounds = imageBounds[0];// Add the image to proper subject and aspect threads: articles[ii.Subject].Beads.Add(newArticleBead() { Page = page, Bounds = bounds });if (ii.Aspect == ArticleNames.AspectHorz) horizontals.Beads.Add(newArticleBead() { Page = page, Bounds = bounds });elseif (ii.Aspect == ArticleNames.AspectVert) verticals.Beads.Add(newArticleBead() { Page = page, Bounds = bounds });else squares.Beads.Add(newArticleBead() { Page = page, Bounds = bounds }); }// Add subject and aspect article threads to the PDF:foreach (var article in articles.Select(a_ => a_.Value)) doc.ArticleThreads.Add(article); doc.ArticleThreads.Add(horizontals); doc.ArticleThreads.Add(verticals); doc.ArticleThreads.Add(squares); // Done: doc.Save(stream);return doc.Pages.Count; } }}