none
Cannot draw map tiles by setting MapTileBitmapRequest.PixelData (IRandomAccessStreamReference) RRS feed

  • Question

  • I am trying to use the CustomMapTileDataSource.BitmapRequested event to set the MapTileBitmapRequest.PixelData property. But despite following several examples (and proving that my code will work with BitmapImage.SetSource), the tiles are not drawn on the map.

    private async void CustomMapTileDataSource_OnBitmapRequested(CustomMapTileDataSource sender, MapTileBitmapRequestedEventArgs args)
            {
    
                MapTileBitmapRequestDeferral deferral = args.Request.GetDeferral();
                args.Request.PixelData = await GetBitmapAsync(args);
                deferral.Complete();
            }


    private async Task<RandomAccessStreamReference> GetBitmapAsync(MapTileBitmapRequestedEventArgs args)
            {
                try
                {
                    string tileUri = string.Format(_uriFormatString, args.ZoomLevel, args.X, args.Y);
    
                    using (Windows.Web.Http.HttpClient httpClient = new Windows.Web.Http.HttpClient())
                    {
                        IInputStream tileInputStream = await httpClient.GetInputStreamAsync(new Uri(tileUri));
    
                        using (Stream tileStream = tileInputStream.AsStreamForRead())
                        {
                            //Stream does not support seeking: use an intermediary stream
                            using (MemoryStream memoryStream = new MemoryStream())
                            {
                                await tileStream.CopyToAsync(memoryStream);
    
                                //results in exception: Additional information: This IRandomAccessStream does not support the CloneStream method because it requires cloning and this stream does not support cloning.
                                //memoryStream.Position = 0;
                                //return RandomAccessStreamReference.CreateFromStream(memoryStream.AsRandomAccessStream());
    
                                //no exception, but nothing is drawn
                                byte[] tileBuffer = new byte[memoryStream.Length];
                                memoryStream.Read(tileBuffer, 0, (int)memoryStream.Length);
    
                                InMemoryRandomAccessStream inMemoryRandomAccessStream = new InMemoryRandomAccessStream();
                                IOutputStream outputStream = inMemoryRandomAccessStream.GetOutputStreamAt(0);
    
                                DataWriter writer = new DataWriter(outputStream);
                                writer.WriteBytes(tileBuffer);
                                await writer.StoreAsync();
                                await writer.FlushAsync();
    
                                return RandomAccessStreamReference.CreateFromStream(inMemoryRandomAccessStream);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    string exception = ex.ToString();
    
                    if (Debugger.IsAttached)
                        Debugger.Break();
    
                    return null;
                }
            }

    If I use a BitmapImage, it appears correctly. 

    InMemoryRandomAccessStream inMemoryRandomAccessStream = new InMemoryRandomAccessStream(); IOutputStream outputStream = inMemoryRandomAccessStream.GetOutputStreamAt(0); byte[] tileBuffer = new byte[memoryStream.Length]; memoryStream.Read(tileBuffer, 0, (int)memoryStream.Length);

    DataWriter writer = new DataWriter(outputStream); writer.WriteBytes(tileBuffer); await writer.StoreAsync(); await writer.FlushAsync();

    BitmapImage bitmapImage = new BitmapImage(); bitmapImage.SetSource(inMemoryRandomAccessStream); TestImage.Source = bitmapImage;


    Friday, January 2, 2015 6:22 PM

Answers

All replies

  • Take a look at my code sample here: https://code.msdn.microsoft.com/Adding-Opacity-and-WMS-cf6773f1 It basically downloads a tile from a URL and then edits the pixel data for the opacity (you can skip this step if you want).

    http://rbrundritt.wordpress.com

    • Proposed as answer by Ricky_Brundritt Tuesday, January 6, 2015 11:11 PM
    • Marked as answer by acme_hap Thursday, January 8, 2015 6:55 PM
    Tuesday, January 6, 2015 11:11 PM
  • Thanks Ricky - this was a misunderstanding on my part as to how the byte[] array is being passed to the DataWriter.  I wasn't running it through a BitmapDecoder first!  For anyone else who sees this, the following code snippet works as expected.  (Note that I'm using the Windows.Web.Http.HttpClient instead of System.Net.HttpWebRequest)

    string tileUri = string.Format(_uriFormatString, args.ZoomLevel, args.X, args.Y);
    
                    using (HttpClient httpClient = new HttpClient())
                    {
                        IInputStream tileInputStream = await httpClient.GetInputStreamAsync(new Uri(tileUri));
    
                        using (Stream tileStream = tileInputStream.AsStreamForRead())
                        {
                            //Stream does not support seeking: use an intermediary stream
                            using (MemoryStream memoryStream = new MemoryStream())
                            {
                                await tileStream.CopyToAsync(memoryStream);
                                memoryStream.Position = 0;
    
                                InMemoryRandomAccessStream inMemoryRandomAccessStream = new InMemoryRandomAccessStream();
    
                                IOutputStream outputStream = inMemoryRandomAccessStream.GetOutputStreamAt(0);
    
                                //byte[] tileBuffer = new byte[memoryStream.Length];
                                //memoryStream.Read(tileBuffer, 0, (int)memoryStream.Length);
    
                                //we can't simply pass a byte[] to the DataWriter: we need to decode it first:
                                var decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(memoryStream.AsRandomAccessStream());
    
                                var pixelProvider = await decoder.GetPixelDataAsync(
                                    Windows.Graphics.Imaging.BitmapPixelFormat.Rgba8,
                                    Windows.Graphics.Imaging.BitmapAlphaMode.Straight,
                                    new Windows.Graphics.Imaging.BitmapTransform(),
                                    Windows.Graphics.Imaging.ExifOrientationMode.RespectExifOrientation,
                                    Windows.Graphics.Imaging.ColorManagementMode.ColorManageToSRgb);
    
                                var pixels = pixelProvider.DetachPixelData();
    
                                DataWriter writer = new DataWriter(outputStream);
                                //writer.WriteBytes(tileBuffer);
                                writer.WriteBytes(pixels);
    
                                await writer.StoreAsync();
                                await writer.FlushAsync();
    
                                return RandomAccessStreamReference.CreateFromStream(inMemoryRandomAccessStream);
                            }
                        }

    Thursday, January 8, 2015 6:55 PM