diff options
author | Tiago Conceição <Tiago_caza@hotmail.com> | 2020-07-01 06:29:08 +0300 |
---|---|---|
committer | Tiago Conceição <Tiago_caza@hotmail.com> | 2020-07-01 06:29:08 +0300 |
commit | 8ce59f66121ee664273baf8556cc209ab727181c (patch) | |
tree | cc78025d3a29a04e9159bbe756b97f9adf6e3180 | |
parent | 6a06ab0b89743ab8346820afd9495f6177e5697c (diff) |
v0.6.0.2
* (Add) PrusaSlicer Printer "EPAX X10 4K Mono"
* (Improvement) Better progress window with real progress and cancel button
* (Improvement) Mutators text and name
* (Fix) sl1: After save file gets decoded again
* (Fix) photon, cbddlp, ctb, phz, pws, pw0: Unable to save file, not closed from the decode session
* (Fix) zcodex: Unable to convert file
* (Fix) images: Wasn't opening
* (Fix) images: Wasn't saving
* (Fix) When click on button "New version is available" sometimes it crash the program
* (Fix) Force 1 layer scroll when using Mouse Wheel to scroll the tracker bar
* (Fix) PrusaSlicer printers: Mirror vertically instead to produce equal orientation compared with chitubox
43 files changed, 1244 insertions, 601 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1533ec8..fc7f57f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## ? - v0.6.0.2 + +* (Add) PrusaSlicer Printer "EPAX X10 4K Mono" +* (Improvement) Better progress window with real progress and cancel button +* (Improvement) Mutators text and name +* (Fix) sl1: After save file gets decoded again +* (Fix) photon, cbddlp, ctb, phz, pws, pw0: Unable to save file, not closed from the decode session +* (Fix) zcodex: Unable to convert file +* (Fix) images: Wasn't opening +* (Fix) images: Wasn't saving +* (Fix) When click on button "New version is available" sometimes it crash the program +* (Fix) Force 1 layer scroll when using Mouse Wheel to scroll the tracker bar +* (Fix) PrusaSlicer printers: Mirror vertically instead to produce equal orientation compared with chitubox + + ## 29/06/2020 - v0.6.0.1 * (Improvement) Pixel edit now spare a memory cycle per pixel diff --git a/ImportPrusaSlicerData.bat b/ImportPrusaSlicerData.bat index 7954794..ca76b0f 100644 --- a/ImportPrusaSlicerData.bat +++ b/ImportPrusaSlicerData.bat @@ -8,31 +8,32 @@ SET PRINTER_DIR=printer SET files[0]=EPAX X1.ini SET files[1]=EPAX X10.ini -SET files[2]=EPAX X133 4K Mono.ini -SET files[3]=EPAX X156 4K Color.ini -SET files[4]=Zortrax Inkspire.ini -SET files[5]=Nova3D Elfin.ini -SET files[6]=AnyCubic Photon.ini -SET files[7]=AnyCubic Photon S.ini -SET files[8]=AnyCubic Photon Zero.ini -SET files[9]=Elegoo Mars.ini -SET files[10]=Elegoo Mars Saturn.ini -SET files[11]=Peopoly Phenom.ini -SET files[12]=Peopoly Phenom L.ini -SET files[13]=Peopoly Phenom Noir.ini -SET files[14]=QIDI Shadow5.5.ini -SET files[15]=QIDI Shadow6.0 Pro.ini -SET files[16]=Phrozen Shuffle.ini -SET files[17]=Phrozen Shuffle Lite.ini -SET files[18]=Phrozen Shuffle XL.ini -SET files[19]=Phrozen Shuffle 4K.ini -SET files[20]=Phrozen Sonic.ini -SET files[21]=Phrozen Sonic Mini.ini -SET files[22]=Phrozen Transform.ini -SET files[23]=Kelant S400.ini -SET files[24]=Wanhao D7.ini -SET files[25]=Wanhao D8.ini -SET files[26]=Creality LD-002R.ini +SET files[2]=EPAX X10 4K Mono.ini +SET files[3]=EPAX X133 4K Mono.ini +SET files[4]=EPAX X156 4K Color.ini +SET files[5]=Zortrax Inkspire.ini +SET files[6]=Nova3D Elfin.ini +SET files[7]=AnyCubic Photon.ini +SET files[8]=AnyCubic Photon S.ini +SET files[9]=AnyCubic Photon Zero.ini +SET files[10]=Elegoo Mars.ini +SET files[11]=Elegoo Mars Saturn.ini +SET files[12]=Peopoly Phenom.ini +SET files[13]=Peopoly Phenom L.ini +SET files[14]=Peopoly Phenom Noir.ini +SET files[15]=QIDI Shadow5.5.ini +SET files[16]=QIDI Shadow6.0 Pro.ini +SET files[17]=Phrozen Shuffle.ini +SET files[18]=Phrozen Shuffle Lite.ini +SET files[19]=Phrozen Shuffle XL.ini +SET files[20]=Phrozen Shuffle 4K.ini +SET files[21]=Phrozen Sonic.ini +SET files[22]=Phrozen Sonic Mini.ini +SET files[23]=Phrozen Transform.ini +SET files[24]=Kelant S400.ini +SET files[25]=Wanhao D7.ini +SET files[26]=Wanhao D8.ini +SET files[27]=Creality LD-002R.ini echo PrusaSlicer Printers Instalation echo This will replace printers, all changes will be discarded diff --git a/PrusaSlicer/printer/AnyCubic Photon S.ini b/PrusaSlicer/printer/AnyCubic Photon S.ini index e6f2178..3b3babe 100644 --- a/PrusaSlicer/printer/AnyCubic Photon S.ini +++ b/PrusaSlicer/printer/AnyCubic Photon S.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-12 at 00:39:00 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:22:18 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,121x0,121x68,0x68 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 68 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = portrait display_pixels_x = 2560 display_pixels_y = 1440 diff --git a/PrusaSlicer/printer/AnyCubic Photon Zero.ini b/PrusaSlicer/printer/AnyCubic Photon Zero.ini index 4e7a9ca..59ff711 100644 --- a/PrusaSlicer/printer/AnyCubic Photon Zero.ini +++ b/PrusaSlicer/printer/AnyCubic Photon Zero.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-12 at 00:39:06 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:22:23 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,98.6x0,98.6x55.4,0x55.4 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 55.4 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = portrait display_pixels_x = 854 display_pixels_y = 480 diff --git a/PrusaSlicer/printer/AnyCubic Photon.ini b/PrusaSlicer/printer/AnyCubic Photon.ini index 7086ad1..b438e38 100644 --- a/PrusaSlicer/printer/AnyCubic Photon.ini +++ b/PrusaSlicer/printer/AnyCubic Photon.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-16 at 03:20:05 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:22:12 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,120.96x0,120.96x68.04,0x68.04 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 68.04 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = portrait display_pixels_x = 2560 display_pixels_y = 1440 diff --git a/PrusaSlicer/printer/Creality LD-002R.ini b/PrusaSlicer/printer/Creality LD-002R.ini index 6d5b392..5a9fce4 100644 --- a/PrusaSlicer/printer/Creality LD-002R.ini +++ b/PrusaSlicer/printer/Creality LD-002R.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-16 at 03:20:32 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:22:31 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,120.96x0,120.96x68.04,0x68.04 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 68.04 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = portrait display_pixels_x = 2560 display_pixels_y = 1440 diff --git a/PrusaSlicer/printer/EPAX X1.ini b/PrusaSlicer/printer/EPAX X1.ini index 04b6d45..3407149 100644 --- a/PrusaSlicer/printer/EPAX X1.ini +++ b/PrusaSlicer/printer/EPAX X1.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-12 at 00:39:14 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:22:36 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,120.96x0,120.96x68.04,0x68.04 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 68.04 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = portrait display_pixels_x = 2560 display_pixels_y = 1440 diff --git a/PrusaSlicer/printer/EPAX X10 4K Mono.ini b/PrusaSlicer/printer/EPAX X10 4K Mono.ini new file mode 100644 index 0000000..c36afa4 --- /dev/null +++ b/PrusaSlicer/printer/EPAX X10 4K Mono.ini @@ -0,0 +1,37 @@ +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-30 at 23:52:31 UTC +absolute_correction = 0 +area_fill = 50 +bed_custom_model = +bed_custom_texture = +bed_shape = 0x0,192x0,192x120,0x120 +default_sla_material_profile = Prusa Orange Tough 0.05 +default_sla_print_profile = 0.05 Normal +display_height = 120 +display_mirror_x = 1 +display_mirror_y = 0 +display_orientation = landscape +display_pixels_x = 3840 +display_pixels_y = 2160 +display_width = 192 +elefant_foot_compensation = 0.2 +elefant_foot_min_width = 0.2 +fast_tilt_time = 5 +gamma_correction = 1 +inherits = Original Prusa SL1 +max_exposure_time = 120 +max_initial_exposure_time = 300 +max_print_height = 250 +min_exposure_time = 1 +min_initial_exposure_time = 1 +print_host = +printer_model = SL1 +printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_SL1\nPRINTER_VENDOR_EPAX\nPRINTER_MODEL_X10-4KMONO\n\nSTART_CUSTOM_VALUES\nLayerOffTime_0\nBottomLightOffDelay_10\nBottomLiftHeight_15\nLiftHeight_12\nBottomLiftSpeed_40\nLiftSpeed_40\nRetractSpeed_150\nBottomLightPWM_255\nLightPWM_255\nAntiAliasing_4 ; Use 0 or 1 for disable AntiAliasing with "printer gamma correction" set to 0, otherwise use multiples of 2 and "gamma correction" set to 1 for enable\nEND_CUSTOM_VALUES +printer_settings_id = +printer_technology = SLA +printer_variant = default +printer_vendor = +printhost_apikey = +printhost_cafile = +relative_correction = 1,1 +slow_tilt_time = 8 +thumbnails = 400x400,800x480 diff --git a/PrusaSlicer/printer/EPAX X10.ini b/PrusaSlicer/printer/EPAX X10.ini index d12b2ca..14e3cb3 100644 --- a/PrusaSlicer/printer/EPAX X10.ini +++ b/PrusaSlicer/printer/EPAX X10.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-12 at 00:39:20 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:22:43 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,216.57x0,216.57x135.36,0x135.36 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 135.36 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = portrait display_pixels_x = 2560 display_pixels_y = 1600 diff --git a/PrusaSlicer/printer/Elegoo Mars Saturn.ini b/PrusaSlicer/printer/Elegoo Mars Saturn.ini index 6587859..3bc0f71 100644 --- a/PrusaSlicer/printer/Elegoo Mars Saturn.ini +++ b/PrusaSlicer/printer/Elegoo Mars Saturn.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-12 at 00:40:39 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:32:02 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,192x0,192x120,0x120 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 120 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = landscape display_pixels_x = 2560 display_pixels_y = 1600 diff --git a/PrusaSlicer/printer/Elegoo Mars.ini b/PrusaSlicer/printer/Elegoo Mars.ini index 574bccd..5ab1c72 100644 --- a/PrusaSlicer/printer/Elegoo Mars.ini +++ b/PrusaSlicer/printer/Elegoo Mars.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-12 at 00:40:32 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:31:58 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,120.96x0,120.96x68.04,0x68.04 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 68.04 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = portrait display_pixels_x = 2560 display_pixels_y = 1440 diff --git a/PrusaSlicer/printer/Kelant S400.ini b/PrusaSlicer/printer/Kelant S400.ini index a0a3e36..a9f237a 100644 --- a/PrusaSlicer/printer/Kelant S400.ini +++ b/PrusaSlicer/printer/Kelant S400.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-16 at 02:46:17 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:32:09 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,192x0,192x120,0x120 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 120 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = portrait display_pixels_x = 2560 display_pixels_y = 1440 diff --git a/PrusaSlicer/printer/Peopoly Phenom L.ini b/PrusaSlicer/printer/Peopoly Phenom L.ini index f8171a9..50a835f 100644 --- a/PrusaSlicer/printer/Peopoly Phenom L.ini +++ b/PrusaSlicer/printer/Peopoly Phenom L.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-12 at 00:41:13 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:32:29 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,345.6x0,345.6x194.4,0x194.4 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 194.4 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = landscape display_pixels_x = 3840 display_pixels_y = 2160 diff --git a/PrusaSlicer/printer/Peopoly Phenom Noir.ini b/PrusaSlicer/printer/Peopoly Phenom Noir.ini index e2f5270..23933e3 100644 --- a/PrusaSlicer/printer/Peopoly Phenom Noir.ini +++ b/PrusaSlicer/printer/Peopoly Phenom Noir.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-12 at 00:41:18 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:32:33 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,293.76x0,293.76x165.24,0x165.24 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 165.24 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = landscape display_pixels_x = 3840 display_pixels_y = 2160 diff --git a/PrusaSlicer/printer/Peopoly Phenom.ini b/PrusaSlicer/printer/Peopoly Phenom.ini index 5a80dba..b6d72b0 100644 --- a/PrusaSlicer/printer/Peopoly Phenom.ini +++ b/PrusaSlicer/printer/Peopoly Phenom.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-12 at 00:41:08 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:32:25 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,276.48x0,276.48x155.52,0x155.52 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 155.52 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = landscape display_pixels_x = 3840 display_pixels_y = 2160 diff --git a/PrusaSlicer/printer/QIDI Shadow5.5.ini b/PrusaSlicer/printer/QIDI Shadow5.5.ini index 9b1d73b..bc68866 100644 --- a/PrusaSlicer/printer/QIDI Shadow5.5.ini +++ b/PrusaSlicer/printer/QIDI Shadow5.5.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-12 at 00:42:10 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:32:51 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,120.96x0,120.96x68.04,0x68.04 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 68.04 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = portrait display_pixels_x = 2560 display_pixels_y = 1440 diff --git a/PrusaSlicer/printer/QIDI Shadow6.0 Pro.ini b/PrusaSlicer/printer/QIDI Shadow6.0 Pro.ini index 8541b81..23dee47 100644 --- a/PrusaSlicer/printer/QIDI Shadow6.0 Pro.ini +++ b/PrusaSlicer/printer/QIDI Shadow6.0 Pro.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-12 at 00:42:17 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:32:56 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,132.48x0,132.48x74.52,0x74.52 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 74.52 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = portrait display_pixels_x = 2560 display_pixels_y = 1440 diff --git a/PrusaSlicer/printer/Wanhao D7.ini b/PrusaSlicer/printer/Wanhao D7.ini index 624f7d6..a4088d5 100644 --- a/PrusaSlicer/printer/Wanhao D7.ini +++ b/PrusaSlicer/printer/Wanhao D7.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-16 at 03:14:33 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:33:00 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,120.96x0,120.96x68.5,0x68.5 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 68.5 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = landscape display_pixels_x = 2560 display_pixels_y = 1440 diff --git a/PrusaSlicer/printer/Wanhao D8.ini b/PrusaSlicer/printer/Wanhao D8.ini index 5eb9538..9d74056 100644 --- a/PrusaSlicer/printer/Wanhao D8.ini +++ b/PrusaSlicer/printer/Wanhao D8.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0+win64 on 2020-06-16 at 03:15:34 UTC +# generated by PrusaSlicer 2.2.0+win64 on 2020-06-29 at 20:33:04 UTC absolute_correction = 0 area_fill = 50 bed_custom_model = @@ -7,8 +7,8 @@ bed_shape = 0x0,192x0,192x120,0x120 default_sla_material_profile = Prusa Orange Tough 0.05 default_sla_print_profile = 0.05 Normal display_height = 120 -display_mirror_x = 1 -display_mirror_y = 0 +display_mirror_x = 0 +display_mirror_y = 1 display_orientation = landscape display_pixels_x = 2560 display_pixels_y = 1600 diff --git a/UVtools.Core/CWSFile.cs b/UVtools.Core/CWSFile.cs index bdfd0bb..4dcfa76 100644 --- a/UVtools.Core/CWSFile.cs +++ b/UVtools.Core/CWSFile.cs @@ -13,6 +13,7 @@ using System.IO.Compression; using System.Linq; using System.Reflection; using System.Text; +using System.Threading.Tasks; using UVtools.Core.Extensions; namespace UVtools.Core @@ -173,15 +174,14 @@ namespace UVtools.Core GCode = null; } - public override void Encode(string fileFullPath) + public override void Encode(string fileFullPath, OperationProgress progress = null) { - base.Encode(fileFullPath); - using (ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Update)) + base.Encode(fileFullPath, progress); + using (ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create)) { string arch = Environment.Is64BitOperatingSystem ? "64-bits" : "32-bits"; - var entry = outputFile.GetPutFile("slice.conf"); + var entry = outputFile.CreateEntry("slice.conf"); var stream = entry.Open(); - stream.SetLength(0); using (TextWriter tw = new StreamWriter(stream)) { @@ -197,23 +197,25 @@ namespace UVtools.Core tw.WriteLine($"{displayNameAttribute.DisplayName.PadRight(24)}= {propertyInfo.GetValue(SliceSettings)}"); } } + - - for(uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) + for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) { + progress.Token.ThrowIfCancellationRequested(); Layer layer = this[layerIndex]; - var layerimagePath = $"{Path.GetFileNameWithoutExtension(fileFullPath)}{layer.Index.ToString().PadLeft(LayerCount.ToString().Length, '0')}.png"; - outputFile.PutFileContent(layerimagePath, layer.CompressedBytes); + var layerImagePath = $"{Path.GetFileNameWithoutExtension(fileFullPath)}{layer.Index.ToString().PadLeft(LayerCount.ToString().Length, '0')}.png"; + outputFile.PutFileContent(layerImagePath, layer.CompressedBytes, ZipArchiveMode.Create); + progress++; } UpdateGCode(); - outputFile.PutFileContent($"{Path.GetFileNameWithoutExtension(fileFullPath)}.gcode", GCode.ToString()); + outputFile.PutFileContent($"{Path.GetFileNameWithoutExtension(fileFullPath)}.gcode", GCode.ToString(), ZipArchiveMode.Create); } } - public override void Decode(string fileFullPath) + public override void Decode(string fileFullPath, OperationProgress progress = null) { - base.Decode(fileFullPath); + base.Decode(fileFullPath, progress); FileFullPath = fileFullPath; using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read)) @@ -298,10 +300,9 @@ namespace UVtools.Core uint iLayer = uint.Parse(layerStr); LayerManager[iLayer] = new Layer(iLayer, zipArchiveEntry.Open(), zipArchiveEntry.Name); } - } - var rect = LayerManager.BoundingRectangle; + LayerManager.GetBoundingRectangle(progress); } public override object GetValueFromPrintParameterModifier(PrintParameterModifier modifier) @@ -379,7 +380,7 @@ namespace UVtools.Core return false; } - public override void SaveAs(string filePath = null) + public override void SaveAs(string filePath = null, OperationProgress progress = null) { if (!string.IsNullOrEmpty(filePath)) { @@ -418,20 +419,20 @@ namespace UVtools.Core break; } } - outputFile.PutFileContent($"{Path.GetFileNameWithoutExtension(FileFullPath)}.gcode", GCode.ToString()); + outputFile.PutFileContent($"{Path.GetFileNameWithoutExtension(FileFullPath)}.gcode", GCode.ToString(), ZipArchiveMode.Update); foreach (var layer in this) { if (!layer.IsModified) continue; - outputFile.PutFileContent(layer.Filename, layer.CompressedBytes); + outputFile.PutFileContent(layer.Filename, layer.CompressedBytes, ZipArchiveMode.Update); layer.IsModified = false; } } - //Decode(FileFullPath); + //Decode(FileFullPath, progress); } - public override bool Convert(Type to, string fileFullPath) + public override bool Convert(Type to, string fileFullPath, OperationProgress progress = null) { throw new NotImplementedException(); } diff --git a/UVtools.Core/ChituboxFile.cs b/UVtools.Core/ChituboxFile.cs index 0c23d7b..a011dd0 100644 --- a/UVtools.Core/ChituboxFile.cs +++ b/UVtools.Core/ChituboxFile.cs @@ -988,9 +988,9 @@ namespace UVtools.Core LayersDefinitions = null; } - public override void Encode(string fileFullPath) + public override void Encode(string fileFullPath, OperationProgress progress = null) { - base.Encode(fileFullPath); + base.Encode(fileFullPath, progress); LayersHash.Clear(); HeaderSettings.Magic = fileFullPath.EndsWith(".ctb") ? MAGIC_CBT : MAGIC_CBDDLP; @@ -1071,21 +1071,31 @@ namespace UVtools.Core HeaderSettings.LayersDefinitionOffsetAddress = currentOffset; uint layerDataCurrentOffset = currentOffset + (uint)Helpers.Serializer.SizeOf(new LayerData()) * HeaderSettings.LayerCount * HeaderSettings.AntiAliasLevel; - + + progress.ItemCount *= 2 * HeaderSettings.AntiAliasLevel; + for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++) { + progress.Token.ThrowIfCancellationRequested(); Parallel.For(0, LayerCount, /*new ParallelOptions{MaxDegreeOfParallelism = 1},*/ layerIndex => { + if (progress.Token.IsCancellationRequested) return; LayerData layerData = new LayerData(this, (uint) layerIndex); using (var image = this[layerIndex].LayerMat) { layerData.Encode(image, aaIndex, (uint) layerIndex); LayersDefinitions[aaIndex, layerIndex] = layerData; } + + lock (progress.Mutex) + { + progress++; + } }); for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) { + progress.Token.ThrowIfCancellationRequested(); var layerData = LayersDefinitions[aaIndex, layerIndex]; LayerData layerDataHash = null; @@ -1113,15 +1123,14 @@ namespace UVtools.Core outputFile.Seek(currentOffset, SeekOrigin.Begin); currentOffset += Helpers.SerializeWriteFileStream(outputFile, layerData); + + progress++; } } outputFile.Seek(0, SeekOrigin.Begin); Helpers.SerializeWriteFileStream(outputFile, HeaderSettings); - outputFile.Close(); - outputFile.Dispose(); - Debug.WriteLine("Encode Results:"); Debug.WriteLine(HeaderSettings); Debug.WriteLine(Previews[0]); @@ -1134,110 +1143,131 @@ namespace UVtools.Core - public override void Decode(string fileFullPath) + public override void Decode(string fileFullPath, OperationProgress progress = null) { - base.Decode(fileFullPath); - - var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read); + base.Decode(fileFullPath, progress); - //HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile); - //HeaderSettings = Helpers.Serializer.Deserialize<Header>(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header)))); - HeaderSettings = Helpers.Deserialize<Header>(inputFile); - if (HeaderSettings.Magic != MAGIC_CBDDLP && HeaderSettings.Magic != MAGIC_CBT) + using (var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read)) { - throw new FileLoadException("Not a valid CBDDLP nor CTB nor Photon file!", fileFullPath); - } + //HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile); + //HeaderSettings = Helpers.Serializer.Deserialize<Header>(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header)))); + HeaderSettings = Helpers.Deserialize<Header>(inputFile); + if (HeaderSettings.Magic != MAGIC_CBDDLP && HeaderSettings.Magic != MAGIC_CBT) + { + throw new FileLoadException("Not a valid CBDDLP nor CTB nor Photon file!", fileFullPath); + } - if (HeaderSettings.Version == 1 || HeaderSettings.AntiAliasLevel == 0) - { - HeaderSettings.AntiAliasLevel = 1; - } + if (HeaderSettings.Version == 1 || HeaderSettings.AntiAliasLevel == 0) + { + HeaderSettings.AntiAliasLevel = 1; + } - FileFullPath = fileFullPath; + FileFullPath = fileFullPath; + progress.Reset(OperationProgress.StatusDecodeThumbnails, ThumbnailsCount); + Debug.Write("Header -> "); + Debug.WriteLine(HeaderSettings); - Debug.Write("Header -> "); - Debug.WriteLine(HeaderSettings); + for (byte i = 0; i < ThumbnailsCount; i++) + { + uint offsetAddress = i == 0 + ? HeaderSettings.PreviewSmallOffsetAddress + : HeaderSettings.PreviewLargeOffsetAddress; + if (offsetAddress == 0) continue; - for (byte i = 0; i < ThumbnailsCount; i++) - { - uint offsetAddress = i == 0 ? HeaderSettings.PreviewSmallOffsetAddress : HeaderSettings.PreviewLargeOffsetAddress; - if (offsetAddress == 0) continue; + inputFile.Seek(offsetAddress, SeekOrigin.Begin); + Previews[i] = Helpers.Deserialize<Preview>(inputFile); - inputFile.Seek(offsetAddress, SeekOrigin.Begin); - Previews[i] = Helpers.Deserialize<Preview>(inputFile); + Debug.Write($"Preview {i} -> "); + Debug.WriteLine(Previews[i]); - Debug.Write($"Preview {i} -> "); - Debug.WriteLine(Previews[i]); + inputFile.Seek(Previews[i].ImageOffset, SeekOrigin.Begin); + byte[] rawImageData = new byte[Previews[i].ImageLength]; + inputFile.Read(rawImageData, 0, (int) Previews[i].ImageLength); - inputFile.Seek(Previews[i].ImageOffset, SeekOrigin.Begin); - byte[] rawImageData = new byte[Previews[i].ImageLength]; - inputFile.Read(rawImageData, 0, (int)Previews[i].ImageLength); + Thumbnails[i] = Previews[i].Decode(rawImageData); + progress++; + } - Thumbnails[i] = Previews[i].Decode(rawImageData); - } + //if (HeaderSettings.Version == 2) + //{ + if (HeaderSettings.PrintParametersOffsetAddress > 0) + { + inputFile.Seek(HeaderSettings.PrintParametersOffsetAddress, SeekOrigin.Begin); + PrintParametersSettings = Helpers.Deserialize<PrintParameters>(inputFile); + Debug.Write("Print Parameters -> "); + Debug.WriteLine(PrintParametersSettings); - //if (HeaderSettings.Version == 2) - //{ - if (HeaderSettings.PrintParametersOffsetAddress > 0) - { - inputFile.Seek(HeaderSettings.PrintParametersOffsetAddress, SeekOrigin.Begin); - PrintParametersSettings = Helpers.Deserialize<PrintParameters>(inputFile); - Debug.Write("Print Parameters -> "); - Debug.WriteLine(PrintParametersSettings); - - } + } - if (HeaderSettings.SlicerOffset > 0) - { - inputFile.Seek(HeaderSettings.SlicerOffset, SeekOrigin.Begin); - SlicerInfoSettings = Helpers.Deserialize<SlicerInfo>(inputFile); - Debug.Write("Slicer Info -> "); - Debug.WriteLine(SlicerInfoSettings); - } + if (HeaderSettings.SlicerOffset > 0) + { + inputFile.Seek(HeaderSettings.SlicerOffset, SeekOrigin.Begin); + SlicerInfoSettings = Helpers.Deserialize<SlicerInfo>(inputFile); + Debug.Write("Slicer Info -> "); + Debug.WriteLine(SlicerInfoSettings); + } - /*InputFile.BaseStream.Seek(MachineInfoSettings.MachineNameAddress, SeekOrigin.Begin); - byte[] bytes = InputFile.ReadBytes((int)MachineInfoSettings.MachineNameSize); - MachineName = System.Text.Encoding.UTF8.GetString(bytes); - Debug.WriteLine($"{nameof(MachineName)}: {MachineName}");*/ - //} + /*InputFile.BaseStream.Seek(MachineInfoSettings.MachineNameAddress, SeekOrigin.Begin); + byte[] bytes = InputFile.ReadBytes((int)MachineInfoSettings.MachineNameSize); + MachineName = System.Text.Encoding.UTF8.GetString(bytes); + Debug.WriteLine($"{nameof(MachineName)}: {MachineName}");*/ + //} - LayersDefinitions = new LayerData[HeaderSettings.AntiAliasLevel, HeaderSettings.LayerCount]; + LayersDefinitions = new LayerData[HeaderSettings.AntiAliasLevel, HeaderSettings.LayerCount]; - uint layerOffset = HeaderSettings.LayersDefinitionOffsetAddress; + uint layerOffset = HeaderSettings.LayersDefinitionOffsetAddress; + progress.Reset(OperationProgress.StatusGatherLayers, + HeaderSettings.AntiAliasLevel * HeaderSettings.LayerCount); - for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++) - { - Debug.WriteLine($"-Image GROUP {aaIndex}-"); - for (uint layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++) + for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++) { - inputFile.Seek(layerOffset, SeekOrigin.Begin); - LayerData layerData = Helpers.Deserialize<LayerData>(inputFile); - layerData.Parent = this; - LayersDefinitions[aaIndex, layerIndex] = layerData; - - layerOffset += (uint)Helpers.Serializer.SizeOf(layerData); - //Debug.Write($"LAYER {layerIndex} -> "); - //Debug.WriteLine(layerData); - - layerData.EncodedRle = new byte[layerData.DataSize]; - inputFile.Seek(layerData.DataAddress, SeekOrigin.Begin); - inputFile.Read(layerData.EncodedRle, 0, (int)layerData.DataSize); + Debug.WriteLine($"-Image GROUP {aaIndex}-"); + for (uint layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++) + { + inputFile.Seek(layerOffset, SeekOrigin.Begin); + LayerData layerData = Helpers.Deserialize<LayerData>(inputFile); + layerData.Parent = this; + LayersDefinitions[aaIndex, layerIndex] = layerData; + + layerOffset += (uint) Helpers.Serializer.SizeOf(layerData); + //Debug.Write($"LAYER {layerIndex} -> "); + //Debug.WriteLine(layerData); + + layerData.EncodedRle = new byte[layerData.DataSize]; + inputFile.Seek(layerData.DataAddress, SeekOrigin.Begin); + inputFile.Read(layerData.EncodedRle, 0, (int) layerData.DataSize); + progress++; + progress.Token.ThrowIfCancellationRequested(); + } } - } - LayerManager = new LayerManager(HeaderSettings.LayerCount); + LayerManager = new LayerManager(HeaderSettings.LayerCount); - Parallel.For(0, LayerCount, layerIndex => - { - using (var image = LayersDefinitions[0, layerIndex].Decode((uint) layerIndex)) + progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount); + + Parallel.For(0, LayerCount, layerIndex => { - this[layerIndex] = new Layer((uint) layerIndex, image); - } - }); + if (progress.Token.IsCancellationRequested) + { + return; + } + + using (var image = LayersDefinitions[0, layerIndex].Decode((uint) layerIndex)) + { + this[layerIndex] = new Layer((uint) layerIndex, image); + lock (progress.Mutex) + { + progress++; + } + } + }); + } + + progress.Token.ThrowIfCancellationRequested(); } public override object GetValueFromPrintParameterModifier(PrintParameterModifier modifier) @@ -1349,7 +1379,7 @@ namespace UVtools.Core return false; } - public override void SaveAs(string filePath = null) + public override void SaveAs(string filePath = null, OperationProgress progress = null) { if (LayerManager.IsModified) { @@ -1357,7 +1387,7 @@ namespace UVtools.Core { FileFullPath = filePath; } - Encode(FileFullPath); + Encode(FileFullPath, progress); return; } @@ -1390,13 +1420,12 @@ namespace UVtools.Core layerOffset += Helpers.SerializeWriteFileStream(outputFile, LayersDefinitions[aaIndex, layerIndex]); } } - outputFile.Close(); } - //Decode(FileFullPath); + //Decode(FileFullPath, progress); } - public override bool Convert(Type to, string fileFullPath) + public override bool Convert(Type to, string fileFullPath, OperationProgress progress = null) { if (to == typeof(ChituboxZipFile)) { @@ -1445,7 +1474,7 @@ namespace UVtools.Core }; file.SetThumbnails(Thumbnails); - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } @@ -1475,7 +1504,7 @@ namespace UVtools.Core }; file.SetThumbnails(Thumbnails); - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } @@ -1523,7 +1552,7 @@ namespace UVtools.Core file.SetThumbnails(Thumbnails); - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } @@ -1610,7 +1639,7 @@ namespace UVtools.Core } file.SetThumbnails(Thumbnails); - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } diff --git a/UVtools.Core/ChituboxZipFile.cs b/UVtools.Core/ChituboxZipFile.cs index 31c8a2d..5fea234 100644 --- a/UVtools.Core/ChituboxZipFile.cs +++ b/UVtools.Core/ChituboxZipFile.cs @@ -155,15 +155,17 @@ namespace UVtools.Core GCode = null; } - public override void Encode(string fileFullPath) + public override void Encode(string fileFullPath, OperationProgress progress = null) { - base.Encode(fileFullPath); - using (ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Update)) + base.Encode(fileFullPath, progress); + using (ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create)) { for(uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) { + progress.Token.ThrowIfCancellationRequested(); Layer layer = this[layerIndex]; - outputFile.PutFileContent($"{layerIndex+1}.png", layer.CompressedBytes); + outputFile.PutFileContent($"{layerIndex+1}.png", layer.CompressedBytes, ZipArchiveMode.Create); + progress++; } if (Thumbnails.Length > 0 && !ReferenceEquals(Thumbnails[0], null)) @@ -189,13 +191,13 @@ namespace UVtools.Core } UpdateGCode(); - outputFile.PutFileContent("run.gcode", GCode.ToString()); + outputFile.PutFileContent("run.gcode", GCode.ToString(), ZipArchiveMode.Create); } } - public override void Decode(string fileFullPath) + public override void Decode(string fileFullPath, OperationProgress progress = null) { - base.Decode(fileFullPath); + base.Decode(fileFullPath, progress); FileFullPath = fileFullPath; using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read)) @@ -238,6 +240,8 @@ namespace UVtools.Core LayerManager = new LayerManager(HeaderSettings.LayerCount); + progress.ItemCount = LayerCount; + for (uint layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++) { entry = inputFile.GetEntry($"{layerIndex+1}.png"); @@ -248,6 +252,7 @@ namespace UVtools.Core } LayerManager[layerIndex] = new Layer(layerIndex, entry.Open(), entry.Name); + progress++; } entry = inputFile.GetEntry("preview.png"); @@ -263,7 +268,7 @@ namespace UVtools.Core } } - var rect = LayerManager.BoundingRectangle; + LayerManager.GetBoundingRectangle(progress); } public override object GetValueFromPrintParameterModifier(PrintParameterModifier modifier) @@ -368,7 +373,7 @@ namespace UVtools.Core return false; } - public override void SaveAs(string filePath = null) + public override void SaveAs(string filePath = null, OperationProgress progress = null) { if (!string.IsNullOrEmpty(filePath)) { @@ -387,20 +392,20 @@ namespace UVtools.Core } } - outputFile.PutFileContent("run.gcode", GCode.ToString()); + outputFile.PutFileContent("run.gcode", GCode.ToString(), ZipArchiveMode.Update); foreach (var layer in this) { if (!layer.IsModified) continue; - outputFile.PutFileContent(layer.Filename, layer.CompressedBytes); + outputFile.PutFileContent(layer.Filename, layer.CompressedBytes, ZipArchiveMode.Update); layer.IsModified = false; } } - //Decode(FileFullPath); + //Decode(FileFullPath, progress); } - public override bool Convert(Type to, string fileFullPath) + public override bool Convert(Type to, string fileFullPath, OperationProgress progress = null) { throw new NotImplementedException(); } diff --git a/UVtools.Core/Extensions/FileStreamExtensions.cs b/UVtools.Core/Extensions/FileStreamExtensions.cs index b61019d..d772033 100644 --- a/UVtools.Core/Extensions/FileStreamExtensions.cs +++ b/UVtools.Core/Extensions/FileStreamExtensions.cs @@ -17,13 +17,6 @@ namespace UVtools.Core.Extensions return (uint)fs.Read(bytes, offset, bytes.Length); } - public static byte[] ReadBytes(this Stream stream) - { - byte[] buff = new byte[stream.Length]; - stream.Read(buff, 0, buff.Length); - return buff; - } - public static uint WriteStream(this FileStream fs, MemoryStream stream, int offset = 0) { return fs.WriteBytes(stream.ToArray(), offset); diff --git a/UVtools.Core/Extensions/ZipArchiveExtensions.cs b/UVtools.Core/Extensions/ZipArchiveExtensions.cs index 6ba71f2..6e71025 100644 --- a/UVtools.Core/Extensions/ZipArchiveExtensions.cs +++ b/UVtools.Core/Extensions/ZipArchiveExtensions.cs @@ -296,14 +296,23 @@ namespace UVtools.Core.Extensions /// <param name="input"><see cref="ZipArchive"/></param> /// <param name="filename">Filename to create</param> /// <param name="content">Content to write</param> + /// <param name="checkExists"></param> /// <returns>Created <see cref="ZipArchiveEntry"/></returns> - public static ZipArchiveEntry PutFileContent(this ZipArchive input, string filename, string content) + public static ZipArchiveEntry PutFileContent(this ZipArchive input, string filename, string content, ZipArchiveMode mode) { - ZipArchiveEntry entry = input.GetEntry(filename) ?? input.CreateEntry(filename); + ZipArchiveEntry entry; + if (mode == ZipArchiveMode.Update) + { + entry = input.GetEntry(filename) ?? input.CreateEntry(filename); + } + else + { + entry = input.CreateEntry(filename); + } if (string.IsNullOrEmpty(content)) return entry; Stream stream = entry.Open(); - stream.SetLength(0); + if (mode == ZipArchiveMode.Update) stream.SetLength(0); using (TextWriter tw = new StreamWriter(stream)) { tw.Write(content); @@ -319,14 +328,23 @@ namespace UVtools.Core.Extensions /// <param name="filename">Filename to create</param> /// <param name="content">Content to write</param> /// <returns>Created <see cref="ZipArchiveEntry"/></returns> - public static ZipArchiveEntry PutFileContent(this ZipArchive input, string filename, byte[] content) + public static ZipArchiveEntry PutFileContent(this ZipArchive input, string filename, byte[] content, ZipArchiveMode mode) { - ZipArchiveEntry entry = input.GetEntry(filename) ?? input.CreateEntry(filename); + ZipArchiveEntry entry; + if (mode == ZipArchiveMode.Update) + { + entry = input.GetEntry(filename) ?? input.CreateEntry(filename); + } + else + { + entry = input.CreateEntry(filename); + } if (ReferenceEquals(content, null)) return entry; Stream stream = entry.Open(); - stream.SetLength(0); + if (mode == ZipArchiveMode.Update) stream.SetLength(0); stream.Write(content, 0, content.Length); + stream.Close(); return entry; } } diff --git a/UVtools.Core/FileFormat.cs b/UVtools.Core/FileFormat.cs index 110cfac..7d12768 100644 --- a/UVtools.Core/FileFormat.cs +++ b/UVtools.Core/FileFormat.cs @@ -273,7 +273,7 @@ namespace UVtools.Core public float TotalHeight => (float)Math.Round(LayerCount * LayerHeight, 2); - public uint LayerCount => LayerManager.Count; + public uint LayerCount => LayerManager?.Count ?? 0; public abstract ushort InitialLayerCount { get; } @@ -448,7 +448,7 @@ namespace UVtools.Core } } - public virtual void Encode(string fileFullPath) + public virtual void Encode(string fileFullPath, OperationProgress progress = null) { FileFullPath = fileFullPath; @@ -462,6 +462,9 @@ namespace UVtools.Core if (ReferenceEquals(Thumbnails[i], null)) continue; CvInvoke.Resize(Thumbnails[i], Thumbnails[i], new Size(ThumbnailsOriginalSize[i].Width, ThumbnailsOriginalSize[i].Height)); } + + if(ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset(OperationProgress.StatusEncodeLayers, LayerCount); } /*public virtual void BeginEncode(string fileFullPath) @@ -473,31 +476,36 @@ namespace UVtools.Core public abstract void EndEncode();*/ - public virtual void Decode(string fileFullPath) + public virtual void Decode(string fileFullPath, OperationProgress progress = null) { Clear(); FileValidation(fileFullPath); FileFullPath = fileFullPath; + if(ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.ItemName = OperationProgress.StatusGatherLayers; } - public virtual void Extract(string path, bool genericConfigExtract = true, bool genericLayersExtract = true) + public virtual void Extract(string path, bool genericConfigExtract = true, bool genericLayersExtract = true, + OperationProgress progress = null) { - /*if (emptyFirst) - { - if (Directory.Exists(path)) + if (ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.ItemName = OperationProgress.StatusExtracting; + /*if (emptyFirst) { - DirectoryInfo di = new DirectoryInfo(path); - - foreach (FileInfo file in di.GetFiles()) - { - file.Delete(); - } - foreach (DirectoryInfo dir in di.GetDirectories()) + if (Directory.Exists(path)) { - dir.Delete(true); + DirectoryInfo di = new DirectoryInfo(path); + + foreach (FileInfo file in di.GetFiles()) + { + file.Delete(); + } + foreach (DirectoryInfo dir in di.GetDirectories()) + { + dir.Delete(true); + } } - } - }*/ + }*/ //if (!Directory.Exists(path)) //{ @@ -507,11 +515,15 @@ namespace UVtools.Core if (FileType == FileFormatType.Archive) { + + progress.CanCancel = false; //ZipFile.ExtractToDirectory(FileFullPath, path); ZipArchiveExtensions.ImprovedExtractToDirectory(FileFullPath, path, ZipArchiveExtensions.Overwrite.Always); return; } + progress.ItemCount = LayerCount; + if (genericConfigExtract) { if (!ReferenceEquals(Configs, null)) @@ -556,12 +568,17 @@ namespace UVtools.Core { Parallel.ForEach(this, (layer) => { + if (progress.Token.IsCancellationRequested) return; var byteArr = layer.CompressedBytes; using (FileStream stream = File.Create(Path.Combine(path, $"Layer{layer.Index}.png"), byteArr.Length)) { stream.Write(byteArr, 0, byteArr.Length); stream.Close(); + lock (progress.Mutex) + { + progress++; + } } }); } @@ -624,17 +641,17 @@ namespace UVtools.Core public abstract bool SetValueFromPrintParameterModifier(PrintParameterModifier modifier, string value); - public void Save() + public void Save(OperationProgress progress = null) { - SaveAs(); + SaveAs(null, progress); } - public abstract void SaveAs(string filePath = null); + public abstract void SaveAs(string filePath = null, OperationProgress progress = null); - public abstract bool Convert(Type to, string fileFullPath); - public bool Convert(FileFormat to, string fileFullPath) + public abstract bool Convert(Type to, string fileFullPath, OperationProgress progress = null); + public bool Convert(FileFormat to, string fileFullPath, OperationProgress progress = null) { - return Convert(to.GetType(), fileFullPath); + return Convert(to.GetType(), fileFullPath, progress); } public byte ValidateAntiAliasingLevel() diff --git a/UVtools.Core/IFileFormat.cs b/UVtools.Core/IFileFormat.cs index 825804b..058298d 100644 --- a/UVtools.Core/IFileFormat.cs +++ b/UVtools.Core/IFileFormat.cs @@ -233,7 +233,8 @@ namespace UVtools.Core /// Encode to an output file /// </summary> /// <param name="fileFullPath">Output file</param> - void Encode(string fileFullPath); + /// <param name="progress"></param> + void Encode(string fileFullPath, OperationProgress progress = null); /* /// <summary> @@ -258,7 +259,8 @@ namespace UVtools.Core /// Decode a slicer file /// </summary> /// <param name="fileFullPath"></param> - void Decode(string fileFullPath); + /// <param name="progress"></param> + void Decode(string fileFullPath, OperationProgress progress = null); /// <summary> /// Extract contents to a folder @@ -266,7 +268,9 @@ namespace UVtools.Core /// <param name="path">Path to folder where content will be extracted</param> /// <param name="genericConfigExtract"></param> /// <param name="genericLayersExtract"></param> - void Extract(string path, bool genericConfigExtract = true, bool genericLayersExtract = true); + /// <param name="progress"></param> + void Extract(string path, bool genericConfigExtract = true, bool genericLayersExtract = true, + OperationProgress progress = null); /// <summary> /// Get height in mm from layer height @@ -312,29 +316,33 @@ namespace UVtools.Core /// <summary> /// Saves current configuration on input file /// </summary> - void Save(); + /// <param name="progress"></param> + void Save(OperationProgress progress = null); /// <summary> /// Saves current configuration on a copy /// </summary> /// <param name="filePath">File path to save copy as, use null to overwrite active file (Same as <see cref="Save"/>)</param> - void SaveAs(string filePath = null); + /// <param name="progress"></param> + void SaveAs(string filePath = null, OperationProgress progress = null); /// <summary> /// Converts this file type to another file type /// </summary> /// <param name="to">Target file format</param> /// <param name="fileFullPath">Output path file</param> + /// <param name="progress"></param> /// <returns>True if convert succeed, otherwise false</returns> - bool Convert(Type to, string fileFullPath); + bool Convert(Type to, string fileFullPath, OperationProgress progress = null); /// <summary> /// Converts this file type to another file type /// </summary> /// <param name="to">Target file format</param> /// <param name="fileFullPath">Output path file</param> + /// <param name="progress"></param> /// <returns>True if convert succeed, otherwise false</returns> - bool Convert(FileFormat to, string fileFullPath); + bool Convert(FileFormat to, string fileFullPath, OperationProgress progress = null); /// <summary> /// Validate AntiAlias Level diff --git a/UVtools.Core/ImageFile.cs b/UVtools.Core/ImageFile.cs index 4d351b5..a9c6ac5 100644 --- a/UVtools.Core/ImageFile.cs +++ b/UVtools.Core/ImageFile.cs @@ -1,9 +1,8 @@ using System; using System.IO; -using System.Net.Mime; +using System.Threading.Tasks; using Emgu.CV; using Emgu.CV.CvEnum; -using UVtools.Core.Extensions; using Size = System.Drawing.Size; namespace UVtools.Core @@ -50,10 +49,9 @@ namespace UVtools.Core throw new NotImplementedException(); } - public override void Decode(string fileFullPath) + public override void Decode(string fileFullPath, OperationProgress progress = null) { - base.Decode(fileFullPath); - var grayMat = new Mat(); + base.Decode(fileFullPath, progress); ImageMat = CvInvoke.Imread(fileFullPath, ImreadModes.AnyColor); const byte startDivisor = 2; @@ -65,18 +63,21 @@ namespace UVtools.Core new Size(ImageMat.Width / divisor, ImageMat.Height / divisor)); } - CvInvoke.CvtColor(ImageMat, ImageMat, ColorConversion.Bgr2Gray); + if (ImageMat.NumberOfChannels > 1) + { + CvInvoke.CvtColor(ImageMat, ImageMat, ColorConversion.Bgr2Gray); + } LayerManager = new LayerManager(1); this[0] = new Layer(0, ImageMat, Path.GetFileName(fileFullPath)); } - public override void SaveAs(string filePath = null) + public override void SaveAs(string filePath = null, OperationProgress progress = null) { - this[0].LayerMat.Save(filePath); + this[0].LayerMat.Save(filePath ?? FileFullPath); } - public override bool Convert(Type to, string fileFullPath) + public override bool Convert(Type to, string fileFullPath, OperationProgress progress = null) { throw new NotImplementedException(); } diff --git a/UVtools.Core/LayerManager.cs b/UVtools.Core/LayerManager.cs index 77c9d55..d56384b 100644 --- a/UVtools.Core/LayerManager.cs +++ b/UVtools.Core/LayerManager.cs @@ -928,25 +928,7 @@ namespace UVtools.Core private Rectangle _boundingRectangle = Rectangle.Empty; public Rectangle BoundingRectangle { - get - { - if(!_boundingRectangle.IsEmpty) return _boundingRectangle; - _boundingRectangle = this[0].BoundingRectangle; - if (_boundingRectangle.IsEmpty) // Safe checking - { - Parallel.For(0, Count, layerIndex => - { - this[layerIndex].GetBoundingRectangle(); - }); - _boundingRectangle = this[0].BoundingRectangle; - } - for (int i = 1; i < Count; i++) - { - _boundingRectangle = Rectangle.Union(_boundingRectangle, this[i].BoundingRectangle); - } - - return _boundingRectangle; - } + get => GetBoundingRectangle(); set => _boundingRectangle = value; } @@ -1066,6 +1048,49 @@ namespace UVtools.Core #region Methods + public Rectangle GetBoundingRectangle(OperationProgress progress = null) + { + if (!_boundingRectangle.IsEmpty) return _boundingRectangle; + _boundingRectangle = this[0].BoundingRectangle; + if (_boundingRectangle.IsEmpty) // Safe checking + { + progress?.Reset(OperationProgress.StatusOptimizingBounds, Count); + Parallel.For(0, Count, layerIndex => + { + if (!ReferenceEquals(progress, null) && progress.Token.IsCancellationRequested) + { + return; + } + + this[layerIndex].GetBoundingRectangle(); + + if (ReferenceEquals(progress, null)) return; + lock (progress.Mutex) + { + progress++; + } + }); + _boundingRectangle = this[0].BoundingRectangle; + + if (!ReferenceEquals(progress, null) && progress.Token.IsCancellationRequested) + { + _boundingRectangle = Rectangle.Empty; + progress.Token.ThrowIfCancellationRequested(); + } + + } + + progress?.Reset(OperationProgress.StatusCalculatingBounds, Count); + for (int i = 1; i < Count; i++) + { + _boundingRectangle = Rectangle.Union(_boundingRectangle, this[i].BoundingRectangle); + if (ReferenceEquals(progress, null)) continue; + progress++; + } + + return _boundingRectangle; + } + /// <summary> /// Add a layer /// </summary> @@ -1095,15 +1120,19 @@ namespace UVtools.Core /// <param name="x">X factor, starts at 1</param> /// <param name="y">Y factor, starts at 1</param> /// <param name="isFade">Fade X/Y towards 100%</param> - public void MutateResize(uint startLayerIndex, uint endLayerIndex, double x, double y, bool isFade) + public void MutateResize(uint startLayerIndex, uint endLayerIndex, double x, double y, bool isFade, OperationProgress progress = null) { if (x == 1.0 && y == 1.0) return; + if(ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset("Resizing", Count); + double xSteps = Math.Abs(x - 1.0) / (endLayerIndex - startLayerIndex); double ySteps = Math.Abs(y - 1.0) / (endLayerIndex - startLayerIndex); Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex => { + if (progress.Token.IsCancellationRequested) return; var newX = x; var newY = y; if (isFade) @@ -1135,34 +1164,64 @@ namespace UVtools.Core } } + lock (progress.Mutex) + { + progress++; + } + if (newX == 1.0 && newY == 1.0) return; this[layerIndex].MutateResize(newX, newY); }); + progress.Token.ThrowIfCancellationRequested(); } - public void MutateFlip(uint startLayerIndex, uint endLayerIndex, FlipType flipType, bool makeCopy = false) + public void MutateFlip(uint startLayerIndex, uint endLayerIndex, FlipType flipType, bool makeCopy = false, OperationProgress progress = null) { + if (ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset("Fliping", Count); Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex => { + if (progress.Token.IsCancellationRequested) return; this[layerIndex].MutateFlip(flipType, makeCopy); + lock (progress.Mutex) + { + progress++; + } }); + progress.Token.ThrowIfCancellationRequested(); } - public void MutateRotate(uint startLayerIndex, uint endLayerIndex, double angle, Inter interpolation = Inter.Linear) + public void MutateRotate(uint startLayerIndex, uint endLayerIndex, double angle, Inter interpolation = Inter.Linear, OperationProgress progress = null) { + if (ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset("Rotating", Count); Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex => { + if (progress.Token.IsCancellationRequested) return; this[layerIndex].MutateRotate(angle, interpolation); + lock (progress.Mutex) + { + progress++; + } }); + progress.Token.ThrowIfCancellationRequested(); } - public void MutateSolidify(uint startLayerIndex, uint endLayerIndex) + public void MutateSolidify(uint startLayerIndex, uint endLayerIndex, OperationProgress progress = null) { + if (ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset("Solidifing", Count); Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex => { + if (progress.Token.IsCancellationRequested) return; this[layerIndex].MutateSolidify(); + lock (progress.Mutex) + { + progress++; + } }); + progress.Token.ThrowIfCancellationRequested(); } private void MutateGetVarsIterationFade(uint startLayerIndex, uint endLayerIndex, int iterationsStart, int iterationsEnd, ref bool isFade, out int iterationSteps, out int maxIteration) @@ -1187,7 +1246,7 @@ namespace UVtools.Core return Math.Min(Math.Max(1, iterations), maxIteration); } - public void MutateErode(uint startLayerIndex, uint endLayerIndex, int iterationsStart = 1, int iterationsEnd = 1, bool isFade = false, + public void MutateErode(uint startLayerIndex, uint endLayerIndex, int iterationsStart = 1, int iterationsEnd = 1, bool isFade = false, OperationProgress progress = null, IInputArray kernel = null, Point anchor = default, BorderType borderType = BorderType.Default, MCvScalar borderValue = default) { @@ -1201,14 +1260,23 @@ namespace UVtools.Core out var maxIteration ); + if (ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset("Eroding", Count); + Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex => { + if (progress.Token.IsCancellationRequested) return; int iterations = MutateGetIterationVar(isFade, iterationsStart, iterationsEnd, iterationSteps, maxIteration, startLayerIndex, (uint) layerIndex); this[layerIndex].MutateErode(iterations, kernel, anchor, borderType, borderValue); + lock (progress.Mutex) + { + progress++; + } }); + progress.Token.ThrowIfCancellationRequested(); } - public void MutateDilate(uint startLayerIndex, uint endLayerIndex, int iterationsStart = 1, int iterationsEnd = 1, bool isFade = false, + public void MutateDilate(uint startLayerIndex, uint endLayerIndex, int iterationsStart = 1, int iterationsEnd = 1, bool isFade = false, OperationProgress progress = null, IInputArray kernel = null, Point anchor = default, BorderType borderType = BorderType.Default, MCvScalar borderValue = default) { @@ -1222,14 +1290,23 @@ namespace UVtools.Core out var maxIteration ); + if (ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset("Dilating", Count); + Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex => { + if (progress.Token.IsCancellationRequested) return; int iterations = MutateGetIterationVar(isFade, iterationsStart, iterationsEnd, iterationSteps, maxIteration, startLayerIndex, (uint)layerIndex); this[layerIndex].MutateDilate(iterations, kernel, anchor, borderType, borderValue); + lock (progress.Mutex) + { + progress++; + } }); + progress.Token.ThrowIfCancellationRequested(); } - public void MutateOpen(uint startLayerIndex, uint endLayerIndex, int iterationsStart = 1, int iterationsEnd = 1, bool isFade = false, + public void MutateOpen(uint startLayerIndex, uint endLayerIndex, int iterationsStart = 1, int iterationsEnd = 1, bool isFade = false, OperationProgress progress = null, IInputArray kernel = null, Point anchor = default, BorderType borderType = BorderType.Default, MCvScalar borderValue = default) { @@ -1243,14 +1320,23 @@ namespace UVtools.Core out var maxIteration ); + if (ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset("Removing Noise", Count); + Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex => { + if (progress.Token.IsCancellationRequested) return; int iterations = MutateGetIterationVar(isFade, iterationsStart, iterationsEnd, iterationSteps, maxIteration, startLayerIndex, (uint)layerIndex); this[layerIndex].MutateOpen(iterations, kernel, anchor, borderType, borderValue); + lock (progress.Mutex) + { + progress++; + } }); + progress.Token.ThrowIfCancellationRequested(); } - public void MutateClose(uint startLayerIndex, uint endLayerIndex, int iterationsStart = 1, int iterationsEnd = 1, bool isFade = false, + public void MutateClose(uint startLayerIndex, uint endLayerIndex, int iterationsStart = 1, int iterationsEnd = 1, bool isFade = false, OperationProgress progress = null, IInputArray kernel = null, Point anchor = default, BorderType borderType = BorderType.Default, MCvScalar borderValue = default) { @@ -1264,14 +1350,23 @@ namespace UVtools.Core out var maxIteration ); + if (ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset("Gap Closing", Count); + Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex => { + if (progress.Token.IsCancellationRequested) return; int iterations = MutateGetIterationVar(isFade, iterationsStart, iterationsEnd, iterationSteps, maxIteration, startLayerIndex, (uint)layerIndex); this[layerIndex].MutateClose(iterations, kernel, anchor, borderType, borderValue); + lock (progress.Mutex) + { + progress++; + } }); + progress.Token.ThrowIfCancellationRequested(); } - public void MutateGradient(uint startLayerIndex, uint endLayerIndex, int iterationsStart = 1, int iterationsEnd = 1, bool isFade = false, + public void MutateGradient(uint startLayerIndex, uint endLayerIndex, int iterationsStart = 1, int iterationsEnd = 1, bool isFade = false, OperationProgress progress = null, IInputArray kernel = null, Point anchor = default, BorderType borderType = BorderType.Default, MCvScalar borderValue = default) { @@ -1285,54 +1380,100 @@ namespace UVtools.Core out var maxIteration ); + if (ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset("Gradient", Count); + Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex => { + if (progress.Token.IsCancellationRequested) return; int iterations = MutateGetIterationVar(isFade, iterationsStart, iterationsEnd, iterationSteps, maxIteration, startLayerIndex, (uint)layerIndex); this[layerIndex].MutateGradient(iterations, kernel, anchor, borderType, borderValue); + lock (progress.Mutex) + { + progress++; + } }); + progress.Token.ThrowIfCancellationRequested(); } - public void MutatePyrDownUp(uint startLayerIndex, uint endLayerIndex, BorderType borderType = BorderType.Default) + public void MutatePyrDownUp(uint startLayerIndex, uint endLayerIndex, BorderType borderType = BorderType.Default, OperationProgress progress = null) { + if (ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset("PryDownUp", Count); Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex => { + if (progress.Token.IsCancellationRequested) return; this[layerIndex].MutatePyrDownUp(borderType); + lock (progress.Mutex) + { + progress++; + } }); + progress.Token.ThrowIfCancellationRequested(); } - public void MutateMedianBlur(uint startLayerIndex, uint endLayerIndex, int aperture = 1) + public void MutateMedianBlur(uint startLayerIndex, uint endLayerIndex, int aperture = 1, OperationProgress progress = null) { + if (ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset("Bluring", Count); Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex => { + if (progress.Token.IsCancellationRequested) return; this[layerIndex].MutateMedianBlur(aperture); + lock (progress.Mutex) + { + progress++; + } }); + progress.Token.ThrowIfCancellationRequested(); } - public void MutateGaussianBlur(uint startLayerIndex, uint endLayerIndex, Size size = default, int sigmaX = 0, int sigmaY = 0, BorderType borderType = BorderType.Reflect101) + public void MutateGaussianBlur(uint startLayerIndex, uint endLayerIndex, Size size = default, int sigmaX = 0, int sigmaY = 0, BorderType borderType = BorderType.Reflect101, OperationProgress progress = null) { + if (ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset("Bluring", Count); Parallel.For(startLayerIndex, endLayerIndex + 1, layerIndex => { + if (progress.Token.IsCancellationRequested) return; this[layerIndex].MutateGaussianBlur(size, sigmaX, sigmaY, borderType); + lock (progress.Mutex) + { + progress++; + } }); + progress.Token.ThrowIfCancellationRequested(); } - public ConcurrentDictionary<uint, List<LayerIssue>> GetAllIssues(IslandDetectionConfiguration islandConfig = null, ResinTrapDetectionConfiguration resinTrapConfig = null) + public ConcurrentDictionary<uint, List<LayerIssue>> GetAllIssues( + IslandDetectionConfiguration islandConfig = null, ResinTrapDetectionConfiguration resinTrapConfig = null, + OperationProgress progress = null) { if(ReferenceEquals(islandConfig, null)) islandConfig = new IslandDetectionConfiguration(); if(ReferenceEquals(resinTrapConfig, null)) resinTrapConfig = new ResinTrapDetectionConfiguration(); + if(ReferenceEquals(progress, null)) progress = new OperationProgress(); const byte minTouchingBondsPixelColor = 200; var result = new ConcurrentDictionary<uint, List<LayerIssue>>(); var layerHollowAreas = new ConcurrentDictionary<uint, List<LayerHollowArea>>(); + + bool islandsFinished = false; + + progress.Reset(OperationProgress.StatusIslands, Count); + Parallel.Invoke(() => { - if (!islandConfig.Enabled) return; + if (!islandConfig.Enabled) + { + islandsFinished = true; + return; + } // Detect contours Parallel.ForEach(this, //new ParallelOptions{MaxDegreeOfParallelism = 1}, layer => { + if (progress.Token.IsCancellationRequested) return; using (var image = layer.LayerMat) { int step = image.Step; @@ -1407,6 +1548,7 @@ namespace UVtools.Core Span<byte> previousSpan = null; for (int i = 0; i < contours.Size; i++) { + if ((int) arr.GetValue(0, i, 2) == -1 && (int) arr.GetValue(0, i, 3) != -1) continue; var rect = CvInvoke.BoundingRectangle(contours[i]); if (rect.GetArea() < islandConfig.RequiredAreaToProcessCheck) @@ -1448,6 +1590,7 @@ namespace UVtools.Core } } + if (points.Count == 0) continue; if (pixelsSupportingIsland >= islandConfig.RequiredPixelsToSupport) continue; // Not a island, bounding is strong, i think... @@ -1469,7 +1612,13 @@ namespace UVtools.Core hierarchy.Dispose(); previousImage?.Dispose(); } + + lock (progress.Mutex) + { + progress++; + } }); + islandsFinished = true; }, () => { if (!resinTrapConfig.Enabled) return; @@ -1478,6 +1627,7 @@ namespace UVtools.Core //new ParallelOptions{MaxDegreeOfParallelism = 1}, layer => { + if (progress.Token.IsCancellationRequested) return; using (var image = layer.LayerMat) { if (resinTrapConfig.BinaryThreshold > 0) @@ -1527,6 +1677,7 @@ namespace UVtools.Core for (uint layerIndex = 0; layerIndex < Count - 1; layerIndex++) // Last layers, always drains { + if (progress.Token.IsCancellationRequested) break; if (!layerHollowAreas.TryGetValue(layerIndex, out var areas)) continue; // No hollow areas in this layer, ignore @@ -1535,6 +1686,7 @@ namespace UVtools.Core Parallel.ForEach(from t in areas where t.Type == LayerHollowArea.AreaType.Unknown select t, area => { + if (progress.Token.IsCancellationRequested) return; if (area.Type != LayerHollowArea.AreaType.Unknown) return; // processed, ignore area.Type = LayerHollowArea.AreaType.Trap; @@ -1551,6 +1703,8 @@ namespace UVtools.Core int nextLayerIndex = (int) layerIndex; while (queue.Count > 0 && area.Type != LayerHollowArea.AreaType.Drain) { + if (progress.Token.IsCancellationRequested) return; + LayerHollowArea checkArea = queue.Dequeue(); if (checkArea.Processed) continue; checkArea.Processed = true; @@ -1560,7 +1714,12 @@ namespace UVtools.Core break; // Exhausted layers bool haveNextAreas = layerHollowAreas.TryGetValue((uint) nextLayerIndex, out var nextAreas); Dictionary<int, LayerHollowArea> intersectingAreas = new Dictionary<int, LayerHollowArea>(); - + + if (islandsFinished) + { + progress.Reset(OperationProgress.StatusResinTraps, Count, (uint) nextLayerIndex); + } + using (var image = this[nextLayerIndex].LayerMat) { var span = image.GetPixelSpan<byte>(); @@ -1700,6 +1859,8 @@ namespace UVtools.Core } }); + if (progress.Token.IsCancellationRequested) return result; + for (uint layerIndex = 0; layerIndex < Count; layerIndex++) { if (!layerHollowAreas.TryGetValue(layerIndex, out var list)) continue; @@ -1722,10 +1883,14 @@ namespace UVtools.Core } public void RepairLayers(uint layerStart, uint layerEnd, uint closingIterations = 1, uint openingIterations = 1, - bool repairIslands = true, bool repairResinTraps = true, Dictionary<uint, List<LayerIssue>> issues = null) + bool repairIslands = true, bool repairResinTraps = true, Dictionary<uint, List<LayerIssue>> issues = null, + OperationProgress progress = null) { + if(ReferenceEquals(progress, null)) progress = new OperationProgress(); + progress.Reset(OperationProgress.StatusRepairLayers, layerEnd - layerStart + 1); Parallel.For(layerStart, layerEnd + 1, layerIndex => { + if (progress.Token.IsCancellationRequested) return; Layer layer = this[layerIndex]; using (var image = layer.LayerMat) { @@ -1773,8 +1938,14 @@ namespace UVtools.Core } layer.LayerMat = image; + lock (progress.Mutex) + { + progress++; + } } }); + + progress.Token.ThrowIfCancellationRequested(); } /// <summary> diff --git a/UVtools.Core/OperationProgress.cs b/UVtools.Core/OperationProgress.cs new file mode 100644 index 0000000..8b6559d --- /dev/null +++ b/UVtools.Core/OperationProgress.cs @@ -0,0 +1,113 @@ +using System; +using System.Threading; + +namespace UVtools.Core +{ + public sealed class OperationProgress + { + public const string StatusDecodeThumbnails = "Decoding Thumbnails"; + public const string StatusGatherLayers = "Gathering Layers"; + public const string StatusDecodeLayers = "Decoding Layers"; + public const string StatusEncodeLayers = "Encoding Layers"; + public const string StatusWritingFile = "Writing File"; + public const string StatusEncodeGcode = "Encoding GCode"; + + public const string StatusOptimizingBounds = "Gathering Bounds"; + public const string StatusCalculatingBounds = "Calculating Bounds"; + + public const string StatusExtracting = "Extracting"; + + public const string StatusIslands = "Islands"; + public const string StatusResinTraps = "Resin traps"; + public const string StatusRepairLayers = "Repair Layers"; + + public object Mutex = new object(); + + public CancellationTokenSource TokenSource { get; } = new CancellationTokenSource(); + public CancellationToken Token => TokenSource.Token; + + private bool _canCancel = true; + + public OperationProgress() + { + } + + public OperationProgress(bool canCancel) + { + _canCancel = canCancel; + } + + /// <summary> + /// Gets or sets if operation can be cancelled + /// </summary> + public bool CanCancel + { + get + { + if (!_canCancel) return _canCancel; + return !Token.IsCancellationRequested && Token.CanBeCanceled && _canCancel; + } + set => _canCancel = value; + } + + /// <summary> + /// Gets or sets the item name for the operation + /// </summary> + public string ItemName { get; set; } = StatusDecodeLayers; + + /// <summary> + /// Gets or sets the number of processed items + /// </summary> + public uint ProcessedItems { get; set; } + + /// <summary> + /// Gets or sets the total of item count on this operation + /// </summary> + public uint ItemCount { get; set; } + + /// <summary> + /// Gets the remaining items to be processed + /// </summary> + public uint RemainingItems => ItemCount - ProcessedItems; + + public int ProgressStep => (int) Math.Min(ProcessedItems * 100 / ItemCount, 100); + + /// <summary> + /// Gets the progress from 0 to 100% + /// </summary> + public double ProgressPercent => Math.Round(ProcessedItems * 100.0 / ItemCount, 2); + + public static OperationProgress operator +(OperationProgress progress, uint value) + { + progress.ProcessedItems += value; + return progress; + } + + public static OperationProgress operator ++(OperationProgress progress) + { + progress.ProcessedItems++; + return progress; + } + + public static OperationProgress operator --(OperationProgress progress) + { + progress.ProcessedItems--; + return progress; + } + + public void Reset(string name = "", uint itemCount = 0, uint items = 0) + { + ItemName = name; + ItemCount = itemCount; + ProcessedItems = items; + } + + + public override string ToString() + { + return ItemCount == 0 ? + $"{ProcessedItems} / ? {ItemName}" : + $"{RemainingItems} / {ItemCount} / {ProcessedItems} | {ItemName} | {ProgressPercent:0.00}%"; + } + } +} diff --git a/UVtools.Core/PHZFile.cs b/UVtools.Core/PHZFile.cs index d12bb42..bf1b791 100644 --- a/UVtools.Core/PHZFile.cs +++ b/UVtools.Core/PHZFile.cs @@ -14,6 +14,7 @@ using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using BinarySerialization; @@ -754,9 +755,9 @@ namespace UVtools.Core LayersDefinitions = null; } - public override void Encode(string fileFullPath) + public override void Encode(string fileFullPath, OperationProgress progress = null) { - base.Encode(fileFullPath); + base.Encode(fileFullPath, progress); LayersHash.Clear(); /*if (HeaderSettings.EncryptionKey == 0) @@ -817,18 +818,27 @@ namespace UVtools.Core Parallel.For(0, LayerCount, /*new ParallelOptions{MaxDegreeOfParallelism = 1},*/ layerIndex => { + if(progress.Token.IsCancellationRequested) return; LayerData layer = new LayerData(this, (uint)layerIndex); using (var image = this[layerIndex].LayerMat) { layer.Encode(image, (uint) layerIndex); LayersDefinitions[layerIndex] = layer; } + + lock (progress.Mutex) + { + progress++; + } }); + progress.Reset(OperationProgress.StatusWritingFile, LayerCount); + HeaderSettings.LayersDefinitionOffsetAddress = currentOffset; uint layerDataCurrentOffset = currentOffset + (uint) Helpers.Serializer.SizeOf(LayersDefinitions[0]) * LayerCount; for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) { + progress.Token.ThrowIfCancellationRequested(); LayerData layerData = LayersDefinitions[layerIndex]; LayerData layerDataHash = null; @@ -859,14 +869,12 @@ namespace UVtools.Core outputFile.Seek(currentOffset, SeekOrigin.Begin); currentOffset += Helpers.SerializeWriteFileStream(outputFile, layerData); + progress++; } outputFile.Seek(0, SeekOrigin.Begin); Helpers.SerializeWriteFileStream(outputFile, HeaderSettings); - outputFile.Close(); - outputFile.Dispose(); - Debug.WriteLine("Encode Results:"); Debug.WriteLine(HeaderSettings); Debug.WriteLine(Previews[0]); @@ -875,87 +883,109 @@ namespace UVtools.Core } } - public override void Decode(string fileFullPath) + public override void Decode(string fileFullPath, OperationProgress progress = null) { - base.Decode(fileFullPath); - - var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read); + base.Decode(fileFullPath, progress); - //HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile); - //HeaderSettings = Helpers.Serializer.Deserialize<Header>(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header)))); - HeaderSettings = Helpers.Deserialize<Header>(inputFile); - if (HeaderSettings.Magic != MAGIC_PHZ) + using (var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read)) { - throw new FileLoadException("Not a valid PHZ file!", fileFullPath); - } - HeaderSettings.AntiAliasLevel = 1; + //HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile); + //HeaderSettings = Helpers.Serializer.Deserialize<Header>(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header)))); + HeaderSettings = Helpers.Deserialize<Header>(inputFile); + if (HeaderSettings.Magic != MAGIC_PHZ) + { + throw new FileLoadException("Not a valid PHZ file!", fileFullPath); + } - FileFullPath = fileFullPath; + HeaderSettings.AntiAliasLevel = 1; + FileFullPath = fileFullPath; - Debug.Write("Header -> "); - Debug.WriteLine(HeaderSettings); + progress.Reset(OperationProgress.StatusDecodeThumbnails, ThumbnailsCount); + Debug.Write("Header -> "); + Debug.WriteLine(HeaderSettings); - for (byte i = 0; i < ThumbnailsCount; i++) - { - uint offsetAddress = i == 0 ? HeaderSettings.PreviewSmallOffsetAddress : HeaderSettings.PreviewLargeOffsetAddress; - if (offsetAddress == 0) continue; + for (byte i = 0; i < ThumbnailsCount; i++) + { + uint offsetAddress = i == 0 + ? HeaderSettings.PreviewSmallOffsetAddress + : HeaderSettings.PreviewLargeOffsetAddress; + if (offsetAddress == 0) continue; - inputFile.Seek(offsetAddress, SeekOrigin.Begin); - Previews[i] = Helpers.Deserialize<Preview>(inputFile); + inputFile.Seek(offsetAddress, SeekOrigin.Begin); + Previews[i] = Helpers.Deserialize<Preview>(inputFile); - Debug.Write($"Preview {i} -> "); - Debug.WriteLine(Previews[i]); + Debug.Write($"Preview {i} -> "); + Debug.WriteLine(Previews[i]); - inputFile.Seek(Previews[i].ImageOffset, SeekOrigin.Begin); - byte[] rawImageData = new byte[Previews[i].ImageLength]; - inputFile.Read(rawImageData, 0, (int)Previews[i].ImageLength); + inputFile.Seek(Previews[i].ImageOffset, SeekOrigin.Begin); + byte[] rawImageData = new byte[Previews[i].ImageLength]; + inputFile.Read(rawImageData, 0, (int) Previews[i].ImageLength); - Thumbnails[i] = Previews[i].Decode(rawImageData); - } + Thumbnails[i] = Previews[i].Decode(rawImageData); + progress++; + } - if (HeaderSettings.MachineNameAddress > 0 && HeaderSettings.MachineNameSize > 0) - { - inputFile.Seek(HeaderSettings.MachineNameAddress, SeekOrigin.Begin); - byte[] buffer = new byte[HeaderSettings.MachineNameSize]; - inputFile.Read(buffer, 0, (int) HeaderSettings.MachineNameSize); - HeaderSettings.MachineName = Encoding.ASCII.GetString(buffer); - } + if (HeaderSettings.MachineNameAddress > 0 && HeaderSettings.MachineNameSize > 0) + { + inputFile.Seek(HeaderSettings.MachineNameAddress, SeekOrigin.Begin); + byte[] buffer = new byte[HeaderSettings.MachineNameSize]; + inputFile.Read(buffer, 0, (int) HeaderSettings.MachineNameSize); + HeaderSettings.MachineName = Encoding.ASCII.GetString(buffer); + } - LayersDefinitions = new LayerData[HeaderSettings.LayerCount]; + LayersDefinitions = new LayerData[HeaderSettings.LayerCount]; + + uint layerOffset = HeaderSettings.LayersDefinitionOffsetAddress; - uint layerOffset = HeaderSettings.LayersDefinitionOffsetAddress; + progress.Reset(OperationProgress.StatusGatherLayers, HeaderSettings.LayerCount); + for (uint layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++) + { + inputFile.Seek(layerOffset, SeekOrigin.Begin); + LayerData layerData = Helpers.Deserialize<LayerData>(inputFile); + layerData.Parent = this; + LayersDefinitions[layerIndex] = layerData; + layerOffset += (uint) Helpers.Serializer.SizeOf(layerData); + Debug.Write($"LAYER {layerIndex} -> "); + Debug.WriteLine(layerData); - for (uint layerIndex = 0; layerIndex < HeaderSettings.LayerCount; layerIndex++) - { - inputFile.Seek(layerOffset, SeekOrigin.Begin); - LayerData layerData = Helpers.Deserialize<LayerData>(inputFile); - layerData.Parent = this; - LayersDefinitions[layerIndex] = layerData; - - layerOffset += (uint)Helpers.Serializer.SizeOf(layerData); - Debug.Write($"LAYER {layerIndex} -> "); - Debug.WriteLine(layerData); - - layerData.EncodedRle = new byte[layerData.DataSize]; - inputFile.Seek(layerData.DataAddress, SeekOrigin.Begin); - inputFile.Read(layerData.EncodedRle, 0, (int)layerData.DataSize); - } + layerData.EncodedRle = new byte[layerData.DataSize]; + inputFile.Seek(layerData.DataAddress, SeekOrigin.Begin); + inputFile.Read(layerData.EncodedRle, 0, (int) layerData.DataSize); - LayerManager = new LayerManager(HeaderSettings.LayerCount); + progress++; + progress.Token.ThrowIfCancellationRequested(); + } - Parallel.For(0, LayerCount, layerIndex => - { - using (var image = LayersDefinitions[layerIndex].Decode((uint) layerIndex, true)) + LayerManager = new LayerManager(HeaderSettings.LayerCount); + + progress.Reset(OperationProgress.StatusDecodeLayers, HeaderSettings.LayerCount); + + Parallel.For(0, LayerCount, layerIndex => { - this[layerIndex] = new Layer((uint) layerIndex, image); - } - }); + if (progress.Token.IsCancellationRequested) + { + return; + } + + using (var image = LayersDefinitions[layerIndex].Decode((uint) layerIndex, true)) + { + this[layerIndex] = new Layer((uint) layerIndex, image); + } + + lock (progress.Mutex) + { + progress++; + } + }); + } + + progress.Token.ThrowIfCancellationRequested(); } public override object GetValueFromPrintParameterModifier(PrintParameterModifier modifier) @@ -1064,7 +1094,7 @@ namespace UVtools.Core return false; } - public override void SaveAs(string filePath = null) + public override void SaveAs(string filePath = null, OperationProgress progress = null) { if (LayerManager.IsModified) { @@ -1072,7 +1102,7 @@ namespace UVtools.Core { FileFullPath = filePath; } - Encode(FileFullPath); + Encode(FileFullPath, progress); return; } @@ -1084,7 +1114,6 @@ namespace UVtools.Core using (var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write)) { - outputFile.Seek(0, SeekOrigin.Begin); Helpers.SerializeWriteFileStream(outputFile, HeaderSettings); @@ -1102,13 +1131,12 @@ namespace UVtools.Core Helpers.SerializeWriteFileStream(outputFile, LayersDefinitions[layerIndex]); layerOffset += (uint)Helpers.Serializer.SizeOf(LayersDefinitions[layerIndex]); } - outputFile.Close(); } - //Decode(FileFullPath); + //Decode(FileFullPath, progress); } - public override bool Convert(Type to, string fileFullPath) + public override bool Convert(Type to, string fileFullPath, OperationProgress progress = null) { if (to == typeof(ChituboxFile)) { @@ -1159,7 +1187,7 @@ namespace UVtools.Core file.SetThumbnails(Thumbnails); - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } @@ -1211,7 +1239,7 @@ namespace UVtools.Core }; file.SetThumbnails(Thumbnails); - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } @@ -1241,7 +1269,7 @@ namespace UVtools.Core }; file.SetThumbnails(Thumbnails); - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } @@ -1328,7 +1356,7 @@ namespace UVtools.Core } file.SetThumbnails(Thumbnails); - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } diff --git a/UVtools.Core/PWSFile.cs b/UVtools.Core/PWSFile.cs index 1075d01..45eb55b 100644 --- a/UVtools.Core/PWSFile.cs +++ b/UVtools.Core/PWSFile.cs @@ -821,9 +821,9 @@ namespace UVtools.Core LayersDefinition = null; } - public override void Encode(string fileFullPath) + public override void Encode(string fileFullPath, OperationProgress progress = null) { - base.Encode(fileFullPath); + base.Encode(fileFullPath, progress); LayersHash.Clear(); LayersDefinition = new LayerDefinition(LayerCount); @@ -848,12 +848,17 @@ namespace UVtools.Core Parallel.For(0, LayerCount, layerIndex => { + if (progress.Token.IsCancellationRequested) return; LayerData layer = new LayerData(this, (uint) layerIndex); using (var image = this[layerIndex].LayerMat) { layer.Encode(image); LayersDefinition.Layers[layerIndex] = layer; } + lock (progress.Mutex) + { + progress++; + } }); LayersDefinition.Section.Length += (uint)Helpers.Serializer.SizeOf(LayersDefinition[0]) * LayerCount; @@ -862,9 +867,11 @@ namespace UVtools.Core currentOffset += Helpers.SerializeWriteFileStream(outputFile, LayersDefinition); - + progress.Reset(OperationProgress.StatusWritingFile, LayerCount); + foreach (var layer in LayersDefinition.Layers) { + progress.Token.ThrowIfCancellationRequested(); string hash = Helpers.ComputeSHA1Hash(layer.EncodedRle); if (LayersHash.TryGetValue(hash, out var layerDataHash)) @@ -884,122 +891,133 @@ namespace UVtools.Core outputFile.Seek(currentOffset, SeekOrigin.Begin); currentOffset += Helpers.SerializeWriteFileStream(outputFile, layer); + + progress++; } // Rewind outputFile.Seek(0, SeekOrigin.Begin); Helpers.SerializeWriteFileStream(outputFile, FileMarkSettings); - } } - public override void Decode(string fileFullPath) + public override void Decode(string fileFullPath, OperationProgress progress = null) { - base.Decode(fileFullPath); + base.Decode(fileFullPath, progress); - var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read); + using (var inputFile = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read)) + { - //HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile); - //HeaderSettings = Helpers.Serializer.Deserialize<Header>(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header)))); - FileMarkSettings = Helpers.Deserialize<FileMark>(inputFile); + //HeaderSettings = Helpers.ByteToType<CbddlpFile.Header>(InputFile); + //HeaderSettings = Helpers.Serializer.Deserialize<Header>(InputFile.ReadBytes(Helpers.Serializer.SizeOf(typeof(Header)))); + FileMarkSettings = Helpers.Deserialize<FileMark>(inputFile); - Debug.Write("FileMark -> "); - Debug.WriteLine(FileMarkSettings); + Debug.Write("FileMark -> "); + Debug.WriteLine(FileMarkSettings); - if (!FileMarkSettings.Mark.Equals(FileMark.SectionMarkFile)) - { - throw new FileLoadException($"Invalid Filemark {FileMarkSettings.Mark}, expected {FileMark.SectionMarkFile}", fileFullPath); - } + if (!FileMarkSettings.Mark.Equals(FileMark.SectionMarkFile)) + { + throw new FileLoadException( + $"Invalid Filemark {FileMarkSettings.Mark}, expected {FileMark.SectionMarkFile}", fileFullPath); + } - if (FileMarkSettings.Version != 1) - { - throw new FileLoadException($"Invalid Version {FileMarkSettings.Version}, expected 1", fileFullPath); - } + if (FileMarkSettings.Version != 1) + { + throw new FileLoadException($"Invalid Version {FileMarkSettings.Version}, expected 1", + fileFullPath); + } - FileFullPath = fileFullPath; + FileFullPath = fileFullPath; - inputFile.Seek(FileMarkSettings.HeaderAddress, SeekOrigin.Begin); - //Section sectionHeader = Helpers.Deserialize<Section>(inputFile); - //Debug.Write("SectionHeader -> "); - //Debug.WriteLine(sectionHeader); + inputFile.Seek(FileMarkSettings.HeaderAddress, SeekOrigin.Begin); + //Section sectionHeader = Helpers.Deserialize<Section>(inputFile); + //Debug.Write("SectionHeader -> "); + //Debug.WriteLine(sectionHeader); - var section = Helpers.Deserialize<Section>(inputFile); - HeaderSettings = Helpers.Deserialize<Header>(inputFile); - HeaderSettings.Section = section; + var section = Helpers.Deserialize<Section>(inputFile); + HeaderSettings = Helpers.Deserialize<Header>(inputFile); + HeaderSettings.Section = section; - Debug.Write("Header -> "); - Debug.WriteLine(HeaderSettings); + Debug.Write("Header -> "); + Debug.WriteLine(HeaderSettings); - HeaderSettings.Validate(); + HeaderSettings.Validate(); - if (FileMarkSettings.PreviewAddress > 0) - { - inputFile.Seek(FileMarkSettings.PreviewAddress, SeekOrigin.Begin); + if (FileMarkSettings.PreviewAddress > 0) + { + inputFile.Seek(FileMarkSettings.PreviewAddress, SeekOrigin.Begin); - section = Helpers.Deserialize<Section>(inputFile); - PreviewSettings = Helpers.Deserialize<Preview>(inputFile); - PreviewSettings.Section = section; - Debug.Write("Preview -> "); - Debug.WriteLine(PreviewSettings); + section = Helpers.Deserialize<Section>(inputFile); + PreviewSettings = Helpers.Deserialize<Preview>(inputFile); + PreviewSettings.Section = section; + Debug.Write("Preview -> "); + Debug.WriteLine(PreviewSettings); - uint datasize = PreviewSettings.Width * PreviewSettings.Height * 2; - PreviewSettings.Validate(datasize); + uint datasize = PreviewSettings.Width * PreviewSettings.Height * 2; + PreviewSettings.Validate(datasize); - PreviewSettings.Data = new byte[datasize]; - inputFile.ReadBytes(PreviewSettings.Data); + PreviewSettings.Data = new byte[datasize]; + inputFile.ReadBytes(PreviewSettings.Data); - Thumbnails[0] = PreviewSettings.Decode(true); - } + Thumbnails[0] = PreviewSettings.Decode(true); + } - inputFile.Seek(FileMarkSettings.LayerDefinitionAddress, SeekOrigin.Begin); + inputFile.Seek(FileMarkSettings.LayerDefinitionAddress, SeekOrigin.Begin); - section = Helpers.Deserialize<Section>(inputFile); - LayersDefinition = Helpers.Deserialize<LayerDefinition>(inputFile); - LayersDefinition.Section = section; - Debug.Write("LayersDefinition -> "); - Debug.WriteLine(LayersDefinition); + section = Helpers.Deserialize<Section>(inputFile); + LayersDefinition = Helpers.Deserialize<LayerDefinition>(inputFile); + LayersDefinition.Section = section; + Debug.Write("LayersDefinition -> "); + Debug.WriteLine(LayersDefinition); - LayerManager = new LayerManager(LayersDefinition.LayersCount); - LayersDefinition.Layers = new LayerData[LayerCount]; - + LayerManager = new LayerManager(LayersDefinition.LayersCount); + LayersDefinition.Layers = new LayerData[LayerCount]; - LayersDefinition.Validate(); - for (int i = 0; i < LayerCount; i++) - { - LayersDefinition[i] = Helpers.Deserialize<LayerData>(inputFile); - LayersDefinition[i].Parent = this; - } + LayersDefinition.Validate(); - for (int i = 0; i < LayerCount; i++) - { - var layer = LayersDefinition[i]; - inputFile.Seek(layer.DataAddress, SeekOrigin.Begin); - layer.EncodedRle = new byte[layer.DataLength]; - inputFile.ReadBytes(layer.EncodedRle); + for (int i = 0; i < LayerCount; i++) + { + LayersDefinition[i] = Helpers.Deserialize<LayerData>(inputFile); + LayersDefinition[i].Parent = this; + } + + progress.Reset(OperationProgress.StatusGatherLayers, LayerCount); + + for (int i = 0; i < LayerCount; i++) + { + var layer = LayersDefinition[i]; + inputFile.Seek(layer.DataAddress, SeekOrigin.Begin); + layer.EncodedRle = new byte[layer.DataLength]; + inputFile.ReadBytes(layer.EncodedRle); + + progress++; + progress.Token.ThrowIfCancellationRequested(); + } - /*if (LayerFormat == LayerRleFormat.PW0) + progress.Reset(OperationProgress.StatusDecodeLayers, LayerCount); + + Parallel.For(0, LayerCount, layerIndex => { - var crcBytes = new byte[2]; - inputFile.Read(crcBytes, 0, 2); - ushort crcExpected = BitConverter.ToUInt16(crcBytes, 0); - ushort crcEncodedRle = LayersDefinition.Layers[i].CRCEncodedRle(); + if (progress.Token.IsCancellationRequested) + { + return; + } + + using (var image = LayersDefinition[(uint) layerIndex].Decode()) + { + this[layerIndex] = new Layer((uint) layerIndex, image); + } - if (crcExpected != crcEncodedRle) + lock (progress.Mutex) { - Debug.WriteLine($"Error: Checksum expected {crcExpected}, got {crcEncodedRle}"); + progress++; } - }*/ + }); } - Parallel.For(0, LayerCount, layerIndex => - { - using (var image = LayersDefinition[(uint) layerIndex].Decode()) - { - this[layerIndex] = new Layer((uint) layerIndex, image); - } - }); + progress.Token.ThrowIfCancellationRequested(); } public override object GetValueFromPrintParameterModifier(PrintParameterModifier modifier) @@ -1074,7 +1092,7 @@ namespace UVtools.Core return false; } - public override void SaveAs(string filePath = null) + public override void SaveAs(string filePath = null, OperationProgress progress = null) { if (LayerManager.IsModified) { @@ -1082,7 +1100,7 @@ namespace UVtools.Core { FileFullPath = filePath; } - Encode(FileFullPath); + Encode(FileFullPath, progress); return; } @@ -1095,7 +1113,6 @@ namespace UVtools.Core using (var outputFile = new FileStream(FileFullPath, FileMode.Open, FileAccess.Write)) { - outputFile.Seek(FileMarkSettings.HeaderAddress+Helpers.Serializer.SizeOf(HeaderSettings.Section), SeekOrigin.Begin); Helpers.SerializeWriteFileStream(outputFile, HeaderSettings); @@ -1105,13 +1122,12 @@ namespace UVtools.Core { Helpers.SerializeWriteFileStream(outputFile, LayersDefinition[layerIndex]); } - outputFile.Close(); } - //Decode(FileFullPath); + //Decode(FileFullPath, progress); } - public override bool Convert(Type to, string fileFullPath) + public override bool Convert(Type to, string fileFullPath, OperationProgress progress = null) { /*if (to == typeof(PHZFile)) { @@ -1155,7 +1171,7 @@ namespace UVtools.Core file.HeaderSettings.MachineNameSize = (uint) MachineName.Length; file.SetThumbnails(Thumbnails); - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } @@ -1242,7 +1258,7 @@ namespace UVtools.Core } file.SetThumbnails(Thumbnails); - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } */ diff --git a/UVtools.Core/SL1File.cs b/UVtools.Core/SL1File.cs index 59d077f..e92f193 100644 --- a/UVtools.Core/SL1File.cs +++ b/UVtools.Core/SL1File.cs @@ -13,6 +13,7 @@ using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; +using System.Threading.Tasks; using Emgu.CV; using Emgu.CV.CvEnum; using UVtools.Core.Extensions; @@ -353,10 +354,6 @@ namespace UVtools.Core #region Contructors public SL1File() { } - public SL1File(string fileFullPath) - { - Decode(fileFullPath); - } #endregion #region Static Methods @@ -394,15 +391,15 @@ namespace UVtools.Core Statistics.Clear(); } - public override void Encode(string fileFullPath) + public override void Encode(string fileFullPath, OperationProgress progress = null) { throw new NotImplementedException(); } - public override void Decode(string fileFullPath) + public override void Decode(string fileFullPath, OperationProgress progress = null) { - base.Decode(fileFullPath); + base.Decode(fileFullPath, progress); FileFullPath = fileFullPath; @@ -451,6 +448,8 @@ namespace UVtools.Core LayerManager = new LayerManager((uint) (OutputConfigSettings.NumSlow + OutputConfigSettings.NumFast)); + progress.ItemCount = LayerCount; + foreach (ZipArchiveEntry entity in inputFile.Entries) { if (!entity.Name.EndsWith(".png")) continue; @@ -459,7 +458,7 @@ namespace UVtools.Core using (Stream stream = entity.Open()) { Mat image = new Mat(); - CvInvoke.Imdecode(stream.ReadBytes(), ImreadModes.AnyColor, image); + CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, image); byte thumbnailIndex = (byte) (image.Width == ThumbnailsOriginalSize[(int) FileThumbnailSize.Small].Width && image.Height == ThumbnailsOriginalSize[(int) FileThumbnailSize.Small].Height @@ -478,10 +477,11 @@ namespace UVtools.Core string layerStr = entity.Name.Substring(entity.Name.Length - 4 - 5, 5); uint iLayer = uint.Parse(layerStr); LayerManager[iLayer] = new Layer(iLayer, entity.Open(), entity.Name); + progress.ProcessedItems++; } } - var rect = LayerManager.BoundingRectangle; + LayerManager.GetBoundingRectangle(progress); Statistics.ExecutionTime.Stop(); @@ -523,7 +523,7 @@ namespace UVtools.Core return false; } - public override void SaveAs(string filePath = null) + public override void SaveAs(string filePath = null, OperationProgress progress = null) { if (!string.IsNullOrEmpty(filePath)) { @@ -536,7 +536,7 @@ namespace UVtools.Core { //InputFile.CreateEntry("Modified"); - using (TextWriter tw = new StreamWriter(outputFile.PutFileContent("config.ini", string.Empty).Open())) + using (TextWriter tw = new StreamWriter(outputFile.PutFileContent("config.ini", string.Empty, ZipArchiveMode.Update).Open())) { var properties = OutputConfigSettings.GetType() .GetProperties(BindingFlags.Public | BindingFlags.Instance); @@ -550,7 +550,7 @@ namespace UVtools.Core tw.Close(); } - using (TextWriter tw = new StreamWriter(outputFile.PutFileContent("prusaslicer.ini", string.Empty).Open())) + using (TextWriter tw = new StreamWriter(outputFile.PutFileContent("prusaslicer.ini", string.Empty, ZipArchiveMode.Update).Open())) { foreach (var config in Configs) { @@ -571,16 +571,16 @@ namespace UVtools.Core foreach (var layer in this) { if (!layer.IsModified) continue; - outputFile.PutFileContent(layer.Filename, layer.CompressedBytes); + outputFile.PutFileContent(layer.Filename, layer.CompressedBytes, ZipArchiveMode.Update); layer.IsModified = false; } } - Decode(FileFullPath); + //Decode(FileFullPath, progress); } - public override bool Convert(Type to, string fileFullPath) + public override bool Convert(Type to, string fileFullPath, OperationProgress progress = null) { if (!IsValid) return false; @@ -606,7 +606,7 @@ namespace UVtools.Core LayerOffTime = LookupCustomValue<float>(Keyword_LayerOffTime, defaultFormat.HeaderSettings.LayerOffTime), LightPWM = LookupCustomValue<ushort>(Keyword_LightPWM, defaultFormat.HeaderSettings.LightPWM), PrintTime = (uint) OutputConfigSettings.PrintTime, - ProjectorType = PrinterSettings.DisplayMirrorX ? 1u : 0u, + ProjectorType = PrinterSettings.DisplayMirrorX || PrinterSettings.DisplayMirrorY ? 1u : 0u, ResolutionX = ResolutionX, ResolutionY = ResolutionY, AntiAliasLevel = ValidateAntiAliasingLevel() @@ -644,7 +644,7 @@ namespace UVtools.Core } file.SetThumbnails(Thumbnails); - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } @@ -665,13 +665,13 @@ namespace UVtools.Core MachineY = PrinterSettings.DisplayHeight, MachineZ = PrinterSettings.MaxPrintHeight, MachineType = MachineName, - ProjectType = PrinterSettings.DisplayMirrorX ? "LCD_mirror" : "Normal", + ProjectType = PrinterSettings.DisplayMirrorX || PrinterSettings.DisplayMirrorY ? "LCD_mirror" : "Normal", Resin = MaterialName, Price = MaterialCost, Weight = (float) Math.Round(UsedMaterial * MaterialSettings.MaterialDensity, 2), Volume = UsedMaterial, - Mirror = (byte) (PrinterSettings.DisplayMirrorX ? 1 : 0), + Mirror = (byte) (PrinterSettings.DisplayMirrorX || PrinterSettings.DisplayMirrorY ? 1 : 0), BottomLayerLiftHeight = LookupCustomValue<float>(Keyword_BottomLiftHeight, defaultFormat.HeaderSettings.BottomLayerLiftHeight), @@ -704,7 +704,7 @@ namespace UVtools.Core } file.SetThumbnails(Thumbnails); - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } @@ -742,7 +742,7 @@ namespace UVtools.Core } file.SetThumbnails(Thumbnails); - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } @@ -769,7 +769,7 @@ namespace UVtools.Core LayerOffTime = LookupCustomValue<float>(Keyword_LayerOffTime, defaultFormat.HeaderSettings.LayerOffTime), LightPWM = LookupCustomValue<ushort>(Keyword_LightPWM, defaultFormat.HeaderSettings.LightPWM), PrintTime = (uint) OutputConfigSettings.PrintTime, - ProjectorType = PrinterSettings.DisplayMirrorX ? 1u : 0u, + ProjectorType = PrinterSettings.DisplayMirrorX || PrinterSettings.DisplayMirrorY ? 1u : 0u, ResolutionX = PrinterSettings.DisplayPixelsX, ResolutionY = PrinterSettings.DisplayPixelsY, BottomLayerCount = PrintSettings.FadedLayers, @@ -795,7 +795,7 @@ namespace UVtools.Core } file.SetThumbnails(Thumbnails); - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } @@ -832,7 +832,7 @@ namespace UVtools.Core LayerThickness = $"{LayerHeight} mm", AntiAliasing = (byte) (ValidateAntiAliasingLevel() > 1 ? 1 : 0), CrossSupportEnabled = 1, - ExposureOffTime = LookupCustomValue<uint>(Keyword_LayerOffTime, defaultFormat.UserSettings.ExposureOffTime) *1000, + ExposureOffTime = LookupCustomValue<uint>(Keyword_LayerOffTime, defaultFormat.UserSettings.ExposureOffTime) * 1000, HollowEnabled = PrintSettings.HollowingEnable ? (byte)1 : (byte)0, HollowThickness = PrintSettings.HollowingMinThickness, InfillDensity = 0, @@ -883,7 +883,7 @@ namespace UVtools.Core } file.SetThumbnails(Thumbnails); - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } @@ -932,7 +932,7 @@ namespace UVtools.Core file.SliceSettings.Yres = file.OutputSettings.YResolution = (ushort) ResolutionX; } - file.Encode(fileFullPath); + file.Encode(fileFullPath, progress); return true; } diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index 768e0b6..89b5bb2 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, repair, conversion and manipulation</Description> - <Version>0.6.0.1</Version> + <Version>0.6.0.2</Version> <Copyright>Copyright © 2020 PTRTECH</Copyright> <PackageIcon>UVtools.png</PackageIcon> </PropertyGroup> diff --git a/UVtools.Core/ZCodexFile.cs b/UVtools.Core/ZCodexFile.cs index b173259..cf7803e 100644 --- a/UVtools.Core/ZCodexFile.cs +++ b/UVtools.Core/ZCodexFile.cs @@ -137,9 +137,9 @@ namespace UVtools.Core #endregion #region Properties - public ResinMetadata ResinMetadataSettings { get; set; } - public UserSettingsdata UserSettings { get; set; } - public ZCodeMetadata ZCodeMetadataSettings { get; set; } + public ResinMetadata ResinMetadataSettings { get; set; } = new ResinMetadata(); + public UserSettingsdata UserSettings { get; set; } = new UserSettingsdata(); + public ZCodeMetadata ZCodeMetadataSettings { get; set; } = new ZCodeMetadata(); public List<LayerData> LayersSettings { get; } = new List<LayerData>(); @@ -205,15 +205,14 @@ namespace UVtools.Core LayersSettings.Clear(); } - public override void Encode(string fileFullPath) + public override void Encode(string fileFullPath, OperationProgress progress = null) { - base.Encode(fileFullPath); + base.Encode(fileFullPath, progress); using (ZipArchive outputFile = ZipFile.Open(fileFullPath, ZipArchiveMode.Create)) { - - outputFile.PutFileContent("ResinMetadata", JsonConvert.SerializeObject(ResinMetadataSettings)); - outputFile.PutFileContent("UserSettingsData", JsonConvert.SerializeObject(UserSettings)); - outputFile.PutFileContent("ZCodeMetadata", JsonConvert.SerializeObject(ZCodeMetadataSettings)); + outputFile.PutFileContent("ResinMetadata", JsonConvert.SerializeObject(ResinMetadataSettings), ZipArchiveMode.Create); + outputFile.PutFileContent("UserSettingsData", JsonConvert.SerializeObject(UserSettings), ZipArchiveMode.Create); + outputFile.PutFileContent("ZCodeMetadata", JsonConvert.SerializeObject(ZCodeMetadataSettings), ZipArchiveMode.Create); if (CreatedThumbnailsCount > 0) { @@ -230,6 +229,8 @@ namespace UVtools.Core for (uint layerIndex = 0; layerIndex < LayerCount; layerIndex++) { + progress.Token.ThrowIfCancellationRequested(); + GCode.AppendLine($"{GCodeKeywordSlice} {layerIndex}"); GCode.AppendLine($"G1 Z{LiftHeight} F{LiftSpeed}"); GCode.AppendLine($"G1 Z-{LiftHeight - LayerHeight} F{RetractSpeed}"); @@ -247,18 +248,20 @@ namespace UVtools.Core stream.Write(byteArr, 0, byteArr.Length); stream.Close(); } + + progress++; } GCode.AppendLine($"G1 Z40.0 F{UserSettings.ZLiftFeedRate}"); GCode.AppendLine("M18"); - outputFile.PutFileContent("ResinGCodeData", GCode.ToString()); + outputFile.PutFileContent("ResinGCodeData", GCode.ToString(), ZipArchiveMode.Create); } } - public override void Decode(string fileFullPath) + public override void Decode(string fileFullPath, OperationProgress progress = null) { - base.Decode(fileFullPath); + base.Decode(fileFullPath, progress); FileFullPath = fileFullPath; using (var inputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Read)) @@ -341,13 +344,14 @@ namespace UVtools.Core { using (Stream stream = entry.Open()) { - CvInvoke.Imdecode(stream.ReadBytes(), ImreadModes.AnyColor, Thumbnails[0]); + + CvInvoke.Imdecode(stream.ToArray(), ImreadModes.AnyColor, Thumbnails[0]); stream.Close(); } } } - var rect = LayerManager.BoundingRectangle; + LayerManager.GetBoundingRectangle(progress); } public override bool SetValueFromPrintParameterModifier(PrintParameterModifier modifier, string value) @@ -393,7 +397,7 @@ namespace UVtools.Core return false; } - public override void SaveAs(string filePath = null) + public override void SaveAs(string filePath = null, OperationProgress progress = null) { if (!string.IsNullOrEmpty(filePath)) { @@ -404,23 +408,23 @@ namespace UVtools.Core using (var outputFile = ZipFile.Open(FileFullPath, ZipArchiveMode.Update)) { - outputFile.PutFileContent("ResinMetadata", JsonConvert.SerializeObject(ResinMetadataSettings)); - outputFile.PutFileContent("UserSettingsData", JsonConvert.SerializeObject(UserSettings)); - outputFile.PutFileContent("ZCodeMetadata", JsonConvert.SerializeObject(ZCodeMetadataSettings)); - outputFile.PutFileContent("ResinGCodeData", GCode.ToString()); + outputFile.PutFileContent("ResinMetadata", JsonConvert.SerializeObject(ResinMetadataSettings), ZipArchiveMode.Update); + outputFile.PutFileContent("UserSettingsData", JsonConvert.SerializeObject(UserSettings), ZipArchiveMode.Update); + outputFile.PutFileContent("ZCodeMetadata", JsonConvert.SerializeObject(ZCodeMetadataSettings), ZipArchiveMode.Update); + outputFile.PutFileContent("ResinGCodeData", GCode.ToString(), ZipArchiveMode.Update); foreach (var layer in this) { if (!layer.IsModified) continue; - outputFile.PutFileContent(layer.Filename, layer.CompressedBytes); + outputFile.PutFileContent(layer.Filename, layer.CompressedBytes, ZipArchiveMode.Update); layer.IsModified = false; } } - //Decode(FileFullPath); + //Decode(FileFullPath, progress); } - public override bool Convert(Type to, string fileFullPath) + public override bool Convert(Type to, string fileFullPath, OperationProgress progress = null) { throw new NotImplementedException(); } diff --git a/UVtools.GUI/Forms/FrmLoading.Designer.cs b/UVtools.GUI/Forms/FrmLoading.Designer.cs index ebb59d5..35d2f11 100644 --- a/UVtools.GUI/Forms/FrmLoading.Designer.cs +++ b/UVtools.GUI/Forms/FrmLoading.Designer.cs @@ -36,15 +36,19 @@ this.lbElapsedTime = new System.Windows.Forms.Label(); this.lbWait = new System.Windows.Forms.Label(); this.panel1 = new System.Windows.Forms.Panel(); + this.lbOperation = new System.Windows.Forms.Label(); + this.panel2 = new System.Windows.Forms.Panel(); + this.btnCancel = new System.Windows.Forms.Button(); this.panel1.SuspendLayout(); + this.panel2.SuspendLayout(); this.SuspendLayout(); // // progressBar // - this.progressBar.Dock = System.Windows.Forms.DockStyle.Bottom; - this.progressBar.Location = new System.Drawing.Point(0, 72); + this.progressBar.Dock = System.Windows.Forms.DockStyle.Left; + this.progressBar.Location = new System.Drawing.Point(0, 0); this.progressBar.Name = "progressBar"; - this.progressBar.Size = new System.Drawing.Size(430, 23); + this.progressBar.Size = new System.Drawing.Size(374, 29); this.progressBar.Style = System.Windows.Forms.ProgressBarStyle.Marquee; this.progressBar.TabIndex = 0; // @@ -53,7 +57,7 @@ this.lbDescription.AutoSize = true; this.lbDescription.Location = new System.Drawing.Point(3, 12); this.lbDescription.Name = "lbDescription"; - this.lbDescription.Size = new System.Drawing.Size(60, 13); + this.lbDescription.Size = new System.Drawing.Size(83, 18); this.lbDescription.TabIndex = 1; this.lbDescription.Text = "Description"; // @@ -68,40 +72,70 @@ this.lbElapsedTime.AutoSize = true; this.lbElapsedTime.Location = new System.Drawing.Point(3, 39); this.lbElapsedTime.Name = "lbElapsedTime"; - this.lbElapsedTime.Size = new System.Drawing.Size(30, 13); + this.lbElapsedTime.Size = new System.Drawing.Size(41, 18); this.lbElapsedTime.TabIndex = 2; this.lbElapsedTime.Text = "Time"; // // lbWait // - this.lbWait.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); + this.lbWait.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.lbWait.AutoSize = true; - this.lbWait.Location = new System.Drawing.Point(334, 39); + this.lbWait.Location = new System.Drawing.Point(362, 39); this.lbWait.Name = "lbWait"; - this.lbWait.Size = new System.Drawing.Size(70, 13); + this.lbWait.Size = new System.Drawing.Size(95, 18); this.lbWait.TabIndex = 3; this.lbWait.Text = "Please wait..."; // // panel1 // this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.panel1.Controls.Add(this.lbOperation); this.panel1.Controls.Add(this.lbDescription); this.panel1.Controls.Add(this.lbWait); this.panel1.Controls.Add(this.lbElapsedTime); - this.panel1.Controls.Add(this.progressBar); + this.panel1.Controls.Add(this.panel2); this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.panel1.Location = new System.Drawing.Point(0, 0); this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(432, 97); + this.panel1.Size = new System.Drawing.Size(470, 124); this.panel1.TabIndex = 4; // + // lbOperation + // + this.lbOperation.Dock = System.Windows.Forms.DockStyle.Bottom; + this.lbOperation.Location = new System.Drawing.Point(0, 67); + this.lbOperation.Name = "lbOperation"; + this.lbOperation.Size = new System.Drawing.Size(468, 26); + this.lbOperation.TabIndex = 4; + this.lbOperation.Text = "Operation"; + this.lbOperation.TextAlign = System.Drawing.ContentAlignment.TopCenter; + // + // panel2 + // + this.panel2.Controls.Add(this.btnCancel); + this.panel2.Controls.Add(this.progressBar); + this.panel2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.panel2.Location = new System.Drawing.Point(0, 93); + this.panel2.Name = "panel2"; + this.panel2.Size = new System.Drawing.Size(468, 29); + this.panel2.TabIndex = 5; + // + // btnCancel + // + this.btnCancel.Dock = System.Windows.Forms.DockStyle.Fill; + this.btnCancel.Location = new System.Drawing.Point(374, 0); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.Size = new System.Drawing.Size(94, 29); + this.btnCancel.TabIndex = 1; + this.btnCancel.Text = "Cancel"; + this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); + // // FrmLoading // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(432, 97); + this.ClientSize = new System.Drawing.Size(470, 124); this.ControlBox = false; this.Controls.Add(this.panel1); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; @@ -116,6 +150,7 @@ this.Text = "Loading"; this.panel1.ResumeLayout(false); this.panel1.PerformLayout(); + this.panel2.ResumeLayout(false); this.ResumeLayout(false); } @@ -128,5 +163,8 @@ private System.Windows.Forms.Label lbElapsedTime; private System.Windows.Forms.Label lbWait; private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label lbOperation; + private System.Windows.Forms.Panel panel2; + private System.Windows.Forms.Button btnCancel; } }
\ No newline at end of file diff --git a/UVtools.GUI/Forms/FrmLoading.cs b/UVtools.GUI/Forms/FrmLoading.cs index 71a4942..9774a9f 100644 --- a/UVtools.GUI/Forms/FrmLoading.cs +++ b/UVtools.GUI/Forms/FrmLoading.cs @@ -1,12 +1,26 @@ using System; using System.Diagnostics; +using System.Threading.Tasks; using System.Windows.Forms; +using UVtools.Core; namespace UVtools.GUI.Forms { public partial class FrmLoading : Form { public Stopwatch StopWatch { get; } = new Stopwatch(); + public OperationProgress Progress { get; set; } + + //public Task RunningTask { get; set; } + + public string Description + { + get => Text; + set => Text = lbDescription.Text = value; + } + + public bool CanCancel => Progress?.CanCancel ?? false; + public FrmLoading() { InitializeComponent(); @@ -38,8 +52,15 @@ namespace UVtools.GUI.Forms protected override void OnShown(EventArgs e) { base.OnShown(e); + lbOperation.Text = string.Empty; + progressBar.Style = ProgressBarStyle.Marquee; + progressBar.Step = 10; StopWatch.Restart(); + timer_Tick(timer, null); timer.Start(); + + btnCancel.Enabled = CanCancel; + btnCancel.Text = "Cancel"; } protected override void OnClosed(EventArgs e) @@ -47,6 +68,13 @@ namespace UVtools.GUI.Forms base.OnClosed(e); timer.Stop(); StopWatch.Stop(); + Progress = null; + } + + public OperationProgress RestartProgress(bool canCancel = true) + { + Progress = new OperationProgress(canCancel); + return Progress; } public void SetDescription(string description) @@ -63,7 +91,30 @@ namespace UVtools.GUI.Forms private void timer_Tick(object sender, EventArgs e) { - lbElapsedTime.Text = $"Elapsed Time: {StopWatch.ElapsedMilliseconds}ms"; + var ts = TimeSpan.FromMilliseconds(StopWatch.ElapsedMilliseconds); + lbElapsedTime.Text = $"Elapsed Time: {ts.Minutes}m {ts.Seconds}s {ts.Milliseconds}ms"; + btnCancel.Enabled = CanCancel; + if (ReferenceEquals(Progress, null)) return; + + lbOperation.Text = Progress.ToString(); + if (Progress.ItemCount == 0) + { + progressBar.Style = ProgressBarStyle.Marquee; + progressBar.Step = 10; + } + else + { + SetProgress(Progress.ProgressStep); + } + } + + private void btnCancel_Click(object sender, EventArgs e) + { + if (ReferenceEquals(Progress, null) || Progress.TokenSource.IsCancellationRequested) return; + Progress.TokenSource.Cancel(); + Progress.CanCancel = false; + btnCancel.Enabled = false; + btnCancel.Text = "Canceling..."; } } } diff --git a/UVtools.GUI/Forms/FrmMutation.cs b/UVtools.GUI/Forms/FrmMutation.cs index be92c0e..e8ba854 100644 --- a/UVtools.GUI/Forms/FrmMutation.cs +++ b/UVtools.GUI/Forms/FrmMutation.cs @@ -88,7 +88,7 @@ namespace UVtools.GUI.Forms false; } - Text = $"Mutate: {mutation.Mutate}"; + Text = $"Mutate: {mutation.MenuName}"; lbDescription.Text = Mutation.Description; if (ReferenceEquals(mutation.Image, null)) diff --git a/UVtools.GUI/Forms/FrmMutationOneComoboBox.cs b/UVtools.GUI/Forms/FrmMutationOneComoboBox.cs index b68012f..a1467e6 100644 --- a/UVtools.GUI/Forms/FrmMutationOneComoboBox.cs +++ b/UVtools.GUI/Forms/FrmMutationOneComoboBox.cs @@ -50,7 +50,7 @@ namespace UVtools.GUI.Forms Mutation = mutation; DialogResult = DialogResult.Cancel; - Text = $"Mutate: {mutation.Mutate}"; + Text = $"Mutate: {mutation.MenuName}"; lbDescription.Text = Mutation.Description; nmLayerRangeEnd.Value = Program.SlicerFile.LayerCount-1; diff --git a/UVtools.GUI/Forms/FrmMutationOneNumericalInput.cs b/UVtools.GUI/Forms/FrmMutationOneNumericalInput.cs index a44bc21..e874f24 100644 --- a/UVtools.GUI/Forms/FrmMutationOneNumericalInput.cs +++ b/UVtools.GUI/Forms/FrmMutationOneNumericalInput.cs @@ -44,7 +44,7 @@ namespace UVtools.GUI.Forms Mutation = mutation; DialogResult = DialogResult.Cancel; - Text = $"Mutate: {mutation.Mutate}"; + Text = $"Mutate: {mutation.MenuName}"; lbDescription.Text = Mutation.Description; nmLayerRangeEnd.Value = Program.SlicerFile.LayerCount-1; diff --git a/UVtools.GUI/Forms/FrmMutationResize.cs b/UVtools.GUI/Forms/FrmMutationResize.cs index 0260726..ae8edc5 100644 --- a/UVtools.GUI/Forms/FrmMutationResize.cs +++ b/UVtools.GUI/Forms/FrmMutationResize.cs @@ -63,7 +63,7 @@ namespace UVtools.GUI.Forms nmX.Select(); - Text = $"Mutate: {mutation.Mutate}"; + Text = $"Mutate: {mutation.MenuName}"; lbDescription.Text = Mutation.Description; nmLayerRangeEnd.Value = Program.SlicerFile.LayerCount-1; diff --git a/UVtools.GUI/FrmMain.cs b/UVtools.GUI/FrmMain.cs index c591651..11e6159 100644 --- a/UVtools.GUI/FrmMain.cs +++ b/UVtools.GUI/FrmMain.cs @@ -37,40 +37,40 @@ namespace UVtools.GUI public static readonly Dictionary<LayerManager.Mutate, Mutation> Mutations = new Dictionary<LayerManager.Mutate, Mutation> { - {LayerManager.Mutate.Resize, new Mutation(LayerManager.Mutate.Resize, + {LayerManager.Mutate.Resize, new Mutation(LayerManager.Mutate.Resize, null, "Resizes layer images in a X and/or Y factor, starting from 100% value\n" + "NOTE 1: Build volume bounds are not validated after operation, please ensure scaling stays inside your limits.\n" + "NOTE 2: X and Y are applied to original image, not to the rotated preview (If enabled)." )}, - {LayerManager.Mutate.Flip, new Mutation(LayerManager.Mutate.Flip, + {LayerManager.Mutate.Flip, new Mutation(LayerManager.Mutate.Flip, null, "Flips layer images vertically and/or horizontally" )}, - {LayerManager.Mutate.Rotate, new Mutation(LayerManager.Mutate.Rotate, + {LayerManager.Mutate.Rotate, new Mutation(LayerManager.Mutate.Rotate, null, "Rotate layer images in a certain degrees" )}, - {LayerManager.Mutate.Solidify, new Mutation(LayerManager.Mutate.Solidify, + {LayerManager.Mutate.Solidify, new Mutation(LayerManager.Mutate.Solidify, null, "Solidifies the selected layers, closes all inner holes.\n" + "Warning: All surrounded holes are filled, no exceptions! Make sure you don't require any of holes in layer path.", Properties.Resources.mutation_solidify )}, - {LayerManager.Mutate.Erode, new Mutation(LayerManager.Mutate.Erode, + {LayerManager.Mutate.Erode, new Mutation(LayerManager.Mutate.Erode, null, "The basic idea of erosion is just like soil erosion only, it erodes away the boundaries of foreground object (Always try to keep foreground in white). " + "So what happends is that, all the pixels near boundary will be discarded depending upon the size of kernel. So the thickness or size of the foreground object decreases or simply white region decreases in the image. It is useful for removing small white noises, detach two connected objects, etc.", Properties.Resources.mutation_erosion )}, - {LayerManager.Mutate.Dilate, new Mutation(LayerManager.Mutate.Dilate, + {LayerManager.Mutate.Dilate, new Mutation(LayerManager.Mutate.Dilate, null, "It is just opposite of erosion. Here, a pixel element is '1' if atleast one pixel under the kernel is '1'. So it increases the white region in the image or size of foreground object increases. Normally, in cases like noise removal, erosion is followed by dilation. Because, erosion removes white noises, but it also shrinks our object. So we dilate it. Since noise is gone, they won't come back, but our object area increases. It is also useful in joining broken parts of an object.", - Properties.Resources.mutation_dilation + Resources.mutation_dilation )}, - {LayerManager.Mutate.Opening, new Mutation(LayerManager.Mutate.Opening, - "Opening is just another name of erosion followed by dilation. It is useful in removing noise.", + {LayerManager.Mutate.Opening, new Mutation(LayerManager.Mutate.Opening, "Noise Removal", + "Noise Removal/Opening is just another name of erosion followed by dilation. It is useful in removing noise.", Properties.Resources.mutation_opening )}, - {LayerManager.Mutate.Closing, new Mutation(LayerManager.Mutate.Closing, - "Closing is reverse of Opening, Dilation followed by Erosion. It is useful in closing small holes inside the foreground objects, or small black points on the object.", + {LayerManager.Mutate.Closing, new Mutation(LayerManager.Mutate.Closing, "Gap Closing", + "Gap Closing is reverse of Opening, Dilation followed by Erosion. It is useful in closing small holes inside the foreground objects, or small black points on the object.", Properties.Resources.mutation_closing )}, - {LayerManager.Mutate.Gradient, new Mutation(LayerManager.Mutate.Gradient, + {LayerManager.Mutate.Gradient, new Mutation(LayerManager.Mutate.Gradient, null, "It's the difference between dilation and erosion of an image.", Properties.Resources.mutation_gradient )}, @@ -86,16 +86,16 @@ namespace UVtools.GUI "The Hit-or-Miss transformation is useful to find patterns in binary images. In particular, it finds those pixels whose neighbourhood matches the shape of a first structuring element B1 while not matching the shape of a second structuring element B2 at the same time.", null )},*/ - {LayerManager.Mutate.PyrDownUp, new Mutation(LayerManager.Mutate.PyrDownUp, + {LayerManager.Mutate.PyrDownUp, new Mutation(LayerManager.Mutate.PyrDownUp, null, "Performs downsampling step of Gaussian pyramid decomposition.\n" + "First it convolves image with the specified filter and then downsamples the image by rejecting even rows and columns.\n" + "After performs up-sampling step of Gaussian pyramid decomposition\n" )}, - {LayerManager.Mutate.SmoothMedian, new Mutation(LayerManager.Mutate.SmoothMedian, + {LayerManager.Mutate.SmoothMedian, new Mutation(LayerManager.Mutate.SmoothMedian, "Smooth Median", "Each pixel becomes the median of its surrounding pixels. Also a good way to remove noise.\n" + "Note: Iterations must be a odd number." )}, - {LayerManager.Mutate.SmoothGaussian, new Mutation(LayerManager.Mutate.SmoothGaussian, + {LayerManager.Mutate.SmoothGaussian, new Mutation(LayerManager.Mutate.SmoothGaussian, "Smooth Gaussian", "Each pixel is a sum of fractions of each pixel in its neighborhood\n" + "Very fast, but does not preserve sharp edges well.\n" + "Note: Iterations must be a odd number." @@ -162,7 +162,7 @@ namespace UVtools.GUI foreach (LayerManager.Mutate mutate in (LayerManager.Mutate[])Enum.GetValues(typeof(LayerManager.Mutate))) { if(!Mutations.ContainsKey(mutate)) continue; - var item = new ToolStripMenuItem(mutate.ToString()) + var item = new ToolStripMenuItem(Mutations[mutate].MenuName) { ToolTipText = Mutations[mutate].Description, Tag = mutate, AutoToolTip = true, Image = Properties.Resources.filter_filled_16x16 }; @@ -177,6 +177,8 @@ namespace UVtools.GUI lvIssues.Groups.Add(group); } + tbLayer.MouseWheel += TbLayerOnMouseWheel; + if (Settings.Default.CheckForUpdatesOnStartup) { Task.Factory.StartNew(AppLoadTask); @@ -403,9 +405,13 @@ namespace UVtools.GUI bool result = false; try { - SlicerFile.Save(); + SlicerFile.Save(FrmLoading.RestartProgress()); result = true; } + catch (OperationCanceledException) + { + + } catch (Exception ex) { MessageBox.Show(ex.Message, "Error while saving the file", MessageBoxButtons.OK, @@ -449,9 +455,13 @@ namespace UVtools.GUI bool result = false; try { - SlicerFile.SaveAs(dialog.FileName); + SlicerFile.SaveAs(dialog.FileName, FrmLoading.RestartProgress()); result = true; } + catch (OperationCanceledException) + { + + } catch (Exception ex) { MessageBox.Show(ex.Message, "Error while saving the file", MessageBoxButtons.OK, @@ -542,15 +552,28 @@ namespace UVtools.GUI var task = Task.Factory.StartNew(() => { - SlicerFile.Extract(finalPath); - Invoke((MethodInvoker) delegate + try { - // Running on the UI thread - EnableGUI(true); - }); + SlicerFile.Extract(finalPath, true, true, FrmLoading.RestartProgress()); + } + catch (OperationCanceledException) + { + + } + finally + { + Invoke((MethodInvoker)delegate { + // Running on the UI thread + EnableGUI(true); + }); + } }); - FrmLoading.ShowDialog(); + var loadingResult = FrmLoading.ShowDialog(); + /*if (loadingResult != DialogResult.OK) + { + return; + }*/ if (MessageBox.Show( $"Extraction was successful ({FrmLoading.StopWatch.ElapsedMilliseconds / 1000}s), browser folder to see it contents.\n{finalPath}\nPress 'Yes' if you want open the target folder, otherwise select 'No' to continue.", @@ -640,15 +663,18 @@ namespace UVtools.GUI } DisableGUI(); - FrmLoading.SetDescription("Reparing Layers and Issues"); + FrmLoading.SetDescription("Repairing Layers and Issues"); - Task<bool> task = Task<bool>.Factory.StartNew(() => + var task = Task.Factory.StartNew(() => { - bool result = false; try { - SlicerFile.LayerManager.RepairLayers(layerStart, layerEnd, closingIterations, openingIterations, repairIslands, repairResinTraps, Issues); - result = true; + SlicerFile.LayerManager.RepairLayers(layerStart, layerEnd, closingIterations, + openingIterations, repairIslands, repairResinTraps, Issues, FrmLoading.RestartProgress()); + } + catch (OperationCanceledException) + { + } catch (Exception ex) { @@ -662,11 +688,14 @@ namespace UVtools.GUI EnableGUI(true); }); } - - return result; }); - FrmLoading.ShowDialog(); + var loadingResult = FrmLoading.ShowDialog(); + /*if (loadingResult != DialogResult.OK) + { + return; + }*/ + ShowLayer(); @@ -724,7 +753,7 @@ namespace UVtools.GUI return; } } - + using (FrmInstallPEProfiles form = new FrmInstallPEProfiles()) { form.ShowDialog(); @@ -736,7 +765,15 @@ namespace UVtools.GUI if (ReferenceEquals(sender, menuNewVersion)) { - using (Process.Start(menuNewVersion.Tag.ToString())) { } + try + { + using (Process.Start(menuNewVersion.Tag.ToString())) { } + } + catch (Exception exception) + { + Debug.WriteLine(exception); + } + return; } @@ -951,7 +988,9 @@ namespace UVtools.GUI DisableGUI(); FrmLoading.SetDescription("Removing selected issues"); + var progress = FrmLoading.RestartProgress(false); + progress.Reset("Removing selected issues", (uint) processIssues.Count); Task<bool> task = Task<bool>.Factory.StartNew(() => { bool result = false; @@ -959,6 +998,7 @@ namespace UVtools.GUI { Parallel.ForEach(processIssues, layerIssues => { + if (progress.Token.IsCancellationRequested) return; using (var image = SlicerFile[layerIssues.Key].LayerMat) { var bytes = image.GetPixelSpan<byte>(); @@ -990,10 +1030,14 @@ namespace UVtools.GUI } - if (!edited) return; - SlicerFile[layerIssues.Key].LayerMat = image; - result = true; + if (edited) + { + SlicerFile[layerIssues.Key].LayerMat = image; + result = true; + } } + + progress++; }); } catch (Exception ex) @@ -1189,12 +1233,15 @@ namespace UVtools.GUI DisableGUI(); FrmLoading.SetDescription($"Converting {Path.GetFileName(SlicerFile.FileFullPath)} to {Path.GetExtension(dialog.FileName)}"); - Task<bool> task = Task<bool>.Factory.StartNew(() => + Task task = Task.Factory.StartNew(() => { - bool result = false; try { - result = SlicerFile.Convert(fileFormat, dialog.FileName); + SlicerFile.Convert(fileFormat, dialog.FileName, FrmLoading.RestartProgress()); + } + catch (OperationCanceledException) + { + } catch (Exception ex) { @@ -1207,13 +1254,9 @@ namespace UVtools.GUI EnableGUI(true); }); } - - return result; }); - FrmLoading.ShowDialog(); - - if (task.Result) + if (FrmLoading.ShowDialog() == DialogResult.OK) { if (MessageBox.Show($"Convertion is completed: {Path.GetFileName(dialog.FileName)} in {FrmLoading.StopWatch.ElapsedMilliseconds / 1000}s\n" + "Do you want open the converted file in a new window?", @@ -1225,6 +1268,18 @@ namespace UVtools.GUI } else { + try + { + if (File.Exists(dialog.FileName)) + { + File.Delete(dialog.FileName); + } + } + catch (Exception ex) + { + Debug.WriteLine(ex); + } + //MessageBox.Show("Convertion was unsuccessful! Maybe not implemented...", "Convertion unsuccessful", MessageBoxButtons.OK, MessageBoxIcon.Error); } } @@ -1327,6 +1382,20 @@ namespace UVtools.GUI } } + + private void TbLayerOnMouseWheel(object sender, MouseEventArgs e) + { + ((HandledMouseEventArgs)e).Handled = true; + if (!tbLayer.Enabled) return; + if (e.Delta > 0) + { + ShowLayer(true); + } + else if (e.Delta < 0) + { + ShowLayer(false); + } + } #endregion #region Methods @@ -1438,7 +1507,19 @@ namespace UVtools.GUI void EnableGUI(bool closeLoading = false) { - if(closeLoading) FrmLoading.Close(); + if (closeLoading) + { + if (ReferenceEquals(FrmLoading.Progress, null)) + { + FrmLoading.DialogResult = DialogResult.OK; + } + else + { + FrmLoading.DialogResult = FrmLoading.Progress.Token.IsCancellationRequested ? DialogResult.Cancel : DialogResult.OK; + } + + //FrmLoading.Close(); + } mainTable.Enabled = menu.Enabled = true; @@ -1476,20 +1557,34 @@ namespace UVtools.GUI if (ReferenceEquals(SlicerFile, null)) return; DisableGUI(); - FrmLoading.SetDescription($"Loading {Path.GetFileName(fileName)}"); - + FrmLoading.Description = $"Decoding {Path.GetFileName(fileName)}"; + var task = Task.Factory.StartNew(() => { - SlicerFile.Decode(fileName); - Invoke((MethodInvoker)delegate { - // Running on the UI thread - EnableGUI(true); - }); + try + { + SlicerFile.Decode(fileName, FrmLoading.RestartProgress()); + } + catch (OperationCanceledException) + { + SlicerFile.Clear(); + } + finally + { + Invoke((MethodInvoker)delegate { + // Running on the UI thread + EnableGUI(true); + }); + } }); - FrmLoading.ShowDialog(); - - if (SlicerFile.LayerCount == 0) + var loadingResult = FrmLoading.ShowDialog(); + if (loadingResult != DialogResult.OK) + { + return; + } + + if (SlicerFile.LayerCount == 0 ) { MessageBox.Show("It seens the file don't have any layer, the causes can be:\n" + "- Empty\n" + @@ -1497,7 +1592,7 @@ namespace UVtools.GUI "- Lacking a sliced model\n" + "- A programing internal error\n\n" + "Please check your file and retry", "Error reading the file - Lacking of layers", MessageBoxButtons.OK, MessageBoxIcon.Error); - Clear(); + //Clear(); return; } @@ -2292,17 +2387,17 @@ namespace UVtools.GUI DisableGUI(); - FrmLoading.SetDescription($"Mutating - {mutator}"); + FrmLoading.SetDescription($"Mutating - {Mutations[mutator].MenuName}"); + var progress = FrmLoading.RestartProgress(); - Task<bool> task = Task<bool>.Factory.StartNew(() => + var task = Task.Factory.StartNew(() => { - bool result = false; try { switch (mutator) { case LayerManager.Mutate.Resize: - SlicerFile.LayerManager.MutateResize(layerStart, layerEnd, x / 100.0, y / 100.0, fade); + SlicerFile.LayerManager.MutateResize(layerStart, layerEnd, x / 100.0, y / 100.0, fade, progress); break; case LayerManager.Mutate.Flip: FlipType flipType = FlipType.Horizontal; @@ -2318,28 +2413,28 @@ namespace UVtools.GUI flipType = FlipType.Horizontal | FlipType.Vertical; break; } - SlicerFile.LayerManager.MutateFlip(layerStart, layerEnd, flipType, fade); + SlicerFile.LayerManager.MutateFlip(layerStart, layerEnd, flipType, fade, progress); break; case LayerManager.Mutate.Rotate: - SlicerFile.LayerManager.MutateRotate(layerStart, layerEnd, x); + SlicerFile.LayerManager.MutateRotate(layerStart, layerEnd, x, Inter.Linear, progress); break; case LayerManager.Mutate.Solidify: - SlicerFile.LayerManager.MutateSolidify(layerStart, layerEnd); + SlicerFile.LayerManager.MutateSolidify(layerStart, layerEnd, progress); break; case LayerManager.Mutate.Erode: - SlicerFile.LayerManager.MutateErode(layerStart, layerEnd, (int) iterationsStart, (int) iterationsEnd, fade); + SlicerFile.LayerManager.MutateErode(layerStart, layerEnd, (int) iterationsStart, (int) iterationsEnd, fade, progress); break; case LayerManager.Mutate.Dilate: - SlicerFile.LayerManager.MutateDilate(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade); + SlicerFile.LayerManager.MutateDilate(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade, progress); break; case LayerManager.Mutate.Opening: - SlicerFile.LayerManager.MutateOpen(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade); + SlicerFile.LayerManager.MutateOpen(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade, progress); break; case LayerManager.Mutate.Closing: - SlicerFile.LayerManager.MutateClose(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade); + SlicerFile.LayerManager.MutateClose(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade, progress); break; case LayerManager.Mutate.Gradient: - SlicerFile.LayerManager.MutateGradient(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade); + SlicerFile.LayerManager.MutateGradient(layerStart, layerEnd, (int)iterationsStart, (int)iterationsEnd, fade, progress); break; /*case Mutation.Mutates.TopHat: kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(9, 9), @@ -2358,21 +2453,23 @@ namespace UVtools.GUI new Point(-1, -1), (int) iterations, BorderType.Default, new MCvScalar()); break;*/ case LayerManager.Mutate.PyrDownUp: - SlicerFile.LayerManager.MutatePyrDownUp(layerStart, layerEnd); + SlicerFile.LayerManager.MutatePyrDownUp(layerStart, layerEnd, BorderType.Default, progress); break; case LayerManager.Mutate.SmoothMedian: - SlicerFile.LayerManager.MutateMedianBlur(layerStart, layerEnd, (int)iterationsStart); + SlicerFile.LayerManager.MutateMedianBlur(layerStart, layerEnd, (int)iterationsStart, progress); break; case LayerManager.Mutate.SmoothGaussian: - SlicerFile.LayerManager.MutateGaussianBlur(layerStart, layerEnd, new Size((int) iterationsStart, (int) iterationsStart)); + SlicerFile.LayerManager.MutateGaussianBlur(layerStart, layerEnd, new Size((int) iterationsStart, (int) iterationsStart), 0,0, BorderType.Default, progress); break; } - result = true; + } + catch (OperationCanceledException) + { + } catch (Exception ex) { - result = false; MessageBox.Show($"{ex.Message}\nPlease try different values for the mutation", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally @@ -2382,8 +2479,6 @@ namespace UVtools.GUI EnableGUI(true); }); } - - return result; }); FrmLoading.ShowDialog(); @@ -2429,12 +2524,11 @@ namespace UVtools.GUI DisableGUI(); FrmLoading.SetDescription("Computing Issues"); - Task<bool> task = Task<bool>.Factory.StartNew(() => + var task = Task.Factory.StartNew(() => { - bool result = false; try { - var issues = SlicerFile.LayerManager.GetAllIssues(islandConfig, resinTrapConfig); + var issues = SlicerFile.LayerManager.GetAllIssues(islandConfig, resinTrapConfig, FrmLoading.RestartProgress()); Issues = new Dictionary<uint, List<LayerIssue>>(); for (uint i = 0; i < SlicerFile.LayerCount; i++) @@ -2444,8 +2538,10 @@ namespace UVtools.GUI Issues.Add(i, list); } } + } + catch (OperationCanceledException) + { - result = true; } catch (Exception ex) { @@ -2454,16 +2550,15 @@ namespace UVtools.GUI } finally { - Invoke((MethodInvoker)delegate { + Invoke((MethodInvoker)delegate + { // Running on the UI thread EnableGUI(true); }); } - - return result; }); - FrmLoading.ShowDialog(); + var loadingResult = FrmLoading.ShowDialog(); lvIssues.BeginUpdate(); uint count = 0; diff --git a/UVtools.GUI/Mutation.cs b/UVtools.GUI/Mutation.cs index e9ba085..b1b0c1a 100644 --- a/UVtools.GUI/Mutation.cs +++ b/UVtools.GUI/Mutation.cs @@ -16,6 +16,7 @@ namespace UVtools.GUI #region Properties public LayerManager.Mutate Mutate { get; } + public string MenuName { get; } public string Description { get; } public Image Image { get; } @@ -23,9 +24,10 @@ namespace UVtools.GUI #region Constructor - public Mutation(LayerManager.Mutate mutate, string description, Image image = null) + public Mutation(LayerManager.Mutate mutate, string menuName, string description, Image image = null) { Mutate = mutate; + MenuName = menuName ?? mutate.ToString(); Description = description; Image = image; } diff --git a/UVtools.GUI/Properties/AssemblyInfo.cs b/UVtools.GUI/Properties/AssemblyInfo.cs index 8a6ff17..a90e5b4 100644 --- a/UVtools.GUI/Properties/AssemblyInfo.cs +++ b/UVtools.GUI/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.6.0.1")] -[assembly: AssemblyFileVersion("0.6.0.1")] +[assembly: AssemblyVersion("0.6.0.2")] +[assembly: AssemblyFileVersion("0.6.0.2")] |