Files
UVtools/UVtools.WPF/Controls/Tools/ToolMaskControl.axaml.cs
Tiago Conceição 2c7ad09dc0 v3.13.1
- (Change) `Layer.IsBottomLayer` no longer calculate the value using the position of the layer, a new property `IsBottomLayerByHeight` is now used to get that result
- (Improvement) Tool - Double exposure: Increase the bottom layer count per cloned bottom layer
- (Improvement) Calibration - Exposure time finder: Set the absolute bottom layer count accordingly when also testing for bottom time
- (Improvement) Goo: Enforce Wait times or Light-off-delay flag based on property set
- (Fix) AnyCubic and Goo: `PerLayerSetting` flag was set inverted causing printer not to follow layer settings when it should and also the otherwise (#689)
- (Fix) Tool - Scripting: Prevent from reload UI multiple times when using profiles (#694)
2023-04-27 22:58:05 +01:00

149 lines
4.5 KiB
C#

using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using System;
using System.Drawing;
using UVtools.Core.Extensions;
using UVtools.Core.Operations;
using UVtools.WPF.Extensions;
using UVtools.WPF.Windows;
using Bitmap = Avalonia.Media.Imaging.Bitmap;
namespace UVtools.WPF.Controls.Tools;
public class ToolMaskControl : ToolControl
{
private bool _isMaskInverted;
private byte _genMinimumBrightness = 200;
private byte _genMaximumBrightness = byte.MaxValue;
private uint _genDiameter;
private Bitmap _maskImage;
public OperationMask Operation => BaseOperation as OperationMask;
public bool IsMaskInverted
{
get => _isMaskInverted;
set
{
if(!RaiseAndSetIfChanged(ref _isMaskInverted, value)) return;
if (!Operation.HaveInputMask) return;
Operation.InvertMask();
MaskImage = Operation.Mask.ToBitmapParallel();
}
}
public byte GenMinimumBrightness
{
get => _genMinimumBrightness;
set => RaiseAndSetIfChanged(ref _genMinimumBrightness, value);
}
public byte GenMaximumBrightness
{
get => _genMaximumBrightness;
set => RaiseAndSetIfChanged(ref _genMaximumBrightness, value);
}
public uint GenDiameter
{
get => _genDiameter;
set => RaiseAndSetIfChanged(ref _genDiameter, value);
}
public string InfoPrinterResolutionStr => $"Printer resolution: {App.SlicerFile.Resolution}";
public string InfoMaskResolutionStr => $"Mask resolution: "+ (Operation.HaveInputMask ? Operation.Mask.Size.ToString() : "(Unloaded)");
public Bitmap MaskImage
{
get => _maskImage;
set
{
if(!RaiseAndSetIfChanged(ref _maskImage, value)) return;
RaisePropertyChanged(nameof(InfoMaskResolutionStr));
ParentWindow.ButtonOkEnabled = Operation.HaveInputMask;
}
}
public ToolMaskControl()
{
BaseOperation = new OperationMask(SlicerFile);
if (!ValidateSpawn()) return;
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
public override void Callback(ToolWindow.Callbacks callback)
{
switch (callback)
{
case ToolWindow.Callbacks.Init:
ParentWindow.ButtonOkEnabled = false;
break;
case ToolWindow.Callbacks.AfterLoadProfile:
case ToolWindow.Callbacks.ClearROI:
Operation.Mask = null;
MaskImage = null;
break;
}
}
public async void ImportImageMask()
{
var dialog = new OpenFileDialog
{
Filters = Helpers.ImagesFileFilter,
AllowMultiple = false
};
var result = await dialog.ShowAsync(ParentWindow);
if (result is null || result.Length == 0) return;
try
{
Operation.LoadFromFile(result[0], _isMaskInverted, App.MainWindow.ROI.Size.IsEmpty ? SlicerFile.Resolution : App.MainWindow.ROI.Size);
MaskImage = Operation.Mask.ToBitmapParallel();
}
catch (Exception e)
{
await ParentWindow.MessageBoxError(e.ToString(), "Error while trying to read the image");
}
}
public void GenerateMask()
{
var roi = App.MainWindow.ROI;
Operation.Mask = roi.IsEmpty ? App.MainWindow.LayerCache.Image.NewBlank() : new Mat(roi.Size, DepthType.Cv8U, 1);
int radius = (int)_genDiameter;
if (radius == 0)
{
radius = Math.Min(Operation.Mask.Width, Operation.Mask.Height) / 2;
}
else
{
radius = Math.Clamp(radius, 2, Math.Min(Operation.Mask.Width, Operation.Mask.Height)) / 2;
}
var maxScalar = new MCvScalar(_genMaximumBrightness);
Operation.Mask.SetTo(maxScalar);
var center = new Point(Operation.Mask.Width / 2, Operation.Mask.Height / 2);
var colorDifference = _genMinimumBrightness - _genMaximumBrightness;
//CvInvoke.Circle(Mask, center, radius, minScalar, -1);
for (decimal i = 1; i < radius; i++)
{
int color = (int)(_genMinimumBrightness - i / radius * colorDifference); //or some another color calculation
CvInvoke.Circle(Operation.Mask, center, (int)i, new MCvScalar(color), 2);
}
if (_isMaskInverted) Operation.InvertMask();
MaskImage = Operation.Mask.ToBitmapParallel();
}
}