Catalog/MaddoShared/ImageCreationStuff.cs
2025-07-28 11:25:46 +02:00

341 lines
No EOL
15 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
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
{
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();
// todo immagini counter
//todo set label
await ProcessImagesParallel(options, results, updateEvent, cancellationToken);
// todo set finito label
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)
{
List<FileData> 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();
}
// public async Task CreaImmaginiParallel(Options options, ConcurrentBag<string> results,
// EventHandler<Tuple<string, int>> updateEvent,
// CancellationToken cancellationToken = default(CancellationToken))
// {
// var dataToProcess = new List<FileData>();
// if (options.AggiornaSottodirectory && options.CreaSottocartelle)
// {
// var helper = new FileHelperSharp();
// dataToProcess = 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
// });
// }
// else if (!options.CreaSottocartelle)
// {
// var files = Directory.EnumerateFiles(options.SourcePath, "*.jpg",
// options.AggiornaSottodirectory
// ? SearchOption.AllDirectories
// : SearchOption.TopDirectoryOnly);
//
// dataToProcess = 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));
// }).ToList();
//
// //// TODO
// //dataToProcess =
// // (from f in Directory.EnumerateFiles(options.SourcePath, "*.jpg",
// // options.AggiornaSottodirectory
// // ? SearchOption.AllDirectories
// // : SearchOption.TopDirectoryOnly)
// // select new FileData(new FileInfo(f),
// // new DirectoryInfo(options.DestinationPath.PathCombine(
// // new FileInfo(f).DirectoryName.Replace(options.SourcePath.TrimEnd(new char[] {'\\'}), "")
// // )
// // )
// // )
// // )
// // .ToList();
// }
//
// var threads = options.MaxThreads == 0 ? Environment.ProcessorCount * 2 : options.MaxThreads;
// var scheduler = new ConcurrentExclusiveSchedulerPair(TaskScheduler.Default, threads)
// .ConcurrentScheduler;
//
// //var allTasks = new List<Task>();
// var test = from d in dataToProcess
// select Task.Factory.StartNew(async () =>
// {
// var imgCreator = new ImageCreatorSharp(d.File, d.Directory);
// await imgCreator.CreaImmagineThread(d.File.Name);
//
// //await new ImageCreatorSharp(d.File, d.Directory).CreaImmagineThread(d.File.Name);
//
// imgCreator = null;
//
// //var imgC = new ImageCreatorSharp(d.File, d.Directory);
// //imgC.CreaImmagineThread(d.File.Name);
// //imgC = null;
// }, CancellationToken.None, TaskCreationOptions.None, scheduler);
//
// //int count = 0;
//
// if (options.LinearExecution)
// {
// foreach (var task in test)
// {
// await task;
// }
// }
// else
// {
// if (options.ChunksSize == 0)
// {
// //var opts = new ParallelOptions() { MaxDegreeOfParallelism = threads, CancellationToken = cancellationToken, TaskScheduler = scheduler};
// await dataToProcess.ParallelForEachAsync(async fileData =>
// {
// var imgCreator = new ImageCreatorSharp(fileData.File, fileData.Directory);
// await imgCreator.CreaImmagineThread(fileData.File.Name);
// // await new ImageCreatorSharp(fileData.File, fileData.Directory).CreaImmagineThread(fileData.File.Name);
// results.Add(fileData.File.Name);
// //count = Interlocked.Increment(ref count);
//
// try
// {
// updateEvent?.Invoke(this, new Tuple<string, int>(fileData.File.Name, dataToProcess.Count));
// }
// catch (Exception e)
// {
// logger.LogError(e, "Error in reporting update");
// //Console.WriteLine(e);
// throw;
// }
// finally
// {
// // Disposing of the creator
// imgCreator = null;
// }
// }, maxDegreeOfParallelism: threads, false, cancellationToken);
// }
// else
// {
// var asdf = SplitList(dataToProcess.ToList(), options.ChunksSize).ToList();
//
//
// foreach (var sdaf in asdf)
// {
// await sdaf.ParallelForEachAsync(async fileData =>
// {
// var imgCreator = new ImageCreatorSharp(fileData.File, fileData.Directory);
// await imgCreator.CreaImmagineThread(fileData.File.Name);
// // await new ImageCreatorSharp(fileData.File, fileData.Directory).CreaImmagineThread(
// // fileData.File.Name);
// results.Add(fileData.File.Name);
// //count = Interlocked.Increment(ref count);
// try
// {
// updateEvent?.Invoke(this,
// new Tuple<string, int>(fileData.File.Name, dataToProcess.Count));
// }
// catch (Exception e)
// {
// logger.LogError("Error in reporting update");
// //Console.WriteLine(e);
// throw;
// }
// finally
// {
// imgCreator = null;
// }
// }, maxDegreeOfParallelism: threads, false, cancellationToken);
// }
// }
// }
// }
public 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));
}
}
}
}