diff options
author | Tiago Conceição <Tiago_caza@hotmail.com> | 2021-07-08 00:41:12 +0300 |
---|---|---|
committer | Tiago Conceição <Tiago_caza@hotmail.com> | 2021-07-08 00:41:12 +0300 |
commit | 29c485458ce300e0085d9af01ce2ecc87fd0cbd5 (patch) | |
tree | 668baad2ef63010f22344a27c5edc0c88bde301d | |
parent | c56ddb904c5990fa9557882158333edfe9745fb8 (diff) |
v2.14.1v2.14.1
- (Upgrade) EmguCV from 4.5.1 to 4.5.2
- **File formats:**
- (Add) Getter `IsAntiAliasingEmulated`: Gets whatever a file format uses real or emulated AntiAliasing
- (Add) Getter `IsDisplayPortrait`: Gets if the display is in portrait mode
- (Add) Getter `IsDisplayLandscape`: Gets if the display is in landscape mode
- **Tool - Resize:** (#235)
- (Fix) Division by 0 when start layer is equal to end layer
- (Fix) Calculations when using the option "Increase or decrease towards 100%"
- (Add) About window: OpenCV build number and a button to copy build information to clipboard
- (Improvement) Exposure exposure finder: Improve the **Multiple brightness** section to auto fill with correct values for file formats that use time fractions to emulate AntiAliasing, this can be used to replace the **Multiple exposures** section
- (Fix) UVJ: Error when using a null or empty layer array on manifest `config.json` file (#232)
- (Fix) GCode parser: When only a G4/wait command is present on a layer it was setting the global exposure time and discard the this value per layer
40 files changed, 462 insertions, 237 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index cabc986..2323ed6 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -6,10 +6,10 @@ labels: '' assignees: sn4k3 --- -<span style="color:red"> -**! Before continue, please look/search on closed topics if your case was already been discussed, if yes and related, comment there instead.** -**! Fill the report template and remove the sections you do not used on this bug report** -</span> +<!-- +This is just a template - feel free to delete any and all of it and replace as appropriate. +Before continue, please look/search on closed topics if your case was already been discussed, if yes and related, comment there instead. +!--> ## System - OS: [e.g. Windows 10 x64 v20H2] @@ -27,19 +27,29 @@ Steps to reproduce the behavior: 4. See error ## Expected behavior +<!-- A clear and concise description of what you expected to happen. +!--> ## Screenshots +<!-- If applicable, add screenshots to help explain your problem. Never hide information, full GUI/window screenshot is always a must! If bug is related to GUI/visuals print a screenshot from Help -> About +!--> ## Files +<!-- Were possible attach the problematic file, both source and output file if applicable. +!--> ## Exceptions Log file +<!-- In some unexpected exceptions errors and application crash it will generate and save a log file under AppData\Local\UVtools\errors.log. To navigate to the error.log folder you can open UVtools, go to Help -> Open settings folder If present you can attach the log file here. +!--> ## Additional context +<!-- Add any other context about the problem here. +!-->
\ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 4999274..2fe0bd7 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -8,7 +8,10 @@ assignees: sn4k3 Also look at: https://github.com/sn4k3/UVtools/discussions/categories/ideas -<span style="color:red">**! Before continue, please look/search on closed topics if your case was already been discussed, if yes and related, comment there instead.**</span> +<!-- +This is just a template - feel free to delete any and all of it and replace as appropriate. +Before continue, please look/search on closed topics if your case was already been discussed, if yes and related, comment there instead. +!--> ## Is your feature request related to a problem? Please describe A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] @@ -17,10 +20,16 @@ A clear and concise description of what the problem is. Ex. I'm always frustrate A clear and concise description of what you want to happen. ## Describe alternatives you've considered +<!-- A clear and concise description of any alternative solutions or features you've considered. +!--> ## Screenshots +<!-- If applicable, add screenshots to help explain your request. +!--> ## Additional context +<!-- Add any other context or screenshots about the feature request here. +!-->
\ No newline at end of file @@ -354,6 +354,8 @@ MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder .ionide/ UVtools.Platforms/linux-x64/libcvextern.so +UVtools.Platforms/arch-x64/libcvextern.so build/nuget_api.key -build/*.key
\ No newline at end of file +build/*.key + diff --git a/CHANGELOG.md b/CHANGELOG.md index a1a84c4..b3f2ca7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 07/06/2021 - v2.14.1 + +- (Upgrade) EmguCV from 4.5.1 to 4.5.2 +- **File formats:** + - (Add) Getter `IsAntiAliasingEmulated`: Gets whatever a file format uses real or emulated AntiAliasing + - (Add) Getter `IsDisplayPortrait`: Gets if the display is in portrait mode + - (Add) Getter `IsDisplayLandscape`: Gets if the display is in landscape mode +- **Tool - Resize:** (#235) + - (Fix) Division by 0 when start layer is equal to end layer + - (Fix) Calculations when using the option "Increase or decrease towards 100%" +- (Add) About window: OpenCV build number and a button to copy build information to clipboard +- (Improvement) Exposure exposure finder: Improve the **Multiple brightness** section to auto fill with correct values for file formats that use time fractions to emulate AntiAliasing, this can be used to replace the **Multiple exposures** section +- (Fix) UVJ: Error when using a null or empty layer array on manifest `config.json` file (#232) +- (Fix) GCode parser: When only a G4/wait command is present on a layer it was setting the global exposure time and discard the this value per layer + ## 03/06/2021 - v2.14.0 - **File Formats:** diff --git a/Scripts/ctb.bt b/Scripts/ctb.bt index 835ac3b..88ddc4b 100644 --- a/Scripts/ctb.bt +++ b/Scripts/ctb.bt @@ -86,7 +86,7 @@ struct SLICER_INFO { uint MachineNameAddress <fgcolor=cBlack, bgcolor=cRed>; uint MachineNameSize <fgcolor=cBlack, bgcolor=cRed>; uint EncryptionMode <fgcolor=cBlack, bgcolor=cRed>; // 0/8 for cbddlp files, 0xF (15) for ctb files, 0x2000000F (536870927) for v3 ctb and 1073741839 for v4 ctb files to allow per layer parameters - uint MysteriousId <fgcolor=cBlack, bgcolor=cRed>; // v3 = 305419896 | v4 = 27087675 + uint MysteriousId <fgcolor=cBlack, bgcolor=cRed>; // v3 = 305419896 | v4 lightoff? = 27093086 | v4 rest? = 27093090 uint AntiAliasLevel <fgcolor=cBlack, bgcolor=cRed>; uint SoftwareVersion <fgcolor=cBlack, bgcolor=cRed>; // ctb v3 = 17171200 | ctb v4 = 16777216 float RestTimeAfterRetract <fgcolor=cBlack, bgcolor=cRed>; diff --git a/UVtools.AvaloniaControls/AdvancedImageBox.axaml.cs b/UVtools.AvaloniaControls/AdvancedImageBox.axaml.cs index a5cab57..689f6b4 100644 --- a/UVtools.AvaloniaControls/AdvancedImageBox.axaml.cs +++ b/UVtools.AvaloniaControls/AdvancedImageBox.axaml.cs @@ -980,8 +980,7 @@ namespace UVtools.AvaloniaControls { var rect = SelectionRegion; return new Rectangle((int) Math.Ceiling(rect.X), (int)Math.Ceiling(rect.Y), - (int)Math.Floor(rect.Width), (int)Math.Floor(rect.Height) - ); + (int)rect.Width, (int)rect.Height); } } @@ -990,7 +989,7 @@ namespace UVtools.AvaloniaControls get { var rect = SelectionRegion; - return new PixelSize((int) Math.Floor(rect.Width), (int) Math.Floor(rect.Height)); + return new PixelSize((int) rect.Width, (int) rect.Height); } } @@ -1465,7 +1464,7 @@ namespace UVtools.AvaloniaControls } } - Zoom = (int)Math.Round(Math.Floor(zoom)); + Zoom = (int)zoom; } /// <summary> diff --git a/UVtools.Core/Extensions/EmguExtensions.cs b/UVtools.Core/Extensions/EmguExtensions.cs index 0399fa6..1a6cd42 100644 --- a/UVtools.Core/Extensions/EmguExtensions.cs +++ b/UVtools.Core/Extensions/EmguExtensions.cs @@ -346,9 +346,7 @@ namespace UVtools.Core.Extensions /// <returns></returns> public static byte[] GetPngByes(this Mat mat) { - using var vector = new VectorOfByte(); - CvInvoke.Imencode(".png", mat, vector); - return vector.ToArray(); + return CvInvoke.Imencode(".png", mat); } #endregion @@ -609,7 +607,7 @@ namespace UVtools.Core.Extensions /// <param name="thickness"></param> /// <param name="lineType"></param> /// <param name="flip"></param> - public static void DrawPolygon(this Mat src, int sides, int radius, Point center, MCvScalar color, double startingAngle = 0, int thickness = -1, LineType lineType = LineType.EightConnected, FlipType flip = FlipType.None) + public static void DrawPolygon(this Mat src, int sides, int radius, Point center, MCvScalar color, double startingAngle = 0, int thickness = -1, LineType lineType = LineType.EightConnected, FlipType? flip = null) { if (sides == 1) { @@ -627,8 +625,9 @@ namespace UVtools.Core.Extensions } var points = DrawingExtensions.GetPolygonVertices(sides, radius, center, startingAngle, - (flip & FlipType.Horizontal) != 0, (flip & FlipType.Vertical) != 0); - + flip is FlipType.Horizontal or FlipType.Both, + flip is FlipType.Vertical or FlipType.Both); + if (thickness <= 0) { using var vec = new VectorOfPoint(points); diff --git a/UVtools.Core/FileFormats/CWSFile.cs b/UVtools.Core/FileFormats/CWSFile.cs index 192f5a2..86e5e31 100644 --- a/UVtools.Core/FileFormats/CWSFile.cs +++ b/UVtools.Core/FileFormats/CWSFile.cs @@ -627,11 +627,10 @@ namespace UVtools.Core.FileFormats spanEncode[i] = span[i]; } - using VectorOfByte vec = new(); - CvInvoke.Imencode(".png", matEncode, vec); + var bytes = matEncode.GetPngByes(); lock (progress.Mutex) { - outputFile.PutFileContent(layerImagePath, vec.ToArray(), ZipArchiveMode.Create); + outputFile.PutFileContent(layerImagePath, bytes, ZipArchiveMode.Create); progress++; } } diff --git a/UVtools.Core/FileFormats/ChituboxFile.cs b/UVtools.Core/FileFormats/ChituboxFile.cs index 05cf03f..bc22593 100644 --- a/UVtools.Core/FileFormats/ChituboxFile.cs +++ b/UVtools.Core/FileFormats/ChituboxFile.cs @@ -14,7 +14,6 @@ using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; -using System.Text; using System.Threading.Tasks; using BinarySerialization; using Emgu.CV; @@ -692,8 +691,6 @@ namespace UVtools.Core.FileFormats } span[i] = (byte) newC; - - } return image; @@ -1179,6 +1176,8 @@ namespace UVtools.Core.FileFormats } } + public override bool IsAntiAliasingEmulated => IsCbddlpFile; + public override byte AntiAliasing { get => (byte) (IsCbtFile ? SlicerInfoSettings.AntiAliasLevel : HeaderSettings.AntiAliasLevel); diff --git a/UVtools.Core/FileFormats/ChituboxZipFile.cs b/UVtools.Core/FileFormats/ChituboxZipFile.cs index 213ea1f..a3bd7bb 100644 --- a/UVtools.Core/FileFormats/ChituboxZipFile.cs +++ b/UVtools.Core/FileFormats/ChituboxZipFile.cs @@ -353,12 +353,8 @@ namespace UVtools.Core.FileFormats { using (Stream stream = outputFile.CreateEntry("preview.png").Open()) { - using (var vec = new VectorOfByte()) - { - CvInvoke.Imencode(".png", Thumbnails[0], vec); - stream.WriteBytes(vec.ToArray()); - stream.Close(); - } + stream.WriteBytes(Thumbnails[0].GetPngByes()); + stream.Close(); } } @@ -368,8 +364,7 @@ namespace UVtools.Core.FileFormats { using (var vec = new VectorOfByte()) { - CvInvoke.Imencode(".png", Thumbnails[1], vec); - stream.WriteBytes(vec.ToArray()); + stream.WriteBytes(Thumbnails[1].GetPngByes()); stream.Close(); } } diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs index a639fae..e10e4e7 100644 --- a/UVtools.Core/FileFormats/FileFormat.cs +++ b/UVtools.Core/FileFormats/FileFormat.cs @@ -55,6 +55,8 @@ namespace UVtools.Core.FileFormats public const byte DefaultBottomLightPWM = 255; public const byte DefaultLightPWM = 255; + public const byte MaximumAntiAliasing = 16; + public const float MinimumLayerHeight = 0.01f; public const float MaximumLayerHeight = 0.20f; #endregion @@ -602,6 +604,16 @@ namespace UVtools.Core.FileFormats public virtual bool MirrorDisplay { get; set; } /// <summary> + /// Gets if the display is in portrait mode + /// </summary> + public bool IsDisplayPortrait => ResolutionY > ResolutionX; + + /// <summary> + /// Gets if the display is in landscape mode + /// </summary> + public bool IsDisplayLandscape => !IsDisplayPortrait; + + /// <summary> /// Gets or sets the maximum printer build Z volume /// </summary> public virtual float MachineZ @@ -705,6 +717,11 @@ namespace UVtools.Core.FileFormats public bool HaveAntiAliasing => AntiAliasing > 1; /// <summary> + /// Gets if the AntiAliasing is emulated/fake with fractions of the time or if is real grey levels + /// </summary> + public virtual bool IsAntiAliasingEmulated => false; + + /// <summary> /// Gets or sets the AntiAliasing level /// </summary> public abstract byte AntiAliasing { get; set; } @@ -1692,6 +1709,10 @@ namespace UVtools.Core.FileFormats byteArr.Length); stream.Write(byteArr, 0, byteArr.Length); stream.Close(); + + //using var mat = layer.LayerMat; + //mat.Save(Path.Combine(path, $"{layer.Filename}.jpg")); + progress.LockAndIncrement(); }); } diff --git a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs index 4003f8a..88a0a80 100644 --- a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs +++ b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs @@ -764,7 +764,7 @@ namespace UVtools.Core.FileFormats { int done = reps; - if (lastColor == 0 || lastColor == 0xf) + if (lastColor is 0 or 0xf) { if (done > RLE4EncodingLimit) { @@ -1045,6 +1045,8 @@ namespace UVtools.Core.FileFormats set {} } + public override bool IsAntiAliasingEmulated => true; + public override byte AntiAliasing { get => (byte) HeaderSettings.AntiAliasing; diff --git a/UVtools.Core/FileFormats/SL1File.cs b/UVtools.Core/FileFormats/SL1File.cs index fca0818..c377f1b 100644 --- a/UVtools.Core/FileFormats/SL1File.cs +++ b/UVtools.Core/FileFormats/SL1File.cs @@ -557,9 +557,7 @@ namespace UVtools.Core.FileFormats { if (thumbnail is null) continue; using var stream = outputFile.CreateEntry($"thumbnail/thumbnail{thumbnail.Width}x{thumbnail.Height}.png").Open(); - var vec = new VectorOfByte(); - CvInvoke.Imencode(".png", thumbnail, vec); - stream.WriteBytes(vec.ToArray()); + stream.WriteBytes(thumbnail.GetPngByes()); stream.Close(); } diff --git a/UVtools.Core/FileFormats/UVJFile.cs b/UVtools.Core/FileFormats/UVJFile.cs index 0e9b4b7..feb22c1 100644 --- a/UVtools.Core/FileFormats/UVJFile.cs +++ b/UVtools.Core/FileFormats/UVJFile.cs @@ -113,8 +113,8 @@ namespace UVtools.Core.FileFormats public class Settings { - public Properties Properties { get; set; } = new Properties(); - public List<LayerData> Layers { get; set; } = new List<LayerData>(); + public Properties Properties { get; set; } = new(); + public List<LayerData> Layers { get; set; } = new(); public override string ToString() { @@ -348,18 +348,14 @@ namespace UVtools.Core.FileFormats if (CreatedThumbnailsCount > 0) { using var stream = outputFile.CreateEntry(FilePreviewTinyName).Open(); - using var vec = new VectorOfByte(); - CvInvoke.Imencode(".png", Thumbnails[0], vec); - stream.WriteBytes(vec.ToArray()); + stream.WriteBytes(Thumbnails[0].GetPngByes()); stream.Close(); } if (CreatedThumbnailsCount > 1) { - using Stream stream = outputFile.CreateEntry(FilePreviewHugeName).Open(); - using var vec = new VectorOfByte(); - CvInvoke.Imencode(".png", Thumbnails[1], vec); - stream.WriteBytes(vec.ToArray()); + using var stream = outputFile.CreateEntry(FilePreviewHugeName).Open(); + stream.WriteBytes(Thumbnails[1].GetPngByes()); stream.Close(); } @@ -421,13 +417,13 @@ namespace UVtools.Core.FileFormats using var stream = entry.Open(); this[layerIndex] = new Layer(layerIndex, stream, LayerManager) { - PositionZ = JsonSettings.Layers.Count >= layerIndex ? JsonSettings.Layers[(int) layerIndex].Z : GetHeightFromLayer(layerIndex), - LiftHeight = JsonSettings.Layers.Count >= layerIndex ? JsonSettings.Layers[(int)layerIndex].Exposure.LiftHeight : GetInitialLayerValueOrNormal(layerIndex, BottomLiftHeight, LiftHeight), - LiftSpeed = JsonSettings.Layers.Count >= layerIndex ? JsonSettings.Layers[(int)layerIndex].Exposure.LiftSpeed : GetInitialLayerValueOrNormal(layerIndex, BottomLiftSpeed, LiftSpeed), - RetractSpeed = JsonSettings.Layers.Count >= layerIndex ? JsonSettings.Layers[(int)layerIndex].Exposure.RetractSpeed : RetractSpeed, - LightOffDelay = JsonSettings.Layers.Count >= layerIndex ? JsonSettings.Layers[(int)layerIndex].Exposure.LightOffTime : GetInitialLayerValueOrNormal(layerIndex, BottomLightOffDelay, LightOffDelay), - ExposureTime = JsonSettings.Layers.Count >= layerIndex ? JsonSettings.Layers[(int)layerIndex].Exposure.LightOnTime : GetInitialLayerValueOrNormal(layerIndex, BottomExposureTime, ExposureTime), - LightPWM = JsonSettings.Layers.Count >= layerIndex ? JsonSettings.Layers[(int)layerIndex].Exposure.LightPWM : GetInitialLayerValueOrNormal(layerIndex, BottomLightPWM, LightPWM), + PositionZ = JsonSettings.Layers?.Count > layerIndex ? JsonSettings.Layers[(int) layerIndex].Z : GetHeightFromLayer(layerIndex), + LiftHeight = JsonSettings.Layers?.Count > layerIndex ? JsonSettings.Layers[(int)layerIndex].Exposure.LiftHeight : GetInitialLayerValueOrNormal(layerIndex, BottomLiftHeight, LiftHeight), + LiftSpeed = JsonSettings.Layers?.Count > layerIndex ? JsonSettings.Layers[(int)layerIndex].Exposure.LiftSpeed : GetInitialLayerValueOrNormal(layerIndex, BottomLiftSpeed, LiftSpeed), + RetractSpeed = JsonSettings.Layers?.Count > layerIndex ? JsonSettings.Layers[(int)layerIndex].Exposure.RetractSpeed : RetractSpeed, + LightOffDelay = JsonSettings.Layers?.Count > layerIndex ? JsonSettings.Layers[(int)layerIndex].Exposure.LightOffTime : GetInitialLayerValueOrNormal(layerIndex, BottomLightOffDelay, LightOffDelay), + ExposureTime = JsonSettings.Layers?.Count > layerIndex ? JsonSettings.Layers[(int)layerIndex].Exposure.LightOnTime : GetInitialLayerValueOrNormal(layerIndex, BottomExposureTime, ExposureTime), + LightPWM = JsonSettings.Layers?.Count > layerIndex ? JsonSettings.Layers[(int)layerIndex].Exposure.LightPWM : GetInitialLayerValueOrNormal(layerIndex, BottomLightPWM, LightPWM), }; } diff --git a/UVtools.Core/FileFormats/VDTFile.cs b/UVtools.Core/FileFormats/VDTFile.cs index aa6e7dc..00008cc 100644 --- a/UVtools.Core/FileFormats/VDTFile.cs +++ b/UVtools.Core/FileFormats/VDTFile.cs @@ -421,9 +421,7 @@ namespace UVtools.Core.FileFormats if(Thumbnails[i] is null) continue; using var stream = outputFile.CreateEntry(FilePreviewNames[i]).Open(); - using var vec = new VectorOfByte(); - CvInvoke.Imencode(".png", Thumbnails[i], vec); - stream.WriteBytes(vec.ToArray()); + stream.WriteBytes(Thumbnails[i].GetPngByes()); stream.Close(); } } diff --git a/UVtools.Core/FileFormats/ZCodeFile.cs b/UVtools.Core/FileFormats/ZCodeFile.cs index 10556d3..ffff100 100644 --- a/UVtools.Core/FileFormats/ZCodeFile.cs +++ b/UVtools.Core/FileFormats/ZCodeFile.cs @@ -448,9 +448,7 @@ namespace UVtools.Core.FileFormats if (Thumbnails.Length > 0 && Thumbnails[0] is not null) { using var thumbnailsStream = outputFile.CreateEntry(PreviewFilename).Open(); - using var vec = new VectorOfByte(); - CvInvoke.Imencode(".png", Thumbnails[0], vec); - thumbnailsStream.WriteBytes(vec.ToArray()); + thumbnailsStream.WriteBytes(Thumbnails[0].GetPngByes()); thumbnailsStream.Close(); } diff --git a/UVtools.Core/FileFormats/ZCodexFile.cs b/UVtools.Core/FileFormats/ZCodexFile.cs index 5b3967a..bf7aeaf 100644 --- a/UVtools.Core/FileFormats/ZCodexFile.cs +++ b/UVtools.Core/FileFormats/ZCodexFile.cs @@ -388,11 +388,9 @@ namespace UVtools.Core.FileFormats if (CreatedThumbnailsCount > 0) { - using (Stream stream = outputFile.CreateEntry("Preview.png").Open()) + using (var stream = outputFile.CreateEntry("Preview.png").Open()) { - var vec = new VectorOfByte(); - CvInvoke.Imencode(".png", Thumbnails[0], vec); - stream.WriteBytes(vec.ToArray()); + stream.WriteBytes(Thumbnails[0].GetPngByes()); stream.Close(); } } diff --git a/UVtools.Core/GCode/GCodeBuilder.cs b/UVtools.Core/GCode/GCodeBuilder.cs index 97b4667..03c1d75 100644 --- a/UVtools.Core/GCode/GCodeBuilder.cs +++ b/UVtools.Core/GCode/GCodeBuilder.cs @@ -641,16 +641,16 @@ namespace UVtools.Core.GCode float lightOffDelay = 0; byte pwm = slicerFile.GetInitialLayerValueOrNormal(layerIndex, slicerFile.BottomLightPWM, slicerFile.LightPWM); float exposureTime = slicerFile.GetInitialLayerValueOrNormal(layerIndex, slicerFile.BottomExposureTime, slicerFile.ExposureTime); - var moveG0Regex = Regex.Match(stripGcode, CommandMoveG0.ToStringWithoutComments(@"([+-]?([0-9]*[.])?[0-9]+)", @"(\d+)"), RegexOptions.IgnoreCase); - var moveG1Regex = Regex.Match(stripGcode, CommandMoveG1.ToStringWithoutComments(@"([+-]?([0-9]*[.])?[0-9]+)", @"(\d+)"), RegexOptions.IgnoreCase); - var waitG4Regex = Regex.Match(stripGcode, CommandWaitG4.ToStringWithoutComments(@"(\d+)"), RegexOptions.IgnoreCase); + var moveG0Regex = Regex.Matches(stripGcode, CommandMoveG0.ToStringWithoutComments(@"([+-]?([0-9]*[.])?[0-9]+)", @"(\d+)"), RegexOptions.IgnoreCase); + var moveG1Regex = Regex.Matches(stripGcode, CommandMoveG1.ToStringWithoutComments(@"([+-]?([0-9]*[.])?[0-9]+)", @"(\d+)"), RegexOptions.IgnoreCase); + var waitG4Regex = Regex.Matches(stripGcode, CommandWaitG4.ToStringWithoutComments(@"(\d+)"), RegexOptions.IgnoreCase); var pwmM106Regex = Regex.Match(stripGcode, CommandTurnLEDM106.ToStringWithoutComments(@"(\d+)"), RegexOptions.IgnoreCase); - var moveRegex = moveG0Regex.Success ? moveG0Regex : moveG1Regex; + var moveRegex = moveG0Regex.Count > 0 ? moveG0Regex : moveG1Regex; - if (moveRegex.Success) + if (moveRegex.Count >= 1 && moveRegex[0].Success) { - float liftPosTemp = float.Parse(moveRegex.Groups[1].Value, CultureInfo.InvariantCulture); - float liftSpeedTemp = float.Parse(moveRegex.Groups[3].Value, CultureInfo.InvariantCulture); + float liftPosTemp = float.Parse(moveRegex[0].Groups[1].Value, CultureInfo.InvariantCulture); + float liftSpeedTemp = float.Parse(moveRegex[0].Groups[3].Value, CultureInfo.InvariantCulture); switch (GCodeSpeedUnit) { @@ -666,11 +666,10 @@ namespace UVtools.Core.GCode throw new ArgumentOutOfRangeException(); } - moveRegex = moveRegex.NextMatch(); - if (moveRegex.Success) + if (moveRegex.Count >= 2 && moveRegex[1].Success) { - float retractPos = float.Parse(moveRegex.Groups[1].Value, CultureInfo.InvariantCulture); - retractSpeed = float.Parse(moveRegex.Groups[3].Value, CultureInfo.InvariantCulture); + float retractPos = float.Parse(moveRegex[1].Groups[1].Value, CultureInfo.InvariantCulture); + retractSpeed = float.Parse(moveRegex[1].Groups[3].Value, CultureInfo.InvariantCulture); liftSpeed = liftSpeedTemp; switch (positionType) @@ -727,9 +726,9 @@ namespace UVtools.Core.GCode } } - if (waitG4Regex.Success) + if (waitG4Regex.Count >= 1 && waitG4Regex[0].Success) { - lightOffDelay = float.Parse(waitG4Regex.Groups[1].Value, CultureInfo.InvariantCulture); + lightOffDelay = float.Parse(waitG4Regex[0].Groups[1].Value, CultureInfo.InvariantCulture); switch (GCodeTimeUnit) { case GCodeTimeUnits.Milliseconds: @@ -737,10 +736,9 @@ namespace UVtools.Core.GCode break; } - waitG4Regex = waitG4Regex.NextMatch(); - if (waitG4Regex.Success) + if (waitG4Regex.Count >= 2 && waitG4Regex[1].Success) { - exposureTime = float.Parse(waitG4Regex.Groups[1].Value, CultureInfo.InvariantCulture); + exposureTime = float.Parse(waitG4Regex[1].Groups[1].Value, CultureInfo.InvariantCulture); switch (GCodeTimeUnit) { case GCodeTimeUnits.Milliseconds: @@ -748,8 +746,9 @@ namespace UVtools.Core.GCode break; } } - else // Only one match, meaning light off delay is not present + else // Only one match, meaning light off delay is not present and the only time is the cure time { + exposureTime = lightOffDelay; lightOffDelay = slicerFile.GetInitialLayerValueOrNormal(layerIndex, slicerFile.BottomLightOffDelay, slicerFile.LightOffDelay); } } diff --git a/UVtools.Core/Objects/Material.cs b/UVtools.Core/Objects/Material.cs index 84f39fa..d469c5a 100644 --- a/UVtools.Core/Objects/Material.cs +++ b/UVtools.Core/Objects/Material.cs @@ -119,7 +119,7 @@ namespace UVtools.Core.Objects /// <summary> /// Gets the number of consumed bottles /// </summary> - public uint ConsumedBottles => (uint) Math.Floor(_consumedVolume / _bottleVolume); + public uint ConsumedBottles => (uint)(_consumedVolume / _bottleVolume); /// <summary> /// Gets the total number of owned bottles @@ -236,7 +236,7 @@ namespace UVtools.Core.Objects public bool Consume(decimal volume, double printSeconds = 0) { if (volume <= 0 || _bottleVolume == 0) return true; // Safe check - int consumedBottles = (int) Math.Floor(volume / _bottleVolume); + int consumedBottles = (int)(volume / _bottleVolume); decimal remainder = volume % _bottleVolume; if (remainder > 0) diff --git a/UVtools.Core/Operations/OperationCalculator.cs b/UVtools.Core/Operations/OperationCalculator.cs index 9e48a09..3ea2fe4 100644 --- a/UVtools.Core/Operations/OperationCalculator.cs +++ b/UVtools.Core/Operations/OperationCalculator.cs @@ -285,14 +285,8 @@ namespace UVtools.Core.Operations public static float CalculateSeconds(float liftHeight, float liftSpeed, float retract, float extraWaitTime = 0) { - try - { - return (float) Math.Round(liftHeight / (liftSpeed / 60f) + liftHeight / (retract / 60f) + extraWaitTime, 2); - } - catch (Exception) - { - return extraWaitTime; - } + if (liftSpeed == 0 || retract == 0) return extraWaitTime; + return (float) Math.Round(liftHeight / (liftSpeed / 60f) + liftHeight / (retract / 60f) + extraWaitTime, 2); } diff --git a/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs b/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs index f755e48..855a2f8 100644 --- a/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs +++ b/UVtools.Core/Operations/OperationCalibrateElephantFoot.cs @@ -342,15 +342,15 @@ namespace UVtools.Core.Operations } } - public int ErodeObjects => _isErodeEnabled ? - (int)Math.Floor((_erodeEndIteration - _erodeStartIteration) / (decimal)_erodeIterationSteps) + 1 + public uint ErodeObjects => _isErodeEnabled ? + (uint)((_erodeEndIteration - _erodeStartIteration) / (decimal)_erodeIterationSteps) + 1 : 0; - public int DimmingObjects => _isDimmingEnabled ? - (int) Math.Floor((_dimmingEndBrightness - _dimmingStartBrightness) / (decimal) _dimmingBrightnessSteps) + 1 + public uint DimmingObjects => _isDimmingEnabled ? + (uint)((_dimmingEndBrightness - _dimmingStartBrightness) / (decimal) _dimmingBrightnessSteps) + 1 : 0; - public int ObjectCount => (_outputOriginalPart ? 1 : 0) + ErodeObjects + DimmingObjects; + public uint ObjectCount => (_outputOriginalPart ? 1u : 0) + ErodeObjects + DimmingObjects; #endregion diff --git a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs index 2da010f..c515538 100644 --- a/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs +++ b/UVtools.Core/Operations/OperationCalibrateExposureFinder.cs @@ -101,9 +101,10 @@ namespace UVtools.Core.Operations private bool _multipleBrightness; private CalibrateExposureFinderMultipleBrightnessExcludeFrom _multipleBrightnessExcludeFrom = CalibrateExposureFinderMultipleBrightnessExcludeFrom.BottomAndBase; - private string _multipleBrightnessValues = "255, 242, 230, 217, 204, 191"; + private string _multipleBrightnessValues; private decimal _multipleBrightnessGenExposureTime; - + private byte _multipleBrightnessGenEmulatedAALevel = FileFormat.MaximumAntiAliasing; + private byte _multipleBrightnessGenExposureFractions = 8; private bool _multipleLayerHeight; private decimal _multipleLayerHeightMaximum = 0.1m; @@ -200,10 +201,59 @@ namespace UVtools.Core.Operations if (_multipleBrightness) { - if (MultipleBrightnessValuesArray.Length == 0) + var brightnessValues = MultipleBrightnessValuesArray; + if (brightnessValues.Length == 0) { sb.AppendLine($"Multiple brightness tests are enabled but no valid values are set, use from 1 to 255."); } + else + { + if (SlicerFile.IsAntiAliasingEmulated) + { + if (brightnessValues.Length > 16) + { + sb.AppendLine( + "[ME] This format uses time fractions to emulate AntiAliasing, only up 16 levels of greys/brightness are permitted."); + } + else + { + /*byte aalevel = brightnessValues.Length switch + { + <= 2 => 2, + <= 4 => 4, + <= 8 => 8, + <= 16 => 16, + _ => 2 + };*/ + + var increment = 255f / _multipleBrightnessGenEmulatedAALevel; + + byte[] validAA = new byte[_multipleBrightnessGenEmulatedAALevel]; + + for (byte frac = 0; frac < _multipleBrightnessGenEmulatedAALevel; frac++) + { + validAA[frac] = (byte)(byte.MaxValue - increment * frac); + } + + string invalidAA = string.Empty; + + foreach (var brightness in brightnessValues) + { + if (!validAA.Contains(brightness)) + invalidAA += $"{brightness}, "; + } + + invalidAA = invalidAA.Trim().TrimEnd(','); + + if (!string.IsNullOrWhiteSpace(invalidAA)) + { + sb.AppendLine($"[ME] This format uses time fractions to emulate AntiAliasing, only some levels greys/brightness are permitted, and everything outside that is thresholded."); + sb.AppendLine($" - your input have the following wrong levels: {invalidAA}"); + sb.AppendLine($" - AntiAliasing level: {_multipleBrightnessGenEmulatedAALevel} with usable values of: {string.Join(", ", validAA)}"); + } + } + } + } } if (_patternModel) @@ -459,7 +509,7 @@ namespace UVtools.Core.Operations { if (string.IsNullOrWhiteSpace(mmStr)) continue; if (!decimal.TryParse(mmStr, out var mm)) continue; - var mmPx = (int)Math.Floor(mm * Ppmm); + var mmPx = (int)(mm * Ppmm); if (mmPx is <= 0 or > 500) continue; if(holes.Contains(mmPx)) continue; holes.Add(mmPx); @@ -557,7 +607,7 @@ namespace UVtools.Core.Operations { if (string.IsNullOrWhiteSpace(mmStr)) continue; if (!decimal.TryParse(mmStr, out var mm)) continue; - var mmPx = (int)Math.Floor(mm * Xppmm); + var mmPx = (int)(mm * Xppmm); if (mmPx is <= 0 or > 500) continue; if (bars.Contains(mmPx)) continue; bars.Add(mmPx); @@ -675,6 +725,28 @@ namespace UVtools.Core.Operations set => RaiseAndSetIfChanged(ref _multipleBrightnessGenExposureTime, value); } + public byte MaximumAntiAliasing => FileFormat.MaximumAntiAliasing; + + public byte MultipleBrightnessGenEmulatedAALevel + { + get => _multipleBrightnessGenEmulatedAALevel; + set + { + if(!RaiseAndSetIfChanged(ref _multipleBrightnessGenEmulatedAALevel, value)) return; + GenerateBrightnessExposureFractions(); + } + } + + public byte MultipleBrightnessGenExposureFractions + { + get => _multipleBrightnessGenExposureFractions; + set + { + if(!RaiseAndSetIfChanged(ref _multipleBrightnessGenExposureFractions, value)) return; + GenerateBrightnessExposureFractions(); + } + } + /// <summary> /// Gets all holes in pixels and ordered /// </summary> @@ -689,7 +761,7 @@ namespace UVtools.Core.Operations { if (string.IsNullOrWhiteSpace(brightnessStr)) continue; if (!byte.TryParse(brightnessStr, out var brightness)) continue; - if (brightness <= 0 || brightness > 255) continue; + if (brightness is <= 0 or > 255) continue; if (values.Contains(brightness)) continue; values.Add(brightness); } @@ -881,9 +953,9 @@ namespace UVtools.Core.Operations string.IsNullOrWhiteSpace(splitDiameterThickness[1])) continue; if (!decimal.TryParse(splitDiameterThickness[0], out var diameterMm)) continue; if (!decimal.TryParse(splitDiameterThickness[1], out var thicknessMm)) continue; - var diameter = (int)Math.Floor(diameterMm * Ppmm); + var diameter = (int)(diameterMm * Ppmm); if (diameterMm is <= 0 or > 500) continue; - var thickness = (int)Math.Floor(thicknessMm * Ppmm); + var thickness = (int)(thicknessMm * Ppmm); if (thickness is <= 0 or > 500) continue; if (bulleyes.Exists(circle => circle.Diameter == diameter)) continue; bulleyes.Add(new BullsEyeCircle((ushort)diameter, (ushort)thickness)); @@ -985,6 +1057,14 @@ namespace UVtools.Core.Operations _multipleLayerHeight = false; _multipleExposures = false; } + + if (string.IsNullOrWhiteSpace(_multipleBrightnessValues)) + { + _multipleBrightnessValues = + SlicerFile.IsAntiAliasingEmulated + ? "255, 239, 223, 207, 191, 175, 159, 143" + : "255, 242, 230, 217, 204, 191"; + } } #endregion @@ -1127,7 +1207,22 @@ namespace UVtools.Core.Operations return list; } - public void GenerateExposure() + public void GenerateBrightnessExposureFractions() + { + var fractions = _multipleBrightnessGenExposureFractions; + var increment = 255f / _multipleBrightnessGenEmulatedAALevel; + + byte[] validAA = new byte[fractions]; + + for (byte frac = 0; frac < fractions; frac++) + { + validAA[frac] = (byte)(byte.MaxValue - increment * frac); + } + + MultipleBrightnessValues = string.Join(", ", validAA); + } + + public void GenerateExposureTable() { var endLayerHeight = _multipleLayerHeight ? _multipleLayerHeightMaximum : _layerHeight; List<ExposureItem> list = new(); @@ -1603,10 +1698,10 @@ namespace UVtools.Core.Operations protected override bool ExecuteInternally(OperationProgress progress) { - int sideMarginPx = (int)Math.Floor(_leftRightMargin * Xppmm); - int topBottomMarginPx = (int)Math.Floor(_topBottomMargin * Yppmm); - int partMarginXPx = (int) Math.Floor(_partMargin * Xppmm); - int partMarginYPx = (int) Math.Floor(_partMargin * Yppmm); + int sideMarginPx = (int)(_leftRightMargin * Xppmm); + int topBottomMarginPx = (int)(_topBottomMargin * Yppmm); + int partMarginXPx = (int)(_partMargin * Xppmm); + int partMarginYPx = (int)(_partMargin * Yppmm); var anchor = new Point(-1, -1); using var kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), anchor); @@ -1661,7 +1756,7 @@ namespace UVtools.Core.Operations var layer = SlicerFile[layerIndex]; using var mat = layer.LayerMat; var matRoi = new Mat(mat, boundingRectangle); - int layerCountOnHeight = (int)Math.Floor(layer.PositionZ / SlicerFile.LayerHeight); + int layerCountOnHeight = (int)(layer.PositionZ / SlicerFile.LayerHeight); foreach (var group in tableGrouped) { var newLayer = layer.Clone(); @@ -1800,12 +1895,12 @@ namespace UVtools.Core.Operations if (!layerDifference.IsInteger()) return; // Not at right height to process with layer height //Debug.WriteLine($"{currentHeight} / {layerHeight} = {layerDifference}, Floor={Math.Floor(layerDifference)}"); - int firstFeatureLayer = (int)Math.Floor(_baseHeight / layerHeight); - int lastLayer = (int)Math.Floor((_baseHeight + _featuresHeight) / layerHeight); - int layerCountOnHeight = (int)Math.Floor(currentHeight / layerHeight); + int firstFeatureLayer = (int)(_baseHeight / layerHeight); + int lastLayer = (int)((_baseHeight + _featuresHeight) / layerHeight); + int layerCountOnHeight = (int)(currentHeight / layerHeight); bool isBottomLayer = layerCountOnHeight <= _bottomLayers; bool isBaseLayer = currentHeight <= _baseHeight; - ushort microns = (ushort)Math.Floor(layerHeight * 1000); + ushort microns = (ushort)(layerHeight * 1000); Point position; bool addSomething = false; @@ -1987,6 +2082,19 @@ namespace UVtools.Core.Operations } } + if (_multipleBrightness && SlicerFile.IsAntiAliasingEmulated) + { + /*SlicerFile.AntiAliasing = MultipleBrightnessValuesArray.Length switch + { + <= 2 => 2, + <= 4 => 4, + <= 8 => 8, + <= 16 => 16, + _ => 16 + };*/ + SlicerFile.AntiAliasing = _multipleBrightnessGenEmulatedAALevel; + } + if (SlicerFile.ThumbnailsCount > 0) SlicerFile.SetThumbnails(GetThumbnail()); diff --git a/UVtools.Core/Operations/OperationCalibrateGrayscale.cs b/UVtools.Core/Operations/OperationCalibrateGrayscale.cs index 3085062..9810dee 100644 --- a/UVtools.Core/Operations/OperationCalibrateGrayscale.cs +++ b/UVtools.Core/Operations/OperationCalibrateGrayscale.cs @@ -253,7 +253,7 @@ namespace UVtools.Core.Operations } } - public int Divisions => (int)Math.Floor((_endBrightness - _startBrightness) / (decimal)_brightnessSteps) + 1; + public int Divisions => (int)((_endBrightness - _startBrightness) / (decimal)_brightnessSteps) + 1; public float AngleStep => 360f / Divisions; public bool EnableCenterHoleRelief diff --git a/UVtools.Core/Operations/OperationCalibrateStressTower.cs b/UVtools.Core/Operations/OperationCalibrateStressTower.cs index 7552782..a11f630 100644 --- a/UVtools.Core/Operations/OperationCalibrateStressTower.cs +++ b/UVtools.Core/Operations/OperationCalibrateStressTower.cs @@ -178,7 +178,7 @@ namespace UVtools.Core.Operations set => RaiseAndSetIfChanged(ref _normalExposure, Math.Round(value, 2)); } - public uint LayerCount => (uint) Math.Floor((_baseHeight + _bodyHeight + _ceilHeight) / LayerHeight); + public uint LayerCount => (uint)((_baseHeight + _bodyHeight + _ceilHeight) / LayerHeight); public decimal TotalHeight => _baseHeight + _bodyHeight + _ceilHeight; @@ -317,10 +317,10 @@ namespace UVtools.Core.Operations Slicer.Slicer slicer = new(SlicerFile.Resolution, new SizeF((float) DisplayWidth, (float) DisplayHeight)); Point center = new(SlicerFile.Resolution.Width / 2, SlicerFile.Resolution.Height / 2); uint baseRadius = slicer.PixelsFromMillimeters(_baseDiameter) / 2; - uint baseLayers = (ushort) Math.Floor(_baseHeight / _layerHeight); - uint bodyLayers = (ushort) Math.Floor(_bodyHeight / _layerHeight); - uint spiralLayers = (uint) Math.Floor(_spiralDiameter / _layerHeight); - uint ceilLayers = (ushort) Math.Floor(_ceilHeight / _layerHeight); + uint baseLayers = (ushort)(_baseHeight / _layerHeight); + uint bodyLayers = (ushort)(_bodyHeight / _layerHeight); + uint spiralLayers = (uint)(_spiralDiameter / _layerHeight); + uint ceilLayers = (ushort)(_ceilHeight / _layerHeight); uint currrentlayer = baseLayers; decimal spiralOffsetAngle = 360m / _spirals; diff --git a/UVtools.Core/Operations/OperationCalibrateTolerance.cs b/UVtools.Core/Operations/OperationCalibrateTolerance.cs index 8bc3c5c..033c487 100644 --- a/UVtools.Core/Operations/OperationCalibrateTolerance.cs +++ b/UVtools.Core/Operations/OperationCalibrateTolerance.cs @@ -197,7 +197,7 @@ namespace UVtools.Core.Operations } } - public uint LayerCount => (uint) Math.Floor(ZSize / LayerHeight); + public uint LayerCount => (uint)(ZSize / LayerHeight); public decimal RealZSize => LayerCount * _layerHeight; @@ -282,8 +282,8 @@ namespace UVtools.Core.Operations } } - public uint FemaleDiameterXPixels => (uint)Math.Floor(_femaleDiameter * Xppmm); - public uint FemaleDiameterYPixels => (uint)Math.Floor(_femaleDiameter * Yppmm); + public uint FemaleDiameterXPixels => (uint)(_femaleDiameter * Xppmm); + public uint FemaleDiameterYPixels => (uint)(_femaleDiameter * Yppmm); public decimal FemaleDiameterRealXSize { @@ -316,8 +316,8 @@ namespace UVtools.Core.Operations } } - public uint FemaleHoleDiameterXPixels => (uint)Math.Floor(_femaleHoleDiameter * Xppmm); - public uint FemaleHoleDiameterYPixels => (uint)Math.Floor(_femaleHoleDiameter * Yppmm); + public uint FemaleHoleDiameterXPixels => (uint)(_femaleHoleDiameter * Xppmm); + public uint FemaleHoleDiameterYPixels => (uint)(_femaleHoleDiameter * Yppmm); public decimal FemaleHoleDiameterRealXSize { @@ -543,8 +543,8 @@ namespace UVtools.Core.Operations { decimal millimeters = Math.Round(_femaleHoleDiameter + step, 2); if (millimeters <= 0) return false; - int xPixels = (int) Math.Floor(millimeters * Xppmm); - int yPixels = (int) Math.Floor(millimeters * Yppmm); + int xPixels = (int)(millimeters * Xppmm); + int yPixels = (int)(millimeters * Yppmm); Point partCenterText; if (_fuseParts) diff --git a/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs b/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs index 3542ef4..54f195a 100644 --- a/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs +++ b/UVtools.Core/Operations/OperationCalibrateXYZAccuracy.cs @@ -248,10 +248,10 @@ namespace UVtools.Core.Operations public decimal RealZSize => LayerCount * _layerHeight; - public uint XPixels => (uint)Math.Floor(XSize * Xppmm); - public uint YPixels => (uint)Math.Floor(YSize * Yppmm); + public uint XPixels => (uint)(XSize * Xppmm); + public uint YPixels => (uint)(YSize * Yppmm); - public uint LayerCount => (uint) Math.Floor(ZSize / LayerHeight); + public uint LayerCount => (uint)(ZSize / LayerHeight); public decimal DrainHoleArea { @@ -308,8 +308,8 @@ namespace UVtools.Core.Operations } } - public uint WallThicknessXPixels => (uint)Math.Floor(WallThickness * Xppmm); - public uint WallThicknessYPixels => (uint)Math.Floor(WallThickness * Yppmm); + public uint WallThicknessXPixels => (uint)(WallThickness * Xppmm); + public uint WallThicknessYPixels => (uint)(WallThickness * Yppmm); public bool OutputTLObject { @@ -779,7 +779,7 @@ namespace UVtools.Core.Operations for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) { newLayers[layerIndex] = SlicerFile.GetInitialLayerValueOrNormal(layerIndex, bottomLayer.Clone(), - (_hollowModel || _centerHoleRelief) && _drainHoleArea > 0 && layerIndex <= _bottomLayers + (int)Math.Floor(_drainHoleArea / _layerHeight) + (_hollowModel || _centerHoleRelief) && _drainHoleArea > 0 && layerIndex <= _bottomLayers + (int)(_drainHoleArea / _layerHeight) ? ventLayer.Clone() : layer.Clone()); progress++; diff --git a/UVtools.Core/Operations/OperationLayerExportGif.cs b/UVtools.Core/Operations/OperationLayerExportGif.cs index 69e496a..0762608 100644 --- a/UVtools.Core/Operations/OperationLayerExportGif.cs +++ b/UVtools.Core/Operations/OperationLayerExportGif.cs @@ -155,7 +155,7 @@ namespace UVtools.Core.Operations } } - public int FPSToMilliseconds => (int) Math.Floor(1000.0 / _fps); + public int FPSToMilliseconds => 1000 / _fps; public ushort Repeats { @@ -175,7 +175,7 @@ namespace UVtools.Core.Operations } } - public uint TotalLayers => (uint) Math.Floor(LayerRangeCount / (float) (_skip + 1)); + public uint TotalLayers => (uint)(LayerRangeCount / (float) (_skip + 1)); public uint GifDurationMilliseconds => (uint)(TotalLayers * FPSToMilliseconds); public float GifDurationSeconds => (float)Math.Round(GifDurationMilliseconds / 1000.0, 2); @@ -259,16 +259,16 @@ namespace UVtools.Core.Operations if (_flipDirection != ExportGifFlipDirection.None) { - var flipType = _flipDirection switch + FlipType? flipType = _flipDirection switch { ExportGifFlipDirection.Horizontally => FlipType.Horizontal, ExportGifFlipDirection.Vertically => FlipType.Vertical, - ExportGifFlipDirection.Both => FlipType.Horizontal | FlipType.Vertical, - _ => FlipType.None + ExportGifFlipDirection.Both => FlipType.Both, + _ => null }; - if (flipType != FlipType.None) - CvInvoke.Flip(matRoi, matRoi, flipType); + if (flipType is not null) + CvInvoke.Flip(matRoi, matRoi, flipType.Value); } if (_rotateDirection != ExportGifRotateDirection.None) diff --git a/UVtools.Core/Operations/OperationRepairLayers.cs b/UVtools.Core/Operations/OperationRepairLayers.cs index 9227bef..cdafcc3 100644 --- a/UVtools.Core/Operations/OperationRepairLayers.cs +++ b/UVtools.Core/Operations/OperationRepairLayers.cs @@ -156,7 +156,7 @@ namespace UVtools.Core.Operations var emptyLayersConfig = false; islandConfig.Enabled = true; - islandConfig.RequiredAreaToProcessCheck = (ushort) Math.Floor(_removeIslandsBelowEqualPixelCount / 2.0); + islandConfig.RequiredAreaToProcessCheck = (ushort)(_removeIslandsBelowEqualPixelCount / 2); for (uint i = 0; i < limit; i++) { diff --git a/UVtools.Core/Operations/OperationResize.cs b/UVtools.Core/Operations/OperationResize.cs index 9d528f5..b3d6c50 100644 --- a/UVtools.Core/Operations/OperationResize.cs +++ b/UVtools.Core/Operations/OperationResize.cs @@ -150,51 +150,40 @@ namespace UVtools.Core.Operations protected override bool ExecuteInternally(OperationProgress progress) { - if (X == 1m && Y == 1m) return false; + if (_x <= 0 || _y <= 0) return false; + if (_x == 100 && _y == 100) return false; - decimal xSteps = Math.Abs(X - 1) / (LayerIndexEnd - LayerIndexStart); - decimal ySteps = Math.Abs(Y - 1) / (LayerIndexEnd - LayerIndexStart); + decimal xSteps = Math.Abs(100 - _x) / (LayerIndexEnd - LayerIndexStart + 1); + decimal ySteps = Math.Abs(100 - _y) / (LayerIndexEnd - LayerIndexStart + 1); Parallel.For(LayerIndexStart, LayerIndexEnd + 1, layerIndex => { if (progress.Token.IsCancellationRequested) return; - var newX = X; - var newY = Y; + var newX = _x; + var newY = _y; if (IsFade) { - if (newX != 1m) + if (newX != 100) { - - //maxIteration = Math.Max(iterationsStart, iterationsEnd); - - newX = newX < 1m + newX = newX < 100 ? newX + (layerIndex - LayerIndexStart) * xSteps : newX - (layerIndex - LayerIndexStart) * xSteps; - - // constrain - //iterations = Math.Min(Math.Max(1, iterations), maxIteration); } - if (newY != 1m) + if (newY != 100) { - - //maxIteration = Math.Max(iterationsStart, iterationsEnd); - - newY = (newY < 1m + newY = newY < 100 ? newY + (layerIndex - LayerIndexStart) * ySteps - : newY - (layerIndex - LayerIndexStart) * ySteps); - - // constrain - //iterations = Math.Min(Math.Max(1, iterations), maxIteration); + : newY - (layerIndex - LayerIndexStart) * ySteps; } } progress.LockAndIncrement(); - if (newX == 1.0m && newY == 1.0m) return; + if (newX == 100 && newY == 100) return; using var mat = SlicerFile[layerIndex].LayerMat; - Execute(mat, newX / 100m, newY / 100m); + Execute(mat, newX / 100, newY / 100); SlicerFile[layerIndex].LayerMat = mat; }); diff --git a/UVtools.Core/Slicer/Slicer.cs b/UVtools.Core/Slicer/Slicer.cs index 1a488f3..3731477 100644 --- a/UVtools.Core/Slicer/Slicer.cs +++ b/UVtools.Core/Slicer/Slicer.cs @@ -199,19 +199,19 @@ namespace UVtools.Core.Slicer - public uint PixelsFromMillimetersX(decimal millimeters) => (uint) Math.Floor(millimeters * (decimal) Ppmm.Width); - public uint PixelsFromMillimetersY(decimal millimeters) => (uint) Math.Floor(millimeters * (decimal) Ppmm.Height); - public uint PixelsFromMillimeters (decimal millimeters) => (uint) Math.Floor(millimeters * (decimal) Math.Max(Ppmm.Width, Ppmm.Height)); + public uint PixelsFromMillimetersX(decimal millimeters) => (uint)(millimeters * (decimal) Ppmm.Width); + public uint PixelsFromMillimetersY(decimal millimeters) => (uint)(millimeters * (decimal) Ppmm.Height); + public uint PixelsFromMillimeters (decimal millimeters) => (uint)(millimeters * (decimal) Math.Max(Ppmm.Width, Ppmm.Height)); - public static uint PixelsFromMillimetersX(Size resolution, SizeF display, decimal millimeters) => (uint)Math.Floor(resolution.Width / display.Width * (double) millimeters); - public static uint PixelsFromMillimetersY(Size resolution, SizeF display, decimal millimeters) => (uint)Math.Floor(resolution.Height / display.Height * (double) millimeters); + public static uint PixelsFromMillimetersX(Size resolution, SizeF display, decimal millimeters) => (uint)(resolution.Width / display.Width * (double) millimeters); + public static uint PixelsFromMillimetersY(Size resolution, SizeF display, decimal millimeters) => (uint)(resolution.Height / display.Height * (double) millimeters); - public static uint MillimetersToLayers(float millimeters, float layerHeight) => (uint) Math.Floor(millimeters / layerHeight); - public static uint MillimetersToLayers(double millimeters, double layerHeight) => (uint) Math.Floor(millimeters / layerHeight); - public static uint MillimetersToLayers(decimal millimeters, decimal layerHeight) => (uint) Math.Floor(millimeters / layerHeight); + public static uint MillimetersToLayers(float millimeters, float layerHeight) => (uint)(millimeters / layerHeight); + public static uint MillimetersToLayers(double millimeters, double layerHeight) => (uint)(millimeters / layerHeight); + public static uint MillimetersToLayers(decimal millimeters, decimal layerHeight) => (uint)(millimeters / layerHeight); - public static uint LayersToMillimeters(uint layers, float layerHeight) => (uint)Math.Floor(layers * layerHeight); - public static uint LayersToMillimeters(uint layers, double layerHeight) => (uint)Math.Floor(layers * layerHeight); - public static uint LayersToMillimeters(uint layers, decimal layerHeight) => (uint)Math.Floor(layers * layerHeight); + public static uint LayersToMillimeters(uint layers, float layerHeight) => (uint)(layers * layerHeight); + public static uint LayersToMillimeters(uint layers, double layerHeight) => (uint)(layers * layerHeight); + public static uint LayersToMillimeters(uint layers, decimal layerHeight) => (uint)(layers * layerHeight); } } diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index 1e4bc6c..b9b9c4f 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.14.0</Version> + <Version>2.14.1</Version> <Copyright>Copyright © 2020 PTRTECH</Copyright> <PackageIcon>UVtools.png</PackageIcon> <Platforms>AnyCPU;x64</Platforms> @@ -50,7 +50,7 @@ <ItemGroup> <PackageReference Include="AnimatedGif" Version="1.0.5" /> <PackageReference Include="BinarySerializer" Version="8.6.0" /> - <PackageReference Include="Emgu.CV" Version="4.5.1.4349" /> + <PackageReference Include="Emgu.CV" Version="4.5.2.4673" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="3.11.0-1.final" /> <PackageReference Include="morelinq" Version="3.3.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> diff --git a/UVtools.Platforms/osx-x64/libcvextern.dylib b/UVtools.Platforms/osx-x64/libcvextern.dylib Binary files differindex f95fef5..d2c3c07 100644 --- a/UVtools.Platforms/osx-x64/libcvextern.dylib +++ b/UVtools.Platforms/osx-x64/libcvextern.dylib diff --git a/UVtools.Platforms/rhel-x64/libcvextern.so b/UVtools.Platforms/rhel-x64/libcvextern.so Binary files differindex 07be4d1..3891473 100644 --- a/UVtools.Platforms/rhel-x64/libcvextern.so +++ b/UVtools.Platforms/rhel-x64/libcvextern.so diff --git a/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml b/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml index 0a95292..dd221a6 100644 --- a/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml +++ b/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml @@ -607,24 +607,42 @@ Padding="5"> <Expander IsExpanded="False"> <Expander.Header> + <StackPanel Orientation="Horizontal" Cursor="Hand"> <TextBlock Text="Multiple brightness" - FontWeight="Bold" - Cursor="Hand"/> + IsVisible="{Binding !SlicerFile.IsAntiAliasingEmulated}" + FontWeight="Bold"/> + <TextBlock Text="Multiple brightness/exposures with emulated AntiAliasing and time fractions" + IsVisible="{Binding SlicerFile.IsAntiAliasingEmulated}" + FontWeight="Bold"/> + </StackPanel> </Expander.Header> <StackPanel Spacing="10"> - <TextBlock Text="Only printers able to do Anti-Aliasing and enabled on file can support this, make sure your is supported or else it can print a full white or full black model. + <TextBlock + Text="Only printers able to do Anti-Aliasing and enabled on file can support this. +
Make sure your is supported or else it can print a full white or full black model. 
Also take into consideration some printers/formats have fixed usable AA levels and all in between will be threshold, study this first. +
When using this section, always set the exposure time to the highest time you want to test. 
If your printer is able to do 'Multiple exposures times per layer', please use that method instead of this (More accurate and AA threshold free)."/> + + <TextBlock + IsVisible="{Binding SlicerFile.IsAntiAliasingEmulated}" + TextWrapping="Wrap" + FontWeight="Bold" + Text="Note: This file format uses time fractions to emulate AntiAliasing. +
This can be used to replace the 'Multiple exposures' sections and print multiple models at once at different timings. +
However you can't set the object time, instead fractions of the main exposure must be used. +
The brightness table will tell you the expected exposure time of each object."/> + <CheckBox Content="Enable - For advanced users only!" IsChecked="{Binding Operation.MultipleBrightness}"/> - <Grid RowDefinitions="Auto,10,Auto,10,Auto,10,Auto" + <Grid RowDefinitions="Auto,10,Auto,10,Auto,10,Auto,10,Auto" ColumnDefinitions="Auto,10,200,5,Auto,20,Auto,10,Auto,5,Auto,5,Auto" IsEnabled="{Binding Operation.MultipleBrightness}"> @@ -642,11 +660,13 @@ VerticalAlignment="Center"/> <TextBlock Grid.Row="0" Grid.Column="6" + IsVisible="{Binding !SlicerFile.IsAntiAliasingEmulated}" ToolTip.Tip="Append a brightness level to the list by giving a desired exposure time. Supplied time must be lower than the common exposure time or you need to increase it on the common 'Normal Exposure'." Text="Generate by exposure time:" VerticalAlignment="Center"/> <NumericUpDown Grid.Row="0" Grid.Column="8" + IsVisible="{Binding !SlicerFile.IsAntiAliasingEmulated}" Increment="0.10" Minimum="0.10" Maximum="{Binding Operation.NormalExposure}" @@ -654,11 +674,13 @@ Value="{Binding Operation.MultipleBrightnessGenExposureTime}"/> <TextBlock Grid.Row="0" Grid.Column="10" + IsVisible="{Binding !SlicerFile.IsAntiAliasingEmulated}" Text="s" VerticalAlignment="Center"/> <Button Grid.Row="0" Grid.Column="12" VerticalContentAlignment="Center" + IsVisible="{Binding !SlicerFile.IsAntiAliasingEmulated}" HorizontalContentAlignment="Center" VerticalAlignment="Stretch" Command="{Binding BrightnessExposureGenAdd}"> @@ -678,6 +700,69 @@ <TextBox Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="11" Text="{Binding Operation.MultipleBrightnessValues}"/> + + <!-- + <TextBlock Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="3" + IsVisible="{Binding SlicerFile.IsAntiAliasingEmulated}" + FontWeight="Bold" + Text="Emulated AntiAliasing with time fractions" + VerticalAlignment="Center"/> + !--> + + <TextBlock Grid.Row="4" Grid.Column="0" + IsVisible="{Binding SlicerFile.IsAntiAliasingEmulated}" + ToolTip.Tip="AntiAliasing level to set on file. +
This value is used to set the maximum available time fractions on the next field. +
Lower levels have larger time windows, while higher levels allow lower time windows (Recommended)." + Text="AntiAliasing:" + VerticalAlignment="Center"/> + + <NumericUpDown Grid.Row="4" Grid.Column="2" + IsVisible="{Binding SlicerFile.IsAntiAliasingEmulated}" + Increment="2" + Minimum="2" + Maximum="{Binding Operation.MaximumAntiAliasing}" + Value="{Binding Operation.MultipleBrightnessGenEmulatedAALevel}"/> + + <TextBlock Grid.Row="4" Grid.Column="4" + IsVisible="{Binding SlicerFile.IsAntiAliasingEmulated}" + Text="x" + VerticalAlignment="Center"/> + + + <TextBlock Grid.Row="4" Grid.Column="6" + IsVisible="{Binding SlicerFile.IsAntiAliasingEmulated}" + ToolTip.Tip="Amount of fractions from the main exposure: 2 to 16" + Text="Generate by time fractions:" + VerticalAlignment="Center"/> + + + <NumericUpDown Grid.Row="4" Grid.Column="8" + IsVisible="{Binding SlicerFile.IsAntiAliasingEmulated}" + Increment="1" + Minimum="2" + Maximum="{Binding Operation.MultipleBrightnessGenEmulatedAALevel}" + Value="{Binding Operation.MultipleBrightnessGenExposureFractions}"/> + + <TextBlock Grid.Row="4" Grid.Column="10" + IsVisible="{Binding SlicerFile.IsAntiAliasingEmulated}" + Text="÷" + VerticalAlignment="Center"/> + + <!--<Button + IsVisible="{Binding SlicerFile.IsAntiAliasingEmulated}" + Grid.Row="4" Grid.Column="12" VerticalContentAlignment="Center" + HorizontalContentAlignment="Center" + VerticalAlignment="Stretch" + Command="{Binding Operation.GenerateBrightnessExposureFractions}"> + <StackPanel Orientation="Horizontal" Spacing="10"> + <Image Source="/Assets/Icons/refresh-16x16.png"/> + <TextBlock + VerticalAlignment="Center" + Text="Gen"/> + </StackPanel> + </Button> + !--> </Grid> diff --git a/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs b/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs index 8b331d7..205f874 100644 --- a/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs +++ b/UVtools.WPF/Controls/Calibrators/CalibrateExposureFinderControl.axaml.cs @@ -105,7 +105,7 @@ namespace UVtools.WPF.Controls.Calibrators ) != ButtonResult.Yes) return; } - Operation.GenerateExposure(); + Operation.GenerateExposureTable(); } public async void ExposureTableAddManual() diff --git a/UVtools.WPF/MainWindow.LayerPreview.cs b/UVtools.WPF/MainWindow.LayerPreview.cs index 68dcd05..fedc5ba 100644 --- a/UVtools.WPF/MainWindow.LayerPreview.cs +++ b/UVtools.WPF/MainWindow.LayerPreview.cs @@ -1104,16 +1104,18 @@ namespace UVtools.WPF } } - if (_showLayerImageFlipped) + if (_showLayerImageFlipped && (_showLayerImageFlippedHorizontally || _showLayerImageFlippedVertically)) { - var flipType = FlipType.None; - if (_showLayerImageFlippedHorizontally) - flipType |= FlipType.Horizontal; - if (_showLayerImageFlippedVertically) - flipType |= FlipType.Vertical; - - if (flipType != FlipType.None) - CvInvoke.Flip(LayerCache.ImageBgr, LayerCache.ImageBgr, flipType); + var flipType = FlipType.Both; + + if (_showLayerImageFlippedHorizontally && _showLayerImageFlippedVertically) + flipType = FlipType.Both; + else if (_showLayerImageFlippedHorizontally) + flipType = FlipType.Horizontal; + else if (_showLayerImageFlippedVertically) + flipType = FlipType.Vertical; + + CvInvoke.Flip(LayerCache.ImageBgr, LayerCache.ImageBgr, flipType); } if (_showLayerImageRotated) @@ -1884,16 +1886,18 @@ namespace UVtools.WPF if (DrawingPixelDrawing.BrushShape != PixelDrawing.BrushShapeType.Circle) { - if (_showLayerImageFlipped) + if (_showLayerImageFlipped && (_showLayerImageFlippedHorizontally || _showLayerImageFlippedVertically)) { - var flipType = FlipType.None; - if (_showLayerImageFlippedHorizontally) - flipType |= FlipType.Horizontal; - if (_showLayerImageFlippedVertically) - flipType |= FlipType.Vertical; - - if (flipType != FlipType.None) - CvInvoke.Flip(cursor, cursor, flipType); + var flipType = FlipType.Both; + + if (_showLayerImageFlippedHorizontally && _showLayerImageFlippedVertically) + flipType = FlipType.Both; + else if (_showLayerImageFlippedHorizontally) + flipType = FlipType.Horizontal; + else if (_showLayerImageFlippedVertically) + flipType = FlipType.Vertical; + + CvInvoke.Flip(cursor, cursor, flipType); } if (_showLayerImageRotated) @@ -1955,17 +1959,20 @@ namespace UVtools.WPF cursor.RotateAdjustBounds(DrawingPixelText.Angle); //cursor.Rotate(DrawingPixelText.Angle); //cursor.PutTextRotated(text, cursor.Size.ToPoint().Half(), DrawingPixelText.Font, DrawingPixelText.FontScale, _pixelEditorCursorColor, DrawingPixelText.Thickness, DrawingPixelText.LineType, DrawingPixelText.Mirror, DrawingPixelText.Angle); - if (_showLayerImageFlipped) + if (_showLayerImageFlipped && (_showLayerImageFlippedHorizontally || _showLayerImageFlippedVertically)) { - var flipType = FlipType.None; - if (_showLayerImageFlippedHorizontally) - flipType |= FlipType.Horizontal; - if (_showLayerImageFlippedVertically) - flipType |= FlipType.Vertical; - - if (flipType != FlipType.None) - CvInvoke.Flip(cursor, cursor, flipType); + var flipType = FlipType.Both; + + if (_showLayerImageFlippedHorizontally && _showLayerImageFlippedVertically) + flipType = FlipType.Both; + else if (_showLayerImageFlippedHorizontally) + flipType = FlipType.Horizontal; + else if (_showLayerImageFlippedVertically) + flipType = FlipType.Vertical; + + CvInvoke.Flip(cursor, cursor, flipType); } + if (_showLayerImageRotated) { CvInvoke.Rotate(cursor, cursor, _showLayerImageRotateCcwDirection ? RotateFlags.Rotate90CounterClockwise : RotateFlags.Rotate90Clockwise); diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs index 7f77267..4052fc3 100644 --- a/UVtools.WPF/MainWindow.axaml.cs +++ b/UVtools.WPF/MainWindow.axaml.cs @@ -973,7 +973,7 @@ namespace UVtools.WPF if(!IsFileLoaded) continue; try { - var fileText = File.ReadAllText(files[i]); + var fileText = await File.ReadAllTextAsync(files[i]); var match = Regex.Match(fileText, @"(?:<\/\s*Operation)([a-zA-Z0-9_]+)(?:\s*>)"); if(!match.Success) continue; if(match.Groups.Count < 1) continue; diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj index cc83180..d78fbe3 100644 --- a/UVtools.WPF/UVtools.WPF.csproj +++ b/UVtools.WPF/UVtools.WPF.csproj @@ -12,7 +12,7 @@ <PackageLicenseFile>LICENSE</PackageLicenseFile> <RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl> <RepositoryType>Git</RepositoryType> - <Version>2.14.0</Version> + <Version>2.14.1</Version> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> @@ -29,9 +29,9 @@ <PackageReference Include="Avalonia.Controls.DataGrid" Version="0.10.6" /> <PackageReference Include="Avalonia.Desktop" Version="0.10.6" /> <PackageReference Include="Avalonia.Diagnostics" Version="0.10.6" /> - <PackageReference Include="Emgu.CV.runtime.windows" Version="4.5.1.4349" /> + <PackageReference Include="Emgu.CV.runtime.windows" Version="4.5.2.4673" /> <PackageReference Include="MessageBox.Avalonia" Version="1.5.1" /> - <PackageReference Include="ThemeEditor.Controls.ColorPicker" Version="0.10.4" /> + <PackageReference Include="ThemeEditor.Controls.ColorPicker" Version="0.10.6" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\UVtools.AvaloniaControls\UVtools.AvaloniaControls.csproj" /> diff --git a/UVtools.WPF/Windows/AboutWindow.axaml b/UVtools.WPF/Windows/AboutWindow.axaml index 342c762..f339916 100644 --- a/UVtools.WPF/Windows/AboutWindow.axaml +++ b/UVtools.WPF/Windows/AboutWindow.axaml @@ -33,6 +33,14 @@ UseFloatingWatermark="True"/> <TextBox + Text="{Binding OpenCVDescription}" + IsReadOnly="True" + BorderBrush="Transparent" + CaretBrush="Transparent" + Watermark="OpenCV Version:" + UseFloatingWatermark="True"/> + + <TextBox Text="{Binding ProcessorCount}" IsReadOnly="True" BorderBrush="Transparent" @@ -48,31 +56,11 @@ Watermark="Screens, resolution, working area, usable area:" UseFloatingWatermark="True"/> - <!-- - <TextBox - Text="{Binding ScreenResolution}" - IsReadOnly="True" - BorderBrush="Transparent" - CaretBrush="Transparent" - Watermark="Resolution:" - UseFloatingWatermark="True"/> - - <TextBox - Text="{Binding WorkingArea}" - IsReadOnly="True" - BorderBrush="Transparent" - CaretBrush="Transparent" - Watermark="Working Area:" - UseFloatingWatermark="True"/> - - <TextBox - Text="{Binding RealWorkingArea}" - IsReadOnly="True" - BorderBrush="Transparent" - CaretBrush="Transparent" - Watermark="Real Working Area:" - UseFloatingWatermark="True"/> - --> + <Button + Margin="0,20,0,0" + HorizontalAlignment="Stretch" + Content="Copy OpenCV build information to clipboard" + Command="{Binding SetOpenCVInformationToClipboard}" /> </StackPanel> </Border> <Grid diff --git a/UVtools.WPF/Windows/AboutWindow.axaml.cs b/UVtools.WPF/Windows/AboutWindow.axaml.cs index b94becd..caba156 100644 --- a/UVtools.WPF/Windows/AboutWindow.axaml.cs +++ b/UVtools.WPF/Windows/AboutWindow.axaml.cs @@ -1,8 +1,11 @@ using System; using System.Runtime.InteropServices; using System.Text; +using System.Text.RegularExpressions; using Avalonia; using Avalonia.Markup.Xaml; +using Emgu.CV; +using Emgu.CV.Stitching; using UVtools.Core; using UVtools.WPF.Controls; @@ -18,6 +21,16 @@ namespace UVtools.WPF.Windows public string OSDescription => $"{RuntimeInformation.OSDescription} {RuntimeInformation.OSArchitecture}"; public string FrameworkDescription => RuntimeInformation.FrameworkDescription; + + public string OpenCVDescription + { + get + { + var match = Regex.Match(CvInvoke.BuildInformation, @"(?:Version control:\s*)(\S*)"); + if (!match.Success) return "Not found!"; + return match.Groups[1].Value; + } + } public int ProcessorCount => Environment.ProcessorCount; public int ScreenCount => Screens.ScreenCount; //public string ScreenResolution => $"{Screens.Primary.Bounds.Width} x {Screens.Primary.Bounds.Height} @ {Screens.Primary.PixelDensity*100}%"; @@ -43,7 +56,6 @@ namespace UVtools.WPF.Windows } } - public AboutWindow() { InitializeComponent(); @@ -55,5 +67,10 @@ namespace UVtools.WPF.Windows { AvaloniaXamlLoader.Load(this); } + + public void SetOpenCVInformationToClipboard() + { + Application.Current.Clipboard.SetTextAsync(CvInvoke.BuildInformation); + } } } |