ImageArticles.cs
C# VB
//// This code is part of Document Solutions for PDF .NET demos.// Copyright (c) MESCIUS inc. All rights reserved.//using System.IO;using System.Drawing;using System.Linq;using System.Collections.Generic;using GrapeCity.Documents.Pdf;using GrapeCity.Documents.Pdf.Articles;using GrapeCity.Documents.Drawing;using DsPdfWeb.Demos.Common;
namespace DsPdfWeb.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). public class ImageArticles { // Article names: static class ArticleNames { public static string Landscape => "Subject: landscape"; public static string Art => "Subject: art"; public static string Flora => "Subject: flora"; public static string Buildings => "Subject: buildings"; public static string Misc => "Subject: Miscellaneous"; public static string AspectHorz => "Aspect: horizontal"; public static string AspectVert => "Aspect: vertical"; public static string AspectSquare => "Aspect: square"; }
// Associate known image file names with appropriate subjects: static readonly Dictionary<string, string> _subjects = new Dictionary<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: private class ImageInfo { public string Name; public IImage Image; public string Subject; public string Aspect; }
public int CreatePDF(Stream stream) { // Load images and their associated infos: var imageInfos = new List<ImageInfo>(); foreach (var fname in Directory.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, out string subject); if (string.IsNullOrEmpty(subject)) subject = ArticleNames.Misc; imageInfos.Add(new ImageInfo() { 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 = new Dictionary<string, ArticleThread>(); foreach (var subject in _subjects.Values.Distinct()) articles.Add(subject, new ArticleThread() { Info = new DocumentInfo() { Title = subject } }); articles.Add(ArticleNames.Misc, new ArticleThread() { Info = new DocumentInfo() { Title = ArticleNames.Misc } }); var horizontals = new ArticleThread() { Info = new DocumentInfo() { Title = ArticleNames.AspectHorz } }; var verticals = new ArticleThread() { Info = new DocumentInfo() { Title = ArticleNames.AspectVert } }; var squares = new ArticleThread() { Info = new DocumentInfo() { Title = ArticleNames.AspectSquare } };
// Create the document: var doc = new GcPdfDocument();
// Add images (one per page) to the PDF and article threads: var ia = new ImageAlign(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 = new RectangleF(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, out RectangleF[] imageBounds); var bounds = imageBounds[0]; // Add the image to proper subject and aspect threads: articles[ii.Subject].Beads.Add(new ArticleBead() { Page = page, Bounds = bounds }); if (ii.Aspect == ArticleNames.AspectHorz) horizontals.Beads.Add(new ArticleBead() { Page = page, Bounds = bounds }); else if (ii.Aspect == ArticleNames.AspectVert) verticals.Beads.Add(new ArticleBead() { Page = page, Bounds = bounds }); else squares.Beads.Add(new ArticleBead() { 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; } }}