public byte[] GenerateTile(int x, int y, int zoom) { byte[] tileBytes = null; var font = SixLabors.Fonts.SystemFonts.CreateFont("Arial", 12); var corner = TileUtils.TileXYToGlobalPixel(x, y, TileSize); var latLong = TileUtils.GlobalPixelToPosition(new Point <double>(corner.X, corner.Y), zoom, TileSize); var latLongOffset = TileUtils.GlobalPixelToPosition(new Point <double>(corner.X + TileSize, corner.Y + TileSize), zoom, TileSize); var graticules = graticuleService.DrawCore(latLong, latLongOffset); using (Image <Rgba32> outputImage = new Image <Rgba32>(this.TileSize, this.TileSize)) { string tileText = $"{x}/{y}/{zoom}{Environment.NewLine}"; outputImage.Mutate(o => o .Fill(Rgba32.White) .DrawText(tileText, font, Rgba32.Black, new PointF(10, 10)) ); outputImage.Mutate(o => DrawGraticules(o, graticules, corner, zoom)); // Test if (DebugPoint != null) { var testPixel = TileUtils.PositionToGlobalPixel(new LatLong(DebugPoint.Latitude, DebugPoint.Longitude), zoom, TileSize); var testTile = TileUtils.GlobalPixelToTileXY(testPixel.X, testPixel.Y, TileSize); // Draw test pixel if (testTile.X == x && testTile.Y == y) { var basex = TileUtils.TileXYToGlobalPixel(x, y, TileSize); var ptLoc = new PointF((float)(testPixel.X - basex.X), (float)(testPixel.Y - basex.Y)); outputImage.Mutate(o => o.DrawLines(Rgba32.Blue, 1f, new PointF[] { new PointF(ptLoc.X - 10, ptLoc.Y - 10), new PointF(ptLoc.X + 10, ptLoc.Y + 10) }) .DrawLines(Rgba32.Blue, 1f, new PointF[] { new PointF(ptLoc.X - 10, ptLoc.Y + 10), new PointF(ptLoc.X + 10, ptLoc.Y - 10) })); } } using (MemoryStream ms = new MemoryStream()) { outputImage.SaveAsPng(ms); tileBytes = ms.ToArray(); } } return(tileBytes); }