Add the RecursiveAI.OneImage.Svg package, register SvgFormat in the load options, load the SVG and save it as .png. Put a Resize right after the load and the SVG is drawn at that size, not drawn small and scaled up. The program below converts Wikimedia’s public-domain flag of the United States.
dotnet new console -o SvgToPng && cd SvgToPng dotnet add package RecursiveAI.OneImage.Svg --version 1.10.4 curl -L -o flag.svg \ https://commons.wikimedia.org/wiki/Special:FilePath/Flag_of_the_United_States.svg
OneImage needs the .NET 10 SDK. Put this in Program.cs and run dotnet run:
using OneImage; using OneImage.Svg; // SVG is an add-on format: register it for the load. var options = new LoadOptions { Configuration = new ImageConfiguration().Add(SvgFormat.Instance), }; Image svg = Image.Load("flag.svg", options); Console.WriteLine($"natural size: {svg.Width}x{svg.Height}"); svg.Save("flag.png"); // at its natural size svg.Resize(width: 2400).Save("flag-2400.png"); // drawn at 2400 px wide ImageInfo big = Image.Identify("flag-2400.png"); Console.WriteLine($"flag-2400.png: {big.Width}x{big.Height}");
natural size: 1235x650 flag-2400.png: 2400x1263
The natural size comes from the root element’s width and height (here 1235 and 650), or from the viewBox when they are missing. Areas the SVG doesn’t paint are transparent; for JPEG, add .Flatten(new Rgba32(255, 255, 255, 255)) before saving. .webp, .jpg and .ico work the same way, so one SVG makes every app icon size.
An SVG string, with text in your own font
SVG is a handy way to generate badges and charts. Load the markup’s bytes, and give the renderer the fonts you ship, so the text looks the same on every machine, including containers with no fonts installed:
fonts=https://github.com/notofonts/notofonts.github.io/raw/main/fonts curl -L -o NotoSans-Regular.ttf $fonts/NotoSans/hinted/ttf/NotoSans-Regular.ttf
using System.Text; using OneImage; using OneImage.Svg; var fonts = new SvgFontOptions { UseSystemFonts = false }; fonts.AddFont("NotoSans-Regular.ttf"); var options = new LoadOptions { Configuration = new ImageConfiguration() .Add(new SvgFormat(SvgLimits.Default, ["en"], fonts)), }; string svg = """ <svg xmlns="http://www.w3.org/2000/svg" width="200" height="40"> <rect width="200" height="40" rx="6" fill="#2f6b4f"/> <text x="100" y="26" font-family="Noto Sans" font-size="16" fill="#fff" text-anchor="middle">build passing</text> </svg> """; Image badge = Image.Load(Encoding.UTF8.GetBytes(svg), options).Resize(width: 600); badge.Save("badge.png"); Console.WriteLine($"badge.png: {badge.Width}x{badge.Height}");
badge.png: 600x120AddFont takes TrueType, OpenType, collections, WOFF and WOFF2. With UseSystemFonts left on, installed fonts are used too.
Limits
- Static SVG only. SMIL animation is ignored (you get the first frame), and scripts and
foreignObjectare skipped. The SVG docs list what renders: shapes, gradients, patterns, clip paths, masks, filters, CSS and embedded images. - Nothing external is fetched. Links to other files or URLs are treated as missing, and DTDs are rejected, so user uploads are safe to convert; size limits apply as the file is read.
- No fonts are bundled. In a container without fonts, text needs
AddFont.
For PDF pages, see Convert a PDF to an image; for smaller output, Convert to WebP.