How to Edit SVG Images Programmatically in C# .NET
This blog is the second in the series of articles related to programmatically creating and manipulating SVG images using the Document Solutions (previously known as GrapeCity Documents) .NET library for C# .NET.
In the last article, we discussed the need for programmatic creation of SVG images, the SVG drawing basics, the APIs available by Document Solutions, and a simple walk-through of creating an SVG image from scratch.
But not all situations require creating images from scratch. More often than not, existing images can be transformed or customized to fit a particular business need. For instance:
- change color or gradient to match the current theme or style of the document/website
- flip, rotate or transpose
- add or modify figures or shapes
- scale the same image to fit multiple device screens and orientation
In this blog, we'll see how we can manipulate an SVG image programmatically using C# .NET.
Use-Case
A company recently decided to change its logo to look more modern and innovative as part of the rebranding strategy. The designers suggested a new logo that is not much different from the current design. The new design can be achieved using a few tweaks and edits to the existing logo. You want to use this logo on your website, application, and mobile devices and need multiple copies for different sizes.
Creating these logos from scratch is not a cost-effective solution. So, the designer needs a way to programmatically manipulate the SVG image and generate multiple copies for different sizes with less effort.
For this blog, we will customize the GrapeCity Logo for the following and as shown below:
- Color
- Re-position the logomark closer to the logotype and add a thick border to it
- Rotate the alphabet "e" and add a rectangle around it
Current logo
New logo
In addition to this, we will generate the icon for the following layouts
- Horizontal layout with dimensions 250 x 75 px
- Vertical (Square) layout with dimensions 160 x 160 px
Let's get started and look at the detailed steps to achieve the desired requirements using the DsImaging Library for C# .NET.
Step 1 - Load an SVG document
The first step toward editing an image is loading it into the application. To load an SVG image using the DsImaging Libraries for C#.NET, import the namespace GrapeCity.Documents.Svg and use the FromFile method of the GcSvgDocuments class as in the code below:
using GrapeCity.Documents.Svg;
...
...
var svg = GcSvgDocument.FromFile(@"GrapeCityLogo.svg");
Step 2 - Modify the SVG content
Once you have loaded the SVG image to the SvgDocument, you can easily manipulate its DOM using the various classes, methods, and properties from the GcSvgDocuments class. Modifying the element for the color, position, or other settings, you must find/get the element using the GetElementById or GetElementByClass methods. When elements do not have an Id or class defined, you can traverse the nodes in the SVG's XML, looking for the node you want to modify.
Let us see how we use these data structures to achieve the new logo's requirements described above.
The color of an SVG element is changed using the Fill properties associated with the SVG elements. In the original logo file, the SVG elements have defined classes. Thus, we get the elements using the GetElementByClass method and change the color of the elements as depicted in the code below:
for (int i = 0; i <= 2; i++)
{
var el = svg.GetElementsByClass("st"+ i);
foreach (var e in el)
{
e.Fill = new SvgPaint(Color.FromArgb(56, 93, 171));
}
}
Change icon position and add a border
With Document Solutions, SVG elements are manipulated for the position, rotation, transpose, etc., using the SvgTransform class. This class is inherited in several transformation classes such as SvgTranslateTransform, SvgRotateTransform, SvgMatrixTransform, etc.
We changed the position of the logo's image using the Translate transformation and added the border using the element's Stroke property as depicted in the code below:
var elementLogo = svg.GetElementByID("logo");
elementLogo.Transform = new List<SvgTransform>()
{
new SvgTranslateTransform()
{
TranslateX = new SvgLength(14),
TranslateY = new SvgLength(2),
}
};
elementLogo.Fill = new SvgPaint(Color.FromArgb(102, 153, 204));
elementLogo.Stroke = new SvgPaint(Color.FromArgb(56, 93, 171));
Rotate the alphabet "e" and a rectangle around it
Similar to the logo image, the element representing the alphabet "e" in the logo is rotated using the SvgRotateTransform class as shown below:
var elements = svg.GetElementsByClass("st1");
var elementE = elements[5];
if (elementE != null && elementE is SvgPathElement)
{
elementE.FillOpacity = 0.5f;
elementE.Transform = new List<SvgTransform>()
{
new SvgRotateTransform()
{
Angle = new SvgAngle(-30)
}
};
}
Drawing the rectangle around the alphabet "e" requires searching the parent node of the element "e" and adding a SvgRectElement to it, as shown in the code below:
var parent_of_elementE = elementE.Parent;
if (parent_of_elementE is SvgGroupElement g)
{
var rect = new SvgRectElement()
{
X = new SvgLength(109.6f, SvgLengthUnits.Pixels),
Y = new SvgLength(17.2f, SvgLengthUnits.Pixels),
Width = new SvgLength(16f, SvgLengthUnits.Pixels),
Height = new SvgLength(17.2f, SvgLengthUnits.Pixels),
StrokeWidth = new SvgLength(0.5f, SvgLengthUnits.Pixels),
Stroke = new SvgPaint(Color.FromArgb(56, 93, 171)),
Fill = new SvgPaint(SvgColor.Transparent)
};
g.Children.Add(rect);
}
Step 3 - Save the Image
When all the changes are applied, we save the image using the Save method from the GcSvgDocuments class as below:
svg.Save("GrapeCityLogo_New.svg");
Generate Images for different layouts
When working with images for a website or mobile application, you need the same image for several sizes and layouts. The same image may be required as a favicon, horizontal logo, square or vertical logo, logos for portrait or landscape orientations, and many such scenarios.
One can generate such SVG images quickly with the Document Solutions libraries by configuring the SvgViewBox and/or Viewport.
For this blog, we generate a horizontal layout image with dimensions 250 x 75 px, as shown below, using the following code:
SvgViewBox view = new SvgViewBox();
svg.RootSvg.Width = new SvgLength(250, SvgLengthUnits.Pixels);
svg.RootSvg.Height = new SvgLength(75, SvgLengthUnits.Pixels);
view.MinX = 15;
view.MinY = 5;
view.Width = 180;
view.Height = 40;
svg.RootSvg.ViewBox = view;
svg.Save("GrapeCityLogo_Horizontal.svg");
And generate a vertical layout image with dimension 160 x 160 px as shown below, using the following code:
foreach (var node in svg.RootSvg.Children)
{
if(node is SvgGroupElement gr)
{
gr.Children.RemoveAt(1);
}
}
svg.RootSvg.Width = new SvgLength(160, SvgLengthUnits.Pixels);
svg.RootSvg.Height = new SvgLength(160, SvgLengthUnits.Pixels);
view.MinX = 20.5f;
view.MinY = 20;
view.Width = 36;
view.Height = 17;
svg.RootSvg.ViewBox = view;
svg.Save("GrapeCityLogo_Vertical.svg");
Here, we remove all the other elements from SVG DOM, keeping only the logomark to reduce the file size. You can choose to keep the elements and scale up the logomark to fit in the vertical logo dimension by configuring the view box and view port's settings.
For further understanding, and to streamline your learning process be sure to download the complete sample!