Skip to content

Commit

Permalink
Implement new layer compression and fixes memory leaks
Browse files Browse the repository at this point in the history
- **Layers:**
  - (Add) Brotli compression codec with good performance and compression ratio (Choose it if you have low available RAM)
  - (Improvement) Use `ResizableMemory` instead of `MemoryStream` for `GZip` and `Deflate` compressions, this results in faster compressions and less memory pressure
  - (Improvement) Changed how layers are cached into the memory, before they were compressed and save for the whole image. Now it crops the bitmap to the bounding rectangle of the current layer and save only that portion with pixels.
                  For example, if the image is empty the cached size will be 0 bytes, and in a 12K image but with a 100 x 100 usable area it will save only that area instead of requiring a 12K buffer.
                  The size of the buffer is now dynamic and will depends on layer data, as so, this method can reduce the memory usage greatly, specially when using large images with a lot of empty space, but also boosts the overall performance by relief the allocations and the required memory footprint.
                  Only in few special cases can have drawbacks, however they are very minimal and the performance impact is minimal in that case.
                  When decompressing, the full resolution image is still created and then the cached area is imported to the corresponding position, composing the final and original image. This is still faster than the old method because decompress a larger buffer is more costly.
                  In the end both writes/compresses and reads/decompresses are now faster and using less memory.
                  Note: When printing multiple objects it is recommended to place them close to each other as you can to take better advantage of this new method.
- **Issues Detection:**
  - (Fix) When detecting for Islands but not overhangs it will throw an exception about invalid roi
  - (Fix) Huge memory leak when detecting resin traps (#830)
- (Improvement) Core: Changed the way "Roi" method is returned and try to dispose all it instances
- (Fix) EncryptedCTB, GOO, SVGX: Huge memory leak when decoding files that caused the program to crash (#830)
  • Loading branch information
sn4k3 committed Jan 29, 2024
1 parent ea41162 commit 09f0120
Show file tree
Hide file tree
Showing 59 changed files with 1,916 additions and 1,039 deletions.
17 changes: 15 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
# Changelog

## /01/2024 - v4.1.1
## /01/2024 - v4.2.0

- **Layers:**
- (Improvement) Use `ResizableMemory` instead of `MemoryStream` for GZip and Deflate compressions, this results in faster compressions and less memory pressure
- (Add) Brotli compression codec with good performance and compression ratio (Choose it if you have low available RAM)
- (Improvement) Use `ResizableMemory` instead of `MemoryStream` for `GZip` and `Deflate` compressions, this results in faster compressions and less memory pressure
- (Improvement) Changed how layers are cached into the memory, before they were compressed and save for the whole image. Now it crops the bitmap to the bounding rectangle of the current layer and save only that portion with pixels.
For example, if the image is empty the cached size will be 0 bytes, and in a 12K image but with a 100 x 100 usable area it will save only that area instead of requiring a 12K buffer.
The size of the buffer is now dynamic and will depends on layer data, as so, this method can reduce the memory usage greatly, specially when using large images with a lot of empty space, but also boosts the overall performance by relief the allocations and the required memory footprint.
Only in few special cases can have drawbacks, however they are very minimal and the performance impact is minimal in that case.
When decompressing, the full resolution image is still created and then the cached area is imported to the corresponding position, composing the final and original image. This is still faster than the old method because decompress a larger buffer is more costly.
In the end both writes/compresses and reads/decompresses are now faster and using less memory.
Note: When printing multiple objects it is recommended to place them close to each other as you can to take better advantage of this new method.
- **Issues Detection:**
- (Fix) When detecting for Islands but not overhangs it will throw an exception about invalid roi
- (Fix) Huge memory leak when detecting resin traps (#830)
- (Improvement) Core: Changed the way "Roi" method is returned and try to dispose all it instances
- (Fix) EncryptedCTB, GOO, SVGX: Huge memory leak when decoding files that caused the program to crash (#830)
- (Fix) UI: Missing theme styles
- (Fix) PrusaSlicer profiles for Creality Halot Mage's: Enable the "Horizontal" mirror under the "Printer" tab to produce the correct orientation when printing (#827)

Expand Down
4 changes: 2 additions & 2 deletions Scripts/UVtools.ScriptSample/ScriptCompensateCrossBleeding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ public bool ScriptExecute()
var layersBelowCount = layerIndex > LayerBleed.Value ? LayerBleed.Value : layerIndex;
using var sourceMat = originalLayers[layerIndex].LayerMat;
var source = sourceMat.GetDataByteSpan();
var source = sourceMat.GetDataByteReadOnlySpan();
using var targetMat = sourceMat.NewBlank();
var target = targetMat.GetDataByteSpan();
using var occupancyMat = sourceMat.NewBlank();
var occupancy = occupancyMat.GetDataByteSpan();
var occupancy = occupancyMat.GetDataByteReadOnlySpan();
var sumRectangle = Rectangle.Empty;
for (int i = 0; i < layersBelowCount; i++)
Expand Down
2 changes: 1 addition & 1 deletion Scripts/UVtools.ScriptSample/ScriptInsetSample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public bool ScriptExecute()
using var erodeMat = new Mat(); // Creates a temporary mat for the eroded image
using var wallMat = new Mat(); // Creates a temporary mat for the wall image
var target = Operation.GetRoiOrDefault(mat); // Get ROI from mat if user selected an region
using var target = Operation.GetRoiOrDefault(mat); // Get ROI from mat if user selected an region
// Erode original image by InsetMarginFromEdge pixels, so we get the offset margin from image and put new image on erodeMat
CvInvoke.Erode(target, erodeMat, kernel, EmguExtensions.AnchorCenter, InsetMarginFromEdge.Value, BorderType.Reflect101, default);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public bool ScriptExecute()
using var mat = layer.LayerMat; // Gets this layer mat/image
var original = mat.Clone(); // Keep a original mat copy
var target = Operation.GetRoiOrDefault(mat); // Get ROI from mat if user selected an region
using var target = Operation.GetRoiOrDefault(mat); // Get ROI from mat if user selected an region
for (byte i = 0; i < brightnesses.Length; i++)
{
Expand All @@ -103,7 +103,7 @@ public bool ScriptExecute()
using var subtractMat = EmguExtensions.InitMat(target.Size, new MCvScalar(brightnesses[i]));
using var nextMat = SlicerFile[layerIndexNext].LayerMat;
var nextMatRoi = Operation.GetRoiOrDefault(nextMat);
using var nextMatRoi = Operation.GetRoiOrDefault(nextMat);
CvInvoke.Subtract(target, subtractMat, target, nextMatRoi);
}
Expand Down
Loading

0 comments on commit 09f0120

Please sign in to comment.