SvgToGrayscale.vb
'''' This code is part of Document Solutions for Imaging demos.'' Copyright (c) MESCIUS inc. All rights reserved.''Imports SystemImports System.IOImports System.DrawingImports System.Collections.GenericImports System.LinqImports System.NumericsImports GrapeCity.Documents.DrawingImports GrapeCity.Documents.TextImports GrapeCity.Documents.ImagingImports 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.'''' The SVG clip art used in this sample is from freesvg.org.Public Class SvgToGrayscale Private Sub ToGrayscale(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/): Private Function PaintToGrayscale(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 As Integer = 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
'' Main entry point. Public Function GenerateImage(pixelSize As Size, dpi As Single, opaque As Boolean, Optional sampleParams As String() = Nothing) As GcBitmap Const rows As Integer = 4 Const cols As Integer = 4 Dim margin As Single = dpi / 2.0F Dim sMargin As Single = margin / 4.0F
'' Load images from the resources folder: Dim fnames As New List(Of String)(Directory.GetFiles(Path.Combine("Resources", "SvgClipArt"), "*", SearchOption.AllDirectories)) fnames.Shuffle()
Dim images As New List(Of Tuple(Of String, GcSvgDocument))() For Each fname In fnames.Take(rows * cols) Dim svg = GcSvgDocument.FromFile(fname) ToGrayscale(svg.RootSvg.Children) images.Add(Tuple.Create(Path.GetFileName(fname), svg)) Next
'' Font and format for captions: Dim font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "FreeSans.ttf")) Dim tf = New TextFormat() With {.Font = font, .FontSize = sMargin * 0.65F}
'' Set up a 4x4 layout grid: Dim gapx As Single = margin / 4.0F, gapy As Single = gapx Dim sWidth As Single = (pixelSize.Width - margin * 2 + gapx) / cols Dim sHeight As Single = (pixelSize.Height - margin * 2 + gapy) / rows If sWidth > sHeight Then gapx += sWidth - sHeight sWidth = sHeight Else gapy += sHeight - sWidth sHeight = sWidth End If Dim ip As New PointF(margin, margin)
'' Resulting bitmap: Dim bmp = New GcBitmap(pixelSize.Width, pixelSize.Height, opaque, dpi, dpi)
'' Render all images within the grid: Using g = bmp.CreateGraphics(Color.White) For i As Integer = 0 To images.Count() - 1 '' Draw border around image: Dim rect As 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.0F, 0) ElseIf qSrc > qTgt Then rect.Inflate(0, rect.Height * (qTgt / qSrc - 1) / 2.0F) 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 > pixelSize.Width) AndAlso (i < images.Count() - 1) Then ip.X = margin ip.Y += sHeight End If Next End Using
'' Dispose images after saving the result: images.ForEach(Sub(t_) t_.Item2.Dispose())
'' Done: Return bmp End FunctionEnd Class