SvgToGrayscale.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.Svg;
  13. using GCTEXT = GrapeCity.Documents.Text;
  14. using GCDRAW = GrapeCity.Documents.Drawing;
  15. using DsPdfWeb.Demos.Common;
  16.  
  17. namespace DsPdfWeb.Demos
  18. {
  19. // This sample is similar to SvgClipArt, but after loading each SVG image
  20. // it converts all strokes and fills in it to grayscale.
  21. //
  22. // The SVG clip art used in this sample is from freesvg.org.
  23. public class SvgToGrayscale
  24. {
  25. void ToGrayscale(SvgElementCollection elements)
  26. {
  27. foreach (var el in elements)
  28. {
  29. if (el is SvgGraphicsElement elg)
  30. {
  31. elg.Stroke = PaintToGrayscale(elg.Stroke);
  32. elg.Fill = PaintToGrayscale(elg.Fill);
  33. }
  34. ToGrayscale(el.Children);
  35. }
  36. }
  37.  
  38. // Simplified conversion of an SvgPaint to grayscale
  39. // (Y formula from https://goodcalculators.com/rgb-to-grayscale-conversion-calculator/):
  40. SvgPaint PaintToGrayscale(SvgPaint src)
  41. {
  42. if (src == null)
  43. return null;
  44. else if (src.PaintType == SvgPaintType.Color)
  45. {
  46. var rgb = src.Color.Rgb;
  47. var Y = (int)Math.Round(0.299 * rgb.R + 0.587 * rgb.G + 0.114 * rgb.B);
  48. return new SvgPaint(Color.FromArgb(Y, Y, Y));
  49. }
  50. else
  51. {
  52. return new SvgPaint(Color.Gray);
  53. }
  54. }
  55.  
  56. public int CreatePDF(Stream stream)
  57. {
  58. // Load images from the resources folder:
  59. var images = new List<(string, GcSvgDocument)>();
  60. foreach (var fname in Directory.GetFiles(Path.Combine("Resources", "SvgClipArt"), "*", SearchOption.AllDirectories))
  61. {
  62. var svg = GcSvgDocument.FromFile(fname);
  63. ToGrayscale(svg.RootSvg.Children);
  64. images.Add((Path.GetFileName(fname), svg));
  65. }
  66. images.Shuffle();
  67.  
  68. var doc = new GcPdfDocument();
  69. // Font and format for captions:
  70. const float sMargin = 72f / 6;
  71. var font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "segoeui.ttf"));
  72. var tf = new TextFormat() { Font = font, FontSize = sMargin * 0.65f };
  73.  
  74. // Set up a 3x4 layout grid with 1/2" margins all around:
  75. const float margin = 36;
  76. const int rows = 4;
  77. const int cols = 3;
  78. float gapx = 72f / 4, gapy = gapx;
  79. float sWidth = (doc.PageSize.Width - margin * 2 + gapx) / cols;
  80. float sHeight = (doc.PageSize.Height - margin * 2 + gapy) / rows;
  81. if (sWidth > sHeight)
  82. {
  83. gapx += sWidth - sHeight;
  84. sWidth = sHeight;
  85. }
  86. else
  87. {
  88. gapy += sHeight - sWidth;
  89. sHeight = sWidth;
  90. }
  91. var ip = new PointF(margin, margin);
  92.  
  93. // Render all images within the grid, adding new pages as needed:
  94. var g = doc.NewPage().Graphics;
  95. for (int i = 0; i < images.Count(); ++i)
  96. {
  97. // Draw border around image:
  98. var rect = new RectangleF(ip, new SizeF(sWidth - gapx, sHeight - gapy));
  99. g.FillRectangle(rect, Color.LightGray);
  100. g.DrawRectangle(rect, Color.Black, 0.5f);
  101. rect.Inflate(-sMargin, -sMargin);
  102.  
  103. // Draw the SVG:
  104. var svg = images[i].Item2;
  105. var s = svg.GetIntrinsicSize(SvgLengthUnits.Points);
  106. if (s.Width > 0 && s.Height > 0)
  107. {
  108. // If image proportions are different from our target rectangle,
  109. // we resize the rectangle centering the image in it:
  110. var qSrc = s.Width / s.Height;
  111. var qTgt = rect.Width / rect.Height;
  112. if (qSrc < qTgt)
  113. rect.Inflate(rect.Width * (qSrc / qTgt - 1) / 2, 0);
  114. else if (qSrc > qTgt)
  115. rect.Inflate(0, rect.Height * (qTgt / qSrc - 1) / 2);
  116. }
  117. // Render the SVG:
  118. g.DrawSvg(svg, rect);
  119.  
  120. // Print image file name as caption in the bottom slide margin:
  121. g.DrawString(Path.GetFileName(images[i].Item1), tf,
  122. new RectangleF(rect.X, rect.Bottom, rect.Width, sMargin),
  123. TextAlignment.Center, ParagraphAlignment.Near, false);
  124. ip.X += sWidth;
  125. if (ip.X + sWidth > doc.PageSize.Width && i < images.Count() - 1)
  126. {
  127. ip.X = margin;
  128. ip.Y += sHeight;
  129. if (ip.Y + sHeight > doc.PageSize.Height)
  130. {
  131. g = doc.NewPage().Graphics;
  132. ip.Y = margin;
  133. }
  134. }
  135. }
  136. // Done:
  137. doc.Save(stream);
  138. // Dispose images after saving the PDF:
  139. images.ForEach(t_ => t_.Item2.Dispose());
  140. return doc.Pages.Count;
  141. }
  142. }
  143. }
  144.