wip
This commit is contained in:
parent
11651e5c30
commit
0f931aa2d4
@ -1,9 +1,9 @@
|
||||
using System.Windows;
|
||||
|
||||
using CamBooth.App.Core.AppSettings;
|
||||
using CamBooth.App.Camera;
|
||||
using CamBooth.App.Core.Logging;
|
||||
using CamBooth.App.PictureGallery;
|
||||
using CamBooth.App.Features.Camera;
|
||||
using CamBooth.App.Features.PictureGallery;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Core\Models\" />
|
||||
<Folder Include="Features\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@ -41,4 +42,16 @@
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Features\DebugConsole\DebugConsolePage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Features\LiveView\LiveViewPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Features\PictureGallery\PictureGalleryPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@ -1,46 +1,42 @@
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Threading;
|
||||
|
||||
using CamBooth.App.Core.AppSettings;
|
||||
using CamBooth.App.Core.Logging;
|
||||
using CamBooth.App.LiveView;
|
||||
using CamBooth.App.PictureGallery;
|
||||
using CamBooth.App.Features.PictureGallery;
|
||||
|
||||
using EOSDigital.API;
|
||||
using EOSDigital.SDK;
|
||||
|
||||
namespace CamBooth.App.Camera;
|
||||
namespace CamBooth.App.Features.Camera;
|
||||
|
||||
public class CameraService : IDisposable
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
private readonly AppSettingsService _appSettings;
|
||||
|
||||
private readonly Logger _logger;
|
||||
|
||||
private readonly PictureGalleryService _pictureGalleryService;
|
||||
|
||||
CanonAPI APIHandler;
|
||||
private readonly CanonAPI APIHandler;
|
||||
|
||||
private CameraValue[] AvList;
|
||||
|
||||
private int BulbTime = 30;
|
||||
|
||||
private List<EOSDigital.API.Camera> CamList;
|
||||
|
||||
private int ErrCount;
|
||||
|
||||
private object ErrLock = new();
|
||||
|
||||
private bool IsInit;
|
||||
|
||||
private CameraValue[] ISOList;
|
||||
|
||||
public EOSDigital.API.Camera MainCamera;
|
||||
|
||||
bool IsInit = false;
|
||||
|
||||
List<EOSDigital.API.Camera> CamList;
|
||||
|
||||
CameraValue[] AvList;
|
||||
|
||||
CameraValue[] TvList;
|
||||
|
||||
CameraValue[] ISOList;
|
||||
|
||||
int BulbTime = 30;
|
||||
|
||||
int ErrCount;
|
||||
|
||||
object ErrLock = new object();
|
||||
private CameraValue[] TvList;
|
||||
|
||||
|
||||
public CameraService(Logger logger, AppSettingsService appSettings, PictureGalleryService pictureGalleryService)
|
||||
@ -50,8 +46,8 @@ public class CameraService : IDisposable
|
||||
this._pictureGalleryService = pictureGalleryService;
|
||||
try
|
||||
{
|
||||
APIHandler = new CanonAPI();
|
||||
IsInit = true;
|
||||
this.APIHandler = new CanonAPI();
|
||||
this.IsInit = true;
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
@ -64,12 +60,22 @@ public class CameraService : IDisposable
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.CloseSession();
|
||||
this.IsInit = false;
|
||||
this.APIHandler.Dispose();
|
||||
this.MainCamera.Dispose();
|
||||
}
|
||||
|
||||
|
||||
public void ConnectCamera()
|
||||
{
|
||||
ErrorHandler.SevereErrorHappened += ErrorHandler_SevereErrorHappened;
|
||||
ErrorHandler.NonSevereErrorHappened += ErrorHandler_NonSevereErrorHappened;
|
||||
ErrorHandler.SevereErrorHappened += this.ErrorHandler_SevereErrorHappened;
|
||||
ErrorHandler.NonSevereErrorHappened += this.ErrorHandler_NonSevereErrorHappened;
|
||||
|
||||
RefreshCamera();
|
||||
this.RefreshCamera();
|
||||
List<EOSDigital.API.Camera> cameraList = this.APIHandler.GetCameraList();
|
||||
if (cameraList.Any())
|
||||
{
|
||||
@ -79,20 +85,20 @@ public class CameraService : IDisposable
|
||||
}
|
||||
|
||||
string cameraDeviceNames = string.Join(", ", cameraList.Select(cam => cam.DeviceName));
|
||||
_logger.Info(cameraDeviceNames == string.Empty ? "No cameras / devices found" : cameraDeviceNames);
|
||||
this._logger.Info(cameraDeviceNames == string.Empty ? "No cameras / devices found" : cameraDeviceNames);
|
||||
}
|
||||
|
||||
|
||||
private void SetSettingSaveToComputer()
|
||||
{
|
||||
MainCamera.SetSetting(PropertyID.SaveTo, (int)SaveTo.Host);
|
||||
MainCamera.SetCapacity(4096, int.MaxValue);
|
||||
this.MainCamera.SetSetting(PropertyID.SaveTo, (int)SaveTo.Host);
|
||||
this.MainCamera.SetCapacity(4096, int.MaxValue);
|
||||
}
|
||||
|
||||
|
||||
public void CloseSession()
|
||||
{
|
||||
MainCamera.CloseSession();
|
||||
this.MainCamera.CloseSession();
|
||||
|
||||
// AvCoBox.Items.Clear();
|
||||
// TvCoBox.Items.Clear();
|
||||
@ -108,7 +114,7 @@ public class CameraService : IDisposable
|
||||
private void RefreshCamera()
|
||||
{
|
||||
// CameraListBox.Items.Clear();
|
||||
CamList = APIHandler.GetCameraList();
|
||||
this.CamList = this.APIHandler.GetCameraList();
|
||||
|
||||
// foreach (Camera cam in CamList) CameraListBox.Items.Add(cam.DeviceName);
|
||||
// if (MainCamera?.SessionOpen == true) CameraListBox.SelectedIndex = CamList.FindIndex(t => t.ID == MainCamera.ID);
|
||||
@ -118,17 +124,17 @@ public class CameraService : IDisposable
|
||||
|
||||
private void OpenSession()
|
||||
{
|
||||
MainCamera = CamList[0];
|
||||
MainCamera.OpenSession();
|
||||
this.MainCamera = this.CamList[0];
|
||||
this.MainCamera.OpenSession();
|
||||
|
||||
//MainCamera.ProgressChanged += MainCamera_ProgressChanged;
|
||||
MainCamera.StateChanged += MainCamera_StateChanged;
|
||||
MainCamera.DownloadReady += MainCamera_DownloadReady;
|
||||
this.MainCamera.StateChanged += this.MainCamera_StateChanged;
|
||||
this.MainCamera.DownloadReady += this.MainCamera_DownloadReady;
|
||||
|
||||
//SessionLabel.Content = MainCamera.DeviceName;
|
||||
AvList = MainCamera.GetSettingsList(PropertyID.Av);
|
||||
TvList = MainCamera.GetSettingsList(PropertyID.Tv);
|
||||
ISOList = MainCamera.GetSettingsList(PropertyID.ISO);
|
||||
this.AvList = this.MainCamera.GetSettingsList(PropertyID.Av);
|
||||
this.TvList = this.MainCamera.GetSettingsList(PropertyID.Tv);
|
||||
this.ISOList = this.MainCamera.GetSettingsList(PropertyID.ISO);
|
||||
|
||||
// foreach (var Av in AvList) AvCoBox.Items.Add(Av.StringValue);
|
||||
// foreach (var Tv in TvList) TvCoBox.Items.Add(Tv.StringValue);
|
||||
@ -151,13 +157,13 @@ public class CameraService : IDisposable
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!MainCamera.IsLiveViewOn)
|
||||
if (!this.MainCamera.IsLiveViewOn)
|
||||
{
|
||||
MainCamera.StartLiveView();
|
||||
this.MainCamera.StartLiveView();
|
||||
}
|
||||
else
|
||||
{
|
||||
MainCamera.StopLiveView();
|
||||
this.MainCamera.StopLiveView();
|
||||
|
||||
//LVCanvas.Background = Brushes.LightGray;
|
||||
}
|
||||
@ -169,6 +175,20 @@ public class CameraService : IDisposable
|
||||
}
|
||||
|
||||
|
||||
public void TakePhoto()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.MainCamera.TakePhoto();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.ReportError(ex.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region API Events
|
||||
|
||||
// private void APIHandler_CameraAdded(CanonAPI sender)
|
||||
@ -187,7 +207,7 @@ public class CameraService : IDisposable
|
||||
{
|
||||
try
|
||||
{
|
||||
if (eventID == StateEventID.Shutdown && IsInit)
|
||||
if (eventID == StateEventID.Shutdown && this.IsInit)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() => this.CloseSession());
|
||||
|
||||
@ -266,28 +286,4 @@ public class CameraService : IDisposable
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public void TakePhoto()
|
||||
{
|
||||
try
|
||||
{
|
||||
MainCamera.TakePhoto();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.ReportError(ex.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.CloseSession();
|
||||
IsInit = false;
|
||||
this.APIHandler.Dispose();
|
||||
this.MainCamera.Dispose();
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,8 @@
|
||||
<Page x:Class="CamBooth.App.DebugConsole.DebugConsolePage"
|
||||
<Page x:Class="CamBooth.App.Features.DebugConsole.DebugConsolePage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:CamBooth.App.DebugConsole"
|
||||
mc:Ignorable="d"
|
||||
Title="DebugConsolePage" Width="1600" Height="170" HorizontalAlignment="Stretch">
|
||||
<StackPanel>
|
||||
@ -3,15 +3,15 @@ using System.Windows.Media;
|
||||
|
||||
using CamBooth.App.Core.Logging;
|
||||
|
||||
namespace CamBooth.App.DebugConsole;
|
||||
namespace CamBooth.App.Features.DebugConsole;
|
||||
|
||||
public partial class DebugConsolePage : Page
|
||||
{
|
||||
public DebugConsolePage(Logger logger)
|
||||
{
|
||||
logger.InfoLog += Logger_OnInfoLog;
|
||||
logger.ErrorLog += Logger_OnErrorLog;
|
||||
InitializeComponent();
|
||||
logger.InfoLog += this.Logger_OnInfoLog;
|
||||
logger.ErrorLog += this.Logger_OnErrorLog;
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
<Page x:Class="CamBooth.App.LiveView.LiveViewPage"
|
||||
<Page x:Class="CamBooth.App.Features.LiveView.LiveViewPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:CamBooth.App.LiveView"
|
||||
mc:Ignorable="d"
|
||||
Title="LiveViewPage" Width="1350" Height="900"
|
||||
Background="PaleVioletRed">
|
||||
<Grid HorizontalAlignment="Stretch" >
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<Canvas x:Name="LVCanvas" Background="Bisque" />
|
||||
</Grid>
|
||||
</Page>
|
||||
</Page>
|
||||
@ -1,31 +1,26 @@
|
||||
using System.ComponentModel;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
using CamBooth.App.Core.AppSettings;
|
||||
using CamBooth.App.Camera;
|
||||
using CamBooth.App.Core.Logging;
|
||||
using CamBooth.App.Features.Camera;
|
||||
|
||||
using EOSDigital.API;
|
||||
using EOSDigital.SDK;
|
||||
|
||||
namespace CamBooth.App.LiveView;
|
||||
namespace CamBooth.App.Features.LiveView;
|
||||
|
||||
public partial class LiveViewPage : Page
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
private readonly AppSettingsService _appSettings;
|
||||
|
||||
private readonly CameraService _cameraService;
|
||||
|
||||
Action<BitmapImage> SetImageAction;
|
||||
private readonly Logger _logger;
|
||||
|
||||
private ImageBrush bgbrush = new ImageBrush();
|
||||
private readonly ImageBrush bgbrush = new();
|
||||
|
||||
private readonly Action<BitmapImage> SetImageAction;
|
||||
|
||||
|
||||
public LiveViewPage(Logger logger, AppSettingsService appSettings, CameraService cameraService)
|
||||
@ -33,11 +28,11 @@ public partial class LiveViewPage : Page
|
||||
this._logger = logger;
|
||||
this._appSettings = appSettings;
|
||||
this._cameraService = cameraService;
|
||||
InitializeComponent();
|
||||
SetImageAction = (BitmapImage img) => { bgbrush.ImageSource = img; };
|
||||
LVCanvas.Background = bgbrush;
|
||||
this.InitializeComponent();
|
||||
this.SetImageAction = img => { this.bgbrush.ImageSource = img; };
|
||||
this.LVCanvas.Background = this.bgbrush;
|
||||
cameraService.ConnectCamera();
|
||||
cameraService.MainCamera.LiveViewUpdated += MainCamera_OnLiveViewUpdated;
|
||||
cameraService.MainCamera.LiveViewUpdated += this.MainCamera_OnLiveViewUpdated;
|
||||
}
|
||||
|
||||
|
||||
@ -45,24 +40,24 @@ public partial class LiveViewPage : Page
|
||||
{
|
||||
try
|
||||
{
|
||||
using (WrapStream s = new WrapStream(img))
|
||||
using (WrapStream s = new(img))
|
||||
{
|
||||
img.Position = 0;
|
||||
BitmapImage EvfImage = new BitmapImage();
|
||||
BitmapImage EvfImage = new();
|
||||
EvfImage.BeginInit();
|
||||
EvfImage.StreamSource = s;
|
||||
EvfImage.CacheOption = BitmapCacheOption.OnLoad;
|
||||
EvfImage.EndInit();
|
||||
EvfImage.Freeze();
|
||||
Application.Current.Dispatcher.BeginInvoke(SetImageAction, EvfImage);
|
||||
Application.Current.Dispatcher.BeginInvoke(this.SetImageAction, EvfImage);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex.Message);
|
||||
this._logger.Error(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
127
src/CamBooth/CamBooth.App/Features/LiveView/WrappingStream.cs
Normal file
127
src/CamBooth/CamBooth.App/Features/LiveView/WrappingStream.cs
Normal file
@ -0,0 +1,127 @@
|
||||
using System.IO;
|
||||
|
||||
namespace CamBooth.App.Features.LiveView;
|
||||
|
||||
/// <summary>
|
||||
/// A stream that does nothing more but wrap another stream (needed for a WPF memory leak)
|
||||
/// </summary>
|
||||
public sealed class WrapStream : Stream
|
||||
{
|
||||
private readonly Stream Base;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="WrapStream" /> class.
|
||||
/// </summary>
|
||||
/// <param name="inStream"> The stream that gets wrapped </param>
|
||||
public WrapStream(Stream inStream)
|
||||
{
|
||||
this.Base = inStream;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current stream supports reading.
|
||||
/// </summary>
|
||||
public override bool CanRead => this.Base.CanRead;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current stream supports seeking.
|
||||
/// </summary>
|
||||
public override bool CanSeek => this.Base.CanSeek;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current stream supports writing.
|
||||
/// </summary>
|
||||
public override bool CanWrite => this.Base.CanWrite;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length in bytes of the stream.
|
||||
/// </summary>
|
||||
public override long Length => this.Base.Length;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the position within the current stream.
|
||||
/// </summary>
|
||||
public override long Position
|
||||
{
|
||||
get => this.Base.Position;
|
||||
set => this.Base.Position = value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// reads a sequence of bytes from the current stream and advances
|
||||
/// the position within the stream by the number of bytes read.
|
||||
/// </summary>
|
||||
/// <param name="buffer">
|
||||
/// An array of bytes. When this method returns, the buffer contains the specified
|
||||
/// byte array with the values between offset and (offset + count - 1) replaced
|
||||
/// by the bytes read from the current source.
|
||||
/// </param>
|
||||
/// <param name="offset">
|
||||
/// The zero-based byte offset in buffer at which to begin storing the data read
|
||||
/// from the current stream.
|
||||
/// </param>
|
||||
/// <param name="count"> The maximum number of bytes to be read from the current stream. </param>
|
||||
/// <returns>
|
||||
/// The total number of bytes read into the buffer. This can be less than the
|
||||
/// number of bytes requested if that many bytes are not currently available,
|
||||
/// or zero (0) if the end of the stream has been reached.
|
||||
/// </returns>
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.Base.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// When overridden in a derived class, writes a sequence of bytes to the current
|
||||
/// stream and advances the current position within this stream by the number
|
||||
/// of bytes written.
|
||||
/// </summary>
|
||||
/// <param name="buffer"> An array of bytes. This method copies count bytes from buffer to the current stream. </param>
|
||||
/// <param name="offset">
|
||||
/// The zero-based byte offset in buffer at which to begin copying bytes to the
|
||||
/// current stream.
|
||||
/// </param>
|
||||
/// <param name="count"> The number of bytes to be written to the current stream. </param>
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
this.Base.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// sets the position within the current stream.
|
||||
/// </summary>
|
||||
/// <param name="offset"> A byte offset relative to the origin parameter. </param>
|
||||
/// <param name="origin">
|
||||
/// A value of type System.IO.SeekOrigin indicating the reference point used
|
||||
/// to obtain the new position.
|
||||
/// </param>
|
||||
/// <returns> The new position within the current stream. </returns>
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
return this.Base.Seek(offset, origin);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Clears all buffers for this stream and causes any buffered data to be written to the underlying device.
|
||||
/// </summary>
|
||||
public override void Flush()
|
||||
{
|
||||
this.Base.Flush();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets the length of the current stream.
|
||||
/// </summary>
|
||||
/// <param name="value"> The desired length of the current stream in bytes. </param>
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
this.Base.SetLength(value);
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,10 @@
|
||||
<Page x:Class="CamBooth.App.PictureGallery.PictureGalleryPage"
|
||||
<Page x:Class="CamBooth.App.Features.PictureGallery.PictureGalleryPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:CamBooth.App.PictureGallery"
|
||||
mc:Ignorable="d"
|
||||
Title="PictureGalleryPage" Width="1600" Height="795"
|
||||
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
|
||||
Background="Black">
|
||||
<Grid>
|
||||
<WrapPanel VerticalAlignment="Stretch" x:Name="PicturesPanel" Orientation="Horizontal" />
|
||||
@ -1,8 +1,6 @@
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
using CamBooth.App.Core.AppSettings;
|
||||
@ -10,12 +8,11 @@ using CamBooth.App.Core.Logging;
|
||||
|
||||
using Wpf.Ui.Controls;
|
||||
|
||||
using Button = Wpf.Ui.Controls.Button;
|
||||
using Image = Wpf.Ui.Controls.Image;
|
||||
using MessageBox = System.Windows.MessageBox;
|
||||
using TextBlock = Wpf.Ui.Controls.TextBlock;
|
||||
|
||||
namespace CamBooth.App.PictureGallery;
|
||||
namespace CamBooth.App.Features.PictureGallery;
|
||||
|
||||
public partial class PictureGalleryPage : Page
|
||||
{
|
||||
@ -31,7 +28,7 @@ public partial class PictureGalleryPage : Page
|
||||
this._appSettingsService = appSettingsService;
|
||||
this._logger = logger;
|
||||
this._pictureGalleryService = pictureGalleryService;
|
||||
InitializeComponent();
|
||||
this.InitializeComponent();
|
||||
this.Initialize();
|
||||
}
|
||||
|
||||
@ -40,7 +37,7 @@ public partial class PictureGalleryPage : Page
|
||||
{
|
||||
try
|
||||
{
|
||||
LoadPictures(12);
|
||||
this.LoadPictures(12);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -69,12 +66,12 @@ public partial class PictureGalleryPage : Page
|
||||
{
|
||||
BitmapImage thumbnail = this._pictureGalleryService.ThumbnailsOrderedByNewestDescending[loop];
|
||||
|
||||
var textBlock = new TextBlock();
|
||||
var hyperlink = new Hyperlink();
|
||||
hyperlink.Click += Hyperlink_OnClick;
|
||||
TextBlock? textBlock = new();
|
||||
Hyperlink? hyperlink = new();
|
||||
hyperlink.Click += this.Hyperlink_OnClick;
|
||||
hyperlink.Tag = thumbnail.UriSource;
|
||||
hyperlink.TextDecorations = null;
|
||||
var imageControl = new Wpf.Ui.Controls.Image
|
||||
Image? imageControl = new()
|
||||
{
|
||||
Source = thumbnail,
|
||||
Width = 381,
|
||||
@ -97,24 +94,26 @@ public partial class PictureGalleryPage : Page
|
||||
Application.Current.Dispatcher.BeginInvoke(
|
||||
async () =>
|
||||
{
|
||||
var contentDialog = new ContentDialog(RootContentDialogPresenter);
|
||||
var imageToShow = new Image
|
||||
ContentDialog? contentDialog = new(this.RootContentDialogPresenter);
|
||||
Image? imageToShow = new()
|
||||
{
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
Source = PictureGalleryService.CreateThumbnail(picturePathUri.AbsolutePath, 499, 300)
|
||||
};
|
||||
|
||||
|
||||
contentDialog.DialogWidth = 940;
|
||||
contentDialog.PrimaryButtonAppearance = ControlAppearance.Success;
|
||||
contentDialog.CloseButtonAppearance = ControlAppearance.Primary;
|
||||
|
||||
//contentDialog.SetCurrentValue(ContentDialog.TitleProperty, "Hello World");
|
||||
contentDialog.SetCurrentValue(ContentControl.ContentProperty, imageToShow);
|
||||
contentDialog.SetCurrentValue(ContentDialog.CloseButtonTextProperty, "Schließen");
|
||||
contentDialog.SetCurrentValue(ContentDialog.PrimaryButtonTextProperty, "Drucken");
|
||||
|
||||
// contentDialog.SetCurrentValue(ContentDialog.PrimaryButtonIconProperty, PictureGalleryService.CreateRegularSymbolIcon(SymbolRegular.Print48, Colors.Tomato));
|
||||
|
||||
|
||||
contentDialog.Tag = picturePathUri.AbsolutePath;
|
||||
contentDialog.ButtonClicked += ContentDialog_OnButtonClicked;
|
||||
contentDialog.ButtonClicked += this.ContentDialog_OnButtonClicked;
|
||||
|
||||
await contentDialog.ShowAsync();
|
||||
});
|
||||
@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
@ -8,7 +7,7 @@ using CamBooth.App.Core.Logging;
|
||||
|
||||
using Wpf.Ui.Controls;
|
||||
|
||||
namespace CamBooth.App.PictureGallery;
|
||||
namespace CamBooth.App.Features.PictureGallery;
|
||||
|
||||
public class PictureGalleryService
|
||||
{
|
||||
@ -16,12 +15,7 @@ public class PictureGalleryService
|
||||
|
||||
private readonly Logger _logger;
|
||||
|
||||
public List<BitmapImage> ThumbnailsOrderedByNewestDescending =>
|
||||
this.thumbnails.OrderByDescending(map => map.Key)
|
||||
.Select(ordered => ordered.Value)
|
||||
.ToList();
|
||||
|
||||
private Dictionary<DateTime, BitmapImage> thumbnails = new();
|
||||
private readonly Dictionary<DateTime, BitmapImage> thumbnails = new();
|
||||
|
||||
|
||||
public PictureGalleryService(AppSettingsService appSettings, Logger logger)
|
||||
@ -31,6 +25,12 @@ public class PictureGalleryService
|
||||
}
|
||||
|
||||
|
||||
public List<BitmapImage> ThumbnailsOrderedByNewestDescending =>
|
||||
this.thumbnails.OrderByDescending(map => map.Key)
|
||||
.Select(ordered => ordered.Value)
|
||||
.ToList();
|
||||
|
||||
|
||||
public async Task LoadThumbnailsToCache(int cacheSize = 0)
|
||||
{
|
||||
this._logger.Info("Start load thumbnails into cache");
|
||||
@ -51,7 +51,7 @@ public class PictureGalleryService
|
||||
// add if not exists
|
||||
if (!this.thumbnails.ContainsKey(creationTime))
|
||||
{
|
||||
this.thumbnails.Add(creationTime, CreateThumbnail(picturePath, 244, 0));
|
||||
this.thumbnails.Add(creationTime, PictureGalleryService.CreateThumbnail(picturePath, 244, 0));
|
||||
this._logger.Info($"Thumbnail '{picturePath}' successfully created");
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ public class PictureGalleryService
|
||||
|
||||
public static BitmapImage CreateThumbnail(string filePath, int maxWidth, int maxHeight)
|
||||
{
|
||||
var bitmap = new BitmapImage();
|
||||
BitmapImage? bitmap = new();
|
||||
bitmap.BeginInit();
|
||||
bitmap.UriSource = new Uri(filePath);
|
||||
bitmap.DecodePixelWidth = maxWidth; // Größe des ThumbnailsOrderedByNewestDescending direkt beim Dekodieren festlegen
|
||||
@ -75,16 +75,17 @@ public class PictureGalleryService
|
||||
bitmap.Freeze(); // Threadsicher machen
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static SymbolIcon CreateRegularSymbolIcon(SymbolRegular symbolRegular, Color foregroundColor = default)
|
||||
{
|
||||
return new SymbolIcon
|
||||
{
|
||||
Symbol = symbolRegular,
|
||||
Symbol = symbolRegular,
|
||||
Foreground = new SolidColorBrush(foregroundColor),
|
||||
Width = 24,
|
||||
Width = 24,
|
||||
Height = 24,
|
||||
FontSize = 24
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,120 +0,0 @@
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace CamBooth.App.LiveView
|
||||
{
|
||||
/// <summary>
|
||||
/// A stream that does nothing more but wrap another stream (needed for a WPF memory leak)
|
||||
/// </summary>
|
||||
public sealed class WrapStream : Stream
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current stream supports reading.
|
||||
/// </summary>
|
||||
public override bool CanRead
|
||||
{
|
||||
get { return this.Base.CanRead; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current stream supports seeking.
|
||||
/// </summary>
|
||||
public override bool CanSeek
|
||||
{
|
||||
get { return this.Base.CanSeek; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current stream supports writing.
|
||||
/// </summary>
|
||||
public override bool CanWrite
|
||||
{
|
||||
get { return this.Base.CanWrite; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the length in bytes of the stream.
|
||||
/// </summary>
|
||||
public override long Length
|
||||
{
|
||||
get { return this.Base.Length; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the position within the current stream.
|
||||
/// </summary>
|
||||
public override long Position
|
||||
{
|
||||
get { return this.Base.Position; }
|
||||
set { this.Base.Position = value; }
|
||||
}
|
||||
|
||||
private Stream Base;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="WrapStream"/> class.
|
||||
/// </summary>
|
||||
/// <param name="inStream">The stream that gets wrapped</param>
|
||||
public WrapStream(Stream inStream)
|
||||
{
|
||||
this.Base = inStream;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// reads a sequence of bytes from the current stream and advances
|
||||
/// the position within the stream by the number of bytes read.
|
||||
/// </summary>
|
||||
/// <param name="buffer">An array of bytes. When this method returns, the buffer contains the specified
|
||||
/// byte array with the values between offset and (offset + count - 1) replaced
|
||||
/// by the bytes read from the current source.</param>
|
||||
/// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read
|
||||
/// from the current stream.</param>
|
||||
/// <param name="count">The maximum number of bytes to be read from the current stream.</param>
|
||||
/// <returns>The total number of bytes read into the buffer. This can be less than the
|
||||
/// number of bytes requested if that many bytes are not currently available,
|
||||
/// or zero (0) if the end of the stream has been reached.</returns>
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return this.Base.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When overridden in a derived class, writes a sequence of bytes to the current
|
||||
/// stream and advances the current position within this stream by the number
|
||||
/// of bytes written.
|
||||
/// </summary>
|
||||
/// <param name="buffer">An array of bytes. This method copies count bytes from buffer to the current stream.</param>
|
||||
/// <param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the
|
||||
/// current stream.</param>
|
||||
/// <param name="count">The number of bytes to be written to the current stream.</param>
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
this.Base.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// sets the position within the current stream.
|
||||
/// </summary>
|
||||
/// <param name="offset">A byte offset relative to the origin parameter.</param>
|
||||
/// <param name="origin">A value of type System.IO.SeekOrigin indicating the reference point used
|
||||
/// to obtain the new position.</param>
|
||||
/// <returns>The new position within the current stream.</returns>
|
||||
public override long Seek(long offset, System.IO.SeekOrigin origin)
|
||||
{
|
||||
return this.Base.Seek(offset, origin);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all buffers for this stream and causes any buffered data to be written to the underlying device.
|
||||
/// </summary>
|
||||
public override void Flush()
|
||||
{
|
||||
this.Base.Flush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the length of the current stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The desired length of the current stream in bytes.</param>
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
this.Base.SetLength(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,12 @@
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
|
||||
using CamBooth.App.Camera;
|
||||
using CamBooth.App.Core.AppSettings;
|
||||
using CamBooth.App.Core.Logging;
|
||||
using CamBooth.App.DebugConsole;
|
||||
using CamBooth.App.LiveView;
|
||||
using CamBooth.App.PictureGallery;
|
||||
using CamBooth.App.Features.Camera;
|
||||
using CamBooth.App.Features.DebugConsole;
|
||||
using CamBooth.App.Features.LiveView;
|
||||
using CamBooth.App.Features.PictureGallery;
|
||||
|
||||
namespace CamBooth.App;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user