using InABox.Core; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media.Imaging; using System.Windows.Media; using InABox.WPF; using Color = System.Drawing.Color; using Image = System.Windows.Controls.Image; using System.Diagnostics.CodeAnalysis; using System.IO; using Microsoft.Win32; using System.Drawing.Imaging; namespace InABox.DynamicGrid { public static class EmbeddedImageUtilities { private static BitmapImage? EmptyImage; private static BitmapImage? EmptySignature; public static ImageSource CreateEmptyImage() { EmptyImage ??= new Bitmap(256, 256).WatermarkImage("No Image", Color.Gray).AsBitmapImage(); return EmptyImage; } public static ImageSource CreateEmptySignature() { EmptySignature ??= new Bitmap(400, 400).WatermarkImage("No Signature", Color.Gray).AsBitmapImage(); return EmptySignature; } public static bool SelectImageFile([NotNullWhen(true)] out byte[]? data) { var dlg = new OpenFileDialog(); dlg.Filter = "Image Files (*.jpg;*.png;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp"; if (dlg.ShowDialog() == true) { var filename = Path.GetFileName(dlg.FileName).ToLower(); var timestamp = new FileInfo(dlg.FileName).LastWriteTime; data = File.ReadAllBytes(dlg.FileName); return true; } data = null; return false; } public static byte[]? SaveImageToBytes(Image? image, bool isEmpty, BitmapEncoder encoder) { if (image == null || image.Source is not BitmapImage bmpimg) return null; if (isEmpty) return null; byte[] data; encoder.Frames.Add(BitmapFrame.Create(bmpimg)); using (var ms = new MemoryStream()) { encoder.Save(ms); ms.Seek(0, SeekOrigin.Begin); data = ms.ToArray(); } return data; } public static string SaveImageToString(Image? image, bool isEmpty, BitmapEncoder encoder) { var data = SaveImageToBytes(image, isEmpty, encoder); return data != null ? Convert.ToBase64String(data) : ""; } /// /// Loads a value into an Image object. /// /// /// /// /// if the image is empty. public static bool LoadImageFromData(Image? image, object? value, Func? defImage = null) { if (image == null) return false; BitmapImage? source = null; try { if (value is string str) { source = ImageUtils.BitmapImageFromBase64(str); } else if (value is byte[] data) { source = ImageUtils.BitmapImageFromBytes(data); } } catch (Exception e) { Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace)); } if (source != null) { image.Source = source; return true; } else { image.Source = defImage?.Invoke() ?? CreateEmptyImage(); return false; } } } public class DFEmbeddedImageControl : DynamicFormFieldControl { private Grid Grid = null!; // Late-initialised private Image Image = null!; // Late-initialised private bool _isEmpty = true; protected override FrameworkElement Create() { Grid = new Grid(); Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); Grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) }); Grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); Image = new Image(); Image.StretchDirection = StretchDirection.DownOnly; Image.Source = EmbeddedImageUtilities.CreateEmptyImage(); var pasteButton = new Button { Content = "Paste", Margin = new Thickness(0, 5, 5, 0), Width = 60, Height = 35 }; pasteButton.Click += PasteButton_Click; var clearButton = new Button { Content = "Clear", Margin = new Thickness(0, 5, 5, 0), Width = 60, Height = 35 }; clearButton.Click += EmbeddedImageClear_Click; var selectButton = new Button { Content = "Select", Margin = new Thickness(0, 5, 0, 0), Width = 60, Height = 35 }; selectButton.Click += EmbeddedImageSelect_Click; Image.SetGridPosition(0, 0, 1, 4); pasteButton.SetGridPosition(1, 1, 1, 1); clearButton.SetGridPosition(1, 2, 1, 1); selectButton.SetGridPosition(1, 3, 1, 1); Grid.Children.Add(Image); Grid.Children.Add(pasteButton); Grid.Children.Add(clearButton); Grid.Children.Add(selectButton); return Grid; } private void PasteButton_Click(object sender, RoutedEventArgs e) { if (Clipboard.ContainsImage()) { var paste = Clipboard.GetImage(); var bitmap = ImageUtils.BitmapSourceToBitmap(paste); var img = ImageUtils.ToBitmapImage(bitmap); var empty = img == null; if (_isEmpty != empty) { _isEmpty = empty; if (empty) Image.Source = EmbeddedImageUtilities.CreateEmptyImage(); else Image.Source = img; ChangeField(); } } } public override byte[] GetValue() { return EmbeddedImageUtilities.SaveImageToBytes(Image, _isEmpty, new JpegBitmapEncoder()) ?? Array.Empty(); } public override void SetValue(byte[]? value) { _isEmpty = !EmbeddedImageUtilities.LoadImageFromData(Image, value); } private void EmbeddedImageClear_Click(object sender, RoutedEventArgs e) { if (!_isEmpty) { Image.Source = EmbeddedImageUtilities.CreateEmptyImage(); _isEmpty = true; ChangeField(); } } private void EmbeddedImageSelect_Click(object sender, RoutedEventArgs e) { if (EmbeddedImageUtilities.SelectImageFile(out var data)) { var img = ImageUtils.BitmapImageFromBytes(data); var empty = img == null; if (_isEmpty != empty) { _isEmpty = empty; if (empty) Image.Source = EmbeddedImageUtilities.CreateEmptyImage(); else Image.Source = img; ChangeField(); } } } protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { base.OnPropertyChanged(e); if (e.Property == IsEnabledProperty) { Grid.RowDefinitions[1].Height = (bool)e.NewValue ? GridLength.Auto : new GridLength(0); } } protected override bool IsEmpty() => _isEmpty; } }