diff --git a/Splitter-UI/Converters/ActionToIconConverter.cs b/Splitter-UI/Converters/ActionToIconConverter.cs index b2a5144..676462d 100644 --- a/Splitter-UI/Converters/ActionToIconConverter.cs +++ b/Splitter-UI/Converters/ActionToIconConverter.cs @@ -7,12 +7,15 @@ public sealed class ActionToIconConverter : IValueConverter { public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { - return value switch - { - "crop" => "\uf125", // FA7 crop - "rotate" => "\uf2f1", // FA7 rotate - _ => null - }; + if (value == null) + return null; + + var p = System.Convert.ToInt32(value); + + return p == 0 + ? "\uf125" // FA7 crop + : "\uf2f1" // FA7 rotate + ; } public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) diff --git a/Splitter-UI/Models/PreviewData.cs b/Splitter-UI/Models/PreviewData.cs index 3323dd3..5dcdb87 100644 --- a/Splitter-UI/Models/PreviewData.cs +++ b/Splitter-UI/Models/PreviewData.cs @@ -1,6 +1,4 @@ -using Avalonia; - -namespace Splitter_UI.Models; +namespace Splitter_UI.Models; public class PreviewData { diff --git a/Splitter-UI/Program.cs b/Splitter-UI/Program.cs index abfb923..ee216ba 100644 --- a/Splitter-UI/Program.cs +++ b/Splitter-UI/Program.cs @@ -1,8 +1,6 @@ using Avalonia; using Avalonia.Media; using Microsoft.Extensions.DependencyInjection; -using splitter.algo; -using splitter.tui; namespace Splitter_UI; diff --git a/Splitter-UI/Services/AutoDecisionService.cs b/Splitter-UI/Services/AutoDecisionService.cs index 084643f..c534a40 100644 --- a/Splitter-UI/Services/AutoDecisionService.cs +++ b/Splitter-UI/Services/AutoDecisionService.cs @@ -1,6 +1,4 @@ -using NcnnDotNet.Layers; -using OpenCvSharp; -using splitter.tui; +using OpenCvSharp.Dnn; namespace Splitter_UI.Services; @@ -15,19 +13,63 @@ public sealed class AutoDecisionService(IThumbnailService _thumbnails, IFileProb { try { + job.GravitateTo = new(0.5f, 0.5f); + job.OverrideTargetDuration = 58.0; + job.Mask = "[NAME]_seg[NN].[EXT]"; + job.OutputFolder = Path.Combine(Path.GetDirectoryName(job.InputFile)!, "splitter"); + job.Probe = await _fileProbe.ProbeAsync(job.InputFile); job.Thumbnail = await _thumbnails.CreateThumbnailAsync(job.InputFile, job.Probe, rotateDegree: job.Rotate); - var sampler = new VideoRotationSampler(null); - job.Rotate = await sampler.DetectRotationAsync(job.InputFile, job.Probe.Duration); - job.SuggestedAction = job.Rotate == 0 ? "crop" : "rotate"; - - if (job.SuggestedAction == "crop") + if (job.Probe.Width > job.Probe.Height) + { job.Detect = "body"; + job.Rotate = 0; + + CalculateCrop(job); + } + else + { + var sampler = new VideoRotationSampler(null); + job.Rotate = await sampler.DetectRotationAsync(job.InputFile, job.Probe.Duration); + job.Detect = job.Rotate == 0 ? null : "body"; + } } catch (Exception ex) { _log.LogError($"Error creating thumbnail for {Path.GetFileName(job.InputFile)}: {ex.Message}"); } } + + private static void CalculateCrop(JobViewModel job) + { + var targetAR = (float)CommandLine.DefaultW / CommandLine.DefaultH; + var pixelAspect = job.Probe!.Sar.X / job.Probe.Sar.Y; + + float srcW = job.Probe.Width * pixelAspect; + float srcH = job.Probe.Height; + var srcAR = srcW / srcH; + + float cropH = srcH; + float cropW = cropH * targetAR; + + if (cropW > srcW) + { + cropW = srcW; + cropH = cropW / targetAR; + } + + float x = (srcW - cropW) * 0.5f; + float y = (srcH - cropH) * 0.5f; + + float invPixelAspect = 1f / pixelAspect; + + float cropW_px = cropW * invPixelAspect; + float cropH_px = cropH; + + float x_px = x * invPixelAspect; + float y_px = y; + + job.CropText = $"{(int)MathF.Round(cropW_px)},{(int)MathF.Round(cropH_px)}"; + } } diff --git a/Splitter-UI/Services/AvaloniaBitmapExtensions.cs b/Splitter-UI/Services/AvaloniaBitmapExtensions.cs index f48e98d..099c547 100644 --- a/Splitter-UI/Services/AvaloniaBitmapExtensions.cs +++ b/Splitter-UI/Services/AvaloniaBitmapExtensions.cs @@ -1,7 +1,6 @@ using System.Runtime.InteropServices; using Avalonia; using Avalonia.Media.Imaging; -using OpenCvSharp; namespace Splitter_UI.Services; diff --git a/Splitter-UI/Services/DummyDetector.cs b/Splitter-UI/Services/DummyDetector.cs index d7d26f5..6319264 100644 --- a/Splitter-UI/Services/DummyDetector.cs +++ b/Splitter-UI/Services/DummyDetector.cs @@ -1,7 +1,4 @@ -using OpenCvSharp; -using splitter.algo; - -namespace Splitter_UI.Services; +namespace Splitter_UI.Services; internal class DummyDetector : IObjectDetector { diff --git a/Splitter-UI/Services/FileProbeService.cs b/Splitter-UI/Services/FileProbeService.cs index 0f81954..13cb2d5 100644 --- a/Splitter-UI/Services/FileProbeService.cs +++ b/Splitter-UI/Services/FileProbeService.cs @@ -1,6 +1,4 @@ -using splitter.probe; - -namespace Splitter_UI.Services; +namespace Splitter_UI.Services; public sealed class FileProbeService : IFileProbeService { diff --git a/Splitter-UI/Services/GlobalLogger.cs b/Splitter-UI/Services/GlobalLogger.cs index 81979f8..da5594b 100644 --- a/Splitter-UI/Services/GlobalLogger.cs +++ b/Splitter-UI/Services/GlobalLogger.cs @@ -1,6 +1,4 @@ -using splitter.tui; - -namespace Splitter_UI.Services; +namespace Splitter_UI.Services; internal class GlobalLogger(ILogService _logService) : ILogger { diff --git a/Splitter-UI/Services/IFileProbeService.cs b/Splitter-UI/Services/IFileProbeService.cs index 9fa5bbd..8e60265 100644 --- a/Splitter-UI/Services/IFileProbeService.cs +++ b/Splitter-UI/Services/IFileProbeService.cs @@ -1,6 +1,4 @@ -using splitter.probe; - -namespace Splitter_UI.Services; +namespace Splitter_UI.Services; public interface IFileProbeService { diff --git a/Splitter-UI/Services/IThumbnailService.cs b/Splitter-UI/Services/IThumbnailService.cs index c7a7eee..787abb1 100644 --- a/Splitter-UI/Services/IThumbnailService.cs +++ b/Splitter-UI/Services/IThumbnailService.cs @@ -1,5 +1,4 @@ using Avalonia.Media.Imaging; -using splitter.probe; namespace Splitter_UI.Services; diff --git a/Splitter-UI/Services/SingleThreadedDetector.cs b/Splitter-UI/Services/SingleThreadedDetector.cs index 877cb11..f4f06b8 100644 --- a/Splitter-UI/Services/SingleThreadedDetector.cs +++ b/Splitter-UI/Services/SingleThreadedDetector.cs @@ -1,7 +1,4 @@ -using OpenCvSharp; -using splitter.algo; - -namespace Splitter_UI.Services; +namespace Splitter_UI.Services; public class SingleThreadedDetector(IObjectDetector _detector) : IObjectDetector where T : IObjectDetector diff --git a/Splitter-UI/Services/ThumbnailService.cs b/Splitter-UI/Services/ThumbnailService.cs index 294b422..d8883bf 100644 --- a/Splitter-UI/Services/ThumbnailService.cs +++ b/Splitter-UI/Services/ThumbnailService.cs @@ -2,7 +2,6 @@ using Avalonia; using Avalonia.Media.Imaging; using Avalonia.Platform; -using splitter.probe; namespace Splitter_UI.Services; diff --git a/Splitter-UI/ViewModels/InspectorPaneViewModel.cs b/Splitter-UI/ViewModels/InspectorPaneViewModel.cs index ce73139..9bf3a05 100644 --- a/Splitter-UI/ViewModels/InspectorPaneViewModel.cs +++ b/Splitter-UI/ViewModels/InspectorPaneViewModel.cs @@ -16,11 +16,6 @@ public partial class InspectorPaneViewModel : ObservableObject "face", "body", "none" ]; - public List RotationAngles => - [ - 0, 90, 180, 270 - ]; - [RelayCommand] private void ApplyOverrides() { diff --git a/Splitter-UI/ViewModels/JobViewModel.cs b/Splitter-UI/ViewModels/JobViewModel.cs index 99dce2d..51f1e2e 100644 --- a/Splitter-UI/ViewModels/JobViewModel.cs +++ b/Splitter-UI/ViewModels/JobViewModel.cs @@ -5,9 +5,6 @@ using Avalonia.Media.Imaging; using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using splitter.algo; -using splitter.probe; -using splitter.tui; namespace Splitter_UI.ViewModels; @@ -19,7 +16,6 @@ public partial class JobViewModel : ObservableObject [ObservableProperty] private PreviewData? _preview = new(null, [], null, new(0.5f, 0.5f)); [ObservableProperty] private ProgressInfo? _progress; [ObservableProperty] private Bitmap? _thumbnail; - [ObservableProperty] private string _suggestedAction = ""; [ObservableProperty] private double _sliderLiveValue; [ObservableProperty] private double _positionSeconds; @@ -217,6 +213,13 @@ public partial class JobViewModel : ObservableObject entry.PropertyChanged += OnParameterChanged; } + PropertyChanged += (sender, e) => + { + if (e.PropertyName == nameof(Probe)) + { + OnPropertyChanged(nameof(DurationSeconds)); + } + }; ParametersList.CollectionChanged += OnParametersCollectionChanged; StepForwardCommand = new RelayCommand(StepForward); diff --git a/Splitter-UI/ViewModels/PreviewPaneViewModel.cs b/Splitter-UI/ViewModels/PreviewPaneViewModel.cs index 8939652..c50fe02 100644 --- a/Splitter-UI/ViewModels/PreviewPaneViewModel.cs +++ b/Splitter-UI/ViewModels/PreviewPaneViewModel.cs @@ -1,6 +1,5 @@ using System.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel; -using splitter.algo; namespace Splitter_UI.ViewModels; diff --git a/Splitter-UI/Views/FileListView.axaml b/Splitter-UI/Views/FileListView.axaml index efb8e87..a1da9ee 100644 --- a/Splitter-UI/Views/FileListView.axaml +++ b/Splitter-UI/Views/FileListView.axaml @@ -82,7 +82,7 @@ VerticalAlignment="Center"/> diff --git a/Splitter-UI/Views/MainWindow.axaml.cs b/Splitter-UI/Views/MainWindow.axaml.cs index 19ea835..8d91fe9 100644 --- a/Splitter-UI/Views/MainWindow.axaml.cs +++ b/Splitter-UI/Views/MainWindow.axaml.cs @@ -1,5 +1,3 @@ -using Avalonia.Controls; - namespace Splitter_UI.Views; public partial class MainWindow : Avalonia.Controls.Window diff --git a/Splitter-UI/Views/PreviewCanvas.cs b/Splitter-UI/Views/PreviewCanvas.cs index 5b4a804..4d25321 100644 --- a/Splitter-UI/Views/PreviewCanvas.cs +++ b/Splitter-UI/Views/PreviewCanvas.cs @@ -4,7 +4,6 @@ using Avalonia.Controls; using Avalonia.Input; using Avalonia.Media; using Avalonia.Threading; -using splitter.algo; namespace Splitter_UI.Views; diff --git a/Splitter-UI/Views/PreviewPane.axaml b/Splitter-UI/Views/PreviewPane.axaml index bf17759..d686040 100644 --- a/Splitter-UI/Views/PreviewPane.axaml +++ b/Splitter-UI/Views/PreviewPane.axaml @@ -14,7 +14,7 @@ Preview="{Binding Preview}" Sar="{Binding Sar}" RotateAngle="{Binding Rotate}" - GravitateTo="{Binding GravitateTo}"/> + GravitateTo="{Binding GravitateTo, Mode=TwoWay}"/>