diff --git a/MapControl/Avalonia/GeoImage.Avalonia.cs b/MapControl/Avalonia/GeoImage.Avalonia.cs new file mode 100644 index 00000000..25804ca0 --- /dev/null +++ b/MapControl/Avalonia/GeoImage.Avalonia.cs @@ -0,0 +1,23 @@ +// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control +// Copyright © 2024 Clemens Fischer +// Licensed under the Microsoft Public License (Ms-PL) + +using System; +using System.Threading.Tasks; + +namespace MapControl +{ + public partial class GeoImage : Image + { + private void SetImage(ImageSource image) + { + Source = image; + Stretch = Stretch.Fill; + } + + private static Task ReadGeoTiffAsync(string sourcePath) + { + throw new InvalidOperationException("GeoTIFF is not supported."); + } + } +} diff --git a/MapControl/Shared/GeoImage.cs b/MapControl/Shared/GeoImage.cs index 82f60146..842cf10a 100644 --- a/MapControl/Shared/GeoImage.cs +++ b/MapControl/Shared/GeoImage.cs @@ -10,51 +10,39 @@ using System.Linq; using System.Threading.Tasks; #if WPF using System.Windows; -using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; #elif UWP using Windows.UI.Xaml; -using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media.Imaging; #elif WINUI using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Media; using Microsoft.UI.Xaml.Media.Imaging; #endif namespace MapControl { - public partial class GeoImage : Grid + public partial class GeoImage { - private class DefaultProjection : MapProjection - { - public override Point? LocationToMap(Location location) => new Point(location.Longitude, location.Latitude); - public override Location MapToLocation(Point point) => new Location(point.Y, point.X); - } - private class GeoBitmap { public BitmapSource Bitmap { get; set; } public Matrix Transform { get; set; } - public MapProjection Projection { get; set; } = new DefaultProjection(); + public MapProjection Projection { get; set; } - public void SetProjection(short[] geoKeyDirectory) + public BoundingBox BoundingBox { - for (var i = 4; i < geoKeyDirectory.Length - 3; i += 4) + get { - if (geoKeyDirectory[i] == ProjectedCRSGeoKey && geoKeyDirectory[i + 1] == 0) - { - var epsgCode = geoKeyDirectory[i + 3]; - - var projection = MapProjectionFactory.Instance.GetProjection(epsgCode) ?? - throw new ArgumentException($"Can not create projection EPSG:{epsgCode}."); - - Projection = projection; - break; - } + var p1 = Transform.Transform(new Point()); +#if AVALONIA + var p2 = Transform.Transform(new Point(Bitmap.PixelSize.Width, Bitmap.PixelSize.Height)); +#else + var p2 = Transform.Transform(new Point(Bitmap.PixelWidth, Bitmap.PixelHeight)); +#endif + return Projection != null + ? Projection.MapToBoundingBox(new Rect(p1, p2)) + : new BoundingBox(p1.Y, p1.X, p2.Y, p2.X); } } } @@ -110,37 +98,14 @@ namespace MapControl } } -#if AVALONIA - if (geoBitmap == null) return; - - var width = geoBitmap.Bitmap.PixelSize.Width; - var height = geoBitmap.Bitmap.PixelSize.Height; -#else if (geoBitmap == null) { geoBitmap = await ReadGeoTiffAsync(sourcePath); } - var width = geoBitmap.Bitmap.PixelWidth; - var height = geoBitmap.Bitmap.PixelHeight; -#endif - var image = new Image - { - Source = geoBitmap.Bitmap, - Stretch = Stretch.Fill, - HorizontalAlignment = HorizontalAlignment.Stretch, - VerticalAlignment = VerticalAlignment.Stretch - }; + MapPanel.SetBoundingBox(this, geoBitmap.BoundingBox); - var transform = geoBitmap.Transform; - var p1 = transform.Transform(new Point()); - var p2 = transform.Transform(new Point(width, height)); - var mapRect = new Rect(p1, p2); ; - - MapPanel.SetBoundingBox(this, geoBitmap.Projection.MapToBoundingBox(mapRect)); - - Children.Clear(); - Children.Add(image); + SetImage(geoBitmap.Bitmap); } private static async Task ReadWorldFileImageAsync(string sourcePath, string worldFilePath) @@ -174,5 +139,21 @@ namespace MapControl parameters[4], // line 5: C or OffsetX parameters[5]); // line 6: F or OffsetY } + + private static MapProjection GetProjection(short[] geoKeyDirectory) + { + for (var i = 4; i < geoKeyDirectory.Length - 3; i += 4) + { + if (geoKeyDirectory[i] == ProjectedCRSGeoKey && geoKeyDirectory[i + 1] == 0) + { + var epsgCode = geoKeyDirectory[i + 3]; + + return MapProjectionFactory.Instance.GetProjection(epsgCode) ?? + throw new ArgumentException($"Can not create projection EPSG:{epsgCode}."); + } + } + + return null; + } } } diff --git a/MapControl/WPF/GeoImage.WPF.cs b/MapControl/WPF/GeoImage.WPF.cs index 96df92ae..202c63fb 100644 --- a/MapControl/WPF/GeoImage.WPF.cs +++ b/MapControl/WPF/GeoImage.WPF.cs @@ -6,13 +6,20 @@ using System; using System.IO; using System.Linq; using System.Threading.Tasks; +using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; namespace MapControl { - public partial class GeoImage + public partial class GeoImage : Image { + private void SetImage(ImageSource image) + { + Source = image; + Stretch = Stretch.Fill; + } + private static Task ReadGeoTiffAsync(string sourcePath) { return Task.Run(() => @@ -47,7 +54,7 @@ namespace MapControl if (metadata.GetQuery(QueryString(GeoKeyDirectoryTag)) is short[] geoKeyDirectory) { - geoBitmap.SetProjection(geoKeyDirectory); + geoBitmap.Projection = GetProjection(geoKeyDirectory); } if (metadata.GetQuery(QueryString(NoDataTag)) is string noData && diff --git a/MapControl/WinUI/GeoImage.WinUI.cs b/MapControl/WinUI/GeoImage.WinUI.cs index b759eac8..d18b6ef6 100644 --- a/MapControl/WinUI/GeoImage.WinUI.cs +++ b/MapControl/WinUI/GeoImage.WinUI.cs @@ -6,11 +6,32 @@ using System; using System.Threading.Tasks; using Windows.Graphics.Imaging; using Windows.Storage; +#if UWP +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media; +#else +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Media; +#endif namespace MapControl { - public partial class GeoImage + public partial class GeoImage : Grid { + private void SetImage(ImageSource image) + { + Children.Clear(); + Children.Add(new Image + { + Source = image, + Stretch = Stretch.Fill, + HorizontalAlignment = HorizontalAlignment.Stretch, + VerticalAlignment = VerticalAlignment.Stretch + }); + } + private static async Task ReadGeoTiffAsync(string sourcePath) { var file = await StorageFile.GetFileFromPathAsync(FilePath.GetFullPath(sourcePath)); @@ -60,7 +81,7 @@ namespace MapControl if (metadata.TryGetValue(geoKeyDirectoryQuery, out BitmapTypedValue geoKeyDirValue) && geoKeyDirValue.Value is short[] geoKeyDirectory) { - geoBitmap.SetProjection(geoKeyDirectory); + geoBitmap.Projection = GetProjection(geoKeyDirectory); } return geoBitmap;