using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Drawing; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Presenters; using Avalonia.Controls.Shapes; using Avalonia.Media; using Avalonia.Media.Imaging; using Avalonia.VisualTree; using DownKyi.Commands; using DownKyi.Core.BiliApi.BiliUtils; using DownKyi.Core.FFMpeg; using DownKyi.Core.Storage; using DownKyi.Events; using DownKyi.Utils; using Prism.Commands; using Prism.Events; using Bitmap = Avalonia.Media.Imaging.Bitmap; using Path = System.IO.Path; namespace DownKyi.ViewModels.Toolbox; public class ViewDelogoViewModel : ViewModelBase { public const string Tag = "PageToolboxDelogo"; // 是否正在执行去水印任务 private bool _isDelogo = false; private IImage _source; public IImage Source { get => _source; set => SetProperty(ref _source, value); } #region 页面属性申明 private string? _videoPath; public string? VideoPath { get => _videoPath; set => SetProperty(ref _videoPath, value); } private int _logoWidth; public int LogoWidth { get => _logoWidth; set { WatermarkArea = new Rect(_watermarkArea.X, _watermarkArea.Y, value, _watermarkArea.Height ); SetProperty(ref _logoWidth, value); } } private int _logoHeight; public int LogoHeight { get => _logoHeight; set { WatermarkArea = new Rect(_watermarkArea.X, _watermarkArea.Y, _watermarkArea.Width,value ); SetProperty(ref _logoHeight, value); } } private int _logoX; public int LogoX { get => _logoX; set { WatermarkArea = new Rect(value, _watermarkArea.Y, _watermarkArea.Width,_watermarkArea.Height ); SetProperty(ref _logoX, value); } } private int _logoY; public int LogoY { get => _logoY; set { WatermarkArea = new Rect( _watermarkArea.X, value, _watermarkArea.Width,_watermarkArea.Height ); SetProperty(ref _logoY, value); } } private string _status; public string Status { get => _status; set => SetProperty(ref _status, value); } private bool _updatingWatermarkArea; private Rect _watermarkArea; public Rect WatermarkArea { get => _watermarkArea; set { if (_updatingWatermarkArea) return; _updatingWatermarkArea = true; LogoHeight = (int)Math.Round(value.Height); LogoWidth = (int)Math.Round(value.Width); LogoX = (int)Math.Round(value.X); LogoY = (int)Math.Round(value.Y); SetProperty(ref _watermarkArea, value); _updatingWatermarkArea = false; } } public List AvailableColors { get; } private SolidColorBrush _selectedColor; public SolidColorBrush SelectedColor { get => _selectedColor; set => SetProperty(ref _selectedColor, value); } #endregion public ViewDelogoViewModel(IEventAggregator eventAggregator) : base(eventAggregator) { #region 属性初始化 VideoPath = string.Empty; AvailableColors = new (){ new SolidColorBrush(Colors.Red), new SolidColorBrush(Colors.Green), new SolidColorBrush(Colors.Blue), new SolidColorBrush(Colors.White), new SolidColorBrush(Colors.Black), new SolidColorBrush(Colors.Gray), new SolidColorBrush(Colors.Fuchsia), }; SelectedColor = AvailableColors[0]; WatermarkArea = new Rect(20,20,100,100); #endregion } #region 命令申明 // 选择视频事件 private AsyncDelegateCommand? _selectVideoCommand; public AsyncDelegateCommand SelectVideoCommand => _selectVideoCommand ??= new AsyncDelegateCommand(ExecuteSelectVideoCommand); /// /// 选择视频事件 /// private async Task ExecuteSelectVideoCommand(object obj, CancellationToken token) { if (_isDelogo) { EventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipWaitTaskFinished")); return; } VideoPath = await DialogUtils.SelectVideoFile(); if (!string.IsNullOrEmpty(VideoPath)) { try { Source = new Bitmap(await FFMpeg.Instance.ExtractVideoFrame(VideoPath, TimeSpan.FromSeconds(1))); } catch (Exception e) { /**/ } } } // 去水印事件 private DelegateCommand? _delogoCommand; public DelegateCommand DelogoCommand => _delogoCommand ??= new DelegateCommand(ExecuteDelogoCommand); /// /// 去水印事件 /// private async void ExecuteDelogoCommand() { if (_isDelogo) { EventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipWaitTaskFinished")); return; } if (VideoPath is null or "") { EventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipNoSeletedVideo")); return; } if (LogoWidth == -1) { EventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipInputRightLogoWidth")); return; } if (LogoHeight == -1) { EventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipInputRightLogoHeight")); return; } if (LogoX == -1) { EventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipInputRightLogoX")); return; } if (LogoY == -1) { EventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipInputRightLogoY")); return; } // 新文件名 var newFileName = VideoPath.Insert(VideoPath.Length - 4, "_delogo"); Status = string.Empty; await Task.Run(() => { // 执行去水印程序 _isDelogo = true; FFMpeg.Instance.Delogo ( VideoPath, newFileName, _logoX, _logoY, _logoWidth, _logoHeight, output => { Status += output + "\n"; }); _isDelogo = false; }); } // Status改变事件 private DelegateCommand? _statusCommand; public DelegateCommand StatusCommand => _statusCommand ??= new DelegateCommand(ExecuteStatusCommand); /// /// Status改变事件 /// /// private void ExecuteStatusCommand(object parameter) { if (parameter is not TextBox output) { return; } var presenter = output.GetVisualDescendants() .OfType() .FirstOrDefault(); if (presenter == null) return; int lineCount = presenter.TextLayout?.TextLines?.Count ?? 0; if (lineCount > 0) { output.ScrollToLine(lineCount - 1); } } #endregion }