GeoConvert 0.1.3

There is a newer version of this package available.
See the version list below for details.
dotnet add package GeoConvert --version 0.1.3
                    
NuGet\Install-Package GeoConvert -Version 0.1.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="GeoConvert" Version="0.1.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="GeoConvert" Version="0.1.3" />
                    
Directory.Packages.props
<PackageReference Include="GeoConvert" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add GeoConvert --version 0.1.3
                    
#r "nuget: GeoConvert, 0.1.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package GeoConvert@0.1.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=GeoConvert&version=0.1.3
                    
Install as a Cake Addin
#tool nuget:?package=GeoConvert&version=0.1.3
                    
Install as a Cake Tool

<img src="/src/icon.png" height="30px"> GeoConvert

Build status NuGet Status NuGet Status

Convert maps between geospatial formats, with no third-party dependencies — only the .NET base class libraries (System.Text.Json, System.Xml, System.IO.Compression). It can also render a bounding box to a PNG image. Ships as a library and a geoconvert command line tool.

Supported formats

All vector formats can be both read and written; PNG is a write-only raster export.

Format Extension(s) Kind
GeoJSON .geojson, .json JSON
TopoJSON .topojson JSON (topology encoded)
Shapefile .shp (+ .shx, .dbf, .prj) Binary
FlatGeobuf .fgb Binary (FlatBuffers)
KML .kml XML
KMZ .kmz Zipped KML
GPX .gpx XML
WKT .wkt Text
WKB .wkb Binary
CSV .csv Text (WKT or lon/lat columns)
PNG .png Raster image (write-only)

All coordinates are treated as WGS84 (EPSG:4326) longitude/latitude.

Library

Convert a file to another format (both formats inferred from their extensions):

<a id='snippet-Convert'></a>

// Formats are inferred from the file extensions.
GeoConverter.Convert("cities.geojson", "cities.kml");
GeoConverter.Convert("roads.shp", "roads.fgb");

<sup><a href='/src/Tests/Snippets.cs#L6-L10' title='Snippet source file'>snippet source</a> | <a href='#snippet-Convert' title='Start of snippet'>anchor</a></sup>

Read into the common feature model, then write a different format:

<a id='snippet-ReadModifyWrite'></a>

// Read any supported format into the common feature model.
var collection = GeoConverter.Read("roads.shp");

foreach (var feature in collection)
{
    if (feature.Properties.TryGetValue("name", out var name))
    {
        Console.WriteLine(name);
    }
}

// Write it back out as a different format.
GeoConverter.Write(collection, "roads.fgb");

<sup><a href='/src/Tests/Snippets.cs#L15-L29' title='Snippet source file'>snippet source</a> | <a href='#snippet-ReadModifyWrite' title='Start of snippet'>anchor</a></sup>

Build a collection in memory and serialize it:

<a id='snippet-BuildModel'></a>

var collection = new FeatureCollection
{
    new Feature(
        new Point(new(151.21, -33.87)),
        new Dictionary<string, object?> { ["name"] = "Sydney" }),
};

var geoJson = GeoJson.WriteString(collection);

<sup><a href='/src/Tests/Snippets.cs#L34-L43' title='Snippet source file'>snippet source</a> | <a href='#snippet-BuildModel' title='Start of snippet'>anchor</a></sup>

Raster export (PNG)

Render a FeatureCollection to a PNG, clipped to a bounding box, with a software rasterizer and a hand-written PNG encoder (no third-party dependencies):

<a id='snippet-RenderToPng'></a>

var collection = GeoConverter.Read("countries.geojson");

// Render a specific bounding box (min lon, min lat, max lon, max lat) to a PNG.
var options = new RenderOptions
{
    Bounds = new Envelope(-10, 35, 30, 60),
    Width = 1200,
    Height = 900,
};

MapRenderer.RenderPng(collection, "europe.png", options);

<sup><a href='/src/Tests/Snippets.cs#L49-L61' title='Snippet source file'>snippet source</a> | <a href='#snippet-RenderToPng' title='Start of snippet'>anchor</a></sup>

RenderOptions controls the extent (Bounds), pixel Width/Height (height is derived from the aspect ratio when left at 0), Padding, and the Background/Stroke/Fill colors. From the command line, output a .png and pass --bbox and --size:

geoconvert world.geojson europe.png --bbox -10,35,30,60 --size 1200x900

Exampl generated png

All Australian suburbs

