diff --git a/MapImages/Shared/GeoTaggedImage.cs b/MapImages/Shared/GeoTaggedImage.cs index c0f39e92..f2e8cd15 100644 --- a/MapImages/Shared/GeoTaggedImage.cs +++ b/MapImages/Shared/GeoTaggedImage.cs @@ -31,6 +31,11 @@ namespace MapControl.Images { public partial class GeoTaggedImage { + private const string PixelScaleQuery = "/ifd/{ushort=33550}"; + private const string TiePointQuery = "/ifd/{ushort=33922}"; + private const string TransformQuery = "/ifd/{ushort=34264}"; + private const string NoDataQuery = "/ifd/{ushort=42113}"; + public static readonly DependencyProperty PathProperty = DependencyProperty.RegisterAttached( "Path", typeof(string), typeof(GeoTaggedImage), new PropertyMetadata(null, PathPropertyChanged)); diff --git a/MapImages/WPF/GeoTaggedImage.WPF.cs b/MapImages/WPF/GeoTaggedImage.WPF.cs index e7687a1a..bfc9a6d1 100644 --- a/MapImages/WPF/GeoTaggedImage.WPF.cs +++ b/MapImages/WPF/GeoTaggedImage.WPF.cs @@ -3,7 +3,6 @@ // Licensed under the Microsoft Public License (Ms-PL) using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -14,11 +13,6 @@ namespace MapControl.Images { public partial class GeoTaggedImage { - private const string PixelScaleQuery = "/ifd/{ushort=33550}"; - private const string TiePointQuery = "/ifd/{ushort=33922}"; - private const string TransformationQuery = "/ifd/{ushort=34264}"; - private const string NoDataQuery = "/ifd/{ushort=42113}"; - public static Task ReadGeoTiff(string imageFilePath) { return Task.Run(() => @@ -31,24 +25,23 @@ namespace MapControl.Images bitmap = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); } - var mdata = bitmap.Metadata as BitmapMetadata; + var metadata = bitmap.Metadata as BitmapMetadata; - if (mdata.GetQuery(PixelScaleQuery) is double[] ps && - mdata.GetQuery(TiePointQuery) is double[] tp && - ps.Length == 3 && tp.Length >= 6) + if (metadata.GetQuery(PixelScaleQuery) is double[] pixelScale && pixelScale.Length == 3 && + metadata.GetQuery(TiePointQuery) is double[] tiePoint && tiePoint.Length >= 6) { - transform = new Matrix(ps[0], 0d, 0d, -ps[1], tp[3], tp[4]); + transform = new Matrix(pixelScale[0], 0d, 0d, -pixelScale[1], tiePoint[3], tiePoint[4]); } - else if (mdata.GetQuery(TransformationQuery) is double[] tf && tf.Length == 16) + else if (metadata.GetQuery(TransformQuery) is double[] tform && tform.Length == 16) { - transform = new Matrix(tf[0], tf[1], tf[4], tf[5], tf[3], tf[7]); + transform = new Matrix(tform[0], tform[1], tform[4], tform[5], tform[3], tform[7]); } else { throw new ArgumentException("No coordinate transformation found in \"" + imageFilePath + "\"."); } - if (mdata.GetQuery(NoDataQuery) is string noData && int.TryParse(noData, out int noDataValue)) + if (metadata.GetQuery(NoDataQuery) is string noData && int.TryParse(noData, out int noDataValue)) { bitmap = ConvertTransparentPixel(bitmap, noDataValue); } @@ -59,43 +52,44 @@ namespace MapControl.Images public static BitmapSource ConvertTransparentPixel(BitmapSource source, int transparentPixel) { + BitmapPalette sourcePalette = null; var targetFormat = source.Format; - List colors = null; if (source.Format == PixelFormats.Indexed8 || source.Format == PixelFormats.Indexed4 || source.Format == PixelFormats.Indexed2 || source.Format == PixelFormats.Indexed1) { - targetFormat = source.Format; - colors = source.Palette.Colors.ToList(); + sourcePalette = source.Palette; } else if (source.Format == PixelFormats.Gray8) { + sourcePalette = BitmapPalettes.Gray256; targetFormat = PixelFormats.Indexed8; - colors = BitmapPalettes.Gray256.Colors.ToList(); } else if (source.Format == PixelFormats.Gray4) { + sourcePalette = BitmapPalettes.Gray16; targetFormat = PixelFormats.Indexed4; - colors = BitmapPalettes.Gray16.Colors.ToList(); } else if (source.Format == PixelFormats.Gray2) { + sourcePalette = BitmapPalettes.Gray4; targetFormat = PixelFormats.Indexed2; - colors = BitmapPalettes.Gray4.Colors.ToList(); } else if (source.Format == PixelFormats.BlackWhite) { + sourcePalette = BitmapPalettes.BlackAndWhite; targetFormat = PixelFormats.Indexed1; - colors = BitmapPalettes.BlackAndWhite.Colors.ToList(); } - if (colors == null || transparentPixel >= colors.Count) + if (sourcePalette == null || transparentPixel >= sourcePalette.Colors.Count) { return source; } + var colors = sourcePalette.Colors.ToList(); + colors[transparentPixel] = Colors.Transparent; var stride = (source.PixelWidth * source.Format.BitsPerPixel + 7) / 8; diff --git a/MapImages/WinUI/GeoTaggedImage.WinUI.cs b/MapImages/WinUI/GeoTaggedImage.WinUI.cs index 2fbcc2f2..889baca2 100644 --- a/MapImages/WinUI/GeoTaggedImage.WinUI.cs +++ b/MapImages/WinUI/GeoTaggedImage.WinUI.cs @@ -3,15 +3,65 @@ // Licensed under the Microsoft Public License (Ms-PL) using System; +using System.IO; using System.Threading.Tasks; +using Windows.Storage; +using System.Collections.Generic; +#if WINUI +using Windows.Graphics.Imaging; +using Microsoft.UI.Xaml.Media.Imaging; +#else +using Windows.Graphics.Imaging; +using Windows.UI.Xaml.Media.Imaging; +#endif namespace MapControl.Images { public partial class GeoTaggedImage { - public static Task ReadGeoTiff(string imageFilePath) + public static async Task ReadGeoTiff(string imageFilePath) { - throw new NotImplementedException(); + var file = await StorageFile.GetFileFromPathAsync(Path.GetFullPath(imageFilePath)); + + using (var stream = await file.OpenReadAsync()) + { + WriteableBitmap bitmap; + Matrix transform; + + var decoder = await BitmapDecoder.CreateAsync(stream); + + using (var swbmp = await decoder.GetSoftwareBitmapAsync()) + { + bitmap = new WriteableBitmap(swbmp.PixelWidth, swbmp.PixelHeight); + swbmp.CopyToBuffer(bitmap.PixelBuffer); + } + + var query = new List + { + PixelScaleQuery, TiePointQuery, TransformQuery //, NoDataQuery + }; + + var metadata = await decoder.BitmapProperties.GetPropertiesAsync(query); + + if (metadata.TryGetValue(PixelScaleQuery, out BitmapTypedValue pixelScaleValue) && + pixelScaleValue.Value is double[] pixelScale && pixelScale.Length == 3 && + metadata.TryGetValue(TiePointQuery, out BitmapTypedValue tiePointValue) && + tiePointValue.Value is double[] tiePoint && tiePoint.Length >= 6) + { + transform = new Matrix(pixelScale[0], 0d, 0d, -pixelScale[1], tiePoint[3], tiePoint[4]); + } + else if (metadata.TryGetValue(TransformQuery, out BitmapTypedValue tformValue) && + tformValue.Value is double[] tform && tform.Length == 16) + { + transform = new Matrix(tform[0], tform[1], tform[4], tform[5], tform[3], tform[7]); + } + else + { + throw new ArgumentException("No coordinate transformation found in \"" + imageFilePath + "\"."); + } + + return new GeoTaggedImage(bitmap, transform, null); + } } } }