Image markers appear smaller through GPU geometry than through a classic overlay. Both use the same PointStyle with ImageScale = 1.25. Our GPU path rasterizes that style with DrawSample, then displays the sprite through TrackPoint.
The comparison below places CPU left and GPU right.
using ThinkGeo.Core;
using ThinkGeo.Gpu;
using ThinkGeo.UI.Wpf;
// Run once after map is loaded. Use a small icon, e.g. 32×32.
var icon = new GeoImage(@"C:\Temp\marker.png");
var pointStyle = new PointStyle(icon) { ImageScale = 1.25 };
// CPU: draw the original style.
var layer = new InMemoryFeatureLayer();
layer.InternalFeatures.Add(new Feature(-40, 0));
layer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(pointStyle);
layer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel =
ApplyUntilZoomLevel.Level20;
var overlay = new LayerOverlay();
overlay.Layers.Add(layer);
map.Overlays.Add(overlay);
// GPU: rasterize the same style, preserving its pixel dimensions.
const int spriteSize = 128;
var sprite = new GeoImage(spriteSize, spriteSize);
var canvas = GeoCanvas.CreateDefaultGeoCanvas();
canvas.BeginDrawing(sprite,
new RectangleShape(-1, 1, 1, -1), GeographyUnit.Meter);
try { pointStyle.DrawSample(canvas); }
finally { canvas.EndDrawing(); }
var geometry = new InMemoryGeometrySource();
geometry.UpdatePoints(new[]
{
new TrackPoint(40, 0, 0, GeoColors.White, spriteSize, "marker")
});
var style = new MapStyle();
style.SetBackground(GeoColors.White);
style.Images.Add("marker", sprite, pixelRatio: 1);
style.AddGeometry(geometry);
map.MapUnit = GeographyUnit.Meter;
map.Basemap = new GpuBasemap(style);
map.CurrentExtent = new RectangleShape(-100, 60, 100, -60);
await map.RefreshAsync();
CPU Render size:

GPU Render size:
