ThinkGeo.com    |     Documentation    |     Premium Support

14.3.0 SkiaSharp System.AccessViolationException when loading in JPG

Hi, using the current version 14.3.0 and SkiaSharp Version 3.116.1 I get an AccessViolationException when trying to load in a JPG file.
Is this a known issue?

Here is the stacktrace:

|>|SkiaSharp.dll!SkiaSharp.SkiaApi.sk_pixmap_scale_pixels(System.IntPtr cpixmap, System.IntPtr dst, SkiaSharp.SKSamplingOptions* sampling) Line 7461|C#|
| |SkiaSharp.dll!SkiaSharp.SKPixmap.ScalePixels(SkiaSharp.SKPixmap destination, SkiaSharp.SKSamplingOptions sampling) Line 216|C#|
| |SkiaSharp.dll!SkiaSharp.SKBitmap.ScalePixels(SkiaSharp.SKPixmap destination, SkiaSharp.SKSamplingOptions sampling) Line 714|C#|
| |SkiaSharp.dll!SkiaSharp.SKBitmap.ScalePixels(SkiaSharp.SKBitmap destination, SkiaSharp.SKSamplingOptions sampling) Line 709|C#|
| |ThinkGeo.Core.dll!8RQ=.HBU=.JBU=(object image, int width, int height)|Unknown|
| |ThinkGeo.Core.dll!ThinkGeo.Core.GeoImage.Clip(ThinkGeo.Core.DrawingRectangle clippingRectangle, int clippingWidth, int clippingHeight)|Unknown|
| |ThinkGeo.Core.dll!ThinkGeo.Core.NativeImageRasterSource.GetImageCore(ThinkGeo.Core.RectangleShape worldExtent, int canvasWidth, int canvasHeight)|Unknown|
| |ThinkGeo.Core.dll!ThinkGeo.Core.RasterSource.GetImage(ThinkGeo.Core.RectangleShape worldExtent, int canvasWidth, int canvasHeight)|Unknown|
| |ThinkGeo.Core.dll!ThinkGeo.Core.RasterLayer.DrawCore(ThinkGeo.Core.GeoCanvas canvas, System.Collections.ObjectModel.Collection<ThinkGeo.Core.SimpleCandidate> labelsInAllLayers)|Unknown|
| |ThinkGeo.Core.dll!ThinkGeo.Core.Layer.BCA=(ThinkGeo.Core.GeoCanvas canvas, System.Collections.ObjectModel.Collection<ThinkGeo.Core.SimpleCandidate> labelsInAllLayers)|Unknown|
| |ThinkGeo.Core.dll!ThinkGeo.Core.Layer.Draw(ThinkGeo.Core.GeoCanvas canvas, System.Collections.ObjectModel.Collection<ThinkGeo.Core.SimpleCandidate> labelsInAllLayers)|Unknown|
| |ThinkGeo.UI.Wpf.dll!ThinkGeo.UI.Wpf.LayerTileView.DrawLayerAsync.AnonymousMethod__0()|Unknown|

Translation: An attempt was made to read or write to the protected memory. This is often an indication that other memory is damaged.

Here are the jpg files that causes the issue:

Julian,

It seems your download link not working, can you send it again?

Thanks,
Ben

Hi Julian,

It seems they introduced an AccessViolationException in SkiaSharp v3, and it should have been fixed in the latest v3.119, here is the PR:

Fix the SKImage.FromPicture implementation by mattleibow · Pull Request #3231 · mono/SkiaSharp · GitHub

Let me upgrade the Skia to the latest v3.119 in the latest beta branch and you then can have another try.

Thanks,
Ben

All right, the latest beta (14.4.0-beta003) with SkiaSharp v3.119.0 is now available on Nuget, please have a try.

Hi, thanks for your help.

I tried the latest beta, sadly I still get the same System.AccessViolationException exception:

|>|SkiaSharp.dll!SkiaSharp.SkiaApi.sk_pixmap_scale_pixels(System.IntPtr cpixmap, System.IntPtr dst, SkiaSharp.SKSamplingOptions* sampling) Line 11900|C#|
| |SkiaSharp.dll!SkiaSharp.SKPixmap.ScalePixels(SkiaSharp.SKPixmap destination, SkiaSharp.SKSamplingOptions sampling) Line 199|C#|
| |SkiaSharp.dll!SkiaSharp.SKBitmap.ScalePixels(SkiaSharp.SKPixmap destination, SkiaSharp.SKSamplingOptions sampling) Line 704|C#|
| |SkiaSharp.dll!SkiaSharp.SKBitmap.ScalePixels(SkiaSharp.SKBitmap destination, SkiaSharp.SKSamplingOptions sampling) Line 698|C#|
| |ThinkGeo.Core.dll!8RQ=.HBU=.JBU=(object image, int width, int height)|Unknown|
| |ThinkGeo.Core.dll!ThinkGeo.Core.GeoImage.Clip(ThinkGeo.Core.DrawingRectangle clippingRectangle, int clippingWidth, int clippingHeight)|Unknown|
| |ThinkGeo.Core.dll!ThinkGeo.Core.SkiaRasterSource.GetImageCore(ThinkGeo.Core.RectangleShape worldExtent, int canvasWidth, int canvasHeight)|Unknown|
| |ThinkGeo.Core.dll!ThinkGeo.Core.RasterSource.GetImage(ThinkGeo.Core.RectangleShape worldExtent, int canvasWidth, int canvasHeight)|Unknown|
| |ThinkGeo.Core.dll!ThinkGeo.Core.RasterLayer.DrawCore(ThinkGeo.Core.GeoCanvas canvas, System.Collections.ObjectModel.Collection<ThinkGeo.Core.SimpleCandidate> labelsInAllLayers)|Unknown|
| |ThinkGeo.Core.dll!ThinkGeo.Core.Layer.BCA=(ThinkGeo.Core.GeoCanvas canvas, System.Collections.ObjectModel.Collection<ThinkGeo.Core.SimpleCandidate> labelsInAllLayers)|Unknown|
| |ThinkGeo.Core.dll!ThinkGeo.Core.Layer.Draw(ThinkGeo.Core.GeoCanvas canvas, System.Collections.ObjectModel.Collection<ThinkGeo.Core.SimpleCandidate> labelsInAllLayers)|Unknown|
| |ThinkGeo.UI.Wpf.dll!ThinkGeo.UI.Wpf.LayerTileView.DrawLayerAsync.AnonymousMethod__0()|Unknown|

