SvgToGrayscale.vb
'''' This code is part of Document Solutions for PDF .NET demos.'' Copyright (c) MESCIUS inc. All rights reserved.''Imports SystemImports System.IOImports System.DrawingImports System.LinqImports System.Collections.GenericImports GrapeCity.Documents.PdfImports GrapeCity.Documents.TextImports GrapeCity.Documents.SvgImports GCTEXT = GrapeCity.Documents.Text
'' This sample is similar to SvgClipArt, but after loading each SVG image'' it converts all strokes and fills in it to grayscale.Public Class SvgToGrayscale Sub ToGrayscale(ByVal elements As SvgElementCollection) For Each el In elements If TypeOf el Is SvgGraphicsElement Then Dim elg = DirectCast(el, SvgGraphicsElement) elg.Stroke = PaintToGrayscale(elg.Stroke) elg.Fill = PaintToGrayscale(elg.Fill) End If ToGrayscale(el.Children) Next End Sub
'' Simplified conversion of an SvgPaint to grayscale '' (Y formula from https://goodcalculators.com/rgb-to-grayscale-conversion-calculator/): Function PaintToGrayscale(ByVal src As SvgPaint) As SvgPaint If src Is Nothing Then Return Nothing ElseIf src.PaintType = SvgPaintType.Color Then Dim rgb = src.Color.Rgb Dim Y = CInt(Math.Round(0.299 * rgb.R + 0.587 * rgb.G + 0.114 * rgb.B)) Return New SvgPaint(Color.FromArgb(Y, Y, Y)) Else Return New SvgPaint(Color.Gray) End If End Function
Function CreatePDF(ByVal stream As Stream) As Integer '' Load images from the resources folder: Dim images = New List(Of (String, GcSvgDocument))() For Each fname In Directory.GetFiles(Path.Combine("Resources", "SvgClipArt"), "*", SearchOption.AllDirectories) Dim svg = GcSvgDocument.FromFile(fname) ToGrayscale(svg.RootSvg.Children) images.Add((Path.GetFileName(fname), svg)) Next images.Shuffle()
Dim doc = New GcPdfDocument() '' Font and format for captions: Const sMargin As Single = 72.0F / 6 Dim font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "NotoSans-Regular.ttf")) Dim tf = New TextFormat() With {.Font = font, .FontSize = sMargin * 0.65F}
'' Set up a 3x4 layout grid with 1/2" margins all around: Const margin As Single = 36 Const rows As Integer = 4 Const cols As Integer = 3 Dim gapx As Single = 72.0F / 4 Dim gapy As Single = gapx Dim sWidth As Single = (doc.PageSize.Width - margin * 2 + gapx) / cols Dim sHeight As Single = (doc.PageSize.Height - margin * 2 + gapy) / rows If sWidth > sHeight Then gapx += sWidth - sHeight sWidth = sHeight Else gapy += sHeight - sWidth sHeight = sWidth End If Dim ip = New PointF(margin, margin)
'' Render all images within the grid, adding new pages as needed: Dim g = doc.NewPage().Graphics For i = 0 To images.Count - 1 '' Draw border around image: Dim rect = New RectangleF(ip, New SizeF(sWidth - gapx, sHeight - gapy)) g.FillRectangle(rect, Color.LightGray) g.DrawRectangle(rect, Color.Black, 0.5F) rect.Inflate(-sMargin, -sMargin)
'' Draw the SVG: Dim svg = images(i).Item2 Dim s = svg.GetIntrinsicSize(SvgLengthUnits.Points) If s.Width > 0 AndAlso s.Height > 0 Then '' If image proportions are different from our target rectangle, '' we resize the rectangle centering the image in it: Dim qSrc = s.Width / s.Height Dim qTgt = rect.Width / rect.Height If qSrc < qTgt Then rect.Inflate(rect.Width * (qSrc / qTgt - 1) / 2, 0) ElseIf qSrc > qTgt Then rect.Inflate(0, rect.Height * (qTgt / qSrc - 1) / 2) End If End If '' Render the SVG: g.DrawSvg(svg, rect)
'' Print image file name as caption in the bottom slide margin: g.DrawString(Path.GetFileName(images(i).Item1), tf, New RectangleF(rect.X, rect.Bottom, rect.Width, sMargin), TextAlignment.Center, ParagraphAlignment.Near, False) ip.X += sWidth If ip.X + sWidth > doc.PageSize.Width AndAlso i < images.Count - 1 Then ip.X = margin ip.Y += sHeight If ip.Y + sHeight > doc.PageSize.Height Then g = doc.NewPage().Graphics ip.Y = margin End If End If Next
'' Done: doc.Save(stream) '' Dispose images after saving the PDF: images.ForEach(Sub(t_) t_.Item2.Dispose()) Return doc.Pages.Count End FunctionEnd Class