ImageLinks.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.Text;
  12. using GrapeCity.Documents.Drawing;
  13. using DsPdfWeb.Demos.Common;
  14. using GrapeCity.Documents.Pdf.Annotations;
  15. using GCTEXT = GrapeCity.Documents.Text;
  16. using GCDRAW = GrapeCity.Documents.Drawing;
  17.  
  18. namespace DsPdfWeb.Demos
  19. {
  20. // This sample loads all images found in a directory, then renders each image
  21. // in the largest possible size on a separate page of the PDF.
  22. // Finally it inserts a TOC of image thumbnails linked to the large images
  23. // into the document.
  24. // See also SlidePages.
  25. public class ImageLinks
  26. {
  27. private class ImageInfo
  28. {
  29. public string Name;
  30. public IImage Image;
  31. public int PageIdx;
  32. }
  33.  
  34. public int CreatePDF(Stream stream)
  35. {
  36. var doc = new GcPdfDocument();
  37. var font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "segoeui.ttf"));
  38. // 1/2" page margins all around:
  39. const float margin = 36;
  40.  
  41. // Load all images from the Resources/Images folder:
  42. List<ImageInfo> imageInfos = new List<ImageInfo>();
  43. foreach (var fname in Directory.GetFiles(Path.Combine("Resources", "Images"), "*", SearchOption.AllDirectories))
  44. imageInfos.Add(new ImageInfo() { Name = Path.GetFileName(fname), Image = Util.ImageFromFile(fname) });
  45. imageInfos.Shuffle();
  46. // Set up image alignment that would center images horizontally and align to top vertically:
  47. var ia = new ImageAlign(ImageAlignHorz.Center, ImageAlignVert.Top, true, true, true, false, false);
  48. // Image rectangle for full-sized images - whole page:
  49. var rBig = new RectangleF(margin, margin, doc.PageSize.Width - margin * 2, doc.PageSize.Height - margin * 2);
  50. // Render all images full-size, one image per page:
  51. for (int i = 0; i < imageInfos.Count; ++i)
  52. {
  53. var g = doc.NewPage().Graphics;
  54. var ii = imageInfos[i];
  55. g.DrawImage(ii.Image, rBig, null, ia);
  56. ii.PageIdx = i;
  57. }
  58. // Insert page(s) with thumbnails into the beginning of the document as a 4x5 grid (see SlidePages):
  59. const int rows = 5;
  60. const int cols = 4;
  61. float gapx = 72f / 4, gapy = gapx;
  62. float sWidth = (doc.PageSize.Width - margin * 2 + gapx) / cols;
  63. float sHeight = (doc.PageSize.Height - margin * 2 + gapy) / rows;
  64. if (sWidth > sHeight)
  65. {
  66. gapx += sWidth - sHeight;
  67. sWidth = sHeight;
  68. }
  69. else
  70. {
  71. gapy += sHeight - sWidth;
  72. sHeight = sWidth;
  73. }
  74. const float sMargin = 72f / 6;
  75. // Center thumbnails vertically too:
  76. ia.AlignVert = ImageAlignVert.Center;
  77. // Text format for image captions:
  78. var tf = new TextFormat() { Font = font, FontSize = sMargin * 0.65f };
  79. // Insertion point:
  80. var ip = new PointF(margin, margin);
  81. var page = doc.Pages.Insert(0);
  82. for (int i = 0; i < imageInfos.Count(); ++i)
  83. {
  84. var ii = imageInfos[i];
  85. var rect = new RectangleF(ip, new SizeF(sWidth - gapx, sHeight - gapy));
  86. // Add a link to the page where the full-sized image is (the page index
  87. // will be updated when we know how many pages are in TOC, see below):
  88. page.Annotations.Add(new LinkAnnotation(rect, new DestinationFit(ii.PageIdx)));
  89. // Draw thumbnail:
  90. var g = page.Graphics;
  91. g.FillRectangle(rect, Color.LightGray);
  92. g.DrawRectangle(rect, Color.Black, 0.5f);
  93. rect.Inflate(-sMargin, -sMargin);
  94. g.DrawImage(ii.Image, rect, null, ia, out RectangleF[] imageRect);
  95. g.DrawRectangle(imageRect[0], Color.DarkGray, 1);
  96. // Print image file name as caption in the bottom slide margin:
  97. g.DrawString(ii.Name, tf,
  98. new RectangleF(rect.X, rect.Bottom, rect.Width, sMargin),
  99. TextAlignment.Center, ParagraphAlignment.Near, false);
  100. ip.X += sWidth;
  101. if (ip.X + sWidth > doc.PageSize.Width)
  102. {
  103. ip.X = margin;
  104. ip.Y += sHeight;
  105. if (ip.Y + sHeight > doc.PageSize.Height)
  106. {
  107. page = doc.Pages.Insert(doc.Pages.IndexOf(page) + 1);
  108. ip.Y = margin;
  109. }
  110. }
  111. }
  112. // We now go through all TOC pages, updating page indices in links' destinations
  113. // to account for the TOC pages inserted in the beginning of the document:
  114. int tocPages = doc.Pages.IndexOf(page) + 1;
  115. for (int i = 0; i < tocPages; ++i)
  116. {
  117. foreach (var ann in doc.Pages[i].Annotations)
  118. if (ann is LinkAnnotation link && link.Dest is DestinationFit dest)
  119. link.Dest = new DestinationFit(dest.PageIndex.Value + tocPages);
  120. }
  121. // Done:
  122. doc.Save(stream);
  123. imageInfos.ForEach((ii_) => ii_.Image.Dispose());
  124. return doc.Pages.Count;
  125. }
  126. }
  127. }
  128.  
  129.