It seems like the forum link “onebox” cuts off the link after the #. It works when copying it in directly, please remove the space after /

https://limewire.com/ d/LqOu9#vnnPRSLtCR

Hi Julian,

I couldn’t recreate the issue with neither v14.3.0 nor v14.4.0-beta003, the following code works fine for me.

private void mapView_Loaded(object sender, RoutedEventArgs e)
{
mapView.MapUnit = GeographyUnit.Meter;

   var layerOverlay = new LayerOverlay();
   mapView.Overlays.Add(layerOverlay);

   var geoTiffRasterLayer = new SkiaRasterLayer(@"d:\Downloads\Stadtkarte_farbig_75\Stadtkarte_farbig_75.jpg");

   //var geoTiffRasterLayer = new WpfRasterLayer(@"d:\Downloads\Stadtkarte_farbig_75\Stadtkarte_farbig_75.jpg");
   layerOverlay.Layers.Add(geoTiffRasterLayer);

     geoTiffRasterLayer.Open();
   mapView.CurrentExtent = geoTiffRasterLayer.GetBoundingBox();
   _ = mapView.RefreshAsync();

}

Can you send me your code snippet?

FYI: Besides SkiaRasterLayer, you can also use WpfRasterLayer, it’s specific for Desktop with better performance.

Thanks,
Ben

Hi, thanks, are there any other special WPF layers that I should use? Or only this one?
It works with WpfRasterLayer. I also tried the test jpgs in the HowDoI Project and they work, for whatever reason only some jpgs don’t work. I sadly don’t have a code snippet as this is a WPF application from 2003 and extremely huge and convoluted. The general structure looks like this:

I have a special ProjMap : MapView which defines two overlays, ShapefileOverlay and ImageOverlay (image is the same as below)

public LayerOverlay ShapefileOverlay
{
    get
    {
        if (!this.Overlays.Contains("ShapefileOverlay"))
        {
            this.Overlays.Add("ShapefileOverlay", new LayerOverlay());
            ((LayerOverlay)this.Overlays["ShapefileOverlay"]).DrawingQuality = DrawingQuality.HighSpeed;
        }

        return (LayerOverlay)this.Overlays["ShapefileOverlay"];
    }
}

The layers I define as special Layers as I need meta information on, so we have special classes for this.

public ViewerImageLayer(IViewerLayer layer)
{
     switch (layer.FileType)
     {
         case FileType.Tiff:
             this.MapLayer = new GeoTiffRasterLayer(this.FilePath);
              break;
          case FileType.JPG:
          case FileType.JPEG:
          case FileType.PNG:
              this.MapLayer = new WpfRasterLayer(this.FilePath);
              break;
}

with

public interface IViewerLayer
{
    ProjMap Map { set; }
    Layer MapLayer { get; set; }
    ... other meta info

Again, this is an extremely old application from 2003 which used a legacy ThinkGeo version, so if there’s anything obvious that is necessary / unnecessary I’d appreciate it :slight_smile:

E.g. is it good practice to separate Shapes and Images in two different Layers? Or is that unnecessary and better to keep them in one?
We have 3 Layers in total, one for Shapes, one for Images, and one for Temporary Highlights. We are increasing the amount of Layer Types that can be displayed (so adding WPF, WMS, File Geodatabases etc.) - how would the best way of structuring the Overlays be? Or just render everything in one & then the Temporary Highlights in the other?

Thanks Ben!

Hi Julian,

Here are the answers for your questions:

  1. Raster layer types
  • In ThinkGeo.Core, the built‑in RasterLayer uses SkiaSharp and works cross‑platform.
  • WpfRasterLayer is the only “special WPF layer” we have at this time, it’s desktop‑only (WPF/WinForms) and have better performance.
  1. About updating to the newer version
  • My suggestion is to rebuild your project and address any ThinkGeo warnings. Those deprecation hints will point you to the new APIs in the latest ThinkGeo release.
  1. Overlay strategy
    Q: Is it good practice to separate Shapes and Images in two different Layers? Or is that unnecessary and better to keep them in one?

    A: I think you meant Overlays. They should be two different layers anyway, but whether we should put them into one or two overlays.

  • When to combine (one overlay):

    • Layers always drawn and refreshed together (e.g. shapes and images are both for your background so every time you pan/zoom around the map, they will be refreshed at the same time).
  • When to separate (multiple overlays):

    • Layers that update at different times (e.g. highlights, so you need to refresh the features in the highlight layers without redrawing the background layers).
  1. Suggested overlay structure for your case
  • You can put highlight layer to a separate overlay and all the other layers to one overlay. Because all the other layers are always refreshed at the same time, I suppose.
  • You can consider putting WMS layer into its own overlay (or just use WmsOverlay instead) because WMS might be slow requesting the tiles, you don’t want it show down the other layers. Put it into a separate overlay so even the wms is slow, the other background layers will also be rendered.

Let us know if you have more questions.

Thanks,
Ben

1 Like