mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
Removed MapImages library
This commit is contained in:
parent
135473b799
commit
b04ed4eebe
|
|
@ -1,204 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2022 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using MapControl.Projections;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
#if WINUI
|
||||
using Windows.Foundation;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
#elif UWP
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
#endif
|
||||
|
||||
namespace MapControl.Images
|
||||
{
|
||||
public partial class GeoImage
|
||||
{
|
||||
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(GeoImage), new PropertyMetadata(null, PathPropertyChanged));
|
||||
|
||||
public BitmapSource Bitmap { get; }
|
||||
public Matrix Transform { get; }
|
||||
public MapProjection Projection { get; }
|
||||
public BoundingBox BoundingBox { get; }
|
||||
public double Rotation { get; }
|
||||
|
||||
public GeoImage(BitmapSource bitmap, Matrix transform, MapProjection projection)
|
||||
{
|
||||
Bitmap = bitmap;
|
||||
Transform = transform;
|
||||
Projection = projection;
|
||||
|
||||
if (transform.M12 != 0 || transform.M21 != 0)
|
||||
{
|
||||
Rotation = (Math.Atan2(transform.M12, transform.M11) + Math.Atan2(transform.M21, -transform.M22)) * 90d / Math.PI;
|
||||
|
||||
// effective unrotated transform
|
||||
transform.M11 = Math.Sqrt(transform.M11 * transform.M11 + transform.M12 * transform.M12);
|
||||
transform.M22 = -Math.Sqrt(transform.M22 * transform.M22 + transform.M21 * transform.M21);
|
||||
transform.M12 = 0;
|
||||
transform.M21 = 0;
|
||||
}
|
||||
|
||||
var rect = new Rect(
|
||||
transform.Transform(new Point()),
|
||||
transform.Transform(new Point(bitmap.PixelWidth, bitmap.PixelHeight)));
|
||||
|
||||
BoundingBox = projection != null
|
||||
? projection.RectToBoundingBox(rect)
|
||||
: new BoundingBox
|
||||
{
|
||||
West = rect.X,
|
||||
East = rect.X + rect.Width,
|
||||
South = rect.Y,
|
||||
North = rect.Y + rect.Height
|
||||
};
|
||||
}
|
||||
|
||||
public static string GetPath(Image image)
|
||||
{
|
||||
return (string)image.GetValue(PathProperty);
|
||||
}
|
||||
|
||||
public static void SetPath(Image image, string path)
|
||||
{
|
||||
image.SetValue(PathProperty, path);
|
||||
}
|
||||
|
||||
public static Task<GeoImage> ReadImage(string imageFilePath)
|
||||
{
|
||||
var ext = Path.GetExtension(imageFilePath);
|
||||
if (ext.Length < 4)
|
||||
{
|
||||
throw new ArgumentException("Invalid image file path extension, must have at least three characters.");
|
||||
}
|
||||
|
||||
var dir = Path.GetDirectoryName(imageFilePath);
|
||||
var file = Path.GetFileNameWithoutExtension(imageFilePath);
|
||||
var worldFilePath = Path.Combine(dir, file + ext.Remove(2, 1) + "w");
|
||||
|
||||
if (File.Exists(worldFilePath))
|
||||
{
|
||||
return ReadImage(imageFilePath, worldFilePath, Path.Combine(dir, file + ".prj"));
|
||||
}
|
||||
|
||||
return ReadGeoTiff(imageFilePath);
|
||||
}
|
||||
|
||||
public static async Task<GeoImage> ReadImage(string imageFilePath, string worldFilePath, string projFilePath = null)
|
||||
{
|
||||
var transform = ReadWorldFile(worldFilePath);
|
||||
|
||||
var projection = (projFilePath != null && File.Exists(projFilePath))
|
||||
? ReadProjectionFile(projFilePath)
|
||||
: null;
|
||||
|
||||
var bitmap = (BitmapSource)await ImageLoader.LoadImageAsync(imageFilePath);
|
||||
|
||||
return new GeoImage(bitmap, transform, projection);
|
||||
}
|
||||
|
||||
public static Matrix ReadWorldFile(string path)
|
||||
{
|
||||
var parameters = File.ReadLines(path)
|
||||
.Take(6)
|
||||
.Select((line, i) =>
|
||||
{
|
||||
if (!double.TryParse(line, NumberStyles.Float, CultureInfo.InvariantCulture, out double parameter))
|
||||
{
|
||||
throw new ArgumentException("Failed parsing line " + (i + 1) + " in world file \"" + path + "\".");
|
||||
}
|
||||
return parameter;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
if (parameters.Count != 6)
|
||||
{
|
||||
throw new ArgumentException("Insufficient number of parameters in world file \"" + path + "\".");
|
||||
}
|
||||
|
||||
return new Matrix(
|
||||
parameters[0], // line 1: A or M11
|
||||
parameters[1], // line 2: D or M12
|
||||
parameters[2], // line 3: B or M21
|
||||
parameters[3], // line 4: E or M22
|
||||
parameters[4], // line 5: C or OffsetX
|
||||
parameters[5]); // line 6: F or OffsetY
|
||||
}
|
||||
|
||||
public static MapProjection ReadProjectionFile(string path)
|
||||
{
|
||||
return new GeoApiProjection { WKT = File.ReadAllText(path) };
|
||||
}
|
||||
|
||||
public void ApplyToImage(Image image)
|
||||
{
|
||||
if (Rotation != 0d)
|
||||
{
|
||||
throw new InvalidOperationException("Rotation must be zero.");
|
||||
}
|
||||
|
||||
image.Source = Bitmap;
|
||||
image.Stretch = Stretch.Fill;
|
||||
|
||||
MapPanel.SetBoundingBox(image, BoundingBox);
|
||||
}
|
||||
|
||||
public FrameworkElement CreateImage()
|
||||
{
|
||||
FrameworkElement image = new Image
|
||||
{
|
||||
Source = Bitmap,
|
||||
Stretch = Stretch.Fill
|
||||
};
|
||||
|
||||
if (Rotation != 0d)
|
||||
{
|
||||
image.RenderTransform = new RotateTransform { Angle = Rotation };
|
||||
var panel = new Grid();
|
||||
panel.Children.Add(image);
|
||||
image = panel;
|
||||
}
|
||||
|
||||
MapPanel.SetBoundingBox(image, BoundingBox);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
public static async Task<FrameworkElement> CreateImage(string imageFilePath)
|
||||
{
|
||||
return (await ReadImage(imageFilePath)).CreateImage();
|
||||
}
|
||||
|
||||
private static async void PathPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (o is Image image && e.NewValue is string imageFilePath)
|
||||
{
|
||||
(await ReadImage(imageFilePath)).ApplyToImage(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,276 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2022 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
#elif UWP
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
#endif
|
||||
|
||||
namespace MapControl.Images
|
||||
{
|
||||
public class GroundOverlayPanel : MapPanel
|
||||
{
|
||||
class LatLonBox : BoundingBox
|
||||
{
|
||||
public LatLonBox(double south, double west, double north, double east, double rotation)
|
||||
: base(south, west, north, east)
|
||||
{
|
||||
Rotation = rotation;
|
||||
}
|
||||
|
||||
public double Rotation { get; }
|
||||
}
|
||||
|
||||
class ImageOverlay
|
||||
{
|
||||
public ImageOverlay(LatLonBox latLonBox, string imagePath, int zIndex)
|
||||
{
|
||||
LatLonBox = latLonBox;
|
||||
ImagePath = imagePath;
|
||||
ZIndex = zIndex;
|
||||
}
|
||||
|
||||
public LatLonBox LatLonBox { get; }
|
||||
public string ImagePath { get; }
|
||||
public int ZIndex { get; }
|
||||
public ImageSource ImageSource { get; set; }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty KmlFileProperty = DependencyProperty.Register(
|
||||
nameof(KmlFile), typeof(string), typeof(GroundOverlayPanel),
|
||||
new PropertyMetadata(null, async (o, e) => await ((GroundOverlayPanel)o).KmlFilePropertyChanged((string)e.NewValue)));
|
||||
|
||||
public string KmlFile
|
||||
{
|
||||
get { return (string)GetValue(KmlFileProperty); }
|
||||
set { SetValue(KmlFileProperty, value); }
|
||||
}
|
||||
|
||||
private async Task KmlFilePropertyChanged(string path)
|
||||
{
|
||||
IEnumerable<ImageOverlay> imageOverlays = null;
|
||||
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
try
|
||||
{
|
||||
var ext = Path.GetExtension(path).ToLower();
|
||||
if (ext == ".kmz")
|
||||
{
|
||||
imageOverlays = await ReadGroundOverlaysFromArchiveAsync(path);
|
||||
}
|
||||
else if (ext == ".kml")
|
||||
{
|
||||
imageOverlays = await ReadGroundOverlaysFromFileAsync(path);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"GroundOverlayPanel: {path}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
Children.Clear();
|
||||
|
||||
if (imageOverlays != null)
|
||||
{
|
||||
AddImageOverlays(imageOverlays);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddImageOverlays(IEnumerable<ImageOverlay> imageOverlays)
|
||||
{
|
||||
foreach (var imageOverlay in imageOverlays.Where(i => i.ImageSource != null))
|
||||
{
|
||||
FrameworkElement overlay = new Image
|
||||
{
|
||||
Source = imageOverlay.ImageSource,
|
||||
Stretch = Stretch.Fill,
|
||||
UseLayoutRounding = false
|
||||
};
|
||||
|
||||
if (imageOverlay.LatLonBox.Rotation != 0d)
|
||||
{
|
||||
overlay.RenderTransform = new RotateTransform { Angle = -imageOverlay.LatLonBox.Rotation };
|
||||
overlay.RenderTransformOrigin = new Point(0.5, 0.5);
|
||||
|
||||
// additional Panel for map rotation, see MapPanel.ArrangeElementWithBoundingBox
|
||||
var panel = new Grid { UseLayoutRounding = false };
|
||||
panel.Children.Add(overlay);
|
||||
overlay = panel;
|
||||
}
|
||||
|
||||
SetBoundingBox(overlay, imageOverlay.LatLonBox);
|
||||
Canvas.SetZIndex(overlay, imageOverlay.ZIndex);
|
||||
Children.Add(overlay);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<IEnumerable<ImageOverlay>> ReadGroundOverlaysFromArchiveAsync(string archiveFile)
|
||||
{
|
||||
using (var archive = await Task.Run(() => ZipFile.OpenRead(archiveFile)))
|
||||
{
|
||||
var docEntry = await Task.Run(() => archive.GetEntry("doc.kml") ?? archive.Entries.FirstOrDefault(e => e.Name.EndsWith(".kml")));
|
||||
|
||||
if (docEntry == null)
|
||||
{
|
||||
throw new ArgumentException("No KML entry found in " + archiveFile);
|
||||
}
|
||||
|
||||
var imageOverlays = await Task.Run(() =>
|
||||
{
|
||||
var kmlDocument = new XmlDocument();
|
||||
|
||||
using (var docStream = docEntry.Open())
|
||||
{
|
||||
kmlDocument.Load(docStream);
|
||||
}
|
||||
|
||||
return ReadGroundOverlays(kmlDocument).ToList();
|
||||
});
|
||||
|
||||
foreach (var imageOverlay in imageOverlays)
|
||||
{
|
||||
var imageEntry = await Task.Run(() => archive.GetEntry(imageOverlay.ImagePath));
|
||||
|
||||
if (imageEntry != null)
|
||||
{
|
||||
using (var zipStream = imageEntry.Open())
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
await zipStream.CopyToAsync(memoryStream);
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
imageOverlay.ImageSource = await ImageLoader.LoadImageAsync(memoryStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return imageOverlays;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<IEnumerable<ImageOverlay>> ReadGroundOverlaysFromFileAsync(string docFile)
|
||||
{
|
||||
docFile = Path.GetFullPath(docFile);
|
||||
var docUri = new Uri(docFile);
|
||||
|
||||
var imageOverlays = await Task.Run(() =>
|
||||
{
|
||||
var kmlDocument = new XmlDocument();
|
||||
kmlDocument.Load(docFile);
|
||||
|
||||
return ReadGroundOverlays(kmlDocument).ToList();
|
||||
});
|
||||
|
||||
foreach (var imageOverlay in imageOverlays)
|
||||
{
|
||||
imageOverlay.ImageSource = await ImageLoader.LoadImageAsync(new Uri(docUri, imageOverlay.ImagePath));
|
||||
}
|
||||
|
||||
return imageOverlays;
|
||||
}
|
||||
|
||||
private static IEnumerable<ImageOverlay> ReadGroundOverlays(XmlDocument kmlDocument)
|
||||
{
|
||||
foreach (XmlElement groundOverlayElement in kmlDocument.GetElementsByTagName("GroundOverlay"))
|
||||
{
|
||||
LatLonBox latLonBox = null;
|
||||
string imagePath = null;
|
||||
int zIndex = 0;
|
||||
|
||||
foreach (var childElement in groundOverlayElement.ChildNodes.OfType<XmlElement>())
|
||||
{
|
||||
switch (childElement.LocalName)
|
||||
{
|
||||
case "LatLonBox":
|
||||
latLonBox = ReadLatLonBox(childElement);
|
||||
break;
|
||||
case "Icon":
|
||||
imagePath = ReadImagePath(childElement);
|
||||
break;
|
||||
case "drawOrder":
|
||||
int.TryParse(childElement.InnerText.Trim(), out zIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (latLonBox != null && imagePath != null)
|
||||
{
|
||||
yield return new ImageOverlay(latLonBox, imagePath, zIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string ReadImagePath(XmlElement element)
|
||||
{
|
||||
string href = null;
|
||||
|
||||
foreach (var childElement in element.ChildNodes.OfType<XmlElement>())
|
||||
{
|
||||
switch (childElement.LocalName)
|
||||
{
|
||||
case "href":
|
||||
href = childElement.InnerText.Trim();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return href;
|
||||
}
|
||||
|
||||
private static LatLonBox ReadLatLonBox(XmlElement element)
|
||||
{
|
||||
double north = double.NaN;
|
||||
double south = double.NaN;
|
||||
double east = double.NaN;
|
||||
double west = double.NaN;
|
||||
double rotation = 0d;
|
||||
|
||||
foreach (var childElement in element.ChildNodes.OfType<XmlElement>())
|
||||
{
|
||||
switch (childElement.LocalName)
|
||||
{
|
||||
case "north":
|
||||
double.TryParse(childElement.InnerText.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out north);
|
||||
break;
|
||||
case "south":
|
||||
double.TryParse(childElement.InnerText.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out south);
|
||||
break;
|
||||
case "east":
|
||||
double.TryParse(childElement.InnerText.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out east);
|
||||
break;
|
||||
case "west":
|
||||
double.TryParse(childElement.InnerText.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out west);
|
||||
break;
|
||||
case "rotation":
|
||||
double.TryParse(childElement.InnerText.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out rotation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return !double.IsNaN(north) && !double.IsNaN(south) && !double.IsNaN(east) && !double.IsNaN(west)
|
||||
? new LatLonBox(south, west, north, east, rotation)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{BE08B7BC-8C89-4837-BCE7-EDDDABEAB372}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>MapControl.Images</RootNamespace>
|
||||
<AssemblyName>MapImages.UWP</AssemblyName>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.19041.0</TargetPlatformVersion>
|
||||
<TargetPlatformMinVersion>10.0.17134.0</TargetPlatformMinVersion>
|
||||
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;UWP</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>UWP</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Shared\GeoImage.cs">
|
||||
<Link>GeoImage.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\GroundOverlayPanel.cs">
|
||||
<Link>GroundOverlayPanel.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\GeoImage.WinUI.cs">
|
||||
<Link>GeoImage.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="Properties\MapImages.UWP.rd.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||
<Version>6.2.13</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\MapControl\UWP\MapControl.UWP.csproj">
|
||||
<Project>{9545f73c-9c35-4cf6-baae-19a0baebd344}</Project>
|
||||
<Name>MapControl.UWP</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\MapProjections\UWP\MapProjections.UWP.csproj">
|
||||
<Project>{9ee69591-5edc-45e3-893e-2f9a4b82d538}</Project>
|
||||
<Name>MapProjections.UWP</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\MapControl.snk">
|
||||
<Link>MapControl.snk</Link>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AssemblyOriginatorKeyFile>..\..\MapControl.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
||||
</Project>
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("XAML Map Control Image Support Library for UWP")]
|
||||
[assembly: AssemblyProduct("XAML Map Control")]
|
||||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("7.1.0")]
|
||||
[assembly: AssemblyFileVersion("7.1.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
This file contains Runtime Directives, specifications about types your application accesses
|
||||
through reflection and other dynamic code patterns. Runtime Directives are used to control the
|
||||
.NET Native optimizer and ensure that it does not remove code accessed by your library. If your
|
||||
library does not do any reflection, then you generally do not need to edit this file. However,
|
||||
if your library reflects over types, especially types passed to it or derived from its types,
|
||||
then you should write Runtime Directives.
|
||||
|
||||
The most common use of reflection in libraries is to discover information about types passed
|
||||
to the library. Runtime Directives have three ways to express requirements on types passed to
|
||||
your library.
|
||||
|
||||
1. Parameter, GenericParameter, TypeParameter, TypeEnumerableParameter
|
||||
Use these directives to reflect over types passed as a parameter.
|
||||
|
||||
2. SubTypes
|
||||
Use a SubTypes directive to reflect over types derived from another type.
|
||||
|
||||
3. AttributeImplies
|
||||
Use an AttributeImplies directive to indicate that your library needs to reflect over
|
||||
types or methods decorated with an attribute.
|
||||
|
||||
For more information on writing Runtime Directives for libraries, please visit
|
||||
https://go.microsoft.com/fwlink/?LinkID=391919
|
||||
-->
|
||||
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
|
||||
<Library Name="MapImages.UWP">
|
||||
|
||||
<!-- add directives for your library here -->
|
||||
|
||||
</Library>
|
||||
</Directives>
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2022 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace MapControl.Images
|
||||
{
|
||||
public partial class GeoImage
|
||||
{
|
||||
public static Task<GeoImage> ReadGeoTiff(string imageFilePath)
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
BitmapSource bitmap;
|
||||
Matrix transform;
|
||||
|
||||
using (var stream = File.OpenRead(imageFilePath))
|
||||
{
|
||||
bitmap = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
||||
}
|
||||
|
||||
var metadata = bitmap.Metadata as BitmapMetadata;
|
||||
|
||||
if (metadata.GetQuery((string)PixelScaleQuery) is double[] pixelScale && pixelScale.Length == 3 &&
|
||||
metadata.GetQuery((string)TiePointQuery) is double[] tiePoint && tiePoint.Length >= 6)
|
||||
{
|
||||
transform = new Matrix(pixelScale[0], 0d, 0d, -pixelScale[1], tiePoint[3], tiePoint[4]);
|
||||
}
|
||||
else if (metadata.GetQuery((string)TransformQuery) 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 + "\".");
|
||||
}
|
||||
|
||||
if (metadata.GetQuery((string)NoDataQuery) is string noData && int.TryParse(noData, out int noDataValue))
|
||||
{
|
||||
bitmap = ConvertTransparentPixel(bitmap, noDataValue);
|
||||
}
|
||||
|
||||
return new GeoImage(bitmap, transform, (MapProjection)null);
|
||||
});
|
||||
}
|
||||
|
||||
public static BitmapSource ConvertTransparentPixel(BitmapSource source, int transparentPixel)
|
||||
{
|
||||
BitmapPalette sourcePalette = null;
|
||||
var targetFormat = source.Format;
|
||||
|
||||
if (source.Format == PixelFormats.Indexed8 ||
|
||||
source.Format == PixelFormats.Indexed4 ||
|
||||
source.Format == PixelFormats.Indexed2 ||
|
||||
source.Format == PixelFormats.Indexed1)
|
||||
{
|
||||
sourcePalette = source.Palette;
|
||||
}
|
||||
else if (source.Format == PixelFormats.Gray8)
|
||||
{
|
||||
sourcePalette = BitmapPalettes.Gray256;
|
||||
targetFormat = PixelFormats.Indexed8;
|
||||
}
|
||||
else if (source.Format == PixelFormats.Gray4)
|
||||
{
|
||||
sourcePalette = BitmapPalettes.Gray16;
|
||||
targetFormat = PixelFormats.Indexed4;
|
||||
}
|
||||
else if (source.Format == PixelFormats.Gray2)
|
||||
{
|
||||
sourcePalette = BitmapPalettes.Gray4;
|
||||
targetFormat = PixelFormats.Indexed2;
|
||||
}
|
||||
else if (source.Format == PixelFormats.BlackWhite)
|
||||
{
|
||||
sourcePalette = BitmapPalettes.BlackAndWhite;
|
||||
targetFormat = PixelFormats.Indexed1;
|
||||
}
|
||||
|
||||
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;
|
||||
var buffer = new byte[stride * source.PixelHeight];
|
||||
|
||||
source.CopyPixels(buffer, stride, 0);
|
||||
|
||||
var target = BitmapSource.Create(
|
||||
source.PixelWidth, source.PixelHeight, source.DpiX, source.DpiY,
|
||||
targetFormat, new BitmapPalette(colors), buffer, stride);
|
||||
|
||||
target.Freeze();
|
||||
|
||||
return target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0-windows;net5.0-windows;netcoreapp3.1;net48;net462</TargetFrameworks>
|
||||
<UseWPF>true</UseWPF>
|
||||
<RootNamespace>MapControl.Images</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control Image Support Library for WPF</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.1.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>..\..\MapControl.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||
<PackageId>XAML.MapControl.MapImages</PackageId>
|
||||
<DefineConstants></DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\..\MapControl.snk" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Shared\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='net48' or '$(TargetFramework)'=='net462'">
|
||||
<Reference Include="System.IO.Compression" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\MapControl\WPF\MapControl.WPF.csproj" />
|
||||
<ProjectReference Include="..\..\MapProjections\WPF\MapProjections.WPF.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2022 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using Windows.Graphics.Imaging;
|
||||
using Windows.Storage;
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
#else
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
#endif
|
||||
|
||||
namespace MapControl.Images
|
||||
{
|
||||
public partial class GeoImage
|
||||
{
|
||||
public static async Task<GeoImage> ReadGeoTiff(string imageFilePath)
|
||||
{
|
||||
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<string>
|
||||
{
|
||||
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 GeoImage(bitmap, transform, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<RootNamespace>MapControl.Images</RootNamespace>
|
||||
<AssemblyTitle>XAML Map Control Image Support Library for WinUI</AssemblyTitle>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>7.1.0</Version>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2022 Clemens Fischer</Copyright>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>..\..\MapControl.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||
<PackageId>XAML.MapControl.MapImages</PackageId>
|
||||
<DefineConstants>WINUI</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\..\MapControl.snk" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Shared\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.0.0" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22000.196" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\MapControl\WinUI\MapControl.WinUI.csproj" />
|
||||
<ProjectReference Include="..\..\MapProjections\WinUI\MapProjections.WinUI.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Loading…
Reference in a new issue