diff options
author | Tiago Conceição <Tiago_caza@hotmail.com> | 2021-05-24 01:19:58 +0300 |
---|---|---|
committer | Tiago Conceição <Tiago_caza@hotmail.com> | 2021-05-24 01:19:58 +0300 |
commit | ff4e0dfe28572b151b4831f905110eeeaf57fb62 (patch) | |
tree | 1b9c363009c3ab0c9dafbcc5f03eb038d0c413f9 /UVtools.Core | |
parent | ad92a0aa5cef5a9be46e2ba20ac5482fc9030015 (diff) |
v2.13.0v2.13.0
- (Add) Tool - Light bleed compensation: Compensate the over-curing and light bleed from clear resins by dimming the sequential pixels
- (Add) Infill: Honeycomb infill type
- (Upgrade) MessageBox from 1.2.0 to 1.3.1 to fix the small size messages
Diffstat (limited to 'UVtools.Core')
-rw-r--r-- | UVtools.Core/Extensions/PointExtensions.cs | 2 | ||||
-rw-r--r-- | UVtools.Core/Operations/Operation.cs | 8 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationBlur.cs | 6 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationChangeResolution.cs | 3 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationDynamicLifts.cs | 2 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationInfill.cs | 158 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationLayerExportGif.cs | 2 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationLayerExportHeatMap.cs | 2 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationLayerReHeight.cs | 3 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationLightBleedCompensation.cs | 277 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationPixelArithmetic.cs | 2 | ||||
-rw-r--r-- | UVtools.Core/Operations/OperationScripting.cs | 3 | ||||
-rw-r--r-- | UVtools.Core/UVtools.Core.csproj | 2 |
13 files changed, 408 insertions, 62 deletions
diff --git a/UVtools.Core/Extensions/PointExtensions.cs b/UVtools.Core/Extensions/PointExtensions.cs index 4ba31d8..8b0056c 100644 --- a/UVtools.Core/Extensions/PointExtensions.cs +++ b/UVtools.Core/Extensions/PointExtensions.cs @@ -16,7 +16,7 @@ namespace UVtools.Core.Extensions public static Point Rotate(this Point point, double angleDegree, Point pivot = default) { - if (angleDegree == 0 || angleDegree == 360) return point; + if (angleDegree is 0 or 360) return point; double angle = angleDegree * Math.PI / 180; double cos = Math.Cos(angle); double sin = Math.Sin(angle); diff --git a/UVtools.Core/Operations/Operation.cs b/UVtools.Core/Operations/Operation.cs index f8b9b10..acf78b2 100644 --- a/UVtools.Core/Operations/Operation.cs +++ b/UVtools.Core/Operations/Operation.cs @@ -383,6 +383,14 @@ namespace UVtools.Core.Operations ROI = roi; } + public Size GetRoiSizeOrDefault() => GetRoiSizeOrDefault(SlicerFile.Resolution); + public Size GetRoiSizeOrDefault(Mat defaultMat) => GetRoiSizeOrDefault(defaultMat.Size); + + public Size GetRoiSizeOrDefault(Size defaultSize) + { + return HaveROI && defaultSize != _roi.Size ? _roi.Size : defaultSize; + } + public Mat GetRoiOrDefault(Mat defaultMat) { return HaveROI && defaultMat.Size != _roi.Size ? new Mat(defaultMat, _roi) : defaultMat; diff --git a/UVtools.Core/Operations/OperationBlur.cs b/UVtools.Core/Operations/OperationBlur.cs index 255c57f..9642812 100644 --- a/UVtools.Core/Operations/OperationBlur.cs +++ b/UVtools.Core/Operations/OperationBlur.cs @@ -21,15 +21,17 @@ namespace UVtools.Core.Operations [Serializable] public sealed class OperationBlur : Operation { + #region Members private BlurAlgorithm _blurOperation = BlurAlgorithm.Blur; private uint _size = 1; + #endregion #region Overrides public override string Title => "Blur"; public override string Description => - $"Blur layer images by applying a low pass filter\n\n" + - "NOTE: Target printer must support AntiAliasing in order to use this function.\n\n" + + $"Blur layer images by applying a low pass filter.\n\n" + + "NOTE: Target printer must support AntiAliasing in order to use this function.\n" + "See https://docs.opencv.org/master/d4/d13/tutorial_py_filtering.html"; public override string ConfirmationText => diff --git a/UVtools.Core/Operations/OperationChangeResolution.cs b/UVtools.Core/Operations/OperationChangeResolution.cs index 4982cd4..c40d3f7 100644 --- a/UVtools.Core/Operations/OperationChangeResolution.cs +++ b/UVtools.Core/Operations/OperationChangeResolution.cs @@ -12,7 +12,6 @@ using System.Text; using System.Threading.Tasks; using Emgu.CV; using UVtools.Core.FileFormats; -using UVtools.Core.Objects; namespace UVtools.Core.Operations { @@ -58,7 +57,7 @@ namespace UVtools.Core.Operations public override bool CanROI => false; public override string Title => "Change print resolution"; public override string Description => - "Crops or resizes all layer images to fit an alternate print resolution\n" + + "Crops or resizes all layer images to fit an alternate print resolution.\n" + "Useful to make files printable on a different printer than they were originally sliced for without the need to re-slice.\n\n" + "NOTE: Please ensure that the actual model will fit within the new print resolution. The operation will be aborted if it will result in any of the actual model being clipped.\n" + "Only use this tool if both source and target printer have the same pixel pitch spec, otherwise the model size will be invalidated and result in a different size than the originally sliced for. " + diff --git a/UVtools.Core/Operations/OperationDynamicLifts.cs b/UVtools.Core/Operations/OperationDynamicLifts.cs index 7444f0f..5fab1d9 100644 --- a/UVtools.Core/Operations/OperationDynamicLifts.cs +++ b/UVtools.Core/Operations/OperationDynamicLifts.cs @@ -54,7 +54,7 @@ namespace UVtools.Core.Operations public override string Title => "Dynamic lifts"; public override string Description => - "Generate dynamic lift height and speeds for each layer given it mass\n" + + "Generate dynamic lift height and speeds for each layer given it mass.\n" + "Larger masses requires more lift height and less speed while smaller masses can go with shorter lift height and more speed.\n" + "If you have a raft, start after it layer number to not influence the calculations.\n" + "Note: Only few printers support this. Running this on an unsupported printer will cause no harm."; diff --git a/UVtools.Core/Operations/OperationInfill.cs b/UVtools.Core/Operations/OperationInfill.cs index b07ba06..01b3ae9 100644 --- a/UVtools.Core/Operations/OperationInfill.cs +++ b/UVtools.Core/Operations/OperationInfill.cs @@ -33,7 +33,7 @@ namespace UVtools.Core.Operations public override string Title => "Infill"; public override string Description => - $"Generate infill patterns in the model\n\nNOTES:\n1) You must exclude floor and ceil layers from the range.\n2) You must take care of drain holes after the operation."; + $"Generate infill patterns in the model.\n\nNOTES:\n1) You must exclude floor and ceil layers from the range.\n2) You must take care of drain holes after the operation."; public override string ConfirmationText => $"infill model with {InfillType} from layers {LayerIndexStart} through {LayerIndexEnd}?"; @@ -53,6 +53,7 @@ namespace UVtools.Core.Operations CubicCenterLink, CubicDynamicLink, CubicInterlinked, + Honeycomb } #endregion @@ -128,17 +129,23 @@ namespace UVtools.Core.Operations protected override bool ExecuteInternally(OperationProgress progress) { + Mat mask = null; + if (_infillType == InfillAlgorithm.Honeycomb) + { + mask = GetHoneycombMask(GetRoiSizeOrDefault()); + } + Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex => { if (progress.Token.IsCancellationRequested) return; using var mat = SlicerFile[layerIndex].LayerMat; - Execute(mat, layerIndex); + Execute(mat, layerIndex, mask); SlicerFile[layerIndex].LayerMat = mat; progress.LockAndIncrement(); }); - + mask?.Dispose(); return !progress.Token.IsCancellationRequested; } @@ -149,22 +156,22 @@ namespace UVtools.Core.Operations var kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), anchor); uint index = Convert.ToUInt32(arguments[0]); uint layerIndex = index - LayerIndexStart; - var infillColor = new MCvScalar(InfillBrightness); + var infillColor = new MCvScalar(_infillBrightness); Mat patternMask = null; using Mat erode = new (); using Mat diff = new (); - Mat target = GetRoiOrDefault(mat); + var target = GetRoiOrDefault(mat); using var mask = GetMask(mat); - + bool disposeTargetMask = true; - if (InfillType == InfillAlgorithm.Cubic || - InfillType == InfillAlgorithm.CubicCenterLink || - InfillType == InfillAlgorithm.CubicDynamicLink || - InfillType == InfillAlgorithm.CubicInterlinked) + if (_infillType is InfillAlgorithm.Cubic + or InfillAlgorithm.CubicCenterLink + or InfillAlgorithm.CubicDynamicLink + or InfillAlgorithm.CubicInterlinked) { - using var infillPattern = EmguExtensions.InitMat(new Size(InfillSpacing, InfillSpacing)); - using Mat matPattern = mat.CloneBlank(); + using var infillPattern = EmguExtensions.InitMat(new Size(_infillSpacing, _infillSpacing)); + using var matPattern = mat.CloneBlank(); bool firstPattern = true; uint accumulator = 0; bool dynamicCenter = false; @@ -172,16 +179,16 @@ namespace UVtools.Core.Operations { dynamicCenter = !dynamicCenter; firstPattern = true; - accumulator += InfillSpacing; + accumulator += _infillSpacing; if (accumulator >= layerIndex) break; firstPattern = false; - accumulator += InfillThickness; + accumulator += _infillThickness; } if (firstPattern) { - int thickness = InfillThickness / 2; + int thickness = _infillThickness / 2; // Top Left CvInvoke.Rectangle(infillPattern, new Rectangle(0, 0, thickness, thickness), @@ -207,106 +214,159 @@ namespace UVtools.Core.Operations int margin = (int) (InfillSpacing - accumulator + layerIndex) - thickness; int marginInv = (int) (accumulator - layerIndex) - thickness; - if (InfillType == InfillAlgorithm.CubicCenterLink || - (InfillType == InfillAlgorithm.CubicDynamicLink && + if (_infillType == InfillAlgorithm.CubicCenterLink || + (_infillType == InfillAlgorithm.CubicDynamicLink && dynamicCenter) || - InfillType == InfillAlgorithm.CubicInterlinked) + _infillType == InfillAlgorithm.CubicInterlinked) { CvInvoke.Rectangle(infillPattern, - new Rectangle(margin, margin, InfillThickness, InfillThickness), + new Rectangle(margin, margin, _infillThickness, _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, - new Rectangle(marginInv, marginInv, InfillThickness, - InfillThickness), + new Rectangle(marginInv, marginInv, _infillThickness, + _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, - new Rectangle(margin, marginInv, InfillThickness, - InfillThickness), + new Rectangle(margin, marginInv, _infillThickness, + _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, - new Rectangle(marginInv, margin, InfillThickness, - InfillThickness), + new Rectangle(marginInv, margin, _infillThickness, + _infillThickness), infillColor, -1); } - if (InfillType == InfillAlgorithm.CubicInterlinked || - (InfillType == InfillAlgorithm.CubicDynamicLink && + if (_infillType == InfillAlgorithm.CubicInterlinked || + (_infillType == InfillAlgorithm.CubicDynamicLink && !dynamicCenter)) { CvInvoke.Rectangle(infillPattern, - new Rectangle(margin, -thickness, InfillThickness, - InfillThickness), + new Rectangle(margin, -thickness, _infillThickness, + _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, - new Rectangle(marginInv, -thickness, InfillThickness, - InfillThickness), + new Rectangle(marginInv, -thickness, _infillThickness, + _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, - new Rectangle(-thickness, margin, InfillThickness, - InfillThickness), + new Rectangle(-thickness, margin, _infillThickness, + _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, - new Rectangle(-thickness, marginInv, InfillThickness, - InfillThickness), + new Rectangle(-thickness, marginInv, _infillThickness, + _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, new Rectangle(InfillSpacing - thickness, margin, - InfillThickness, InfillThickness), + _infillThickness, _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, new Rectangle(InfillSpacing - thickness, marginInv, - InfillThickness, InfillThickness), + _infillThickness, _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, new Rectangle(margin, InfillSpacing - thickness, - InfillThickness, InfillThickness), + _infillThickness, _infillThickness), infillColor, -1); CvInvoke.Rectangle(infillPattern, new Rectangle(marginInv, InfillSpacing - thickness, - InfillThickness, InfillThickness), + _infillThickness, _infillThickness), infillColor, -1); } - - } else { CvInvoke.Rectangle(infillPattern, - new Rectangle(0, 0, InfillSpacing, InfillSpacing), - infillColor, InfillThickness); + new Rectangle(0, 0, _infillSpacing, _infillSpacing), + infillColor, _infillThickness); } + CvInvoke.Repeat(infillPattern, target.Rows / infillPattern.Rows + 1, + target.Cols / infillPattern.Cols + 1, matPattern); + patternMask = new Mat(matPattern, new Rectangle(0, 0, target.Width, target.Height)); + disposeTargetMask = true; + } + else if (_infillType == InfillAlgorithm.Honeycomb) + { + if (arguments.Length >= 2) + { + patternMask = (Mat)arguments[1]; + disposeTargetMask = false; + } + else { - CvInvoke.Repeat(infillPattern, target.Rows / infillPattern.Rows + 1, - target.Cols / infillPattern.Cols + 1, matPattern); - patternMask = new Mat(matPattern, new Rectangle(0, 0, target.Width, target.Height)); + patternMask = GetHoneycombMask(target.Size); + disposeTargetMask = true; } } - + //patternMask.Save("D:\\pattern.png"); CvInvoke.Erode(target, erode, kernel, anchor, WallThickness, BorderType.Reflect101, default); CvInvoke.Subtract(target, erode, diff); - + CvInvoke.BitwiseAnd(erode, patternMask, target, mask); CvInvoke.Add(target, diff, target, mask); - patternMask?.Dispose(); + + if (disposeTargetMask) + { + patternMask.Dispose(); + } return true; } + public Mat GetHoneycombMask(Size targetSize) + { + var patternMask = EmguExtensions.InitMat(targetSize); + + var halfInfillSpacing = _infillSpacing / 2; + var halfThickenss = _infillThickness / 2; + int width = (int)Math.Round(4 * (_infillSpacing / 2.0 / Math.Sqrt(3))); + var infillColor = new MCvScalar(_infillBrightness); + + for (int col = 0; col <= targetSize.Width / _infillSpacing; col++) + { + for (int row = 0; row <= targetSize.Height / _infillSpacing; row++) + { + // Move over for the column number. + int x = (int)Math.Round(col * (width * 0.75f)); + + // Move down the required number of rows. + int y = row * _infillSpacing; + + // If the column is odd, move down half a hex more. + if (col % 2 == 1) y += halfInfillSpacing; + + var points = new Point[] + { + new(x, y), + new((int) Math.Round(x + width * 0.25f), y - _infillSpacing / 2), + new((int) Math.Round(x + width * 0.75f), y - _infillSpacing / 2), + new(x + width, y), + new((int) Math.Round(x + width * 0.75f), y + _infillSpacing / 2), + new((int) Math.Round(x + width * 0.25f), y + _infillSpacing / 2), + }; + + CvInvoke.Polylines(patternMask, points, true, infillColor, _infillThickness); + } + } + + return patternMask; + } + #endregion } } diff --git a/UVtools.Core/Operations/OperationLayerExportGif.cs b/UVtools.Core/Operations/OperationLayerExportGif.cs index e863f89..d0a0d24 100644 --- a/UVtools.Core/Operations/OperationLayerExportGif.cs +++ b/UVtools.Core/Operations/OperationLayerExportGif.cs @@ -65,7 +65,7 @@ namespace UVtools.Core.Operations public override string Title => "Export layers to GIF"; public override string Description => - "Export a layer range to an animated GIF file\n" + + "Export a layer range to an animated GIF file.\n" + "Note: This process is slow, optimize the parameters to output few layers as possible and/or scale them down."; public override string ConfirmationText => diff --git a/UVtools.Core/Operations/OperationLayerExportHeatMap.cs b/UVtools.Core/Operations/OperationLayerExportHeatMap.cs index eb6482c..2c0bccb 100644 --- a/UVtools.Core/Operations/OperationLayerExportHeatMap.cs +++ b/UVtools.Core/Operations/OperationLayerExportHeatMap.cs @@ -28,7 +28,7 @@ namespace UVtools.Core.Operations #region Overrides public override bool CanHaveProfiles => false; - public override string Title => "Export layers to heat map"; + public override string Title => "Export layers to heat map."; public override string Description => "Export a layer range to a grayscale heat map image that represents the median of the mass in the Z depth/perception\n" + diff --git a/UVtools.Core/Operations/OperationLayerReHeight.cs b/UVtools.Core/Operations/OperationLayerReHeight.cs index 1aee091..548c25c 100644 --- a/UVtools.Core/Operations/OperationLayerReHeight.cs +++ b/UVtools.Core/Operations/OperationLayerReHeight.cs @@ -34,6 +34,7 @@ namespace UVtools.Core.Operations Average } #endregion + #region Members private OperationLayerReHeightItem _selectedItem; private OperationLayerReHeightAntiAliasingType _antiAliasingType; @@ -46,7 +47,7 @@ namespace UVtools.Core.Operations public override bool CanROI => false; public override string Title => "Adjust layer height"; public override string Description => - "Adjust the layer height of the model\n\n" + + "Adjust the layer height of the model.\n\n" + "Adjusting to values lower than current height will reduce layer lines, adjusting to values higher" + " than current height will reduce model detail.\n\n" + "Note: Using dedicated slicer software to re-slice will usually yeild better results."; diff --git a/UVtools.Core/Operations/OperationLightBleedCompensation.cs b/UVtools.Core/Operations/OperationLightBleedCompensation.cs new file mode 100644 index 0000000..c3175af --- /dev/null +++ b/UVtools.Core/Operations/OperationLightBleedCompensation.cs @@ -0,0 +1,277 @@ +/* + * 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 System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Emgu.CV; +using Emgu.CV.Structure; +using UVtools.Core.Extensions; +using UVtools.Core.FileFormats; + +namespace UVtools.Core.Operations +{ + [Serializable] + public class OperationLightBleedCompensation : Operation + { + #region Enums + + public enum LightBleedCompensationLookupMode : byte + { + [Description("Previous: Look for sequential pixels relative to the previous layers")] + Previous, + + [Description("Next: Look for sequential pixels relative to the next layers")] + Next, + + [Description("Both: Look for sequential pixels relative to the previous and next layers")] + Both + } + + #endregion + + #region Members + + private LightBleedCompensationLookupMode _lookupMode = LightBleedCompensationLookupMode.Next; + private string _dimBy = "25,15,10,5"; + + #endregion + + #region Overrides + + public override Enumerations.LayerRangeSelection StartLayerRangeSelection => Enumerations.LayerRangeSelection.Normal; + + public override string Title => "Light bleed compensation"; + public override string Description => + "Compensate the over-curing and light bleed from clear resins by dimming the sequential pixels.\n" + + "Note: You need to find the optimal minimum pixel brightness that such resin can print in order to optimize this process.\n" + + "With more translucent resins you can go with lower brightness but stick to a limit that can form the layer without loss." + + " Tiny details can be lost when using low brightness level.\n" + + "After apply a light bleed compensation, do not apply or re-run this tool over."; + + public override string ConfirmationText => + $"compensate layers {LayerIndexStart} through {LayerIndexEnd}?"; + + public override string ProgressTitle => + $"Compensate layers {LayerIndexStart} through {LayerIndexEnd}"; + + public override string ProgressAction => "Compensated layers"; + + public override string ValidateInternally() + { + StringBuilder sb = new(); + + if (DimByArray.Length == 0) + { + sb.AppendLine($"The dim levels are invalid or not set."); + } + + if (MaximumSubtraction >= byte.MaxValue) + { + sb.AppendLine($"The sum of dim levels are producing black pixels."); + } + + return sb.ToString(); + } + + public override string ToString() + { + var result = $"[Lookup: {_lookupMode}]" + + $" [Dim by: {_dimBy}]" + LayerRangeString; + if (!string.IsNullOrEmpty(ProfileName)) result = $"{ProfileName}: {result}"; + return result; + } + #endregion + + #region Constructor + + public OperationLightBleedCompensation() { } + + public OperationLightBleedCompensation(FileFormat slicerFile) : base(slicerFile) { } + + #endregion + + #region Properties + + public LightBleedCompensationLookupMode LookupMode + { + get => _lookupMode; + set => RaiseAndSetIfChanged(ref _lookupMode, value); + } + + public string DimBy + { + get => _dimBy; + set + { + if(!RaiseAndSetIfChanged(ref _dimBy, value)) return; + RaisePropertyChanged(nameof(MinimumBrightness)); + RaisePropertyChanged(nameof(MaximumSubtraction)); + } + } + + public int MinimumBrightness => 255 - MaximumSubtraction; + public int MaximumSubtraction => DimByArray.Aggregate(0, (current, dim) => current + dim); + + public byte[] DimByArray + { + get + { + List<byte> levels = new(); + var split = _dimBy.Split(',', StringSplitOptions.TrimEntries); + foreach (var str in split) + { + if (!byte.TryParse(str, out var brightness)) continue; + if (brightness is byte.MinValue or byte.MaxValue) continue; + levels.Add(brightness); + } + + return levels.ToArray(); + } + } + + public MCvScalar[] DimByMCvScalar + { + get + { + List<MCvScalar> levels = new(); + var split = _dimBy.Split(',', StringSplitOptions.TrimEntries); + foreach (var str in split) + { + if (!byte.TryParse(str, out var brightness)) continue; + if (brightness is byte.MinValue or byte.MaxValue) continue; + levels.Add(new MCvScalar(brightness)); + } + + return levels.ToArray(); + } + } + + #endregion + + #region Equality + + protected bool Equals(OperationLightBleedCompensation other) + { + return _lookupMode == other._lookupMode && _dimBy == other._dimBy; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((OperationLightBleedCompensation) obj); + } + + public override int GetHashCode() + { + return HashCode.Combine((int) _lookupMode, _dimBy); + } + + #endregion + + #region Methods + + /// <summary> + /// Get the cached dim mat's + /// </summary> + /// <returns></returns> + public Mat[] GetDimMats() + { + var dimLevels = DimByMCvScalar; + if (dimLevels.Length == 0) return Array.Empty<Mat>(); + var mats = new Mat[dimLevels.Length]; + var matSize = GetRoiSizeOrDefault(); + for (var i = 0; i < mats.Length; i++) + { + mats[i] = EmguExtensions.InitMat(matSize, dimLevels[i]); + } + + return mats; + } + + protected override bool ExecuteInternally(OperationProgress progress) + { + var dimMats = GetDimMats(); + if (dimMats.Length == 0) return false; + Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex => + { + if (progress.Token.IsCancellationRequested) return; // Abort operation, user requested cancellation + + var layer = SlicerFile[layerIndex]; + using var mat = layer.LayerMat; + using var original = mat.Clone(); + var target = GetRoiOrDefault(mat); + + for (byte i = 0; i < dimMats.Length; i++) + { + Mat mask = null; + Mat previousMat = null; + Mat previousMatRoi = null; + Mat nextMat = null; + Mat nextMatRoi = null; + + + if (_lookupMode is LightBleedCompensationLookupMode.Previous or LightBleedCompensationLookupMode.Both) + { + int layerPreviousIndex = (int)layerIndex - i - 1; + if (layerPreviousIndex >= LayerIndexStart) + { + previousMat = SlicerFile[layerPreviousIndex].LayerMat; + mask = previousMatRoi = GetRoiOrDefault(previousMat); + } + } + if (_lookupMode is LightBleedCompensationLookupMode.Next or LightBleedCompensationLookupMode.Both) + { + uint layerIndexNext = (uint) (layerIndex + i + 1); + if (layerIndexNext <= LayerIndexEnd) + { + nextMat = SlicerFile[layerIndexNext].LayerMat; + mask = nextMatRoi = GetRoiOrDefault(nextMat); + } + } + + if (previousMat is null && nextMat is null) break; // Nothing more to do + if (previousMat is not null && nextMat is not null) // both, need to merge previous with next layer + { + CvInvoke.Add(previousMatRoi, nextMatRoi, previousMatRoi); + mask = previousMatRoi; + } + + CvInvoke.Subtract(target, dimMats[i], target, mask); + + previousMat?.Dispose(); + nextMat?.Dispose(); + } + + // Apply the results only to the selected masked area, if user selected one + ApplyMask(original, target); + + // Set current layer image with the modified mat we just manipulated + layer.LayerMat = mat; + + // Increment progress bar by 1 + progress.LockAndIncrement(); + }); + + foreach (var dimMat in dimMats) + { + dimMat.Dispose(); + } + + // return true if not cancelled by user + return !progress.Token.IsCancellationRequested; + } + + #endregion + } +} diff --git a/UVtools.Core/Operations/OperationPixelArithmetic.cs b/UVtools.Core/Operations/OperationPixelArithmetic.cs index 0ce74e8..427d7be 100644 --- a/UVtools.Core/Operations/OperationPixelArithmetic.cs +++ b/UVtools.Core/Operations/OperationPixelArithmetic.cs @@ -72,7 +72,7 @@ namespace UVtools.Core.Operations public override string Title => "Pixel arithmetic"; public override string Description => - "Perform arithmetic operations over the pixels"; + "Perform arithmetic operations over the pixels."; public override string ConfirmationText => $"arithmetic {_operator}" + diff --git a/UVtools.Core/Operations/OperationScripting.cs b/UVtools.Core/Operations/OperationScripting.cs index 661daad..a54326c 100644 --- a/UVtools.Core/Operations/OperationScripting.cs +++ b/UVtools.Core/Operations/OperationScripting.cs @@ -12,7 +12,6 @@ using System.Xml.Serialization; using Microsoft.CodeAnalysis.CSharp.Scripting; using Microsoft.CodeAnalysis.Scripting; using UVtools.Core.FileFormats; -using UVtools.Core.Objects; using UVtools.Core.Scripting; namespace UVtools.Core.Operations @@ -36,7 +35,7 @@ namespace UVtools.Core.Operations public override string Title => "Scripting"; public override string Description => - $"Run external scripts to manipulate the loaded file\n" + + $"Run external scripts to manipulate the loaded file.\n" + $"The scripts have wide access to your system and able to do modifications, read/write files, etc. " + $"Make sure to run only the scripts you trust! Or run UVtools in a sandbox while executing this."; diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index 5a6763a..4a97b3d 100644 --- a/UVtools.Core/UVtools.Core.csproj +++ b/UVtools.Core/UVtools.Core.csproj @@ -10,7 +10,7 @@ <RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl> <PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl> <Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description> - <Version>2.12.2</Version> + <Version>2.13.0</Version> <Copyright>Copyright © 2020 PTRTECH</Copyright> <PackageIcon>UVtools.png</PackageIcon> <Platforms>AnyCPU;x64</Platforms> |