ThinkGeo.com    |     Documentation    |     Premium Support

14.5 and DrawingQuality

Hi,

It seems that handling of DrawingQuality has been updated to 14.5 to be overlay specific. With previous versions we have had combinations like:

Overlay - HighSpeed
InMemoryFeatureLayer - HighSpeed
InMemoryFeatureLayer - Default

Is it now so that we need to split layers to different overlays if layers need to have different quality ?

Also I noticed that with new 14.5 HighSpeed quality is not the same compared to previous version. Is this correct observation ? Here is an example where on the left 14.4.5 both overlay/layer are HighSpeed and on the right 14.5 with overlay as HighSpeed.

image

It can be seen that text and outline quality is worse in 14.5.

Br, Simo

Hi Simo,

You’re right.

  1. Skia (the rendering engine used by ThinkGeo) has moved away from the concept of High/Medium/Low quality levels, so we updated our API to align with that direction. The main reason is that a single “HighQuality” setting cannot produce optimal results across different types of maps.

  2. Instead, we now provide more fine-grained control over rendering quality:

  • For Vector rendering (your case): you can use TileOverlay.RenderingOptions to control anti-aliasing for Image, Vector, and Text individually.
  • For Map Tiles you can adjust the resampling algorithm.

By default, DrawingQuality.Standard enables anti-aliasing for Vector and Text, but disables it for Image. When set to HighSpeed , anti-aliasing is also disabled for Text and Vector, which reduces label quality—that’s the trade-off for better performance. In that sense, the newer behavior is more accurate and predictable. We’d recommend you to just leave it to DrawingQuality.Standard which should be good for most of the cases.

If you’re interested, you can find more details here:
https://docs.thinkgeo.com/products/thinkgeo-core/thinkgeo-raster-sampling-matrix/

Thanks,
Ben

Hi,

Not sure if it is related to this quality but were are experiencing weird issue when integrating to 14.5 (earlier version 14.4.5). We have an LayerOverlay with InMemoryFeatureLayer.

In that InMemoryLayer we use PointStyle(GeoImage image) as DefaultPointStyle then we have just one point on that layer. Earlier this has been working without any issues but now with with 14.5 in some environments only one fourth of that GeoImage is drawn to map (on others environments image is drawn correctly).

Do you know what could cause this kind of inconsistent GeoImage drawing with 14.5 ?

Br, Simo

Hi Simo,

It has been fixed in 14.5.0-beta021.

You didn’t mention a high-DPI environment, but based on our investigation, we suspect this issue is related to high-DPI rendering (more specifically, the canvas ScaleFactor). In some cases, when an image marker is drawn near a tile boundary, the drawing query margin was not scaled correctly, so part of the symbol could be clipped or only partially rendered.

We also believe this issue likely existed in 14.4.* as well, but it was harder to reproduce there because it only appears when several conditions line up, such as display scaling, symbol size, and the feature position relative to the tile boundary.

Please pull the latest build and give it a try. You can also set the overlay’s tile type to SingleTile, as a workaround, if that works well for your project.

Thanks,
Ben

Hi,

We already have SingleTile Overlay to fix that issue near tile boundary. I was able to narrow this issue down to RotationAngle. When ever PointStyle.RotationAngle != 0 this issue happens.

It can be easily re-produced with this sample code:

    private async void MapView_Loaded(object sender, RoutedEventArgs e)
    {
        MapView = sender as MapView;
        MapView.MapUnit = GeographyUnit.Meter;

        var layer = new InMemoryFeatureLayer();
        layer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = new PointStyle(new GeoImage(@"./icon_gps_point.gif")) { RotationAngle = 90 };
        layer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
        layer.InternalFeatures.Add(new Feature(new PointShape(MapView.CenterPoint.X, MapView.CenterPoint.Y)));

        var overlay = new LayerOverlay() { TileType = TileType.SingleTile };
        overlay.Layers.Add(layer);
        MapView.Overlays.Add(overlay);
        await MapView.RefreshAsync();
    }

With 14.4.5 image is drawn correctly but with 14.5 only one fourth of image is drawn. Issue seems to happen when drawing without scaling since using scaling on display (display scaling != 100% needs to be set before application is started. Changing it after application start does not cause this issue) or in PointStyle fixes the issue.

Please check if there is any workaround / possibility for hotfix to this issue.

Br, Simo

Hi Simo,

Thanks for the sample. We’ve verified this is a regression introduced in v14.5 by an internal rendering optimization. It has been fixed in latest beta 14.5.0-beta022. We are currently planning to release v15.0.0 in May, mainly alongside the ThinkGeo.GisServer release. This fix will be included in that release.

You can work it around by forcing the image to go through the scaled drawing path by setting ImageScale to a value other than 1, as following:

  new PointStyle(new GeoImage(@"./icon_gps_point.gif"))
  {
      RotationAngle = 90,
      ImageScale = 1.01
  };

Thanks,
Ben

Hi,

Does that scaled drawing have any negative impact to performance e.g. is it slower ?

