// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control // © 2018 Clemens Fischer // Licensed under the Microsoft Public License (Ms-PL) using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using System.Windows.Media; using System.Windows.Media.Imaging; namespace MapControl { public static class ImageLoader { /// /// The HttpClient instance used when image data is downloaded from a web resource. /// public static HttpClient HttpClient { get; set; } = new HttpClient(); public static async Task LoadImageAsync(Uri uri, bool isTileImage) { if (!uri.IsAbsoluteUri || uri.Scheme == "file") { return await LoadLocalImageAsync(uri); } if (uri.Scheme == "http") { return await LoadHttpImageAsync(uri, isTileImage); } return new BitmapImage(uri); } public static Task LoadLocalImageAsync(Uri uri) { return Task.Run(() => { var path = uri.IsAbsoluteUri ? uri.LocalPath : uri.OriginalString; if (!File.Exists(path)) { return null; } using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { return (ImageSource)BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); } }); } public static async Task LoadHttpImageAsync(Uri uri, bool isTileImage) { using (var response = await HttpClient.GetAsync(uri)) { if (!response.IsSuccessStatusCode) { Debug.WriteLine("ImageLoader: {0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase); } else if (!isTileImage || IsTileAvailable(response.Headers)) { using (var stream = new MemoryStream()) { await response.Content.CopyToAsync(stream); stream.Seek(0, SeekOrigin.Begin); return BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); } } return null; } } public static async Task LoadHttpTileImageAsync(Uri uri, Func tileCallback) { using (var response = await HttpClient.GetAsync(uri)) { if (!response.IsSuccessStatusCode) { Debug.WriteLine("ImageLoader: {0}: {1} {2}", uri, (int)response.StatusCode, response.ReasonPhrase); } else if (IsTileAvailable(response.Headers)) { var stream = new MemoryStream(); await response.Content.CopyToAsync(stream); stream.Seek(0, SeekOrigin.Begin); await tileCallback(stream, response.Headers.CacheControl?.MaxAge); } return response.IsSuccessStatusCode; } } private static bool IsTileAvailable(HttpResponseHeaders responseHeaders) { IEnumerable tileInfo; return !responseHeaders.TryGetValues("X-VE-Tile-Info", out tileInfo) || !tileInfo.Contains("no-tile"); } } }