Implement ImageCreatorImageSharp using SixLabors.ImageSharp for image processing
- Added ImageCreatorImageSharp class for image creation, handling EXIF orientation, resizing, and saving images. - Replaced GDI+ dependencies with ImageSharp for cross-platform compatibility. - Introduced methods for drawing text and logos on images, including handling transparency and positioning. - Created a test plan for validating ImageCreatorImageSharp functionality, focusing on image resizing, text positioning, logo features, and EXIF orientation. - Added documentation for the test plan outlining goals, project structure, and implementation notes.
This commit is contained in:
parent
90fb03bf0c
commit
d62342aae1
11 changed files with 455 additions and 74 deletions
|
|
@ -228,23 +228,23 @@ public class ImageCreatorGDI(PicSettings picSettings, ILogger<ImageCreatorGDI> l
|
|||
}
|
||||
}
|
||||
|
||||
private void CreateThumbnails(Image sourceImage, ImageState imgState, Bitmap imgOutputBig, ImageFormat format)
|
||||
{
|
||||
// Only skip thumbnail generation when the global "create thumbnails" flag is false.
|
||||
// Whether thumbnails include text is handled by ShouldRenderText/CreateThumbnailWithText
|
||||
if (!picSettings.CreaMiniature)
|
||||
return;
|
||||
private void CreateThumbnails(Image sourceImage, ImageState imgState, Bitmap imgOutputBig, ImageFormat format)
|
||||
{
|
||||
// Only skip thumbnail generation when the global "create thumbnails" flag is false.
|
||||
// Whether thumbnails include text is handled by ShouldRenderText/CreateThumbnailWithText
|
||||
if (!picSettings.CreaMiniature)
|
||||
return;
|
||||
|
||||
PrepareSignatureText(imgState);
|
||||
PrepareSignatureText(imgState);
|
||||
|
||||
if (IsSameDirectory(picSettings.DirectorySorgente, picSettings.DirectoryDestinazione))
|
||||
UpdateFilenameWithCode(imgState);
|
||||
if (IsSameDirectory(picSettings.DirectorySorgente, picSettings.DirectoryDestinazione))
|
||||
UpdateFilenameWithCode(imgState);
|
||||
|
||||
if (ShouldRenderText())
|
||||
CreateThumbnailWithText(sourceImage, imgState, imgOutputBig, format);
|
||||
else
|
||||
CreateSimpleThumbnail(sourceImage, imgState, format);
|
||||
}
|
||||
if (ShouldRenderText())
|
||||
CreateThumbnailWithText(sourceImage, imgState, imgOutputBig, format);
|
||||
else
|
||||
CreateSimpleThumbnail(sourceImage, imgState, format);
|
||||
}
|
||||
|
||||
private void PrepareSignatureText(ImageState imgState)
|
||||
{
|
||||
|
|
@ -294,7 +294,7 @@ public class ImageCreatorGDI(PicSettings picSettings, ILogger<ImageCreatorGDI> l
|
|||
// 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;
|
||||
|
|
@ -375,20 +375,20 @@ public class ImageCreatorGDI(PicSettings picSettings, ILogger<ImageCreatorGDI> l
|
|||
switch (picSettings.Posizione.ToUpper())
|
||||
{
|
||||
case "ALTO":
|
||||
{
|
||||
imgState.YPosFromBottom = picSettings.Margine;
|
||||
imgState.YPosFromBottom3 = picSettings.MargVert;
|
||||
break;
|
||||
}
|
||||
{
|
||||
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;
|
||||
}
|
||||
{
|
||||
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;
|
||||
|
|
@ -396,27 +396,27 @@ public class ImageCreatorGDI(PicSettings picSettings, ILogger<ImageCreatorGDI> l
|
|||
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;
|
||||
}
|
||||
{
|
||||
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;
|
||||
}
|
||||
{
|
||||
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;
|
||||
}
|
||||
{
|
||||
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;
|
||||
|
|
@ -528,7 +528,7 @@ public class ImageCreatorGDI(PicSettings picSettings, ILogger<ImageCreatorGDI> l
|
|||
{
|
||||
logoTransparencyValue = 100;
|
||||
}
|
||||
|
||||
|
||||
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 },
|
||||
|
|
@ -571,44 +571,44 @@ public class ImageCreatorGDI(PicSettings picSettings, ILogger<ImageCreatorGDI> l
|
|||
{
|
||||
case "SINISTRA":
|
||||
case "NESSUNA":
|
||||
{
|
||||
xPosOfWm = margineUsato;
|
||||
break;
|
||||
}
|
||||
{
|
||||
xPosOfWm = margineUsato;
|
||||
break;
|
||||
}
|
||||
|
||||
case "CENTRO":
|
||||
{
|
||||
xPosOfWm = System.Convert.ToInt32((imgOutputBig.Width - nuovaSize.Width) / (double)2);
|
||||
break;
|
||||
}
|
||||
{
|
||||
xPosOfWm = System.Convert.ToInt32((imgOutputBig.Width - nuovaSize.Width) / (double)2);
|
||||
break;
|
||||
}
|
||||
|
||||
case "DESTRA":
|
||||
{
|
||||
xPosOfWm = ((imgOutputBig.Width - nuovaSize.Width) - margineUsato);
|
||||
break;
|
||||
}
|
||||
{
|
||||
xPosOfWm = ((imgOutputBig.Width - nuovaSize.Width) - margineUsato);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (logoV)
|
||||
{
|
||||
case "ALTO":
|
||||
case "NESSUNA":
|
||||
{
|
||||
yPosOfWm = margineUsato;
|
||||
break;
|
||||
}
|
||||
{
|
||||
yPosOfWm = margineUsato;
|
||||
break;
|
||||
}
|
||||
|
||||
case "CENTRO":
|
||||
{
|
||||
yPosOfWm = System.Convert.ToInt32((imgOutputBig.Height - nuovaSize.Height) / (double)2);
|
||||
break;
|
||||
}
|
||||
{
|
||||
yPosOfWm = System.Convert.ToInt32((imgOutputBig.Height - nuovaSize.Height) / (double)2);
|
||||
break;
|
||||
}
|
||||
|
||||
case "BASSO":
|
||||
{
|
||||
yPosOfWm = ((imgOutputBig.Height - nuovaSize.Height) - margineUsato);
|
||||
break;
|
||||
}
|
||||
{
|
||||
yPosOfWm = ((imgOutputBig.Height - nuovaSize.Height) - margineUsato);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
grWatermark.DrawImage(logo, new Rectangle(xPosOfWm, yPosOfWm, nuovaSize.Width, nuovaSize.Height), 0, 0,
|
||||
|
|
@ -776,7 +776,7 @@ public class ImageCreatorGDI(PicSettings picSettings, ILogger<ImageCreatorGDI> l
|
|||
{
|
||||
// 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())
|
||||
{
|
||||
case "ALTO":
|
||||
|
|
@ -787,18 +787,18 @@ public class ImageCreatorGDI(PicSettings picSettings, ILogger<ImageCreatorGDI> l
|
|||
case "BASSO":
|
||||
var bottomMargin1 = (float)(imgHeight * picSettings.Margine / 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;
|
||||
Loading…
Add table
Add a link
Reference in a new issue