Select to view content in your preferred language

Custom TiledLayer

2045
1
02-21-2014 05:54 AM
Labels (1)
BjørnarSundsbø
Deactivated User
Hi,

I need to support custom data sources in my map (for reasons that I will not go into here), and the datasource is not natively supported by ArcGis Runtime SDK for WPF. The underlying technology can only handle System.Drawing.Bitmap, and these I convert into BitmapImage. This has been implemented as DynamicLayer, and works great. The images are generated on a background thread, and all is pretty good.

Because the underlying data is sometimes somewhat slow, I would like to turn this layer into a TiledLayer. The way of generating the tiles is identical to when using DynamicLayer, and seems to work just fine.

But wait.... There is a memory leak with both approaches, but it becomes more evident with the tiled approach. There are unmanaged bitmap handles related to the conversion process from Bitmap to BitmapImage. I have not yet found a way to convert the bitmap without getting different unmanaged bitmap handles retained in memory (that might be cleared up eventually, but not fast enough). System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap (and deleting the handle), saving bitmap to memorystream, etc still retains memory.

Since I'm creating tiles and storing them on disk for later requests, I would like to assign the UriSource of the bitmapimage to the file path on disk, but I get an exception saying it can't cast FileWebRequest to HttpWebRequest. Is there a particular reason why this can't is not supported? Loading the BitmapImage from disk using different LoadOption, CacheOptions, etc doesn't seem to help with the memory issue. Any suggestions would be welcome, but I know it is not within the scope of this forum.

I event tried wrapping the export operation inside of a REST service to utilize the existing functionality in TiledLayer/TiledMapServiceLayer, but I lost the background functionality (as far as I came, at least). And adding additional layers to be able to return the image through a memorystream is a bit exessive, in addition to other issues that might arise from this.

I think this issue might be resolved using a FileWebRequest, but I'm not sure. And since I can't wait untill this might be supported in the future, do you have any suggestions for getting rid of the memory leak?
0 Kudos
1 Reply
BjørnarSundsbø
Deactivated User
Well, this is embarresing.... At least slightly. Only a few hours after posting the question, I may have found the answer. To my defence, I've been wrestling with this issue for a while, and pulling my hair and banging my head against the desk might actually have helped 🙂

Instead of deleting the question, I'll provide the solution to others who might struggle with similar issues (sadly I can't change the main title, only the title of the reply). Instead of working on the Bitmap and converting it into a BitmapImage, I get the bytes of the image
private byte[] GetBitmapBytes(Bitmap bitmap)
{
    if (bitmap == null)
    {
        return null;
    }

    using (MemoryStream stream = new MemoryStream())
    {
        bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
        stream.Close();
        return stream.ToArray();
    }
}


When I then eventually want the BitmapImage, I create a new BitmapImage based on a new MemoryStream, and return it
private BitmapImage ConvertBytesToImage(byte[] imageBytes)
{
    BitmapImage bitmapImage = new BitmapImage();
    bitmapImage.BeginInit();
    MemoryStream memoryStream = new MemoryStream(imageBytes);
    bitmapImage.StreamSource = memoryStream;
    bitmapImage.EndInit();
    return bitmapImage;
}


I pray that the Map/TiledLayer/BitmapImage disposes of the memorystream when it is done. I have seen no signs that the memory is growing particularly (yet, anyways).

The files I have stored in my cache on disk are read from and written to using File.ReadAllBytes(tilePath) and File.WriteAllBytes(tilePath, imageBytes). I haven't gotten as far as benchmarking the performance, but the leak is gone, and when the tiling works properly, that is probably not an issue.

Hope this was of help to anyone who might run into similar issues. If you can see any problems with this approach, please let me know.
0 Kudos