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