From cfbc6334b6b14c02491f80c9a1a8e5ec8ae07e19 Mon Sep 17 00:00:00 2001 From: MaddoScientisto Date: Wed, 4 Feb 2026 18:38:44 +0100 Subject: [PATCH] Refactoring, upgrades and improvements to memory usage --- MaddoShared/ImageCreationStuff.cs | 43 +- MaddoShared/ImageCreatorSharp.cs | 913 ++++++++++++++--------------- MaddoShared/MaddoShared.csproj | 2 +- imagecatalog/ImageCatalog 2.csproj | 2 +- 4 files changed, 469 insertions(+), 491 deletions(-) diff --git a/MaddoShared/ImageCreationStuff.cs b/MaddoShared/ImageCreationStuff.cs index e437d23..ac78603 100644 --- a/MaddoShared/ImageCreationStuff.cs +++ b/MaddoShared/ImageCreationStuff.cs @@ -49,7 +49,7 @@ namespace MaddoShared stopwatch.Stop(); return - $"{stopwatch.Elapsed.Hours}h {stopwatch.Elapsed.Minutes}m ${stopwatch.Elapsed.Seconds}s ({stopwatch.Elapsed.TotalSeconds}s)"; + $"{stopwatch.Elapsed.Hours}h {stopwatch.Elapsed.Minutes}m {stopwatch.Elapsed.Seconds}s ({stopwatch.Elapsed.TotalSeconds}s)"; } public async Task ProcessImagesParallel( @@ -64,16 +64,17 @@ namespace MaddoShared int threads = options.MaxThreads; Bitmap logoBmp = null; - // Load Logo - if (picSettings.LogoAggiungi & File.Exists(picSettings.LogoNomeFile)) + // Load Logo (short-circuit) + if (picSettings.LogoAggiungi && File.Exists(picSettings.LogoNomeFile)) { logoBmp = new Bitmap(picSettings.LogoNomeFile); } Func processFile = async fileData => { - using var logoCopy = logoBmp.Clone(new Rectangle(0, 0, logoBmp.Width, logoBmp.Height), - logoBmp.PixelFormat); + Bitmap logoCopy = logoBmp is null + ? null + : logoBmp.Clone(new Rectangle(0, 0, logoBmp.Width, logoBmp.Height), logoBmp.PixelFormat); var imgState = new ImageState { @@ -81,26 +82,28 @@ namespace MaddoShared 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(fileData.File.Name, dataToProcess.Count)); + // Ensure CreateImageAsync can accept a null logoCopy value. + await imageCreatorService.CreateImageAsync(imgState, logoCopy); + + results.Add(fileData.File.Name); + + try + { + updateEvent?.Invoke(this, new Tuple(fileData.File.Name, dataToProcess.Count)); + } + catch (Exception e) + { + logger.LogError(e, "Error in reporting update"); + throw; + } } - catch (Exception e) + finally { - logger.LogError(e, "Error in reporting update"); - throw; + // Dispose the clone if it was created + logoCopy?.Dispose(); } - // finally - // { - // imgCreator = null; - // } }; if (options.LinearExecution) diff --git a/MaddoShared/ImageCreatorSharp.cs b/MaddoShared/ImageCreatorSharp.cs index f535a4e..0f77df9 100644 --- a/MaddoShared/ImageCreatorSharp.cs +++ b/MaddoShared/ImageCreatorSharp.cs @@ -17,27 +17,27 @@ namespace MaddoShared; [SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")] public class ImageCreatorSharp(PicSettings picSettings, ILogger logger) { - public async Task CreaImmagineThread(ImageState imgState, Image logo) + public async Task CreateImageAsync(ImageState imgState, Image logo) { try { await Task.Run(() => { logger.LogInformation("File: {FileInfo} Dest: {DirectoryInfo}", imgState.WorkFile, imgState.DestDir); - PreparaVariabili(imgState); + PrepareVariables(imgState); ExtractExif(imgState); using var g = Image.FromFile(imgState.WorkFile.FullName); - // Imposta testo extra - ImpostaTestoExtra(g, imgState); + // Set extra text + SetExtraText(g, imgState); - // Ruota l'immagine in base ai dati EXIF - Rotation(g, imgState); + // Rotate image according to EXIF + ApplyRotation(g, imgState); - // Forza jpeg se è selezionata l'opzione + // Force jpeg if option selected var thisFormat = g.RawFormat; - if (picSettings.UsaForzaJpg == true) + if (picSettings.UsaForzaJpg) thisFormat = ImageFormat.Jpeg; PrepareThumbnailSize(g, imgState); @@ -46,15 +46,15 @@ public class ImageCreatorSharp(PicSettings picSettings, ILogger rotation = null; - var found = img.Metadata?.ExifProfile?.TryGetValue(ExifTag.Orientation, out rotation) ?? false; + var exifProfile = img.Metadata?.ExifProfile; + var found = exifProfile != null && exifProfile.TryGetValue(ExifTag.Orientation, out rotation); if (found) { @@ -80,7 +81,7 @@ public class ImageCreatorSharp(PicSettings picSettings, ILogger date = null; - var creationFound = img.Metadata?.ExifProfile?.TryGetValue(ExifTag.DateTimeOriginal, out date) ?? false; + var creationFound = exifProfile != null && exifProfile.TryGetValue(ExifTag.DateTimeOriginal, out date); if (creationFound) { var succ = DateTime.TryParseExact(date.Value, "yyyy:MM:dd HH:mm:ss", CultureInfo.InvariantCulture, @@ -100,7 +101,7 @@ public class ImageCreatorSharp(PicSettings picSettings, ILoggerImage /// /// ''' - private void ImpostaTestoExtra(Image g, ImageState imgState) + private void SetExtraText(Image g, ImageState imgState) { - if (picSettings.UsaOrarioTestoApplicare | picSettings.UsaTempoGaraTestoApplicare | - picSettings.UsaOrarioMiniatura | picSettings.TestoMin | picSettings.AggTempoGaraMin | + if (picSettings.UsaOrarioTestoApplicare || picSettings.UsaTempoGaraTestoApplicare || + picSettings.UsaOrarioMiniatura || picSettings.TestoMin || picSettings.AggTempoGaraMin || picSettings.AggNumTempMin) { if (g.PropertyIdList.Length <= 0) return; - //ExifReader DatiExif = new ExifReader((Bitmap)g); - imgState.DataFoto = imgState.CreationDate ?? DateTime.Now; //DatiExif.DateTimeOriginal; + imgState.DataFoto = imgState.CreationDate ?? DateTime.Now; imgState.TestoFirma = picSettings.TestoFirmaStart; imgState.TestoFirmaV = picSettings.TestoFirmaStartV; if (imgState.DataFoto.Year == 1) return; imgState.TestoFirmaPiccola = imgState.DataFoto.ToShortTimeString(); - if (picSettings.UsaOrarioTestoApplicare == true) + if (picSettings.UsaOrarioTestoApplicare) { imgState.TestoFirma += $" {imgState.DataFoto.ToShortDateString()} {imgState.DataFoto.ToLongTimeString()}"; @@ -157,11 +157,8 @@ public class ImageCreatorSharp(PicSettings picSettings, ILogger /// ''' - private void PreparaVariabili(ImageState imgState) + private void PrepareVariables(ImageState imgState) { imgState.AlphaScelta = System.Convert.ToInt32((255 * (100 - picSettings.Trasparenza) / (double)100)); imgState.TestoFirma = ""; @@ -203,19 +200,19 @@ public class ImageCreatorSharp(PicSettings picSettings, ILogger g.Height) { - imgState.ThumbSizeSmall = NewthumbSize(g.Width, g.Height, picSettings.LarghezzaSmall, "Larghezza"); + imgState.ThumbSizeSmall = CalculateThumbnailSize(g.Width, g.Height, picSettings.LarghezzaSmall, "Larghezza"); var sizeOrig = new Size(g.Width, g.Height); imgState.ThumbSizeBig = sizeOrig; } else { - imgState.ThumbSizeSmall = NewthumbSize(g.Width, g.Height, picSettings.AltezzaSmall, "Altezza"); + imgState.ThumbSizeSmall = CalculateThumbnailSize(g.Width, g.Height, picSettings.AltezzaSmall, "Altezza"); var sizeOrig = new Size(g.Width, g.Height); imgState.ThumbSizeBig = sizeOrig; } } - private void CreaMiniature(Image sourceImage, ImageState imgState, Bitmap imgOutputBig, ImageFormat format) + private void CreateThumbnails(Image sourceImage, ImageState imgState, Bitmap imgOutputBig, ImageFormat format) { if (!picSettings.CreaMiniature || picSettings.AggiungiScritteMiniature) return; @@ -223,10 +220,10 @@ public class ImageCreatorSharp(PicSettings picSettings, ILogger string.Equals(dir1, dir2, StringComparison.OrdinalIgnoreCase); - private void UpdateFileNameWithCode(ImageState imgState) + private void UpdateFilenameWithCode(ImageState imgState) { var name = imgState.NomeFileSmall; imgState.NomeFileSmall = name[..^4] + picSettings.Codice + name[^4..]; @@ -258,7 +255,7 @@ public class ImageCreatorSharp(PicSettings picSettings, ILogger new Font(fontName, size, bold ? FontStyle.Bold : FontStyle.Regular); + private int FindBestFontSize(Graphics g, string text, string fontName, int maxSize, bool bold, int maxWidth, int minSize = 5) + { + if (maxSize <= minSize) return Math.Max(minSize, maxSize); + + int low = minSize; + int high = Math.Max(minSize, maxSize); + int best = minSize; + + while (low <= high) + { + int mid = (low + high) / 2; + using var testFont = CreateFont(fontName, mid, bold); + var measured = g.MeasureString(text, testFont); + if (measured.Width <= maxWidth) + { + best = mid; + low = mid + 1; // try larger + } + else + { + high = mid - 1; // too big + } + } + + return best; + } + private void AdjustFontToFitWidth(Graphics g, int maxWidth, ImageState imgState, ref SizeF size) { int currentSize = imgState.DimensioneStandardMiniatura; @@ -315,6 +339,390 @@ public class ImageCreatorSharp(PicSettings picSettings, ILogger 0 ? imgState.DimensioneStandard : picSettings.DimStandard; + int bestBaseSize = FindBestFontSize(grPhoto, imgState.TestoFirma ?? string.Empty, picSettings.IlFont, targetBaseSize, picSettings.Grassetto, availableWidth); + imgState.DimensioneStandard = bestBaseSize; + + // Decide final drawing size (use DimVert if rotated) + int drawSize = (imgState.FotoRuotaADestra || imgState.FotoRuotaASinistra) ? picSettings.DimVert : imgState.DimensioneStandard; + + using var drawFont = CreateFont(picSettings.IlFont, drawSize, picSettings.Grassetto); + var crSize = grPhoto.MeasureString(imgState.TestoFirma ?? string.Empty, drawFont); + var larghezzaStandard = Convert.ToInt32(crSize.Width); + + // Vertical positions + switch (picSettings.Posizione.ToUpper()) + { + case "ALTO": + { + imgState.YPosFromBottom = picSettings.Margine; + imgState.YPosFromBottom3 = picSettings.MargVert; + break; + } + + case "BASSO": + { + imgState.YPosFromBottom = + Convert.ToSingle((g.Height - crSize.Height - (g.Height * picSettings.Margine / 100.0))); + imgState.YPosFromBottom3 = + Convert.ToSingle((g.Height - crSize.Height - (g.Height * picSettings.MargVert / 100.0))); + break; + } + } + + float xCenterOfImg = 0; + using var strFormat = new StringFormat(); + switch (picSettings.Allineamento.ToUpper()) + { + case "SINISTRA": + { + xCenterOfImg = Convert.ToSingle((picSettings.Margine + (larghezzaStandard / (double)2))); + if ((larghezzaStandard / (double)2) > (g.Width / (double)2) - picSettings.Margine) + xCenterOfImg = Convert.ToSingle((g.Width / (double)2)); + break; + } + + case "CENTRO": + { + xCenterOfImg = Convert.ToSingle((g.Width / (double)2)); + break; + } + + case "DESTRA": + { + xCenterOfImg = + Convert.ToSingle((g.Width - picSettings.Margine - (larghezzaStandard / (double)2))); + if ((larghezzaStandard / (double)2) > (g.Width / (double)2) - picSettings.Margine) + xCenterOfImg = Convert.ToSingle((g.Width / (double)2)); + break; + } + } + + strFormat.Alignment = StringAlignment.Center; + + using var semiTransBrush2 = new SolidBrush(Color.FromArgb(imgState.AlphaScelta, 0, 0, 0)); + using var semiTransBrush = new SolidBrush(Color.FromArgb(imgState.AlphaScelta, picSettings.FontColoreRGB)); + + // write text (NomeFileBig) + if (picSettings.TestoNome) + { + if (picSettings.NomeData && g.PropertyIdList.Length > 0) + { + imgState.DataFoto = imgState.CreationDate ?? DateTime.Now; + + grPhoto.DrawString((imgState.NomeFileBig + " " + imgState.DataFoto.ToShortDateString()), drawFont, + semiTransBrush2, new PointF(xCenterOfImg + 1, imgState.YPosFromBottom + 1), strFormat); + grPhoto.DrawString((imgState.NomeFileBig + " " + imgState.DataFoto.ToShortDateString()), drawFont, + semiTransBrush, new PointF(xCenterOfImg, imgState.YPosFromBottom), strFormat); + } + else + { + grPhoto.DrawString(imgState.NomeFileBig, drawFont, semiTransBrush2, + new PointF(xCenterOfImg + 1, imgState.YPosFromBottom + 1), strFormat); + grPhoto.DrawString(imgState.NomeFileBig, drawFont, semiTransBrush, + new PointF(xCenterOfImg, imgState.YPosFromBottom), strFormat); + } + } + else + { + if (imgState.FotoRuotaADestra || imgState.FotoRuotaASinistra) + { + if (!picSettings.TestoMin) + { + grPhoto.DrawString(imgState.TestoFirmaV, drawFont, semiTransBrush2, + new PointF(xCenterOfImg + 1, imgState.YPosFromBottom3 + 1), strFormat); + grPhoto.DrawString(imgState.TestoFirmaV, drawFont, semiTransBrush, + new PointF(xCenterOfImg, imgState.YPosFromBottom3), strFormat); + } + + if (picSettings.TestoMin) + { + grPhoto.DrawString(imgState.TestoFirmaV, drawFont, semiTransBrush2, + new PointF(xCenterOfImg + 1, imgState.YPosFromBottom4 + 1), strFormat); + grPhoto.DrawString(imgState.TestoFirmaV, drawFont, semiTransBrush, + new PointF(xCenterOfImg, imgState.YPosFromBottom4), strFormat); + } + } + else + { + grPhoto.DrawString(imgState.TestoFirma, drawFont, semiTransBrush2, + new PointF(xCenterOfImg + 1, imgState.YPosFromBottom + 1), strFormat); + grPhoto.DrawString(imgState.TestoFirma, drawFont, semiTransBrush, + new PointF(xCenterOfImg, imgState.YPosFromBottom), strFormat); + } + } + + if (string.Equals(picSettings.DirectorySorgente, picSettings.DirectoryDestinazione, + StringComparison.OrdinalIgnoreCase)) + { + imgState.NomeFileBig2 = imgState.NomeFileBig; + imgState.NomeFileBig = $"{imgState.NomeFileBig[..^4]}{picSettings.Codice}{imgState.NomeFileBig[^4..]}"; + } + } + + private void AddLogo(Bitmap imgOutputBig, Image logo) + { + // Skip if no logo provided + if (logo is null) return; + + // Load check (use short-circuit &&) + if (!(picSettings.LogoAggiungi && File.Exists(picSettings.LogoNomeFile))) return; + + var logoColoreTrasparente = Color.White; + + // * Load this Bitmap into a new Graphic Object + using var grWatermark = Graphics.FromImage(imgOutputBig); + using ImageAttributes imageAttributes = new ImageAttributes(); + + // * The first step replace the background color with one that is transparent (Alpha=0, R=0, G=0, B=0) + var colorMap = new ColorMap + { + // * background this will be the color we search for and replace with transparency + OldColor = logoColoreTrasparente, + NewColor = Color.FromArgb(0, 0, 0, 0) + }; + + var remapTable = new[] { colorMap }; + 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 + 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[] { 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, 0.0F, 1.0F } + }; + var wmColorMatrix = new ColorMatrix(colorMatrixElements); + imageAttributes.SetColorMatrix(wmColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); + + var fotoLogoH = picSettings.LogoAltezza; + var fotoLogoW = picSettings.LogoLarghezza; + var fattoreAlt = logo.Height / (double)fotoLogoH; + var fattoreLarg = logo.Width / (double)fotoLogoW; + var nuovaSize = fattoreLarg > fattoreAlt + ? CalculateThumbnailSize(logo.Width, logo.Height, fotoLogoW, "Larghezza") + : CalculateThumbnailSize(logo.Width, logo.Height, fotoLogoH, "Altezza"); + + var inPercentualeL = picSettings.LogoMargine.EndsWith('%'); + var margineL = System.Convert.ToInt32(picSettings.LogoMargine); + var margineUsato = + inPercentualeL ? System.Convert.ToInt32(imgOutputBig.Height * margineL / (double)100) : margineL; + + int xPosOfWm = 0; + int yPosOfWm = 0; + switch (picSettings.LogoPosizioneH.ToUpper()) + { + case "SINISTRA": + case "NESSUNA": + { + xPosOfWm = margineUsato; + break; + } + + case "CENTRO": + { + xPosOfWm = System.Convert.ToInt32((imgOutputBig.Width - nuovaSize.Width) / (double)2); + break; + } + + case "DESTRA": + { + xPosOfWm = ((imgOutputBig.Width - nuovaSize.Width) - margineUsato); + break; + } + } + + switch (picSettings.LogoPosizioneV.ToUpper()) + { + case "ALTO": + case "NESSUNA": + { + yPosOfWm = margineUsato; + break; + } + + case "CENTRO": + { + yPosOfWm = System.Convert.ToInt32((imgOutputBig.Height - nuovaSize.Height) / (double)2); + break; + } + + case "BASSO": + { + yPosOfWm = ((imgOutputBig.Height - nuovaSize.Height) - margineUsato); + break; + } + } + + grWatermark.DrawImage(logo, new Rectangle(xPosOfWm, yPosOfWm, nuovaSize.Width, nuovaSize.Height), 0, 0, + logo.Width, logo.Height, GraphicsUnit.Pixel, imageAttributes); + //grWatermark.Dispose(); + } + + + private void SavePhoto(Bitmap imgOutputBig, ImageState imgState, ImageFormat thisFormat) + { + var fileName = Path.Combine(imgState.DestDir.FullName, imgState.NomeFileBig); + + using var image1Stream = new MemoryStream(); + if (picSettings.FotoGrandeDimOrigina == false) + { + // attenzione non controlla se è png + // imgOutputBig.Save(Path.Combine(_DestDir.FullName, "Temp_" & NomeFileBig), thisFormat) + if (thisFormat.Equals(ImageFormat.Jpeg)) + { + MakeImageCustomQuality(imgOutputBig, image1Stream, picSettings.JpegQuality); + } + //SalvaImmagineCustomQuality(imgOutputBig, Path.Combine(DestDir.FullName, "Temp_" + NomeFileBig), _picSettings.jpegQuality); + else + { + imgOutputBig.Save(image1Stream, thisFormat); + } + + //imgOutputBig.Save(Path.Combine(DestDir.FullName, "Temp_" + NomeFileBig), thisFormat); + image1Stream.Seek(0, SeekOrigin.Begin); + using var g2 = Image.FromStream(image1Stream); + imgState.ThumbSizeBig = g2.Width > g2.Height + ? CalculateThumbnailSize(g2.Width, g2.Height, picSettings.LarghezzaBig, "Larghezza") + : CalculateThumbnailSize(g2.Width, g2.Height, picSettings.AltezzaBig, "Altezza"); + using var imgOutputBig2 = new Bitmap(g2, imgState.ThumbSizeBig.Width, imgState.ThumbSizeBig.Height); + + if (!picSettings.OverwriteFiles && File.Exists(fileName)) + { + logger.LogInformation("Saltata foto {FileName}, esiste", fileName); + } + else + { + if (thisFormat.Equals(ImageFormat.Jpeg)) + SaveImageCustomQuality(imgOutputBig2, fileName, picSettings.JpegQuality); + else + imgOutputBig2.Save(fileName, thisFormat); + } + } + else + { + if (!picSettings.OverwriteFiles && File.Exists(fileName)) + { + logger.LogInformation("Saltata foto {FileName}, esiste", fileName); + } + else + { + if (thisFormat.Equals(ImageFormat.Jpeg)) + SaveImageCustomQuality(imgOutputBig, fileName, picSettings.JpegQuality); + else + imgOutputBig.Save(fileName, thisFormat); + } + } + + image1Stream.Seek(0, SeekOrigin.Begin); + + if (!picSettings.CreaMiniature) return; + if (!picSettings.AggiungiScritteMiniature) return; + + using var g1 = picSettings.FotoGrandeDimOrigina ? (Image)imgOutputBig.Clone() : Image.FromStream(image1Stream); + + using var imgOutputSmall = new Bitmap(g1, imgState.ThumbSizeSmall.Width, imgState.ThumbSizeSmall.Height); + + if (string.Equals(picSettings.DirectorySorgente, picSettings.DirectoryDestinazione, + StringComparison.OrdinalIgnoreCase)) + imgState.NomeFileSmall = imgState.NomeFileSmall.Substring(0, imgState.NomeFileSmall.Length - 4) + + picSettings.Codice + + imgState.NomeFileSmall.Substring(imgState.NomeFileSmall.Length - 4); + + var tnFileName = Path.Combine(imgState.DestDir.FullName, imgState.NomeFileSmall); + + if (!picSettings.OverwriteFiles && File.Exists(tnFileName)) + { + logger.LogInformation("Saltata miniatura foto {TnFileName}, esiste", tnFileName); + } + else + { + if (thisFormat.Equals(ImageFormat.Jpeg)) + SaveImageCustomQuality(imgOutputSmall, tnFileName, picSettings.JpegQualityMin); + else + imgOutputSmall.Save(tnFileName, thisFormat); + } + } + + private void SaveImageCustomQuality(Bitmap imageToSave, string nomeFileFinale, long quality) + { + var jgpEncoder = GetEncoder(ImageFormat.Jpeg); + var myEncoder = System.Drawing.Imaging.Encoder.Quality; + + using var myEncoderParameters = new EncoderParameters(1); + + var myEncoderParameter = new EncoderParameter(myEncoder, quality); + myEncoderParameters.Param[0] = myEncoderParameter; + imageToSave.Save(nomeFileFinale, jgpEncoder, myEncoderParameters); + //imageToSave.Dispose(); + } + + private void MakeImageCustomQuality(Bitmap imageToSave, Stream destinationStream, long quality) + { + var jgpEncoder = GetEncoder(ImageFormat.Jpeg); + var myEncoder = System.Drawing.Imaging.Encoder.Quality; + + using var myEncoderParameters = new EncoderParameters(1); + + var myEncoderParameter = new EncoderParameter(myEncoder, quality); + myEncoderParameters.Param[0] = myEncoderParameter; + destinationStream.Seek(0, SeekOrigin.Begin); + imageToSave.Save(destinationStream, jgpEncoder, myEncoderParameters); + //imageToSave.Dispose(); + } + + private ImageCodecInfo GetEncoder(ImageFormat format) + { + var codecs = ImageCodecInfo.GetImageDecoders(); + + foreach (var codec in codecs) + { + if (codec.FormatID == format.Guid) + return codec; + } + + return null /* TODO Change to default(_) if this is not a reference type */; + } + + /// + /// ''' Calculate the Size of the New image + /// ''' + /// ''' Larghezza + /// ''' Altezza + /// ''' + /// ''' + /// ''' + /// ''' + private Size CalculateThumbnailSize(int currentwidth, int currentheight, int maxPixel, string tipoSize) + { + // e + // *** Larghezza, Altezza, Auto + + double tempMultiplier; + + if (tipoSize.ToUpper() == "Larghezza".ToUpper()) + tempMultiplier = maxPixel / (double)currentwidth; + else if (tipoSize.ToUpper() == "Altezza".ToUpper()) + tempMultiplier = maxPixel / (double)currentheight; + else if (currentheight > currentwidth) + tempMultiplier = maxPixel / (double)currentheight; + else + tempMultiplier = maxPixel / (double)currentwidth; + + var newSize = new Size(System.Convert.ToInt32(currentwidth * tempMultiplier), + System.Convert.ToInt32(currentheight * tempMultiplier)); + + return newSize; + } + private void SetVerticalPosition(int imgHeight, float textHeight, ImageState imgState) { switch (picSettings.Posizione.ToUpper()) @@ -379,437 +787,4 @@ public class ImageCreatorSharp(PicSettings picSettings, ILogger System.Convert.ToSingle(g.Width)) - { - var conta = imgState.DimensioneStandard; - do - { - if (conta > 20) - conta -= 5; - else - conta -= 1; - if (picSettings.Grassetto == true) - crFont = new Font(picSettings.IlFont, conta, FontStyle.Bold); - else - crFont = new Font(picSettings.IlFont, conta); - crSize = grPhoto.MeasureString(imgState.TestoFirma, crFont); - if (crSize.Width < System.Convert.ToSingle(g.Width)) - { - larghezzaStandard = System.Convert.ToInt32(crSize.Width); - break; - } - - if (conta <= 5) - break; - } while (true); - - imgState.DimensioneStandard = conta; - } - - switch (picSettings.Posizione.ToUpper()) - { - case "ALTO": - { - imgState.YPosFromBottom = (picSettings.Margine); - imgState.YPosFromBottom3 = (picSettings.MargVert); - break; - } - - case "BASSO": - { - imgState.YPosFromBottom = - System.Convert.ToSingle((g.Height - crSize.Height - - (g.Height * picSettings.Margine / (double)100))); - imgState.YPosFromBottom3 = - System.Convert.ToSingle( - (g.Height - crSize.Height - (g.Height * picSettings.MargVert / (double)100))); - break; - } - } - - float xCenterOfImg = 0; - float xCenterOfImg3 = 0; - using var strFormat = new StringFormat(); - switch (picSettings.Allineamento.ToUpper()) - { - case "SINISTRA": - { - xCenterOfImg = System.Convert.ToSingle((picSettings.Margine + (larghezzaStandard / (double)2))); - xCenterOfImg3 = System.Convert.ToSingle((picSettings.MargVert + (larghezzaStandard / (double)2))); - if ((larghezzaStandard / (double)2) > (g.Width / (double)2) - picSettings.Margine) - xCenterOfImg = System.Convert.ToSingle((g.Width / (double)2)); - if ((larghezzaStandard / (double)2) > (g.Width / (double)2) - picSettings.MargVert) - xCenterOfImg3 = System.Convert.ToSingle((g.Width / (double)2)); - break; - } - - case "CENTRO": - { - xCenterOfImg = System.Convert.ToSingle((g.Width / (double)2)); - break; - } - - case "DESTRA": - { - xCenterOfImg = - System.Convert.ToSingle((g.Width - picSettings.Margine - (larghezzaStandard / (double)2))); - xCenterOfImg3 = - System.Convert.ToSingle((g.Width - picSettings.MargVert - (larghezzaStandard / (double)2))); - if ((larghezzaStandard / (double)2) > (g.Width / (double)2) - picSettings.Margine) - xCenterOfImg = System.Convert.ToSingle((g.Width / (double)2)); - if ((larghezzaStandard / (double)2) > (g.Width / (double)2) - picSettings.MargVert) - xCenterOfImg3 = System.Convert.ToSingle((g.Width / (double)2)); - break; - } - } - - strFormat.Alignment = StringAlignment.Center; - - using var semiTransBrush2 = new SolidBrush(Color.FromArgb(imgState.AlphaScelta, 0, 0, 0)); - // Dim semiTransBrush As SolidBrush = New SolidBrush(Color.FromArgb(AlphaScelta, _FontColoreR, _FontColoreG, _FontColoreB)) - using var semiTransBrush = new SolidBrush(Color.FromArgb(imgState.AlphaScelta, picSettings.FontColoreRGB)); - - if (imgState.FotoRuotaADestra | imgState.FotoRuotaASinistra) - { - if (picSettings.Grassetto == true) - crFont = new Font(picSettings.IlFont, picSettings.DimVert, FontStyle.Bold); - else - crFont = new Font(picSettings.IlFont, picSettings.DimVert); - } - else if (picSettings.Grassetto == true) - crFont = new Font(picSettings.IlFont, imgState.DimensioneStandard, FontStyle.Bold); - else - crFont = new Font(picSettings.IlFont, imgState.DimensioneStandard); - - - // qui scrive il testo (nomefilebig) - if (picSettings.TestoNome) - { - if (picSettings.NomeData & g.PropertyIdList.Length > 0) - { - //ExifReader DatiExif = new ExifReader((Bitmap)g); - imgState.DataFoto = imgState.CreationDate ?? DateTime.Now; //DatiExif.DateTimeOriginal; - - grPhoto.DrawString((imgState.NomeFileBig + " " + imgState.DataFoto.ToShortDateString()), crFont, - semiTransBrush2, new PointF(xCenterOfImg + 1, imgState.YPosFromBottom + 1), strFormat); - grPhoto.DrawString((imgState.NomeFileBig + " " + imgState.DataFoto.ToShortDateString()), crFont, - semiTransBrush, new PointF(xCenterOfImg, imgState.YPosFromBottom), strFormat); - } - else - { - grPhoto.DrawString(imgState.NomeFileBig, crFont, semiTransBrush2, - new PointF(xCenterOfImg + 1, imgState.YPosFromBottom + 1), strFormat); - grPhoto.DrawString(imgState.NomeFileBig, crFont, semiTransBrush, - new PointF(xCenterOfImg, imgState.YPosFromBottom), strFormat); - } - } - - if (picSettings.TestoNome == false) - { - if (imgState.FotoRuotaADestra | imgState.FotoRuotaASinistra) - { - if (picSettings.TestoMin == false) - { - grPhoto.DrawString(imgState.TestoFirmaV, crFont, semiTransBrush2, - new PointF(xCenterOfImg + 1, imgState.YPosFromBottom3 + 1), strFormat); - grPhoto.DrawString(imgState.TestoFirmaV, crFont, semiTransBrush, - new PointF(xCenterOfImg, imgState.YPosFromBottom3), strFormat); - } - - if (picSettings.TestoMin == true) - { - grPhoto.DrawString(imgState.TestoFirmaV, crFont, semiTransBrush2, - new PointF(xCenterOfImg + 1, imgState.YPosFromBottom4 + 1), strFormat); - grPhoto.DrawString(imgState.TestoFirmaV, crFont, semiTransBrush, - new PointF(xCenterOfImg, imgState.YPosFromBottom4), strFormat); - } - } - else - { - grPhoto.DrawString(imgState.TestoFirma, crFont, semiTransBrush2, - new PointF(xCenterOfImg + 1, imgState.YPosFromBottom + 1), strFormat); - grPhoto.DrawString(imgState.TestoFirma, crFont, semiTransBrush, - new PointF(xCenterOfImg, imgState.YPosFromBottom), strFormat); - } - } - - if (string.Equals(picSettings.DirectorySorgente, picSettings.DirectoryDestinazione, - StringComparison.OrdinalIgnoreCase)) - { - imgState.NomeFileBig2 = imgState.NomeFileBig; - imgState.NomeFileBig = $"{imgState.NomeFileBig[..^4]}{picSettings.Codice}{imgState.NomeFileBig[^4..]}"; - } - //grPhoto.Dispose(); - - crFont?.Dispose(); - } - - private void AggiungiLogo(Bitmap imgOutputBig, ImageState imgState, Image logo) - { - // imgOutputBig - if (!(picSettings.LogoAggiungi == true & File.Exists(picSettings.LogoNomeFile))) return; - // using var ImmagineLogo = Image.FromFile(_picSettings.LogoNomeFile); - - var logoColoreTrasparente = Color.White; - - // * Load this Bitmap into a new Graphic Object - using var grWatermark = Graphics.FromImage(imgOutputBig); - using ImageAttributes imageAttributes = new ImageAttributes(); - - // * The first step replace the background color with one that is transparent (Alpha=0, R=0, G=0, B=0) - var colorMap = new ColorMap - { - // * background this will be the color we search for and replace with transparency - OldColor = logoColoreTrasparente, - NewColor = Color.FromArgb(0, 0, 0, 0) - }; - - var remapTable = new[] { colorMap }; - 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 - var colorMatrixElements = new[] - { - new float[] { 1.0F, 0.0F, 0.0F, 0.0F, 0.0F }, new float[] { 0.0F, 1.0F, 0.0F, 0.0F, 0.0F }, - new float[] { 0.0F, 0.0F, 1.0F, 0.0F, 0.0F }, - new float[] { 0.0F, 0.0F, 0.0F, System.Convert.ToSingle(picSettings.LogoTrasparenza) / 100F, 0.0F }, - new float[] { 0.0F, 0.0F, 0.0F, 0.0F, 1.0F } - }; - var wmColorMatrix = new ColorMatrix(colorMatrixElements); - imageAttributes.SetColorMatrix(wmColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); - - var fotoLogoH = picSettings.LogoAltezza; - var fotoLogoW = picSettings.LogoLarghezza; - var fattoreAlt = logo.Height / (double)fotoLogoH; - var fattoreLarg = logo.Width / (double)fotoLogoW; - var nuovaSize = fattoreLarg > fattoreAlt - ? NewthumbSize(logo.Width, logo.Height, fotoLogoW, "Larghezza") - : NewthumbSize(logo.Width, logo.Height, fotoLogoH, "Altezza"); - - var inPercentualeL = picSettings.LogoMargine.EndsWith('%'); - var margineL = System.Convert.ToInt32(picSettings.LogoMargine); - var margineUsato = - inPercentualeL ? System.Convert.ToInt32(imgOutputBig.Height * margineL / (double)100) : margineL; - - int xPosOfWm = 0; - int yPosOfWm = 0; - switch (picSettings.LogoPosizioneH.ToUpper()) - { - case "SINISTRA": - case "NESSUNA": - { - xPosOfWm = margineUsato; - break; - } - - case "CENTRO": - { - xPosOfWm = System.Convert.ToInt32((imgOutputBig.Width - nuovaSize.Width) / (double)2); - break; - } - - case "DESTRA": - { - xPosOfWm = ((imgOutputBig.Width - nuovaSize.Width) - margineUsato); - break; - } - } - - switch (picSettings.LogoPosizioneV.ToUpper()) - { - case "ALTO": - case "NESSUNA": - { - yPosOfWm = margineUsato; - break; - } - - case "CENTRO": - { - yPosOfWm = System.Convert.ToInt32((imgOutputBig.Height - nuovaSize.Height) / (double)2); - break; - } - - case "BASSO": - { - yPosOfWm = ((imgOutputBig.Height - nuovaSize.Height) - margineUsato); - break; - } - } - - grWatermark.DrawImage(logo, new Rectangle(xPosOfWm, yPosOfWm, nuovaSize.Width, nuovaSize.Height), 0, 0, - logo.Width, logo.Height, GraphicsUnit.Pixel, imageAttributes); - //grWatermark.Dispose(); - } - - - private void SalvaFoto(Bitmap imgOutputBig, ImageState imgState, ImageFormat thisFormat) - { - var fileName = Path.Combine(imgState.DestDir.FullName, imgState.NomeFileBig); - - using var image1Stream = new MemoryStream(); - if (picSettings.FotoGrandeDimOrigina == false) - { - // attenzione non controlla se è png - // imgOutputBig.Save(Path.Combine(_DestDir.FullName, "Temp_" & NomeFileBig), thisFormat) - if (thisFormat.Equals(ImageFormat.Jpeg)) - { - MakeImageCustomQuality(imgOutputBig, image1Stream); - } - //SalvaImmagineCustomQuality(imgOutputBig, Path.Combine(DestDir.FullName, "Temp_" + NomeFileBig), _picSettings.jpegQuality); - else - { - imgOutputBig.Save(image1Stream, thisFormat); - } - - //imgOutputBig.Save(Path.Combine(DestDir.FullName, "Temp_" + NomeFileBig), thisFormat); - image1Stream.Seek(0, SeekOrigin.Begin); - using var g2 = Image.FromStream(image1Stream); - imgState.ThumbSizeBig = g2.Width > g2.Height - ? NewthumbSize(g2.Width, g2.Height, picSettings.LarghezzaBig, "Larghezza") - : NewthumbSize(g2.Width, g2.Height, picSettings.AltezzaBig, "Altezza"); - using var imgOutputBig2 = new Bitmap(g2, imgState.ThumbSizeBig.Width, imgState.ThumbSizeBig.Height); - - if (!picSettings.OverwriteFiles && File.Exists(fileName)) - { - logger.LogInformation("Saltata foto {FileName}, esiste", fileName); - } - else - { - if (thisFormat.Equals(ImageFormat.Jpeg)) - SalvaImmagineCustomQuality(imgOutputBig2, fileName, picSettings.JpegQuality); - else - imgOutputBig2.Save(fileName, thisFormat); - } - } - else - { - if (!picSettings.OverwriteFiles && File.Exists(fileName)) - { - logger.LogInformation("Saltata foto {FileName}, esiste", fileName); - } - else - { - if (thisFormat.Equals(ImageFormat.Jpeg)) - SalvaImmagineCustomQuality(imgOutputBig, fileName, picSettings.JpegQuality); - else - imgOutputBig.Save(fileName, thisFormat); - } - } - - image1Stream.Seek(0, SeekOrigin.Begin); - - if (!picSettings.CreaMiniature) return; - if (!picSettings.AggiungiScritteMiniature) return; - - using var g1 = picSettings.FotoGrandeDimOrigina ? (Image)imgOutputBig.Clone() : Image.FromStream(image1Stream); - - using var imgOutputSmall = new Bitmap(g1, imgState.ThumbSizeSmall.Width, imgState.ThumbSizeSmall.Height); - - if (string.Equals(picSettings.DirectorySorgente, picSettings.DirectoryDestinazione, - StringComparison.OrdinalIgnoreCase)) - imgState.NomeFileSmall = imgState.NomeFileSmall.Substring(0, imgState.NomeFileSmall.Length - 4) + - picSettings.Codice + - imgState.NomeFileSmall.Substring(imgState.NomeFileSmall.Length - 4); - - var tnFileName = Path.Combine(imgState.DestDir.FullName, imgState.NomeFileSmall); - - if (!picSettings.OverwriteFiles && File.Exists(tnFileName)) - { - logger.LogInformation("Saltata miniatura foto {TnFileName}, esiste", tnFileName); - } - else - { - if (thisFormat.Equals(ImageFormat.Jpeg)) - SalvaImmagineCustomQuality(imgOutputSmall, tnFileName, picSettings.JpegQualityMin); - else - imgOutputSmall.Save(tnFileName, thisFormat); - } - } - - private void SalvaImmagineCustomQuality(Bitmap imageToSave, string nomeFileFinale, long quality) - { - var jgpEncoder = GetEncoder(ImageFormat.Jpeg); - var myEncoder = System.Drawing.Imaging.Encoder.Quality; - - using var myEncoderParameters = new EncoderParameters(1); - - var myEncoderParameter = new EncoderParameter(myEncoder, picSettings.JpegQuality); - myEncoderParameters.Param[0] = myEncoderParameter; - imageToSave.Save(nomeFileFinale, jgpEncoder, myEncoderParameters); - //imageToSave.Dispose(); - } - - private void MakeImageCustomQuality(Bitmap imageToSave, Stream destinationStream) - { - var jgpEncoder = GetEncoder(ImageFormat.Jpeg); - var myEncoder = System.Drawing.Imaging.Encoder.Quality; - - using var myEncoderParameters = new EncoderParameters(1); - - var myEncoderParameter = new EncoderParameter(myEncoder, picSettings.JpegQuality); - myEncoderParameters.Param[0] = myEncoderParameter; - destinationStream.Seek(0, SeekOrigin.Begin); - imageToSave.Save(destinationStream, jgpEncoder, myEncoderParameters); - //imageToSave.Dispose(); - } - - private ImageCodecInfo GetEncoder(ImageFormat format) - { - var codecs = ImageCodecInfo.GetImageDecoders(); - - foreach (var codec in codecs) - { - if (codec.FormatID == format.Guid) - return codec; - } - - return null /* TODO Change to default(_) if this is not a reference type */; - } - - /// - /// ''' Calculate the Size of the New image - /// ''' - /// ''' Larghezza - /// ''' Altezza - /// ''' - /// ''' - /// ''' - /// ''' - private Size NewthumbSize(int currentwidth, int currentheight, int maxPixel, string tipoSize) - { - // e - // *** Larghezza, Altezza, Auto - - double tempMultiplier; - - if (tipoSize.ToUpper() == "Larghezza".ToUpper()) - tempMultiplier = maxPixel / (double)currentwidth; - else if (tipoSize.ToUpper() == "Altezza".ToUpper()) - tempMultiplier = maxPixel / (double)currentheight; - else if (currentheight > currentwidth) - tempMultiplier = maxPixel / (double)currentheight; - else - tempMultiplier = maxPixel / (double)currentwidth; - - var newSize = new Size(System.Convert.ToInt32(currentwidth * tempMultiplier), - System.Convert.ToInt32(currentheight * tempMultiplier)); - - return newSize; - } -} \ No newline at end of file +} diff --git a/MaddoShared/MaddoShared.csproj b/MaddoShared/MaddoShared.csproj index ffb858a..4a37e7c 100644 --- a/MaddoShared/MaddoShared.csproj +++ b/MaddoShared/MaddoShared.csproj @@ -1,6 +1,6 @@  - net9.0-windows + net10.0-windows Library false true diff --git a/imagecatalog/ImageCatalog 2.csproj b/imagecatalog/ImageCatalog 2.csproj index 2d2ba7b..16182e5 100644 --- a/imagecatalog/ImageCatalog 2.csproj +++ b/imagecatalog/ImageCatalog 2.csproj @@ -1,7 +1,7 @@  WinExe - net9.0-windows + net10.0-windows enable enable true