using Common; using GUI.Model; using ImageMagick; using Microsoft.Win32; using Ocr.Tesseract.Configuration; using Ocr.Tesseract.Models; using Ocr.Tesseract.Screenshots.Configuration; using Process.Interface; using Serilog; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; namespace GUI.ViewModels; internal class ImageViewModel : ScreenshotScanner, INotifyPropertyChanged { private static ITesseractConfiguration CreateTesseractConfiguration() => new TesseractScreenshotConfiguration() { DataPath = "tessdata", Languages = new[] { "eng", "deu" } }; public ImageViewModel() : base(new(), CreateTesseractConfiguration()) { ImageProcessorConfiguration.PropertyChanged += (sender, args) => Task.Run(UpdateImage); OpenFileCommand = new Command(OpenFile); SaveEditedImageCommand = new Command(SaveEditedImage); } #region Overrides of Scanner /// protected override void OnProcessing(IProcessor sender, ICollection inputs) { Application.Current.Dispatcher.Invoke(() => { foreach (var image in inputs) { Edited.Add(image); } }); } /// protected override void OnProcessed(IProcessor sender, ICollection inputs) { ScannedText = $"[{inputs.Count} words] " + string.Join(' ', inputs); } #endregion public ImageViewModel(MagickImage image) : this() { Image = image; } private void Clear() { Application.Current.Dispatcher.Invoke(() => { ScannedText = string.Empty; Words.Clear(); Lookup.Clear(); Edited.Clear(); } ); } private void OpenFile() { var dialog = new OpenFileDialog() { InitialDirectory = Directory.GetCurrentDirectory() }; if (dialog.ShowDialog() == true) { Image = new MagickImage(dialog.FileName); UpdateImage(); } } private void SaveEditedImage() { var basePath = AppDomain.CurrentDomain.BaseDirectory; for (var i = 0; i < Edited.Count; i++) { Edited[i].Write(Path.Combine(basePath, $"edited_{i}.png")); } Log.Information($"Saved image to '{basePath}'"); System.Diagnostics.Process.Start( "explorer.exe", Path.GetDirectoryName(basePath) ?? string.Empty ); } private void UpdateConfidence() { Confidence = Lookup.Keys.Any() ? Lookup.Keys.Sum(key => key.Confidence) / Lookup.Keys.Count : 0; } private void UpdateImage() { Task.Run(() => { IsIdle = false; Clear(); if (Image != null) { Process(new[] { Image }); } UpdateWords(); UpdateConfidence(); IsIdle = true; }); } private void UpdateWords() { Application.Current.Dispatcher.Invoke(() => { foreach (var word in Lookup.Keys) { Words.Add(word); } }); } #region Properties private float _confidence; private MagickImage? _image; private bool _isIdle; private string _scannedText = string.Empty; public string ScannedText { get => _scannedText; set { if (value == _scannedText) { return; } _scannedText = value; OnPropertyChanged(); } } public bool IsIdle { get => _isIdle; set { if (value == _isIdle) { return; } _isIdle = value; OnPropertyChanged(); } } public float Confidence { get => _confidence; set { _confidence = value; OnPropertyChanged(); } } public ObservableCollection Edited { get; } = new(); public MagickImage? Image { get => _image; set { _image = value; OnPropertyChanged(); } } public ObservableCollection Words { get; } = new(); #endregion Properties #region Commands public ICommand OpenFileCommand { get; private set; } public ICommand SaveEditedImageCommand { get; private set; } #endregion Commands #region INotifyPropertyChanged public event PropertyChangedEventHandler? PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #endregion INotifyPropertyChanged }