---
title: "Convert SVG to PNG in C#"
url: https://recursiveai.org/oneimage/articles/svg-to-png-csharp/
description: "Convert SVG to PNG, JPG, WebP or ICO in C# with pure .NET code: render at any size, read the natural size, ship your own fonts and handle untrusted SVG safely."
date: 2026-10-23
author: OneImage team
---

# Convert SVG to PNG in C#

Convert SVG to PNG, JPG, WebP or ICO in C# with pure .NET code: render at any size, read the natural size, ship your own fonts and handle untrusted SVG safely.

October 23, 2026 · OneImage team

To convert an SVG to PNG in C#, add the `RecursiveAI.OneImage.Svg` package, register its SVG format, load the file and save it with a `.png` extension. The SVG is rendered at the size you ask for, so a 24-pixel icon becomes a sharp 512-pixel PNG instead of an upscaled blur. It is pure C#, with no Skia, Cairo or System.Drawing underneath, so the same code runs on Windows, Linux, macOS and in containers. Below: rendering at a given width, natural size, icon sets and favicons, fonts, JPG output, SVG from a string, and untrusted files. Every sample was run against OneImage 1.6.0 and OneImage.Svg 1.6.0 on .NET 10.

*Terminal · NuGet*

```
dotnet add package RecursiveAI.OneImage.Svg
```