<img src="/src/Tests/PngTests.Render_RealMap.verified.png" height="1100px">

Command line

Installed as a .NET tool named geoconvert:

geoconvert <input> <output> [--from <format>] [--to <format>]

Formats are detected from the file extensions; --from/--to override that. Examples:

geoconvert cities.geojson cities.kml
geoconvert roads.shp roads.fgb
geoconvert data.csv data.geojson --from csv

Run geoconvert --list to see the supported format names, or geoconvert --help for usage.

Model

Everything reads into and writes out of a FeatureCollection:

  • Feature — a Geometry plus a string-keyed Properties dictionary and an optional Id.
  • GeometryPoint, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon or GeometryCollection, built from Position values (X = longitude, Y = latitude, optional Z and M).

Benchmarks

BenchmarkDotNet benchmarks live in src/Benchmarks and must run in Release:

dotnet run -c Release --project src/Benchmarks -- --filter "*"

ConvertBenchmarks measures reading and writing a 500-polygon collection through each stream format; RenderBenchmarks measures PNG rasterization. Add --job Dry for a quick smoke run.

Notes and limitations

  • Shapefile holds a single geometry category per file; writing a collection that mixes points, lines and polygons throws. This is mandated by the format, not a GeoConvert choice — the .shp header declares one shape type for the whole file, so a mixed collection has no valid encoding and the consumer must split it into one file per geometry type first. Output is 2D: the format does define Z and M variants, but GeoConvert drops those ordinates rather than emit them. A WGS84 .prj is emitted.
  • FlatGeobuf is written without the optional packed R-tree spatial index (index_node_size = 0) and is 2D. The index is a query accelerator, not data: it lets a reader fetch features in a bounding box without scanning the whole file, but carries no information the feature records don't. So GeoConvert reads an indexed file by computing the index size and skipping past it — full-file conversion needs every feature anyway — and writes none, leaving output that is still valid FlatGeobuf (GDAL, QGIS and flatgeobuf.org read it fine) for the consumer to re-index on import if it wants spatial queries. Emitting one would mean hand-rolling a Hilbert R-tree to honour the no-dependency rule, which is real complexity for a benefit a conversion tool rarely needs.
  • GPX has no native area type: polygons are written as a track with one segment per ring, multi polygons flatten every ring into a single track, and geometry collections write each member geometry in turn. Reading a track with several segments yields a multi line string, so polygons do not survive a round trip as polygons.
  • WKT and WKB carry geometry only — feature attributes are dropped on write.
  • PNG is a write-only raster export; reading a .png throws. It needs an extent — when no Bounds is given, the full extent of the data is used.
  • Property values are scalars (string, long, double, bool); nested JSON is flattened.

Icon

Pattern designed by Kim Sun Young from The Noun Project.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on GeoConvert:

Package Downloads
MapBundle

Core runtime for MapBundle. Loads bundled map data (borders, cities, waterways) that ships as FlatGeobuf in the MapBundle.World and MapBundle.[Region] packages. Data is derived from OpenStreetMap (© OpenStreetMap contributors, ODbL).

GeoConvert.Skia

Optional SkiaSharp-backed PNG render backend for GeoConvert. Rasterizes the same projection, styling and labelling pipeline as the built-in renderer through Skia. Unlike GeoConvert itself, this package takes a third-party dependency (SkiaSharp).

GeoConvert.ImageSharp

Optional SixLabors.ImageSharp-backed PNG render backend for GeoConvert. Rasterizes the same projection, styling and labelling pipeline as the built-in renderer through ImageSharp. Unlike GeoConvert itself, this package takes a third-party dependency (SixLabors.ImageSharp, under the Six Labors Split License).

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.1 124 6/8/2026
1.1.0 115 6/8/2026
1.0.1 3,312 6/6/2026
1.0.0 118 6/6/2026
0.12.0 122 6/5/2026
0.11.0 6,496 6/3/2026
0.10.1 3,306 6/3/2026
0.10.0 3,289 6/2/2026
0.9.1 3,311 6/2/2026
0.9.0 3,321 6/2/2026
0.8.2 3,297 6/2/2026
0.8.1 98 6/2/2026
0.8.0 94 6/1/2026
0.6.0 109 5/30/2026
0.5.1 115 5/28/2026
0.5.0 105 5/28/2026
0.4.0 103 5/28/2026
0.3.0 97 5/27/2026
0.2.0 90 5/27/2026
0.1.3 99 5/25/2026
Loading failed