Welcome to mirror list, hosted at ThFree Co, Russian Federation.

OperationMask.cs « Operations « UVtools.Core - github.com/sn4k3/UVtools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 348f3dea3cb7b8d8817725f9da525b05207eed53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
 *                     GNU AFFERO GENERAL PUBLIC LICENSE
 *                       Version 3, 19 November 2007
 *  Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 *  Everyone is permitted to copy and distribute verbatim copies
 *  of this license document, but changing it is not allowed.
 */

using Emgu.CV;
using System;
using System.Drawing;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Emgu.CV.CvEnum;
using Emgu.CV.DepthAI;
using UVtools.Core.FileFormats;

namespace UVtools.Core.Operations;

[Serializable]
public class OperationMask : Operation
{
    #region Overrides
    public override string IconClass => "fa-solid fa-mask";
    public override string Title => "Mask";
    public override string Description =>
        "Mask the intensity of the LCD output using a greyscale input image.\n\n" +
        "Useful to correct LCD light uniformity for a specific printer.\n\n" +
        "NOTE:  This operation should be run only after repairs and other transformations.  The provided" +
        "input mask image must match the output resolution of the target printer.";

    public override string ConfirmationText =>
        $"mask layers from {LayerIndexStart} through {LayerIndexEnd}";

    public override string ProgressTitle =>
        $"Masking layers from {LayerIndexStart} through {LayerIndexEnd}";

    public override string ProgressAction => "Masked layers";

    public override bool CanHaveProfiles => false;

    public override string? ValidateInternally()
    {
        var sb = new StringBuilder();
        if (!HaveInputMask)
        {
            sb.AppendLine("The mask can not be empty.");
        }

        return sb.ToString();
    }
    #endregion

    #region Properties
    [XmlIgnore]
    public Mat? Mask { get; set; }

    public bool HaveInputMask => Mask is not null;
    #endregion

    #region Constructor

    public OperationMask() { }

    public OperationMask(FileFormat slicerFile) : base(slicerFile) { }

    #endregion

    #region Methods

    /// <summary>
    /// Loads mask from a image file
    /// </summary>
    /// <param name="filePath"></param>
    /// <param name="invertMask"></param>
    /// <param name="maskSize"></param>
    public void LoadFromFile(string filePath, bool invertMask = false, Size maskSize = default)
    {
        Mask = CvInvoke.Imread(filePath, ImreadModes.Grayscale);
        if (maskSize.Width > 0 && maskSize.Height > 0 && Mask.Size != maskSize)
        {
            CvInvoke.Resize(Mask, Mask, maskSize);
        }

        if (invertMask)
        {
            InvertMask();
        }
    }

    public void InvertMask()
    {
        if (!HaveInputMask) return;
        CvInvoke.BitwiseNot(Mask, Mask);
    }

    protected override bool ExecuteInternally(OperationProgress progress)
    {
        Parallel.For(LayerIndexStart, LayerIndexEnd + 1, CoreSettings.GetParallelOptions(progress), layerIndex =>
        {
            using var mat = SlicerFile[layerIndex].LayerMat;
            Execute(mat);
            SlicerFile[layerIndex].LayerMat = mat;
            progress.LockAndIncrement();
        });

        return !progress.Token.IsCancellationRequested;
    }

    public override bool Execute(Mat mat, params object[]? arguments)
    {
        var target = GetRoiOrDefault(mat);
        using var mask = GetMask(mat);
        if (Mask!.Size != target.Size) return false;
        CvInvoke.BitwiseAnd(target, Mask, target, mask);
        return true;
    }

    #endregion
}