The package brings in OneImage and OneImage.Text, which draws SVG text, and targets .NET 10. All three are licensed MIT OR Apache-2.0. The examples use Wikipedia’s public-domain [flag of the United States](https://en.wikipedia.org/wiki/File:Flag_of_the_United_States.svg) SVG, which declares `width="1235" height="650"`, plus a small icon and a badge of our own.

## Convert an SVG file to PNG

*Program.cs · .NET 10*

```
using OneImage;
using OneImage.Svg;
 
// SVG support is a separate package: register its format for the load call.
var options = new LoadOptions
{
    Configuration = new ImageConfiguration().Add(SvgFormat.Instance)
};
 
Image.Load("flag-us.svg", options).Save("flag-us.png");
```

This writes a 1235×650 PNG with a transparent background wherever the SVG paints nothing. As with PDF, the SVG format isn’t in OneImage’s default configuration because it lives in a separate package, so you add it to the configuration you pass to `Load`. Save as `.webp`, `.jpg`, `.gif`, `.tif` or `.bmp` to get those formats instead.

## Render the SVG at a specific size

*Program.cs · .NET 10*

```
using OneImage;
using OneImage.Svg;
 
var options = new LoadOptions
{
    Configuration = new ImageConfiguration().Add(SvgFormat.Instance)
};
 
// Drawn at 2400 px wide, not rendered at 1235 px and scaled up.
Image.Load("flag-us.svg", options).Resize(width: 2400).Save("flag-us-2400.png");
```

The result is 2400×1263: the height follows the aspect ratio and rounds to the nearest pixel. When a resize sits directly on a loaded SVG, OneImage passes the target size to the renderer, so curves and edges are drawn at 2400 px rather than enlarged from a 1235 px raster. Give a height instead, or both with a `fit:`, exactly as for photos. Our guide to [resizing images in C#](https://recursiveai.org/oneimage/articles/resize-image-csharp/) covers the fit modes.

## Get the natural size of an SVG

*Program.cs · .NET 10*

```
using OneImage;
using OneImage.Svg;
 
var options = new LoadOptions
{
    Configuration = new ImageConfiguration().Add(SvgFormat.Instance)
};
 
ImageInfo info = Image.Identify("flag-us.svg", options);
Console.WriteLine($"{info.Width}x{info.Height}");
```

It prints `1235x650`. `Identify` reads only the root element’s start tag. Per the [OneImage.Svg documentation](https://recursiveai.org/oneimage/docs/svg/#natural-size), the natural size in CSS pixels (96 per inch) works like this:

- It is the `width` and `height` when both are absolute lengths (`px`, `pt`, `mm`, `in` and so on).
- A missing side is derived from the other through the `viewBox` aspect ratio, and with neither the `viewBox` size is used.
- When nothing fixes the size, it is the extent of the drawn content.

An icon with only `viewBox="0 0 24 24"` is 24×24.

## Make app icons and a favicon from one SVG

*Program.cs · .NET 10*

```
using OneImage;
using OneImage.Svg;
 
var options = new LoadOptions
{
    Configuration = new ImageConfiguration().Add(SvgFormat.Instance)
};
Image icon = Image.Load("icon.svg", options);
 
foreach (int size in new[] { 32, 180, 192, 512 })
{
    icon.Resize(width: size, height: size).Save($"icon-{size}.png");
}
 
icon.Resize(width: 32, height: 32).Save("favicon.ico");
```

From our 24×24 icon this wrote 32, 180, 192 and 512 px square PNGs, each drawn at its own size, and a 32×32 `favicon.ico`. The loaded `Image` is immutable, so one load feeds every size.

## Text and fonts in SVG

SVG text is drawn with real fonts: `font-family` lists, weights, styles, kerning, ligatures, `textPath`, and right-to-left and complex scripts through OneImage.Text. By default the renderer looks up the fonts installed on the machine. For output that is the same on every machine, including containers that have no fonts, add the font files you ship and turn off the system lookup:

*Program.cs · .NET 10*

```
using OneImage;
using OneImage.Svg;
 
// Draw text with a font you ship, the same on every machine.
var fonts = new SvgFontOptions { UseSystemFonts = false };
fonts.AddFont("NotoSans-Regular.ttf");
 
var svg = new SvgFormat(SvgLimits.Default, ["en"], fonts);
var options = new LoadOptions { Configuration = new ImageConfiguration().Add(svg) };
 
Image.Load("badge.svg", options).Resize(width: 640).Save("badge.png");
```

Our badge, a gradient rectangle with a drop-shadow filter and the text “build passing” in Noto Sans, rendered to a 640×240 PNG. We published the same program and ran it in the stock `mcr.microsoft.com/dotnet/runtime:10.0` image, which has no fonts installed, and got a PNG identical to the one made on our workstation. `AddFont` takes TrueType, OpenType, collections, WOFF and WOFF2, from a file, a stream or bytes. `FallbackFamilies` and `SetGenericFamily` control what `sans-serif` and missing characters resolve to.

## Convert SVG to JPG

*Program.cs · .NET 10*

```
using OneImage;
using OneImage.Svg;
 
var options = new LoadOptions
{
    Configuration = new ImageConfiguration().Add(SvgFormat.Instance)
};
 
// SVG renders on a transparent background; JPEG has no alpha, so put it on white first.
Image.Load("icon.svg", options)
     .Resize(width: 600)
     .Flatten(new Rgba32(255, 255, 255, 255))
     .Save("icon.jpg");
```

Without `Flatten`, transparent areas would be written with whatever color values they store. With it, the 600×600 JPEG has the icon on white.

## Render an SVG string from memory

SVG is a convenient way to generate charts, badges and placeholders in code. Build the markup as a string and load the bytes, with no temporary file:

*Program.cs · .NET 10*

```
using System.Text;
using OneImage;
using OneImage.Svg;
 
var options = new LoadOptions
{
    Configuration = new ImageConfiguration().Add(SvgFormat.Instance)
};
 
int percent = 72;
string svg = $"""
    <svg xmlns="http://www.w3.org/2000/svg" width="200" height="20">
      <rect width="200" height="20" rx="4" fill="#e5e7eb"/>
      <rect width="{percent * 2}" height="20" rx="4" fill="#16a34a"/>
    </svg>
    """;
 
byte[] bytes = Encoding.UTF8.GetBytes(svg);
Image.Load(bytes, options).Resize(width: 400).Save("progress.png");
```

This writes a 400×40 progress bar at 72%. `Image.Load` also takes a `Stream`, for SVG coming from a request or blob storage.

## What SVG features render

The [OneImage.Svg documentation](https://recursiveai.org/oneimage/docs/svg/) lists the full scope. It covers static SVG 1.1 and the SVG 2 and CSS features documents use in practice:

- **Shapes and structure:** paths, basic shapes, groups, `use` and `symbol`, nested `svg`, `switch` and markers.
- **Painting:** strokes with dashes, caps and joins, linear and radial gradients, patterns, opacity and blend modes.
- **Effects:** clip paths and masks, and the full SVG 1.1 filter primitive set plus `feDropShadow` and the CSS filter functions.
- **CSS:** `<style>` sheets with the cascade and common selectors.
- **Images:** embedded `data:` images in PNG, JPEG, GIF, WebP and other raster formats, and nested SVG.
- **Compressed files:** gzip-compressed `.svgz` files are detected and read.

## Converting untrusted SVG files safely

SVG is XML that can point at other resources, so converting user uploads needs care. OneImage.Svg is built for that:

- **Nothing external is fetched.** References to files and URLs (`href` other than `#id` and `data:`, `@import`, `url()` in CSS, `@font-face` sources) are treated as missing, which SVG already defines. We checked this with a document that pointed an `<image>` at a local web server and another at a `file://` path. The render made no request, and only the document’s own rectangle was drawn.
- **No DTDs or entities.** Its own XML parser rejects any `<!DOCTYPE` and expands only the predefined entities, so a document can’t grow while it is read.
- **Limits checked as it reads.** `SvgLimits` caps document size (32 MiB, also after gzip expansion), element count (500,000), nesting depth, `use` fan-out, CSS size, filter area, embedded image bytes and text length. A file over a limit fails with an `ImageException` before the memory is allocated, so you can return a 400.

## How fast is it?

The OneImage repository publishes SVG benchmarks against Svg.Skia 5.2.3. For a 1000×800 illustration of about 3,000 shapes drawn at 1024 px wide, load plus render took 25.2 ms with OneImage and 78.7 ms with Svg.Skia. For a 24×24 icon drawn at 256 px, it took 141 µs against 363 µs. Those are BenchmarkDotNet means (short job) on an AMD Ryzen 9 7950X3D with .NET 10.0.13, on a shared machine that was under load during the run. The [status section of the SVG documentation](https://recursiveai.org/oneimage/docs/svg/#status) has the full table, including allocations and render-only times.

## Other ways to convert SVG to PNG in C#

- **[Svg](https://www.nuget.org/packages/Svg/3.4.8)** 3.4.8 (SVG.NET, MS-PL) depends on System.Drawing.Common for its `net8.0` and `net9.0` targets, according to its NuGet listing. Microsoft supports System.Drawing.Common only on Windows since .NET 6; see our page on [the “not supported on this platform” error](https://recursiveai.org/oneimage/articles/system-drawing-common-not-supported/).
- **[Svg.Skia](https://www.nuget.org/packages/Svg.Skia/5.2.3)** 5.2.3 (MIT) renders through SkiaSharp. Its NuGet listing shows dependencies on SkiaSharp 4.148.0 or later and on HarfBuzzSharp with its native assets. On Linux, SkiaSharp’s native library has to be added separately; see [SkiaSharp on Linux and Docker](https://recursiveai.org/oneimage/articles/skiasharp-linux-docker/). It targets more frameworks than OneImage, including .NET Framework 4.6.1, netstandard2.0 and .NET 6 and 8. If the rest of your code uses SkiaSharp too, our [SkiaSharp migration guide](https://recursiveai.org/oneimage/articles/migrate-from-skiasharp/) shows the OneImage equivalents.
- **[SharpVectors](https://www.nuget.org/packages/SharpVectors/1.8.6)** 1.8.6 (BSD-3-Clause) targets .NET Framework and the Windows-only `net*-windows` frameworks, per its NuGet listing. It suits WPF desktop apps.

For PDF pages, the same approach works with OneImage.Pdf; see [converting PDF to images in C#](https://recursiveai.org/oneimage/articles/pdf-to-image-csharp/). For smaller web output, save the rendered SVG as WebP; our guide to [converting images to WebP](https://recursiveai.org/oneimage/articles/convert-image-to-webp-csharp/) covers quality and lossless settings.
