diff options
| author | Dennis Brentjes <d.brentjes@gmail.com> | 2019-12-24 16:45:22 +0100 |
|---|---|---|
| committer | Dennis Brentjes <d.brentjes@gmail.com> | 2019-12-24 16:45:22 +0100 |
| commit | fbe866f7b26c10bb54d72c029f8c628988a90be2 (patch) | |
| tree | 7617f1209333ff40c31aa156d541e8ea59e991ed | |
| parent | 0f98b398520a3f5cc6a299e7fd3b8fab494480d7 (diff) | |
| download | avalar-fbe866f7b26c10bb54d72c029f8c628988a90be2.tar.gz avalar-fbe866f7b26c10bb54d72c029f8c628988a90be2.tar.bz2 avalar-fbe866f7b26c10bb54d72c029f8c628988a90be2.zip | |
Started on the resizing step of the pipeline + pipeline design.
| -rw-r--r-- | Avalar.csproj | 8 | ||||
| -rw-r--r-- | MainWindow.xaml | 2 | ||||
| -rw-r--r-- | MainWindow.xaml.cs | 15 | ||||
| -rw-r--r-- | Models/ImageModel.cs | 56 | ||||
| -rw-r--r-- | Models/Interfaces/IImageModel.cs | 9 | ||||
| -rw-r--r-- | Models/Interfaces/SettingsModel.cs | 12 | ||||
| -rw-r--r-- | Services/IProcessor.cs | 9 | ||||
| -rw-r--r-- | Services/Resizer/IResizer.cs | 7 | ||||
| -rw-r--r-- | Services/Resizer/ImageMagickResizer.cs | 26 | ||||
| -rw-r--r-- | ViewModels/Image/ImageViewModel.cs | 13 | ||||
| -rw-r--r-- | ViewModels/Settings/SettingsViewModel.cs | 2 | ||||
| -rw-r--r-- | Views/AvalarViewService.cs | 2 | ||||
| -rw-r--r-- | Views/Image/ImageControl.xaml.cs | 8 | ||||
| -rw-r--r-- | Views/Settings/Settings.xaml | 2 | ||||
| -rw-r--r-- | Views/Settings/Settings.xaml.cs | 4 |
15 files changed, 159 insertions, 16 deletions
diff --git a/Avalar.csproj b/Avalar.csproj index 93ac3a3..06e24a5 100644 --- a/Avalar.csproj +++ b/Avalar.csproj @@ -1,6 +1,6 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <OutputType>WinExe</OutputType> + <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.0</TargetFramework> <AllowUnsafeBlocks>false</AllowUnsafeBlocks> </PropertyGroup> @@ -25,6 +25,12 @@ <PackageReference Include="Avalonia.Desktop" Version="0.9.0" /> <PackageReference Include="Avalonia.ReactiveUI" Version="0.9.0" /> <PackageReference Include="Avalonia.Xaml.Behaviors" Version="0.9.0" /> + <PackageReference Include="Magick.NET-Q16-AnyCPU" Version="7.14.5" /> + <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8"> + <PrivateAssets>all</PrivateAssets> + <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> + </PackageReference> + <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.0" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="Views\Image\ImageControl.xaml"> diff --git a/MainWindow.xaml b/MainWindow.xaml index b4a5565..d42cef5 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -13,6 +13,6 @@ <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <image:ImagePanel DataContext="{Binding ImageVm}" Grid.Column="0"/> - <settings:Settings DataContext="{Binding SettingsVm}" Grid.Column="1"/> + <settings:SettingsControl DataContext="{Binding SettingsVm}" Grid.Column="1"/> </Grid> </Window> diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index 154ee31..b2a5090 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -1,8 +1,11 @@ +using Avalar.Models; +using Avalar.Services.Resizer; using Avalar.Viewmodels.Image; using Avalar.ViewModels.Settings; using Avalar.Views; using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Microsoft.Extensions.DependencyInjection; namespace Avalar { @@ -11,14 +14,20 @@ namespace Avalar private ImageViewModel ImageVm { get; } private SettingsViewModel SettingsVm { get; } - private IAvalarViewService ViewService { get; } + private ImageModel ImageM { get; } + public MainWindow() { InitializeComponent(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddScoped(typeof(IResizer), typeof(ImageMagickResizer)); + serviceCollection.AddScoped(typeof(IAvalarViewService), (sp) => new AvalarViewService(this)); + + var serviceProvider = serviceCollection.BuildServiceProvider(); - ViewService = new AvalarViewService(this); + ImageM = new ImageModel(); - ImageVm = new ImageViewModel(ViewService); + ImageVm = new ImageViewModel(ImageM, serviceProvider); SettingsVm = new SettingsViewModel(); DataContext = this; diff --git a/Models/ImageModel.cs b/Models/ImageModel.cs new file mode 100644 index 0000000..e0bb1af --- /dev/null +++ b/Models/ImageModel.cs @@ -0,0 +1,56 @@ +using Avalar.Models.Interfaces; +using Avalonia.Media.Imaging; +using ReactiveUI; +using System; + +namespace Avalar.Models +{ + public class ImageModel : ReactiveObject, IImageModel, ISettingsModel, IDisposable + { + + private IBitmap m_OriginalBitmap; + + private IBitmap m_LatestResult; + + private double m_Width; + public double Width { + get => m_Width; + set => this.RaiseAndSetIfChanged(ref m_Width, value); + } + + private double m_Height; + public double Height + { + get => m_Height; + set => this.RaiseAndSetIfChanged(ref m_Height, value); + } + + public IBitmap LoadImage(string imagePath) + { + m_OriginalBitmap = new Bitmap(imagePath); + m_LatestResult = m_OriginalBitmap; + return m_LatestResult; + } + + private bool disposed = false; + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposed) return; + + if (disposing) + { + m_OriginalBitmap.Dispose(); + m_LatestResult.Dispose(); + } + + disposed = true; + } + } +} diff --git a/Models/Interfaces/IImageModel.cs b/Models/Interfaces/IImageModel.cs new file mode 100644 index 0000000..897a221 --- /dev/null +++ b/Models/Interfaces/IImageModel.cs @@ -0,0 +1,9 @@ +using Avalonia.Media.Imaging; + +namespace Avalar.Models.Interfaces +{ + public interface IImageModel + { + IBitmap LoadImage(string imagePath); + } +} diff --git a/Models/Interfaces/SettingsModel.cs b/Models/Interfaces/SettingsModel.cs new file mode 100644 index 0000000..6149c1e --- /dev/null +++ b/Models/Interfaces/SettingsModel.cs @@ -0,0 +1,12 @@ + +using Avalonia; + +namespace Avalar.Models.Interfaces +{ + interface ISettingsModel + { + public double Width { get; set; } + + public double Height { get; set; } + } +} diff --git a/Services/IProcessor.cs b/Services/IProcessor.cs new file mode 100644 index 0000000..11e83ab --- /dev/null +++ b/Services/IProcessor.cs @@ -0,0 +1,9 @@ +using Avalonia.Media.Imaging; + +namespace Avalar.Services +{ + public interface IProcessor + { + IBitmap Process(IBitmap bitmap); + } +} diff --git a/Services/Resizer/IResizer.cs b/Services/Resizer/IResizer.cs new file mode 100644 index 0000000..e71d4f1 --- /dev/null +++ b/Services/Resizer/IResizer.cs @@ -0,0 +1,7 @@ + +namespace Avalar.Services.Resizer +{ + public interface IResizer : IProcessor + { + } +} diff --git a/Services/Resizer/ImageMagickResizer.cs b/Services/Resizer/ImageMagickResizer.cs new file mode 100644 index 0000000..e48e576 --- /dev/null +++ b/Services/Resizer/ImageMagickResizer.cs @@ -0,0 +1,26 @@ + +using Avalonia.Media.Imaging; +using ImageMagick; +using System.IO; + +namespace Avalar.Services.Resizer +{ + public class ImageMagickResizer : IResizer + { + public IBitmap Process(IBitmap bitmap) + { + using (var stream = new MemoryStream()) + { + bitmap?.Save(stream); + using (var image = new MagickImage(stream)) + { + image.Resize(300, 300); + using (var stream2 = new MemoryStream()) + { + return new Bitmap(stream2); + } + } + } + } + } +} diff --git a/ViewModels/Image/ImageViewModel.cs b/ViewModels/Image/ImageViewModel.cs index 030a95b..3b41919 100644 --- a/ViewModels/Image/ImageViewModel.cs +++ b/ViewModels/Image/ImageViewModel.cs @@ -1,22 +1,27 @@ +using Avalar.Models.Interfaces; using Avalar.ViewModels.Image; using Avalar.Views; using Avalonia.Media.Imaging; using ReactiveUI; +using System; using System.Linq; namespace Avalar.Viewmodels.Image { public class ImageViewModel : ReactiveObject { - public ImageViewModel(IAvalarViewService viewService) + public ImageViewModel(IImageModel imageModel, IServiceProvider serviceProvider) { - ViewService = viewService; + ViewService = serviceProvider?.GetService(typeof(IAvalarViewService)) as IAvalarViewService; + ImageModel = imageModel; ChildViewModel = new ImageNotLoadedViewModel(ReactiveCommand.Create(OpenFile)); } private IAvalarViewService ViewService { get; } + private IImageModel ImageModel { get; } + private object m_ChildViewModel; public object ChildViewModel @@ -29,10 +34,10 @@ namespace Avalar.Viewmodels.Image public async void OpenFile() { - var result = await ViewService.ShowOpenImageFileDialog(); + var result = await ViewService.ShowOpenImageFileDialog().ConfigureAwait(true); if (result.Length != 1) return; - ChildViewModel = new ImageLoadedViewModel(new Bitmap(result.First())); + ChildViewModel = new ImageLoadedViewModel(ImageModel.LoadImage(result.First())); } } } diff --git a/ViewModels/Settings/SettingsViewModel.cs b/ViewModels/Settings/SettingsViewModel.cs index b9f076b..730b662 100644 --- a/ViewModels/Settings/SettingsViewModel.cs +++ b/ViewModels/Settings/SettingsViewModel.cs @@ -1,7 +1,7 @@ namespace Avalar.ViewModels.Settings { - class SettingsViewModel + public class SettingsViewModel { } } diff --git a/Views/AvalarViewService.cs b/Views/AvalarViewService.cs index 994f88b..7b0cc0b 100644 --- a/Views/AvalarViewService.cs +++ b/Views/AvalarViewService.cs @@ -25,7 +25,7 @@ namespace Avalar.Views openFileDialog.Title = "Open Image"; - var result = await openFileDialog.ShowAsync(m_Window); + var result = await openFileDialog.ShowAsync(m_Window).ConfigureAwait(false); return result; } } diff --git a/Views/Image/ImageControl.xaml.cs b/Views/Image/ImageControl.xaml.cs index 2189bb0..e806d6f 100644 --- a/Views/Image/ImageControl.xaml.cs +++ b/Views/Image/ImageControl.xaml.cs @@ -21,7 +21,11 @@ namespace Avalar.Views.Image { InitializeComponent(); - Image = this.FindResource("ImageBrush") as ImageBrush ?? throw new System.ArgumentException("ImageBrush"); + var brushName = "ImageBrush"; + string message = $"The brush with name {brushName} could not be found in the Xaml Resources"; +#pragma warning disable CA1303 // Do not pass literals as localized parameters + Image = (this).FindResource(brushName) as ImageBrush ?? throw new ArgumentException(message); +#pragma warning restore CA1303 // Do not pass literals as localized parameters ImageCanvas = this.FindControl<Canvas>("ImageCanvas"); } @@ -73,7 +77,7 @@ namespace Avalar.Views.Image public void OnPointerWheelChanged(object sender, PointerWheelEventArgs e) { var invOldZoom = InvCurrentZoom; - var zoomFactor = e.Delta.Y * ZoomTick + 1.0; + var zoomFactor = (e?.Delta.Y ?? 0) * ZoomTick + 1.0; CurrentZoom = Math.Clamp(CurrentZoom * zoomFactor, 1, double.PositiveInfinity); var sourceRect = Image.SourceRect.Rect; diff --git a/Views/Settings/Settings.xaml b/Views/Settings/Settings.xaml index dfc8602..fb547e7 100644 --- a/Views/Settings/Settings.xaml +++ b/Views/Settings/Settings.xaml @@ -3,7 +3,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" - x:Class="Avalar.Views.Settings.Settings" + x:Class="Avalar.Views.Settings.SettingsControl" MinWidth="400"> Welcome to Avalonia! </UserControl> diff --git a/Views/Settings/Settings.xaml.cs b/Views/Settings/Settings.xaml.cs index 4504460..1197c39 100644 --- a/Views/Settings/Settings.xaml.cs +++ b/Views/Settings/Settings.xaml.cs @@ -3,9 +3,9 @@ using Avalonia.Markup.Xaml; namespace Avalar.Views.Settings { - public class Settings : UserControl + public class SettingsControl : UserControl { - public Settings() + public SettingsControl() { InitializeComponent(); } |
