Enhance image processing performance and flexibility by introducing atomic counters, improving file pattern matching, and refining logo positioning logic.
This commit is contained in:
parent
ba965e8266
commit
68c1106f65
8 changed files with 134 additions and 68 deletions
|
|
@ -9,26 +9,14 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Moq" Version="4.20.72" />
|
<PackageReference Include="Moq" Version="4.20.2" />
|
||||||
<PackageReference Include="FluentAssertions" Version="8.8.0" />
|
<PackageReference Include="FluentAssertions" Version="8.8.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.7" />
|
||||||
<PackageReference Include="System.Drawing.Common" Version="10.0.2" />
|
<PackageReference Include="System.Drawing.Common" Version="9.0.7" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\MaddoShared\MaddoShared.csproj" />
|
<ProjectReference Include="..\MaddoShared\MaddoShared.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Update="Microsoft.NET.Test.Sdk" Version="18.0.1" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Update="MSTest.TestFramework" Version="4.1.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Update="MSTest.TestAdapter" Version="4.1.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,28 @@ namespace MaddoShared
|
||||||
|
|
||||||
DirectoryInfo destDir;
|
DirectoryInfo destDir;
|
||||||
destDir = new DirectoryInfo(Path.Combine(dirDest.FullName));
|
destDir = new DirectoryInfo(Path.Combine(dirDest.FullName));
|
||||||
foreach (FileInfo file in dir.GetFiles(filter))
|
|
||||||
|
// Support multiple patterns separated by ';' or ','
|
||||||
|
var patterns = (filter ?? "*").Split(new[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries).Select(p => p.Trim()).ToArray();
|
||||||
|
|
||||||
|
// Collect matching files for all patterns and avoid duplicates
|
||||||
|
var matchedFiles = new List<FileInfo>();
|
||||||
|
foreach (var pat in patterns)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
matchedFiles.AddRange(dir.GetFiles(pat));
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore pattern errors and continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove duplicates (by FullName)
|
||||||
|
var distinctFiles = matchedFiles.GroupBy(f => f.FullName, StringComparer.OrdinalIgnoreCase).Select(g => g.First()).OrderBy(f => f.Name).ToList();
|
||||||
|
|
||||||
|
foreach (FileInfo file in distinctFiles)
|
||||||
{
|
{
|
||||||
contaFilePerDir += 1;
|
contaFilePerDir += 1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -142,13 +142,17 @@ namespace MaddoShared
|
||||||
|
|
||||||
private List<FileData> GetFilesToProcess(Options options)
|
private List<FileData> GetFilesToProcess(Options options)
|
||||||
{
|
{
|
||||||
|
// Support multiple common JPEG patterns so files named .jpeg, .jpe, etc. are included
|
||||||
|
var jpgPatterns = new[] { "*.jpg", "*.jpeg", "*.jpe", "*.jfif", "*.pjpeg", "*.pjp" };
|
||||||
|
|
||||||
if (options.AggiornaSottodirectory && options.CreaSottocartelle)
|
if (options.AggiornaSottodirectory && options.CreaSottocartelle)
|
||||||
{
|
{
|
||||||
var helper = new FileHelperSharp();
|
var helper = new FileHelperSharp();
|
||||||
|
// Pass patterns joined by ';' - FileHelperSharp will split and handle multiple patterns
|
||||||
return helper.GetFilesRecursive(
|
return helper.GetFilesRecursive(
|
||||||
new DirectoryInfo(options.SourcePath),
|
new DirectoryInfo(options.SourcePath),
|
||||||
new DirectoryInfo(options.DestinationPath),
|
new DirectoryInfo(options.DestinationPath),
|
||||||
"*.jpg",
|
string.Join(";", jpgPatterns),
|
||||||
new FileHelperOptions
|
new FileHelperOptions
|
||||||
{
|
{
|
||||||
FilesPerFolder = options.FilePerCartella,
|
FilesPerFolder = options.FilePerCartella,
|
||||||
|
|
@ -158,10 +162,13 @@ namespace MaddoShared
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var files = Directory.EnumerateFiles(
|
// For non-recursive or recursive enumeration without using the helper, enumerate for each pattern
|
||||||
options.SourcePath,
|
var searchOption = options.AggiornaSottodirectory ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
||||||
"*.jpg",
|
|
||||||
options.AggiornaSottodirectory ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
|
var files = jpgPatterns
|
||||||
|
.SelectMany(p => Directory.EnumerateFiles(options.SourcePath, p, searchOption))
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
return files.Select(x =>
|
return files.Select(x =>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -267,26 +267,36 @@ public class ImageCreatorSharp(PicSettings picSettings, ILogger<ImageCreatorShar
|
||||||
using var graphics = Graphics.FromImage(imgOutputSmall);
|
using var graphics = Graphics.FromImage(imgOutputSmall);
|
||||||
graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||||
|
|
||||||
imgState.DimensioneStandardMiniatura = 50;
|
// Use the user's configured font size directly
|
||||||
|
|
||||||
using var font1 = CreateFont(picSettings.IlFont, imgState.DimensioneStandardMiniatura, picSettings.Grassetto);
|
using var font1 = CreateFont(picSettings.IlFont, imgState.DimensioneStandardMiniatura, picSettings.Grassetto);
|
||||||
var textSize = graphics.MeasureString(imgState.TestoFirmaPiccola, font1);
|
var textSize = graphics.MeasureString(imgState.TestoFirmaPiccola, font1);
|
||||||
|
|
||||||
AdjustFontToFitWidth(graphics, image.Width, imgState, ref textSize);
|
// Adjust font if it's too large for the image dimensions
|
||||||
|
// Keep text height under 15% of image height to ensure proper spacing when resized
|
||||||
|
// This leaves room for margins and prevents clipping
|
||||||
|
int tempFontSize = imgState.DimensioneStandardMiniatura;
|
||||||
|
float maxTextHeight = image.Height * 0.15f;
|
||||||
|
|
||||||
|
while ((textSize.Width > image.Width * 0.95f || textSize.Height > maxTextHeight) && tempFontSize > 5)
|
||||||
|
{
|
||||||
|
tempFontSize = (tempFontSize > 20) ? tempFontSize - 5 : tempFontSize - 1;
|
||||||
|
using var tempFont = CreateFont(picSettings.IlFont, tempFontSize, picSettings.Grassetto);
|
||||||
|
textSize = graphics.MeasureString(imgState.TestoFirmaPiccola, tempFont);
|
||||||
|
}
|
||||||
|
|
||||||
SetVerticalPosition(image.Height, textSize.Height, imgState);
|
// Re-measure text with the final font size for accurate positioning
|
||||||
|
using var finalFont = CreateFont(picSettings.IlFont, tempFontSize, picSettings.Grassetto);
|
||||||
|
var finalTextSize = graphics.MeasureString(imgState.TestoFirmaPiccola, finalFont);
|
||||||
|
|
||||||
float xCenter = CalculateHorizontalAlignment(image.Width, textSize.Width);
|
SetVerticalPosition(image.Height, finalTextSize.Height, imgState);
|
||||||
|
|
||||||
|
float xCenter = CalculateHorizontalAlignment(image.Width, finalTextSize.Width);
|
||||||
using var stringFormat = new StringFormat();
|
using var stringFormat = new StringFormat();
|
||||||
stringFormat.Alignment = StringAlignment.Center;
|
stringFormat.Alignment = StringAlignment.Center;
|
||||||
|
|
||||||
using var shadowBrush = new SolidBrush(Color.FromArgb(imgState.AlphaScelta, 0, 0, 0));
|
using var shadowBrush = new SolidBrush(Color.FromArgb(imgState.AlphaScelta, 0, 0, 0));
|
||||||
using var textBrush = new SolidBrush(Color.FromArgb(imgState.AlphaScelta, picSettings.FontColoreRGB));
|
using var textBrush = new SolidBrush(Color.FromArgb(imgState.AlphaScelta, picSettings.FontColoreRGB));
|
||||||
|
|
||||||
imgState.DimensioneStandardMiniatura = picSettings.DimMin;
|
|
||||||
|
|
||||||
using var finalFont =
|
|
||||||
CreateFont(picSettings.IlFont, imgState.DimensioneStandardMiniatura, picSettings.Grassetto);
|
|
||||||
DrawText(graphics, imgState, xCenter, stringFormat, shadowBrush, textBrush, finalFont);
|
DrawText(graphics, imgState, xCenter, stringFormat, shadowBrush, textBrush, finalFont);
|
||||||
|
|
||||||
using var finalThumb =
|
using var finalThumb =
|
||||||
|
|
@ -324,20 +334,6 @@ public class ImageCreatorSharp(PicSettings picSettings, ILogger<ImageCreatorShar
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AdjustFontToFitWidth(Graphics g, int maxWidth, ImageState imgState, ref SizeF size)
|
|
||||||
{
|
|
||||||
int currentSize = imgState.DimensioneStandardMiniatura;
|
|
||||||
|
|
||||||
while (size.Width > maxWidth && currentSize > 5)
|
|
||||||
{
|
|
||||||
currentSize = (currentSize > 20) ? currentSize - 5 : currentSize - 1;
|
|
||||||
using var tempFont = CreateFont(picSettings.IlFont, currentSize, picSettings.Grassetto);
|
|
||||||
size = g.MeasureString(imgState.TestoFirmaPiccola, tempFont);
|
|
||||||
//tempFont.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
imgState.DimensioneStandardMiniatura = currentSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddText(Image g, ImageState imgState, Bitmap imgOutputBig)
|
private void AddText(Image g, ImageState imgState, Bitmap imgOutputBig)
|
||||||
{
|
{
|
||||||
|
|
@ -493,11 +489,17 @@ public class ImageCreatorSharp(PicSettings picSettings, ILogger<ImageCreatorShar
|
||||||
imageAttributes.SetRemapTable(remapTable, ColorAdjustType.Bitmap);
|
imageAttributes.SetRemapTable(remapTable, ColorAdjustType.Bitmap);
|
||||||
|
|
||||||
// * The second color manipulation is used to change the opacity by setting the 3rd row and 3rd column to 0.3f
|
// * The second color manipulation is used to change the opacity by setting the 3rd row and 3rd column to 0.3f
|
||||||
|
// Parse transparency safely (default to 100 if parsing fails)
|
||||||
|
if (!int.TryParse(picSettings.LogoTrasparenza, out var logoTransparencyValue))
|
||||||
|
{
|
||||||
|
logoTransparencyValue = 100;
|
||||||
|
}
|
||||||
|
|
||||||
var colorMatrixElements = new[]
|
var colorMatrixElements = new[]
|
||||||
{
|
{
|
||||||
new[] { 1.0F, 0.0F, 0.0F, 0.0F, 0.0F }, new[] { 0.0F, 1.0F, 0.0F, 0.0F, 0.0F },
|
new[] { 1.0F, 0.0F, 0.0F, 0.0F, 0.0F }, new[] { 0.0F, 1.0F, 0.0F, 0.0F, 0.0F },
|
||||||
new[] { 0.0F, 0.0F, 1.0F, 0.0F, 0.0F },
|
new[] { 0.0F, 0.0F, 1.0F, 0.0F, 0.0F },
|
||||||
new[] { 0.0F, 0.0F, 0.0F, System.Convert.ToSingle(picSettings.LogoTrasparenza) / 100F, 0.0F },
|
new[] { 0.0F, 0.0F, 0.0F, System.Convert.ToSingle(logoTransparencyValue) / 100F, 0.0F },
|
||||||
new[] { 0.0F, 0.0F, 0.0F, 0.0F, 1.0F }
|
new[] { 0.0F, 0.0F, 0.0F, 0.0F, 1.0F }
|
||||||
};
|
};
|
||||||
var wmColorMatrix = new ColorMatrix(colorMatrixElements);
|
var wmColorMatrix = new ColorMatrix(colorMatrixElements);
|
||||||
|
|
@ -511,14 +513,27 @@ public class ImageCreatorSharp(PicSettings picSettings, ILogger<ImageCreatorShar
|
||||||
? CalculateThumbnailSize(logo.Width, logo.Height, fotoLogoW, "Larghezza")
|
? CalculateThumbnailSize(logo.Width, logo.Height, fotoLogoW, "Larghezza")
|
||||||
: CalculateThumbnailSize(logo.Width, logo.Height, fotoLogoH, "Altezza");
|
: CalculateThumbnailSize(logo.Width, logo.Height, fotoLogoH, "Altezza");
|
||||||
|
|
||||||
var inPercentualeL = picSettings.LogoMargine.EndsWith('%');
|
// Guard against null/empty LogoMargine and percentage parsing
|
||||||
var margineL = System.Convert.ToInt32(picSettings.LogoMargine);
|
var logoMargineStr = picSettings.LogoMargine ?? string.Empty;
|
||||||
|
var inPercentualeL = logoMargineStr.EndsWith('%');
|
||||||
|
var margineL = 0;
|
||||||
|
if (inPercentualeL)
|
||||||
|
{
|
||||||
|
var trimmed = logoMargineStr.TrimEnd('%');
|
||||||
|
if (!int.TryParse(trimmed, out margineL)) margineL = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!int.TryParse(logoMargineStr, out margineL)) margineL = 0;
|
||||||
|
}
|
||||||
var margineUsato =
|
var margineUsato =
|
||||||
inPercentualeL ? System.Convert.ToInt32(imgOutputBig.Height * margineL / (double)100) : margineL;
|
inPercentualeL ? System.Convert.ToInt32(imgOutputBig.Height * margineL / (double)100) : margineL;
|
||||||
|
|
||||||
int xPosOfWm = 0;
|
int xPosOfWm = 0;
|
||||||
int yPosOfWm = 0;
|
int yPosOfWm = 0;
|
||||||
switch (picSettings.LogoPosizioneH.ToUpper())
|
var logoH = (picSettings.LogoPosizioneH ?? "NESSUNA").ToUpperInvariant();
|
||||||
|
var logoV = (picSettings.LogoPosizioneV ?? "NESSUNA").ToUpperInvariant();
|
||||||
|
switch (logoH)
|
||||||
{
|
{
|
||||||
case "SINISTRA":
|
case "SINISTRA":
|
||||||
case "NESSUNA":
|
case "NESSUNA":
|
||||||
|
|
@ -540,7 +555,7 @@ public class ImageCreatorSharp(PicSettings picSettings, ILogger<ImageCreatorShar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (picSettings.LogoPosizioneV.ToUpper())
|
switch (logoV)
|
||||||
{
|
{
|
||||||
case "ALTO":
|
case "ALTO":
|
||||||
case "NESSUNA":
|
case "NESSUNA":
|
||||||
|
|
@ -725,16 +740,42 @@ public class ImageCreatorSharp(PicSettings picSettings, ILogger<ImageCreatorShar
|
||||||
|
|
||||||
private void SetVerticalPosition(int imgHeight, float textHeight, ImageState imgState)
|
private void SetVerticalPosition(int imgHeight, float textHeight, ImageState imgState)
|
||||||
{
|
{
|
||||||
|
// Use 1% of image height as minimum margin, or 10px, whichever is larger
|
||||||
|
float minMargin = Math.Max(10f, imgHeight * 0.01f);
|
||||||
|
|
||||||
switch (picSettings.Posizione.ToUpper())
|
switch (picSettings.Posizione.ToUpper())
|
||||||
{
|
{
|
||||||
case "ALTO":
|
case "ALTO":
|
||||||
imgState.YPosFromBottom1 = picSettings.Margine;
|
imgState.YPosFromBottom1 = Math.Max(minMargin, picSettings.Margine);
|
||||||
imgState.YPosFromBottom4 = picSettings.MargVert;
|
imgState.YPosFromBottom4 = Math.Max(minMargin, picSettings.MargVert);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "BASSO":
|
case "BASSO":
|
||||||
imgState.YPosFromBottom1 = (float)(imgHeight - textHeight - (imgHeight * picSettings.Margine / 100.0));
|
var bottomMargin1 = (float)(imgHeight * picSettings.Margine / 100.0);
|
||||||
imgState.YPosFromBottom4 = (float)(imgHeight - textHeight - (imgHeight * picSettings.MargVert / 100.0));
|
var bottomMargin4 = (float)(imgHeight * picSettings.MargVert / 100.0);
|
||||||
|
|
||||||
|
// Position from bottom: bottom edge of text at desired margin from bottom
|
||||||
|
// Y = imageHeight - textHeight - bottomMargin
|
||||||
|
var desiredY1 = imgHeight - textHeight - bottomMargin1;
|
||||||
|
var desiredY4 = imgHeight - textHeight - bottomMargin4;
|
||||||
|
|
||||||
|
// Ensure text stays completely within bounds:
|
||||||
|
// - Top edge must be >= minMargin (not clipped at top)
|
||||||
|
// - Bottom edge must be <= imgHeight - minMargin (not clipped at bottom)
|
||||||
|
var maxAllowedY1 = imgHeight - textHeight - minMargin; // Maximum Y to keep bottom margin
|
||||||
|
var maxAllowedY4 = imgHeight - textHeight - minMargin;
|
||||||
|
|
||||||
|
imgState.YPosFromBottom1 = Math.Max(minMargin, Math.Min(desiredY1, maxAllowedY1));
|
||||||
|
imgState.YPosFromBottom4 = Math.Max(minMargin, Math.Min(desiredY4, maxAllowedY4));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "CENTRO":
|
||||||
|
default:
|
||||||
|
// Center the text vertically
|
||||||
|
var centeredY = (imgHeight - textHeight) / 2f;
|
||||||
|
// Clamp to ensure margins are respected
|
||||||
|
imgState.YPosFromBottom1 = Math.Max(minMargin, Math.Min(centeredY, imgHeight - textHeight - minMargin));
|
||||||
|
imgState.YPosFromBottom4 = imgState.YPosFromBottom1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AsyncEnumerator" Version="4.0.2" />
|
<PackageReference Include="AsyncEnumerator" Version="4.0.2" />
|
||||||
<PackageReference Include="AutoMapper" Version="16.0.0" />
|
|
||||||
<PackageReference Include="Ben.Demystifier" Version="0.4.1" />
|
<PackageReference Include="Ben.Demystifier" Version="0.4.1" />
|
||||||
<PackageReference Include="IDisposableAnalyzers" Version="4.0.8">
|
<PackageReference Include="IDisposableAnalyzers" Version="4.0.8">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
|
@ -20,7 +19,7 @@
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.2" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
|
||||||
<PackageReference Include="System.Buffers" Version="4.6.1" />
|
<PackageReference Include="System.Buffers" Version="4.6.1" />
|
||||||
<PackageReference Include="System.Collections.Immutable" Version="10.0.2" />
|
<PackageReference Include="System.Collections.Immutable" Version="9.0.7" />
|
||||||
<PackageReference Include="System.Memory" Version="4.6.3" />
|
<PackageReference Include="System.Memory" Version="4.6.3" />
|
||||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.1.2" />
|
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.1.2" />
|
||||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
|
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
|
||||||
|
|
@ -28,6 +27,6 @@
|
||||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.4.421302">
|
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.4.421302">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.Windows.Compatibility" Version="10.0.2" />
|
<PackageReference Include="Microsoft.Windows.Compatibility" Version="9.0.7" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -38,9 +38,10 @@ public class PicSettings
|
||||||
public int LogoLarghezza { get; set; }
|
public int LogoLarghezza { get; set; }
|
||||||
public Color FontColoreRGB { get; set; }
|
public Color FontColoreRGB { get; set; }
|
||||||
public bool LogoAggiungi { get; set; }
|
public bool LogoAggiungi { get; set; }
|
||||||
public string LogoNomeFile { get; set; }
|
// Initialize logo-related strings to safe defaults to avoid null reference issues
|
||||||
public string LogoTrasparenza { get; set; }
|
public string LogoNomeFile { get; set; } = string.Empty;
|
||||||
public string LogoMargine { get; set; }
|
public string LogoTrasparenza { get; set; } = "100";
|
||||||
|
public string LogoMargine { get; set; } = "0";
|
||||||
public string LogoPosizioneH { get; set; }
|
public string LogoPosizioneH { get; set; }
|
||||||
public string LogoPosizioneV { get; set; }
|
public string LogoPosizioneV { get; set; }
|
||||||
public bool FotoGrandeDimOrigina { get; set; }
|
public bool FotoGrandeDimOrigina { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -846,6 +846,8 @@ namespace ImageCatalog_2
|
||||||
private ConcurrentBag<string> _results = new();
|
private ConcurrentBag<string> _results = new();
|
||||||
private int _currentAmount = 0;
|
private int _currentAmount = 0;
|
||||||
private int _previousAmount = 0;
|
private int _previousAmount = 0;
|
||||||
|
// Atomic counter for processed images — avoids expensive ConcurrentBag.Count enumerations
|
||||||
|
private int _processedAtomic = 0;
|
||||||
private System.Threading.Timer? _speedTimer;
|
private System.Threading.Timer? _speedTimer;
|
||||||
|
|
||||||
private void Test(object parameter)
|
private void Test(object parameter)
|
||||||
|
|
@ -875,7 +877,7 @@ namespace ImageCatalog_2
|
||||||
ProcessingStatus = "Elaborazione in corso...";
|
ProcessingStatus = "Elaborazione in corso...";
|
||||||
TotalImagesCount = 0;
|
TotalImagesCount = 0;
|
||||||
ProcessedImagesCount = 0;
|
ProcessedImagesCount = 0;
|
||||||
SpeedCounter = "-f/m";
|
SpeedCounter = "-f/s";
|
||||||
ProgressBarValue = 0;
|
ProgressBarValue = 0;
|
||||||
ProgressBarMaximum = 100;
|
ProgressBarMaximum = 100;
|
||||||
|
|
||||||
|
|
@ -902,9 +904,10 @@ namespace ImageCatalog_2
|
||||||
_results = new ConcurrentBag<string>();
|
_results = new ConcurrentBag<string>();
|
||||||
_currentAmount = 0;
|
_currentAmount = 0;
|
||||||
_previousAmount = 0;
|
_previousAmount = 0;
|
||||||
|
_processedAtomic = 0;
|
||||||
|
|
||||||
// Start speed timer (every minute)
|
// Start speed timer (sample every second using lightweight atomic reads)
|
||||||
_speedTimer = new System.Threading.Timer(UpdateSpeedCounter, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
|
_speedTimer = new System.Threading.Timer(UpdateSpeedCounter, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
var time = await _imageCreationService.CreaCatalogoParallel(
|
var time = await _imageCreationService.CreaCatalogoParallel(
|
||||||
imageCreationOptions,
|
imageCreationOptions,
|
||||||
|
|
@ -940,17 +943,21 @@ namespace ImageCatalog_2
|
||||||
private void UpdateSpeedCounter(object? state)
|
private void UpdateSpeedCounter(object? state)
|
||||||
{
|
{
|
||||||
_previousAmount = _currentAmount;
|
_previousAmount = _currentAmount;
|
||||||
_currentAmount = _results.Count;
|
// Read the atomic counter without enumerating the ConcurrentBag
|
||||||
|
_currentAmount = System.Threading.Volatile.Read(ref _processedAtomic);
|
||||||
int diff = _currentAmount - _previousAmount;
|
int diff = _currentAmount - _previousAmount;
|
||||||
SpeedCounter = $"{diff} f/m";
|
// Report files per second (timer runs every 1s)
|
||||||
|
SpeedCounter = $"{diff} f/s";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnImageProcessed(object? sender, Tuple<string, int> args)
|
private void OnImageProcessed(object? sender, Tuple<string, int> args)
|
||||||
{
|
{
|
||||||
ProcessedImagesCount = _results.Count;
|
// Increment atomic processed counter once and use its value for all UI updates
|
||||||
|
var processed = System.Threading.Interlocked.Increment(ref _processedAtomic);
|
||||||
|
ProcessedImagesCount = processed;
|
||||||
TotalImagesCount = args.Item2;
|
TotalImagesCount = args.Item2;
|
||||||
ProgressBarMaximum = args.Item2;
|
ProgressBarMaximum = args.Item2;
|
||||||
ProgressBarValue = _results.Count;
|
ProgressBarValue = processed;
|
||||||
ProcessingStatus = args.Item1;
|
ProcessingStatus = args.Item1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1044,4 +1051,6 @@ namespace ImageCatalog_2
|
||||||
await _settingsService.LoadSettingsAsync(filePath, this);
|
await _settingsService.LoadSettingsAsync(filePath, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@
|
||||||
<PackageReference Include="AutoMapper" Version="16.0.0" />
|
<PackageReference Include="AutoMapper" Version="16.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.2" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.2" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.2" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.7" />
|
||||||
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.4.421302">
|
<PackageReference Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.4.421302">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue