190 lines
No EOL
7 KiB
C#
190 lines
No EOL
7 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Dasync.Collections;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace MaddoShared
|
|
{
|
|
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
|
|
public class ImageCreationStuff(ILogger<ImageCreationStuff> logger, PicSettings picSettings, ImageCreatorSharp imageCreatorService)
|
|
{
|
|
public class Options
|
|
{
|
|
public bool AggiornaSottodirectory { get; set; }
|
|
public bool CreaSottocartelle { get; set; }
|
|
|
|
public int FilePerCartella { get; set; }
|
|
public string SuffissoCartelle { get; set; }
|
|
public int CifreContatore { get; set; }
|
|
public NumerazioneType NumerazioneType { get; set; }
|
|
public string SourcePath { get; set; }
|
|
public string DestinationPath { get; set; }
|
|
|
|
public int MaxThreads { get; set; }
|
|
public int ChunksSize { get; set; }
|
|
public bool LinearExecution { get; set; }
|
|
}
|
|
|
|
public async Task<string> CreaCatalogoParallel(Options options, ConcurrentBag<string> results,
|
|
EventHandler<Tuple<string, int>> updateEvent,
|
|
CancellationToken cancellationToken = default(CancellationToken))
|
|
{
|
|
var stopwatch = new Stopwatch();
|
|
stopwatch.Start();
|
|
|
|
await ProcessImagesParallel(options, results, updateEvent, cancellationToken);
|
|
|
|
stopwatch.Stop();
|
|
|
|
return
|
|
$"{stopwatch.Elapsed.Hours}h {stopwatch.Elapsed.Minutes}m ${stopwatch.Elapsed.Seconds}s ({stopwatch.Elapsed.TotalSeconds}s)";
|
|
}
|
|
|
|
public async Task ProcessImagesParallel(
|
|
Options options,
|
|
ConcurrentBag<string> results,
|
|
EventHandler<Tuple<string, int>> updateEvent,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var dataToProcess = GetFilesToProcess(options);
|
|
|
|
// int threads = options.MaxThreads == 0 ? Environment.ProcessorCount * 2 : options.MaxThreads;
|
|
int threads = options.MaxThreads;
|
|
|
|
Bitmap logoBmp = null;
|
|
// Load Logo
|
|
if (picSettings.LogoAggiungi & File.Exists(picSettings.LogoNomeFile))
|
|
{
|
|
logoBmp = new Bitmap(picSettings.LogoNomeFile);
|
|
}
|
|
|
|
Func<FileData, Task> processFile = async fileData =>
|
|
{
|
|
using var logoCopy = logoBmp.Clone(new Rectangle(0, 0, logoBmp.Width, logoBmp.Height),
|
|
logoBmp.PixelFormat);
|
|
|
|
var imgState = new ImageState
|
|
{
|
|
WorkFile = fileData.File,
|
|
DestDir = fileData.Directory,
|
|
};
|
|
|
|
await imageCreatorService.CreaImmagineThread(imgState, logoCopy);
|
|
|
|
// using var imgCreator = new ImageCreatorSharp(fileData.File, fileData.Directory, picSettings);
|
|
// await imgCreator.CreaImmagineThread(fileData.File.Name, logoCopy);
|
|
|
|
results.Add(fileData.File.Name);
|
|
|
|
try
|
|
{
|
|
updateEvent?.Invoke(this, new Tuple<string, int>(fileData.File.Name, dataToProcess.Count));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
logger.LogError(e, "Error in reporting update");
|
|
throw;
|
|
}
|
|
// finally
|
|
// {
|
|
// imgCreator = null;
|
|
// }
|
|
};
|
|
|
|
if (options.LinearExecution)
|
|
{
|
|
foreach (var fileData in dataToProcess)
|
|
await processFile(fileData);
|
|
}
|
|
else
|
|
{
|
|
var chunks = options.ChunksSize > 0
|
|
? SplitList(dataToProcess, options.ChunksSize)
|
|
: new List<List<FileData>> { dataToProcess };
|
|
|
|
foreach (var chunk in chunks)
|
|
{
|
|
await chunk.ParallelForEachAsync(
|
|
processFile,
|
|
maxDegreeOfParallelism: threads,
|
|
false,
|
|
cancellationToken);
|
|
|
|
chunk.Clear();
|
|
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, blocking: false, compacting: false);
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
logoBmp?.Dispose();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
logger.LogError(e, "Error in disposing the logo");
|
|
}
|
|
|
|
}
|
|
|
|
private List<FileData> GetFilesToProcess(Options options)
|
|
{
|
|
if (options.AggiornaSottodirectory && options.CreaSottocartelle)
|
|
{
|
|
var helper = new FileHelperSharp();
|
|
return helper.GetFilesRecursive(
|
|
new DirectoryInfo(options.SourcePath),
|
|
new DirectoryInfo(options.DestinationPath),
|
|
"*.jpg",
|
|
new FileHelperOptions
|
|
{
|
|
FilesPerFolder = options.FilePerCartella,
|
|
Suffix = options.SuffissoCartelle,
|
|
CounterSize = options.CifreContatore,
|
|
NumerationType = options.NumerazioneType
|
|
});
|
|
}
|
|
|
|
var files = Directory.EnumerateFiles(
|
|
options.SourcePath,
|
|
"*.jpg",
|
|
options.AggiornaSottodirectory ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
|
|
|
|
return files.Select(x =>
|
|
{
|
|
var fInfo = new FileInfo(x);
|
|
var filePath = fInfo.DirectoryName;
|
|
var trimmedSourcePath = options.SourcePath.TrimEnd('\\');
|
|
var newFilePath = fInfo.FullName.Replace(trimmedSourcePath, "").TrimStart('\\');
|
|
newFilePath = Path.Combine(options.DestinationPath, newFilePath);
|
|
|
|
var destFolderPath = new FileInfo(newFilePath).DirectoryName;
|
|
var destFolderInfo = new DirectoryInfo(destFolderPath);
|
|
destFolderInfo.EnsureDirectoryExists();
|
|
|
|
return new FileData(fInfo, new DirectoryInfo(new FileInfo(newFilePath).DirectoryName));
|
|
|
|
// var destDir = new FileInfo(newFilePath).Directory!;
|
|
// destDir.Create(); // Ensure exists
|
|
//
|
|
// return new FileData(fInfo, destDir);
|
|
}).ToList();
|
|
}
|
|
|
|
private static IEnumerable<List<T>> SplitList<T>(List<T> bigList, int nSize = 3)
|
|
{
|
|
for (int i = 0; i < bigList.Count; i += nSize)
|
|
{
|
|
yield return bigList.GetRange(i, Math.Min(nSize, bigList.Count - i));
|
|
}
|
|
}
|
|
}
|
|
} |