ImageArticles.cs
  1. //
  2. // This code is part of Document Solutions for PDF demos.
  3. // Copyright (c) MESCIUS inc. All rights reserved.
  4. //
  5. using System;
  6. using System.IO;
  7. using System.Drawing;
  8. using System.Linq;
  9. using System.Collections.Generic;
  10. using GrapeCity.Documents.Pdf;
  11. using GrapeCity.Documents.Pdf.Articles;
  12. using GrapeCity.Documents.Imaging;
  13. using GrapeCity.Documents.Drawing;
  14. using DsPdfWeb.Demos.Common;
  15.  
  16. namespace DsPdfWeb.Demos
  17. {
  18. // This sample shows how to create article threads in a PDF document.
  19. // An article thread is a sequence of related pages or page areas that can be
  20. // navigated sequentially (forward or back) in a supporting PDF viewer.
  21. // In this sample we load a number of photos from a folder and render them
  22. // one per page in a random order.
  23. // Some photos are associated (via known file names) with a specific subject
  24. // (buildings, art, etc.), and we put all images associated with
  25. // each subject into a subject-specific article thread (images that are not
  26. // associated with any known subject are put in the 'Miscellaneous' thread).
  27. // In addition we create 3 threads for different aspect ratios (horizontal,
  28. // vertical and square), and add each image to the appropriate aspect article.
  29. // See section 'Article threads' in Navigating PDF pages
  30. // for details on how to navigate article threads in Acrobat
  31. // (our JavaScript PDF viewer provides a similar UI for this).
  32. public class ImageArticles
  33. {
  34. // Article names:
  35. static class ArticleNames
  36. {
  37. public static string Landscape => "Subject: landscape";
  38. public static string Art => "Subject: art";
  39. public static string Flora => "Subject: flora";
  40. public static string Buildings => "Subject: buildings";
  41. public static string Misc => "Subject: Miscellaneous";
  42. public static string AspectHorz => "Aspect: horizontal";
  43. public static string AspectVert => "Aspect: vertical";
  44. public static string AspectSquare => "Aspect: square";
  45. }
  46.  
  47. // Associate known image file names with appropriate subjects:
  48. static readonly Dictionary<string, string> _subjects = new Dictionary<string, string>()
  49. {
  50. {"aurora.jpg", ArticleNames.Landscape },
  51. {"chairs.jpg", ArticleNames.Buildings },
  52. {"clouds.jpg", ArticleNames.Landscape },
  53. {"colosseum.jpg", ArticleNames.Art },
  54. {"deadwood.jpg", ArticleNames.Flora },
  55. {"door.jpg", ArticleNames.Buildings },
  56. {"ferns.jpg", ArticleNames.Flora },
  57. {"fiord.jpg", ArticleNames.Landscape },
  58. {"firth.jpg", ArticleNames.Landscape },
  59. {"lady.jpg", ArticleNames.Art },
  60. {"lavender.jpg", ArticleNames.Flora },
  61. {"maple.jpg", ArticleNames.Buildings },
  62. {"minerva.jpg", ArticleNames.Art },
  63. {"newfoundland.jpg", ArticleNames.Landscape },
  64. {"pines.jpg", ArticleNames.Flora },
  65. {"purples.jpg", ArticleNames.Flora },
  66. {"reds.jpg", ArticleNames.Flora },
  67. {"road.jpg", ArticleNames.Landscape },
  68. {"rome.jpg", ArticleNames.Art },
  69. {"roofs.jpg", ArticleNames.Buildings },
  70. {"sea.jpg", ArticleNames.Landscape },
  71. {"skye.jpg", ArticleNames.Landscape },
  72. {"tudor.jpg", ArticleNames.Buildings },
  73. {"windswept.jpg", ArticleNames.Flora },
  74. // Images not in this list are 'misc'.
  75. };
  76.  
  77. // Class to hold image info:
  78. private class ImageInfo
  79. {
  80. public string Name;
  81. public IImage Image;
  82. public string Subject;
  83. public string Aspect;
  84. }
  85.  
  86. public int CreatePDF(Stream stream)
  87. {
  88. // Load images and their associated infos:
  89. var imageInfos = new List<ImageInfo>();
  90. foreach (var fname in Directory.GetFiles(Path.Combine("Resources", "Images"), "*", SearchOption.AllDirectories))
  91. {
  92. var image = Util.ImageFromFile(fname);
  93. var aspect = image.Width > image.Height ? ArticleNames.AspectHorz :
  94. (image.Width < image.Height ? ArticleNames.AspectVert : ArticleNames.AspectSquare);
  95. var name = Path.GetFileName(fname);
  96. _subjects.TryGetValue(name, out string subject);
  97. if (string.IsNullOrEmpty(subject))
  98. subject = ArticleNames.Misc;
  99. imageInfos.Add(new ImageInfo()
  100. {
  101. Name = name,
  102. Image = image,
  103. Subject = subject,
  104. Aspect = aspect
  105. });
  106. }
  107. // Randomize the order of images in the PDF:
  108. imageInfos.Shuffle();
  109.  
  110. // Keys are article thread names (from ArticleNames),
  111. // values are ArticleThread objects to be added to the PDF:
  112. var articles = new Dictionary<string, ArticleThread>();
  113. foreach (var subject in _subjects.Values.Distinct())
  114. articles.Add(subject,
  115. new ArticleThread()
  116. {
  117. Info = new DocumentInfo() { Title = subject }
  118. });
  119. articles.Add(ArticleNames.Misc,
  120. new ArticleThread()
  121. {
  122. Info = new DocumentInfo() { Title = ArticleNames.Misc }
  123. });
  124. var horizontals = new ArticleThread()
  125. {
  126. Info = new DocumentInfo() { Title = ArticleNames.AspectHorz }
  127. };
  128. var verticals = new ArticleThread()
  129. {
  130. Info = new DocumentInfo() { Title = ArticleNames.AspectVert }
  131. };
  132. var squares = new ArticleThread()
  133. {
  134. Info = new DocumentInfo() { Title = ArticleNames.AspectSquare }
  135. };
  136.  
  137. // Create the document:
  138. var doc = new GcPdfDocument();
  139.  
  140. // Add images (one per page) to the PDF and article threads:
  141. var ia = new ImageAlign(ImageAlignHorz.Center, ImageAlignVert.Top, true, true, true, false, false);
  142. for (int i = 0; i < imageInfos.Count; ++i)
  143. {
  144. var page = doc.NewPage();
  145. var ii = imageInfos[i];
  146. var rc = new RectangleF(72, 72, doc.PageSize.Width - 144, doc.PageSize.Height - 144);
  147. // Note that we get the actual image bounds to precisely specify the page area in the thread:
  148. page.Graphics.DrawImage(ii.Image, rc, null, ia, out RectangleF[] imageBounds);
  149. var bounds = imageBounds[0];
  150. // Add the image to proper subject and aspect threads:
  151. articles[ii.Subject].Beads.Add(new ArticleBead() { Page = page, Bounds = bounds });
  152. if (ii.Aspect == ArticleNames.AspectHorz)
  153. horizontals.Beads.Add(new ArticleBead() { Page = page, Bounds = bounds });
  154. else if (ii.Aspect == ArticleNames.AspectVert)
  155. verticals.Beads.Add(new ArticleBead() { Page = page, Bounds = bounds });
  156. else
  157. squares.Beads.Add(new ArticleBead() { Page = page, Bounds = bounds });
  158. }
  159. // Add subject and aspect article threads to the PDF:
  160. foreach (var article in articles.Select(a_ => a_.Value))
  161. doc.ArticleThreads.Add(article);
  162. doc.ArticleThreads.Add(horizontals);
  163. doc.ArticleThreads.Add(verticals);
  164. doc.ArticleThreads.Add(squares);
  165.  
  166. // Done:
  167. doc.Save(stream);
  168. return doc.Pages.Count;
  169. }
  170. }
  171. }
  172.