summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Brentjes <d.brentjes@gmail.com>2019-12-24 16:45:22 +0100
committerDennis Brentjes <d.brentjes@gmail.com>2019-12-24 16:45:22 +0100
commitfbe866f7b26c10bb54d72c029f8c628988a90be2 (patch)
tree7617f1209333ff40c31aa156d541e8ea59e991ed
parent0f98b398520a3f5cc6a299e7fd3b8fab494480d7 (diff)
downloadavalar-fbe866f7b26c10bb54d72c029f8c628988a90be2.tar.gz
avalar-fbe866f7b26c10bb54d72c029f8c628988a90be2.tar.bz2
avalar-fbe866f7b26c10bb54d72c029f8c628988a90be2.zip
Started on the resizing step of the pipeline + pipeline design.
-rw-r--r--Avalar.csproj8
-rw-r--r--MainWindow.xaml2
-rw-r--r--MainWindow.xaml.cs15
-rw-r--r--Models/ImageModel.cs56
-rw-r--r--Models/Interfaces/IImageModel.cs9
-rw-r--r--Models/Interfaces/SettingsModel.cs12
-rw-r--r--Services/IProcessor.cs9
-rw-r--r--Services/Resizer/IResizer.cs7
-rw-r--r--Services/Resizer/ImageMagickResizer.cs26
-rw-r--r--ViewModels/Image/ImageViewModel.cs13
-rw-r--r--ViewModels/Settings/SettingsViewModel.cs2
-rw-r--r--Views/AvalarViewService.cs2
-rw-r--r--Views/Image/ImageControl.xaml.cs8
-rw-r--r--Views/Settings/Settings.xaml2
-rw-r--r--Views/Settings/Settings.xaml.cs4
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();
}