We are updating that layer frequently so we cannot use that if it has some negative impact.

Br, Simo

We did a quick local test and did not see any noticeable performance penalty. In our test with a rotated 80x80 image marker drawn 400 times in ThinkGeo.Core 14.5.1, the timings were nearly the same:

  • ScaleFactor = 1: 0.245 ms/frame vs 0.248 ms/frame
  • ScaleFactor = 2: 1.335 ms/frame vs 1.235 ms/frame
1 Like

Hi,

Returning to this topic related to drawing quality.

We are just upgrading from 14.4.5 to 14.5.4 and we noticed that when using GeoTiff images on map with new ThinkGeo drawing the is noticeable slower.

We are using LayerOverlay (TileType.MultiTile and DrawingQuality.HighSpeed) with GeoTiffRasterLayer. With larger tif file (~14MB on my tests) drawing the tiles is noticeable slower e.g. when panning or zooming the map.

Do you know what causes this slower drawing and is there something which could be changed to improve it ?

Br, Simo

Hi Simo,

We recreated this issue. It’s a real regression: an optimization we made for Strip GeoTIFFs in v14.5 ended up decoding and copying the whole image over again for every single tile.

This is fixed in the latest beta125, and it will be fixed in the next stable hotfix release v14.5.5 (available by the end of this month).

Thanks,
Ben

Hi,

Thanks for the quick fix.

Br, Simo

Hi Simo, Just FYI v14.5.5 is available now.

1 Like

Hi,

What is the difference between GeoTiffGdalRasterLayer and GeoTiffRasterLayer ?

As said we have been using GeoTiffRasterLayer which is still quite slow on 14.5.5 but just out of curiosity I tried to switch to GeoTiffGdalRasterLayer and it seems to be significantly (tiles are drawn almost instantly compared to approx ~5s time with GeoTiffRasterLayer) faster when drawing the GeoTiffs. Which one we should use and when ?

Also could you please check if there is anything which could speed up drawing for GeoTiffRasterLayer with larger tiff files ?

Br, Simo

Regarding this, can we, if we have multiple choices for the same thing, add reasons why using x or y is prefered in the Code documentation for those Classes? I think that would help, as I see these questions a lot.

1 Like

Hi Simo, Julian,

In short, the GDAL version is faster and supports more GeoTIFF variants, but it needs the native GDAL dependency and cannot work in some environments (for example on mobile). GeoTiffRasterLayer (ThinkGeo.Core) is the managed version: no native dependencies, but slower and supports fewer formats. Here are the details:

GeoTiffGdalRasterLayer (ThinkGeo.Gdal) asks GDAL for exactly the pixel window a tile needs, at the tile’s resolution. GDAL decodes only the blocks that window touches, uses the file’s internal overviews when zoomed out, and caches blocks, so it never decodes the whole image. That is why it feels instant on your 14 MB file. It also reads anything GDAL reads: BigTIFF, COG, JPEG/ZSTD/WebP/LERC compression, multi-band data, and it can warp to Web Mercator natively.

GeoTiffRasterLayer (ThinkGeo.Core) is a managed TIFF reader. It handles the classic TIFF codecs (LZW, Deflate, PackBits, JPEG, CCITT) with 8- or 16-bit samples. Its read path decodes the whole image to RGBA, and in 14.5.x that happened for every single tile. 14.5.5 removed an extra per-tile copy on top of that, which is why it got a bit faster but still costs seconds per view on a large compressed file.

We did make some changes to the managed version in the latest beta (and upcoming v15): the image is now decoded once and kept in a raster cache instead of being decoded per tile, the file’s overviews are read when the map is zoomed out instead of the full-resolution image, and the decoded bitmap is shared with the renderer rather than copied. Here are some test results, same 13 MB GeoTIFF, 20 tiles:

                    GeoTiffRasterLayer    GeoTiffGdalRasterLayer
  14.5.5            20.1 ms/tile          1.3 ms/tile
  15.0.0-beta131     1.3 ms/tile          1.3 ms/tile

One note: our test file is uncompressed. A compressed file pays one bigger decode on the first tile in 15.0, then the same per-tile cost as above. If you need to stay on 14.5.x, GDAL is the practical choice for a file that size; TileType.SingleTile also helps there since it decodes once per view instead of once per tile.

Julian, I wrote this down regarding documentation improvements. We will make lots of improvements to the products (you will see next week) and the website for v15 release, and I’ll make sure to revisit this one.

Thanks,
Ben

1 Like

Hi @Simo_Karjalainen,

The GPU based rendering is now available in the latest beta branch. Here is a quick description:
ThinkGeo 15 in 1 Minute — Unleash Your GPU, here is the new HowDoI (for .NET 8 +) ThinkGeo HowDoI v15.

We are actively working on it and aiming for having it released in October. I’d recommend to upgrade to the new way if possible (you can easily tell it’s way better). The current CPU renderer will go side by side with it (at least for quite a while), so your current code will also work with the new version.

Thanks,
Ben

1 Like