''
'' This code is part of Document Solutions for Imaging demos.
'' Copyright (c) MESCIUS inc. All rights reserved.
''
Imports System
Imports System.IO
Imports System.Drawing
Imports System.Collections.Generic
Imports System.Linq
Imports System.Numerics
Imports GrapeCity.Documents.Drawing
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Imaging
Imports GrapeCity.Documents.Svg
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing
'' 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 Function
End Class