Skip to content

Commit

Permalink
v0.8.1.0
Browse files Browse the repository at this point in the history
* (Add) Tools can now run inside a ROI (#49)
* (Add) Layer preview: Hold-Shift + Left-drag to select an ROI (Region of interest) on image, that region will be used instead of whole image when running some tools
* (Add) Layer preview: Hold-Shift + Hold-Alt + Left-drag to select and auto adjust the ROI to the contained objects, that region will be used instead of whole image when running some tools
* (Add) Layer preview: Hold-Shift + Right-click on a object to select its bounding area, that region will be used instead of whole image when running some tools
* (Add) Layer preview: ESC key to clear ROI
* (Add) Layer preview: Overlay text with hints for current action
* (Add) Tool - Move: Now possible to do a copy move instead of a cut move
* (Add) Arrow wait cursor to progress loadings
* (Change) Layer preview: Hold-Shift key to select issues and pick pixel position/brightness changed to Hold-Control key
* (Change) Layer preview: Shift+click combination to zoom-in changed to Alt+click
* (Fix) CTB v3: Bad file when re-encoding
  • Loading branch information
sn4k3 committed Sep 12, 2020
1 parent 67c9d71 commit 5cfd62d
Show file tree
Hide file tree
Showing 36 changed files with 845 additions and 217 deletions.
14 changes: 10 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
# Changelog

## /08/2020 - v0.8.1.0
## 12/09/2020 - v0.8.1.0

* (Add) Layer preview: Hold-Shift key to select an ROI (Region of interest) on image, that region will be used instead of whole image when running some tools
* (Add) Tools can now run inside a ROI (#49)
* (Add) Layer preview: Hold-Shift + Left-drag to select an ROI (Region of interest) on image, that region will be used instead of whole image when running some tools
* (Add) Layer preview: Hold-Shift + Hold-Alt + Left-drag to select and auto adjust the ROI to the contained objects, that region will be used instead of whole image when running some tools
* (Add) Layer preview: Hold-Shift + Right-click on a object to select its bounding area, that region will be used instead of whole image when running some tools
* (Add) Layer preview: ESC key to clear ROI
* (Add) Layer preview: Overlay text with hints for current action
* (Add) Tool - Move: Now possible to do a copy move instead of a cut move
* (Add) Arrow wait cursor to progress loadings
* (Change) Layer preview: Hold-Shift key to select issues and pick pixel position/brightness changed to Hold-Control key
* (Change) Layer preview: Shift+click combination to zoom-in changed to Alt+click
* (Fix) CTB v3: Bad file when re-encoding

## 11/08/2020 - v0.8.0.0
## 11/09/2020 - v0.8.0.0

* (Add) LGS and LGS30 file format for Longer Orange 10 and 30 (ezrec/uv3dp#105)
* (Add) CWS: Support the GRAY2RGB and RBG2GRAY encoding for Bene Mono
Expand Down Expand Up @@ -50,7 +56,7 @@ Less frequently used settings for gap and noise removal iterations have been mov
* (Fix) Mask: A crash when check "Invert" when mask is not loaded
* (Fix) Some text and phrases

## 04/08/2020 - v0.7.0.0
## 04/09/2020 - v0.7.0.0

* (Add) "Rebuild GCode" button
* (Add) Issues: Touching Bounds and Empty Layers to the detect button
Expand Down
4 changes: 3 additions & 1 deletion UVtools.Core/FileFormats/ChituboxFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1218,7 +1218,9 @@ public override void Encode(string fileFullPath, OperationProgress progress = nu
if (HeaderSettings.Version >= 3)
{
var layerDataEx = new LayerDataEx(layerData, layerIndex);
layerData.DataAddress = layerDataCurrentOffset += Helpers.SerializeWriteFileStream(outputFile, layerDataEx);
layerDataCurrentOffset += (uint)Helpers.Serializer.SizeOf(layerDataEx);
layerData.DataAddress = layerDataCurrentOffset;
Helpers.SerializeWriteFileStream(outputFile, layerDataEx);
}

layerDataCurrentOffset += outputFile.WriteBytes(layerData.EncodedRle);
Expand Down
118 changes: 62 additions & 56 deletions UVtools.Core/Layer/Layer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -444,35 +444,44 @@ public List<LayerIssue> GetIssues(uint requiredPixelsToSupportIsland = 5)
return result;
}

public void MutateMove(OperationMove operation)
public void Move(OperationMove operation)
{
using (var layer = LayerMat)
using (var mat = LayerMat)
{
if (operation.ImageWidth == 0) operation.ImageWidth = (uint)layer.Width;
if (operation.ImageHeight == 0) operation.ImageHeight = (uint)layer.Height;
if (operation.ImageWidth == 0) operation.ImageWidth = (uint)mat.Width;
if (operation.ImageHeight == 0) operation.ImageHeight = (uint)mat.Height;

/*layer.Transform(1.0, 1.0, move.MarginLeft - move.MarginRight, move.MarginTop-move.MarginBottom);
LayerMat = layer;*/
using (var layerRoi = new Mat(layer, operation.SrcRoi))
/*using (var layerRoi = new Mat(layer, operation.SrcRoi))
using (var dstLayer = layer.CloneBlank())
using (var dstRoi = new Mat(dstLayer, operation.DstRoi))
{
using (var dstLayer = layer.CloneBlank())
layerRoi.CopyTo(dstRoi);
LayerMat = dstLayer;
}*/

using (var srcRoi = new Mat(mat, operation.ROI))
using (var dstRoi = new Mat(mat, operation.DstRoi))
{
srcRoi.CopyTo(dstRoi);
if (operation.IsCutMove)
{
using (var dstRoi = new Mat(dstLayer, operation.DstRoi))
{
layerRoi.CopyTo(dstRoi);
LayerMat = dstLayer;
}
srcRoi.SetTo(new MCvScalar(0));
}

LayerMat = mat;
}
}
}


public void Resize(double xScale, double yScale)
public void Resize(double xScale, double yScale, OperationResize operation)
{
using (var mat = LayerMat)
{
mat.TransformFromCenter(xScale, yScale);
Mat target = operation.GetRoiOrDefault(mat);
target.TransformFromCenter(xScale, yScale);
LayerMat = mat;
}
}
Expand All @@ -481,33 +490,20 @@ public void Flip(OperationFlip operation)
{
using (var mat = LayerMat)
{
Mat target = operation.GetRoiOrDefault(mat);

if (operation.MakeCopy)
{
using (Mat dst = new Mat())
{
CvInvoke.Flip(mat, dst, operation.FlipTypeOpenCV);
CvInvoke.Add(mat, dst, mat);
/*var spanSrc = mat.GetPixelSpan<byte>();
var spanDst = dst.GetPixelSpan<byte>();
for (int i = 0; i < spanSrc.Length; i++)
{
if (spanDst[i] == 0) continue;
spanSrc[i] = spanDst[i];
}*/



LayerMat = mat;

CvInvoke.Flip(target, dst, operation.FlipTypeOpenCV);
CvInvoke.Add(target, dst, target);
}
}
else
{
CvInvoke.Flip(mat, mat, operation.FlipTypeOpenCV);
/*GpuMat gpumat = new GpuMat();
gpumat.Upload(mat);
CudaInvoke.Flip(gpumat, gpumat, flipType);
gpumat.Download(mat);*/
CvInvoke.Flip(target, target, operation.FlipTypeOpenCV);
}

LayerMat = mat;
Expand All @@ -518,8 +514,10 @@ public void Rotate(OperationRotate operation)
{
using (var mat = LayerMat)
{
var halfWidth = mat.Width / 2.0f;
var halfHeight = mat.Height / 2.0f;
Mat target = operation.GetRoiOrDefault(mat);

var halfWidth = target.Width / 2.0f;
var halfHeight = target.Height / 2.0f;
using (var translateTransform = new Matrix<double>(2, 3))
{
CvInvoke.GetRotationMatrix2D(new PointF(halfWidth, halfHeight), (double) operation.AngleDegrees, 1.0, translateTransform);
Expand All @@ -537,20 +535,23 @@ public void Rotate(OperationRotate operation)
translateTransform[1, 2] += bound_h / 2 - halfHeight;*/


CvInvoke.WarpAffine(mat, mat, translateTransform, mat.Size);
CvInvoke.WarpAffine(target, target, translateTransform, target.Size);
}

LayerMat = mat;
}
}

public void MutateSolidify()
public void Solidify(OperationSolidify operation)
{
using (Mat mat = LayerMat)
{
using (Mat filteredMat = new Mat())
{
CvInvoke.Threshold(mat, filteredMat, 254, 255, ThresholdType.Binary); // Clean AA
Mat target = operation.GetRoiOrDefault(mat);


CvInvoke.Threshold(target, filteredMat, 254, 255, ThresholdType.Binary); // Clean AA

using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
{
Expand All @@ -561,7 +562,7 @@ public void MutateSolidify()
for (int i = 0; i < contours.Size; i++)
{
if ((int)arr.GetValue(0, i, 2) != -1 || (int)arr.GetValue(0, i, 3) == -1) continue;
CvInvoke.DrawContours(mat, contours, i, new MCvScalar(255), -1);
CvInvoke.DrawContours(target, contours, i, new MCvScalar(255), -1);
}
}
}
Expand All @@ -571,13 +572,13 @@ public void MutateSolidify()
}
}

public void Mask(OperationMask mask) => Mask(mask.Mask);

public void Mask(Mat mask)
public void Mask(OperationMask operation)
{
using (var mat = LayerMat)
{
CvInvoke.BitwiseAnd(mat, mask, mat);
Mat target = operation.GetRoiOrDefault(mat);
if(operation.Mask.Size != target.Size) return;
CvInvoke.BitwiseAnd(target, operation.Mask, target);
LayerMat = mat;
}
}
Expand Down Expand Up @@ -655,17 +656,19 @@ public void PixelDimming(OperationPixelDimming operation, Mat evenPatternMask, M
using (Mat erode = new Mat())
using (Mat diff = new Mat())
{
CvInvoke.Erode(dst, erode, kernel, anchor, (int) operation.BorderSize, BorderType.Reflect101, default);
CvInvoke.Subtract(dst, erode, diff);
Mat target = operation.GetRoiOrDefault(dst);

CvInvoke.Erode(target, erode, kernel, anchor, (int) operation.BorderSize, BorderType.Reflect101, default);
CvInvoke.Subtract(target, erode, diff);
if (operation.BordersOnly)
{
CvInvoke.BitwiseAnd(diff, Index % 2 == 0 ? evenPatternMask : oddPatternMask, dst);
CvInvoke.Add(erode, dst, dst);
CvInvoke.BitwiseAnd(diff, Index % 2 == 0 ? evenPatternMask : oddPatternMask, target);
CvInvoke.Add(erode, target, target);
}
else
{
CvInvoke.BitwiseAnd(erode, Index % 2 == 0 ? evenPatternMask : oddPatternMask, dst);
CvInvoke.Add(dst, diff, dst);
CvInvoke.BitwiseAnd(erode, Index % 2 == 0 ? evenPatternMask : oddPatternMask, target);
CvInvoke.Add(target, diff, target);
}

LayerMat = dst;
Expand All @@ -679,7 +682,8 @@ public void Morph(OperationMorph operation, int iterations = 1, BorderType borde

using (Mat dst = LayerMat)
{
CvInvoke.MorphologyEx(dst, dst, operation.MorphOperation, operation.Kernel.Matrix, operation.Kernel.Anchor, iterations, borderType, borderValue);
Mat target = operation.GetRoiOrDefault(dst);
CvInvoke.MorphologyEx(target, target, operation.MorphOperation, operation.Kernel.Matrix, operation.Kernel.Anchor, iterations, borderType, borderValue);
LayerMat = dst;
}
}
Expand Down Expand Up @@ -758,7 +762,8 @@ public void ThresholdPixels(OperationThreshold operation)
{
using (Mat dst = LayerMat)
{
CvInvoke.Threshold(dst, dst, operation.Threshold, operation.Maximum, operation.Type);
Mat target = operation.GetRoiOrDefault(dst);
CvInvoke.Threshold(target, target, operation.Threshold, operation.Maximum, operation.Type);
LayerMat = dst;
}
}
Expand All @@ -772,23 +777,24 @@ public void Blur(OperationBlur operation)
//if (anchor.IsEmpty) anchor = new Point(-1, -1);
using (Mat dst = LayerMat)
{
Mat target = operation.GetRoiOrDefault(dst);
switch (operation.BlurOperation)
{
case OperationBlur.BlurAlgorithm.Blur:
CvInvoke.Blur(dst, dst, size, operation.Kernel.Anchor);
CvInvoke.Blur(target, target, size, operation.Kernel.Anchor);
break;
case OperationBlur.BlurAlgorithm.Pyramid:
CvInvoke.PyrDown(dst, dst);
CvInvoke.PyrUp(dst, dst);
CvInvoke.PyrDown(target, target);
CvInvoke.PyrUp(target, target);
break;
case OperationBlur.BlurAlgorithm.MedianBlur:
CvInvoke.MedianBlur(dst, dst, (int) operation.Size);
CvInvoke.MedianBlur(target, target, (int) operation.Size);
break;
case OperationBlur.BlurAlgorithm.GaussianBlur:
CvInvoke.GaussianBlur(dst, dst, size, 0);
CvInvoke.GaussianBlur(target, target, size, 0);
break;
case OperationBlur.BlurAlgorithm.Filter2D:
CvInvoke.Filter2D(dst, dst, operation.Kernel.Matrix, anchor);
CvInvoke.Filter2D(target, target, operation.Kernel.Matrix, anchor);
break;
default:
throw new ArgumentOutOfRangeException();
Expand Down Expand Up @@ -824,7 +830,7 @@ public void ChangeResolution(OperationChangeResolution operation)
public void Pattern(OperationPattern operation)
{
using (var layer = LayerMat)
using (var layerRoi = new Mat(layer, operation.SrcRoi))
using (var layerRoi = new Mat(layer, operation.ROI))
using (var dstLayer = layer.CloneBlank())
{
for (ushort col = 0; col < operation.Cols; col++)
Expand Down
22 changes: 12 additions & 10 deletions UVtools.Core/Layer/LayerManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,13 +247,13 @@ public void Move(OperationMove operation, OperationProgress progress = null)
if (ReferenceEquals(progress, null)) progress = new OperationProgress();
progress.Reset(operation.ProgressAction, operation.LayerRangeCount);

if (operation.SrcRoi == Rectangle.Empty) operation.SrcRoi = GetBoundingRectangle(progress);
if (operation.ROI == Rectangle.Empty) operation.ROI = GetBoundingRectangle(progress);

Parallel.For(operation.LayerIndexStart, operation.LayerIndexEnd + 1, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;

this[layerIndex].MutateMove(operation);
this[layerIndex].Move(operation);

lock (progress.Mutex)
{
Expand Down Expand Up @@ -322,7 +322,7 @@ public void Resize(OperationResize operation, OperationProgress progress = null)

if (newX == 1.0m && newY == 1.0m) return;

this[layerIndex].Resize((double) (newX / 100m), (double) (newY / 100m));
this[layerIndex].Resize((double) (newX / 100m), (double) (newY / 100m), operation);
});
progress.Token.ThrowIfCancellationRequested();
}
Expand Down Expand Up @@ -366,7 +366,7 @@ public void Solidify(OperationSolidify operation, OperationProgress progress = n
Parallel.For(operation.LayerIndexStart, operation.LayerIndexEnd + 1, layerIndex =>
{
if (progress.Token.IsCancellationRequested) return;
this[layerIndex].MutateSolidify();
this[layerIndex].Solidify(operation);
lock (progress.Mutex)
{
progress++;
Expand Down Expand Up @@ -425,13 +425,15 @@ public void PixelDimming(OperationPixelDimming operation, OperationProgress prog
using (Mat matEven = mat.CloneBlank())
using (Mat matOdd = mat.CloneBlank())
{
CvInvoke.Repeat(operation.EvenPattern, mat.Rows / operation.EvenPattern.Rows + 1,
mat.Cols / operation.EvenPattern.Cols + 1, matEven);
CvInvoke.Repeat(operation.OddPattern, mat.Rows / operation.OddPattern.Rows + 1,
mat.Cols / operation.OddPattern.Cols + 1, matOdd);
Mat target = operation.GetRoiOrDefault(mat);

using (var evenPatternMask = new Mat(matEven, new Rectangle(0, 0, mat.Width, mat.Height)))
using (var oddPatternMask = new Mat(matOdd, new Rectangle(0, 0, mat.Width, mat.Height)))
CvInvoke.Repeat(operation.EvenPattern, target.Rows / operation.EvenPattern.Rows + 1,
target.Cols / operation.EvenPattern.Cols + 1, matEven);
CvInvoke.Repeat(operation.OddPattern, target.Rows / operation.OddPattern.Rows + 1,
target.Cols / operation.OddPattern.Cols + 1, matOdd);

using (var evenPatternMask = new Mat(matEven, new Rectangle(0, 0, target.Width, target.Height)))
using (var oddPatternMask = new Mat(matOdd, new Rectangle(0, 0, target.Width, target.Height)))
{
Parallel.For(operation.LayerIndexStart, operation.LayerIndexEnd + 1, layerIndex =>
{
Expand Down
14 changes: 14 additions & 0 deletions UVtools.Core/Operations/Operation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
* of this license document, but changing it is not allowed.
*/

using System.Drawing;
using System.Runtime.CompilerServices;
using Emgu.CV;
using UVtools.Core.Objects;

namespace UVtools.Core.Operations
Expand Down Expand Up @@ -78,5 +80,17 @@ public bool CanValidate(params object[] parameters)
public virtual uint LayerIndexEnd { get; set; }

public uint LayerRangeCount => LayerIndexEnd - LayerIndexStart + 1;

/// <summary>
/// Gets or sets an ROI to process this operation
/// </summary>
public Rectangle ROI { get; set; } = Rectangle.Empty;

public bool HaveROI => !ROI.IsEmpty;

public Mat GetRoiOrDefault(Mat defaultMat)
{
return HaveROI ? new Mat(defaultMat, ROI) : defaultMat;
}
}
}
Loading

0 comments on commit 5cfd62d

Please sign in to comment.