From 7b9d67fe7b9fa618f34cbcb1ef06a28c27f6d38e Mon Sep 17 00:00:00 2001
From: Dustin
Date: Sat, 17 May 2025 22:44:47 -0600
Subject: [PATCH 01/11] Converted to use skia raw
---
CommonImageActions.Core/ImageProcessor.cs | 160 +++++++++++++++-------
CommonImageActions.Pdf/PdfProcessor.cs | 2 +-
2 files changed, 109 insertions(+), 53 deletions(-)
diff --git a/CommonImageActions.Core/ImageProcessor.cs b/CommonImageActions.Core/ImageProcessor.cs
index e3882b2..6079608 100644
--- a/CommonImageActions.Core/ImageProcessor.cs
+++ b/CommonImageActions.Core/ImageProcessor.cs
@@ -1,5 +1,4 @@
using Microsoft.Maui.Graphics;
-using Microsoft.Maui.Graphics.Skia;
using SkiaSharp;
using System;
using System.Collections.Generic;
@@ -91,25 +90,25 @@ await Task.Run(() =>
if (isVirtual)
{
- Color virtualImageColor = null;
+ SKColor virtualImageColor;
//set the text color
if (!string.IsNullOrEmpty(actions.ImageColor))
{
//try regular
- if (Color.TryParse(actions.ImageColor, out var newColor))
+ if (SKColor.TryParse(actions.ImageColor, out var newColor))
{
virtualImageColor = newColor;
}
//try hex
- else if (Color.TryParse($"#{actions.ImageColor}", out var newColorFromHex))
+ else if (SKColor.TryParse($"#{actions.ImageColor}", out var newColorFromHex))
{
virtualImageColor = newColorFromHex;
}
//fall back to white if they both fail
else
{
- virtualImageColor = Colors.Black;
+ virtualImageColor = SKColors.Black;
}
}
else if (actions.ChooseImageColorFromTextValue.HasValue
@@ -123,24 +122,24 @@ await Task.Run(() =>
{
backgroundColor = $"#{backgroundColor}";
}
- if (Color.TryParse(backgroundColor, out var newColor))
+ if (SKColor.TryParse(backgroundColor, out var newColor))
{
virtualImageColor = newColor;
}
else
{
- virtualImageColor = Colors.Black;
+ virtualImageColor = SKColors.Black;
}
}
else
{
- virtualImageColor = Colors.Black;
+ virtualImageColor = SKColors.Black;
}
var newBitmap = new SKBitmap(100, 100);
using var canvas = new SKCanvas(newBitmap);
- canvas.Clear(virtualImageColor.AsSKColor());
- using var newImage = new SkiaImage(newBitmap);
+ canvas.Clear(virtualImageColor);
+ using var newImage = SKImage.FromBitmap(newBitmap);
encodedImage = EncodeSkiaImage(newImage, actions);
}
else
@@ -148,7 +147,7 @@ await Task.Run(() =>
using var stream = new MemoryStream(imageData);
using var codec = SKCodec.Create(stream);
using var originalBitmap = SKBitmap.Decode(codec);
- using var newImage = new SkiaImage(originalBitmap);
+ using var newImage = SKImage.FromBitmap(originalBitmap);
encodedImage = EncodeSkiaImage(newImage, actions, codec);
}
@@ -162,7 +161,7 @@ await Task.Run(() =>
return encodedImage.ToArray();
}
- public static SKData EncodeSkiaImage(SkiaImage newImage, ImageActions imageActions, SKCodec codec = null)
+ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions, SKCodec codec = null)
{
//make sure image was loaded successfully
if (newImage == null)
@@ -215,8 +214,10 @@ public static SKData EncodeSkiaImage(SkiaImage newImage, ImageActions imageActio
}
// Create a new bitmap with the new dimensions
- var skBmp = new SkiaBitmapExportContext(imageActions.Width.Value, imageActions.Height.Value, 1.0f);
- var canvas = skBmp.Canvas;
+ var skBmp = new SKBitmap(imageActions.Width.Value, imageActions.Height.Value);
+ var recorder = new SKPictureRecorder();
+ var rect = new SKRect(0, 0, imageActions.Width.Value, imageActions.Height.Value);
+ var canvas = recorder.BeginRecording(rect);
//if no shape specified, but a corner radius is then set shape to rounded rectangle
if (imageActions.Shape.HasValue == false && imageActions.CornerRadius.HasValue)
@@ -239,28 +240,31 @@ public static SKData EncodeSkiaImage(SkiaImage newImage, ImageActions imageActio
var centerX = imageActions.Width.Value / 2;
var centerY = imageActions.Height.Value / 2;
- var a = new PathF();
- a.AppendCircle(centerX, centerY, radius);
+ var a = new SKPath();
+ a.AddCircle(centerX, centerY, radius);
canvas.ClipPath(a);
}
else if (imageActions.Shape == ImageShape.Ellipse)
{
- var a = new PathF();
+ var a = new SKPath();
var centerX = imageActions.Width.Value / 2;
var centerY = imageActions.Height.Value / 2;
- a.AppendEllipse(0, 0, imageActions.Width.Value, imageActions.Height.Value);
+ var r = new SKRect(0, 0, imageActions.Width.Value, imageActions.Height.Value);
+ a.AddOval(r);
canvas.ClipPath(a);
}
else if (imageActions.Shape == ImageShape.RoundedRectangle)
{
- var a = new PathF();
+ var a = new SKPath();
+ var r = new SKRect(0, 0, imageActions.Width.Value, imageActions.Height.Value);
if (imageActions.CornerRadius.HasValue)
{
- a.AppendRoundedRectangle(0, 0, imageActions.Width.Value, imageActions.Height.Value, imageActions.CornerRadius.Value);
+
+ a.AddRoundRect(r, imageActions.CornerRadius.Value, imageActions.CornerRadius.Value);
}
else
{
- a.AppendRoundedRectangle(0, 0, imageActions.Width.Value, imageActions.Height.Value, CornerRadius);
+ a.AddRoundRect(r, CornerRadius, CornerRadius);
}
canvas.ClipPath(a);
}
@@ -279,33 +283,33 @@ public static SKData EncodeSkiaImage(SkiaImage newImage, ImageActions imageActio
break;
case SKEncodedOrigin.TopRight:
- canvas.Rotate(180, imageActions.Width.Value / 2, imageActions.Height.Value / 2);
+ canvas.RotateDegrees(180, imageActions.Width.Value / 2, imageActions.Height.Value / 2);
break;
case SKEncodedOrigin.BottomRight:
- canvas.Rotate(180, imageActions.Width.Value / 2, imageActions.Height.Value / 2);
+ canvas.RotateDegrees(180, imageActions.Width.Value / 2, imageActions.Height.Value / 2);
break;
case SKEncodedOrigin.BottomLeft:
break;
case SKEncodedOrigin.LeftTop:
- canvas.Rotate(90, imageActions.Width.Value / 2, imageActions.Height.Value / 2);
+ canvas.RotateDegrees(90, imageActions.Width.Value / 2, imageActions.Height.Value / 2);
isOddRotation = true;
break;
case SKEncodedOrigin.RightTop:
- canvas.Rotate(90, imageActions.Width.Value / 2, imageActions.Height.Value / 2);
+ canvas.RotateDegrees(90, imageActions.Width.Value / 2, imageActions.Height.Value / 2);
isOddRotation = true;
break;
case SKEncodedOrigin.RightBottom:
- canvas.Rotate(270, imageActions.Width.Value / 2, imageActions.Height.Value / 2);
+ canvas.RotateDegrees(270, imageActions.Width.Value / 2, imageActions.Height.Value / 2);
isOddRotation = true;
break;
case SKEncodedOrigin.LeftBottom:
- canvas.Rotate(270, imageActions.Width.Value / 2, imageActions.Height.Value / 2);
+ canvas.RotateDegrees(270, imageActions.Width.Value / 2, imageActions.Height.Value / 2);
isOddRotation = true;
break;
}
@@ -330,11 +334,13 @@ public static SKData EncodeSkiaImage(SkiaImage newImage, ImageActions imageActio
case ImageMode.Max:
if (isOddRotation)
{
- canvas.DrawImage(newImage, rotationOffsetX, rotationOffsetY, imageActions.Height.Value, imageActions.Width.Value);
+ var drawRect = new SKRect(rotationOffsetX, rotationOffsetY, imageActions.Height.Value, imageActions.Width.Value);
+ canvas.DrawImage(newImage, drawRect);
}
else
{
- canvas.DrawImage(newImage, 0, 0, imageActions.Width.Value, imageActions.Height.Value);
+ var drawRect = new SKRect(0, 0, imageActions.Width.Value, imageActions.Height.Value);
+ canvas.DrawImage(newImage, drawRect);
}
break;
@@ -349,7 +355,9 @@ public static SKData EncodeSkiaImage(SkiaImage newImage, ImageActions imageActio
var fitScaledHeight = (int)(newImage.Height * fitScale);
var fitOffsetX = (imageActions.Width.Value - fitScaledWidth) / 2;
var fitOffsetY = (imageActions.Height.Value - fitScaledHeight) / 2;
- canvas.DrawImage(newImage, fitOffsetX, fitOffsetY, fitScaledWidth, fitScaledHeight);
+ var drawRect2 = new SKRect(fitOffsetX, fitOffsetY, fitScaledWidth, fitScaledHeight);
+
+ canvas.DrawImage(newImage, drawRect2);
break;
//zoom in and fill canvas while maintaing aspect ratio
@@ -363,7 +371,8 @@ public static SKData EncodeSkiaImage(SkiaImage newImage, ImageActions imageActio
var scaledHeight = (int)(newImage.Height * scale);
var offsetX = (imageActions.Width.Value - scaledWidth) / 2;
var offsetY = (imageActions.Height.Value - scaledHeight) / 2;
- canvas.DrawImage(newImage, offsetX, offsetY, scaledWidth, scaledHeight);
+ var drawRect3 = new SKRect(offsetX, offsetY, scaledWidth, scaledHeight);
+ canvas.DrawImage(newImage, drawRect3);
break;
}
@@ -377,55 +386,63 @@ public static SKData EncodeSkiaImage(SkiaImage newImage, ImageActions imageActio
textToPrint = GetInitials(imageActions.Text);
}
- var myFont = new Font("Arial", weight: 800);
+ var myTypeface = SKTypeface.FromFamilyName("Arial", SKFontStyle.Bold);
var myFontSize = (int)(imageActions.Height.Value * 0.85);
- canvas.Font = myFont;
+
+ // Set up paint for text
+ using var paint = new SKPaint
+ {
+ Typeface = myTypeface,
+ IsAntialias = true,
+ TextSize = myFontSize,
+ Color = SKColors.Black, // Default text color
+ TextAlign = SKTextAlign.Center
+ };
//calculate string size where height is image height to get scale of text
- var textSize = canvas.GetStringSize(textToPrint, myFont, myFontSize);
+ var textSize = paint.MeasureText(textToPrint);
//specify the max width that is wanted
var maxWidth = imageActions.Width.Value * 0.75;
// it needs to fit in the image, so if it is too narrow then we need to shrink down the font
- if (textSize.Width > maxWidth)
+ if (textSize > maxWidth)
{
- myFontSize = (int)((maxWidth / textSize.Width) * myFontSize);
+ myFontSize = (int)((maxWidth / textSize) * myFontSize);
}
- //calculate the text size again with the new font size
- var point = new Point(
- x: (skBmp.Width - textSize.Width) / 2,
- y: (skBmp.Height - textSize.Height) / 2);
- var myTextRectangle = new Rect(point, textSize);
- canvas.FontSize = myFontSize;
+ // Calculate maximum font size to fit text within the image
+ paint.TextSize = myFontSize;
//set the text color
if (!string.IsNullOrEmpty(imageActions.TextColor))
{
//try regular
- if (Color.TryParse(imageActions.TextColor, out var newColor))
+ if (SKColor.TryParse(imageActions.TextColor, out var newColor))
{
- canvas.FontColor = newColor;
+ paint.Color = newColor;
}
//try hex
- else if (Color.TryParse($"#{imageActions.TextColor}", out var newColorFromHex))
+ else if (SKColor.TryParse($"#{imageActions.TextColor}", out var newColorFromHex))
{
- canvas.FontColor = newColorFromHex;
+ paint.Color = newColorFromHex;
}
//fall back to white if they both fail
else
{
- canvas.FontColor = Colors.White;
+ paint.Color = SKColors.White;
}
}
else
{
- canvas.FontColor = Colors.White;
+ paint.Color = SKColors.White;
}
- canvas.DrawString(textToPrint, myTextRectangle, HorizontalAlignment.Center, VerticalAlignment.Center, TextFlow.OverflowBounds);
+ // Calculate text position
+ var x = imageActions.Width.Value / 2f;
+ var y = (imageActions.Height.Value / 2f) - ((paint.FontMetrics.Ascent + paint.FontMetrics.Descent) / 2);
+ canvas.DrawText(textToPrint, x, y, paint);
}
//set export format
@@ -444,24 +461,63 @@ public static SKData EncodeSkiaImage(SkiaImage newImage, ImageActions imageActio
//set encoding quality
SKData encodedImage = null;
+ var picture = recorder.EndRecording();
+ var ouputSize = new SKSizeI(imageActions.Width.Value, imageActions.Height.Value);
+ var outputImage = SKImage.FromPicture(picture, ouputSize);
switch (exportImageType)
{
default:
- encodedImage = skBmp.SKImage.Encode(exportImageType, 100);
+ encodedImage = outputImage.Encode(exportImageType, 100);
break;
case SKEncodedImageFormat.Jpeg:
- encodedImage = skBmp.SKImage.Encode(SKEncodedImageFormat.Jpeg, JpegQuality);
+ encodedImage = outputImage.Encode(SKEncodedImageFormat.Jpeg, JpegQuality);
break;
case SKEncodedImageFormat.Gif:
- encodedImage = skBmp.SKImage.Encode(SKEncodedImageFormat.Gif, GifQuality);
+ encodedImage = outputImage.Encode(SKEncodedImageFormat.Gif, GifQuality);
break;
}
return encodedImage;
}
+ public static float GetMaxFontSize(double sectorSize, SKTypeface typeface, string text, float degreeOfCertainty = 1f, float maxFont = 100f)
+ {
+ var max = maxFont; // The upper bound. We know the font size is below this value
+ var min = 0f; // The lower bound, We know the font size is equal to or above this value
+ var last = -1f; // The last calculated value.
+ float value;
+ while (true)
+ {
+ value = min + ((max - min) / 2); // Find the half way point between Max and Min
+ using (SKFont ft = new SKFont(typeface, value))
+ using (SKPaint paint = new SKPaint(ft))
+ {
+ if (paint.MeasureText(text) > sectorSize) // Measure the string size at this font size
+ {
+ // The text size is too large
+ // therefore the max possible size is below value
+ last = value;
+ max = value;
+ }
+ else
+ {
+ // The text fits within the area
+ // therefore the min size is above or equal to value
+ min = value;
+
+ // Check if this value is within our degree of certainty
+ if (Math.Abs(last - value) <= degreeOfCertainty)
+ return last; // Value is within certainty range, we found the best font size!
+
+ //This font difference is not within our degree of certainty
+ last = value;
+ }
+ }
+ }
+ }
+
public static UInt64 CalculateHash(string read)
{
UInt64 hashedValue = 3074457345618258791ul;
diff --git a/CommonImageActions.Pdf/PdfProcessor.cs b/CommonImageActions.Pdf/PdfProcessor.cs
index e5acad4..6788490 100644
--- a/CommonImageActions.Pdf/PdfProcessor.cs
+++ b/CommonImageActions.Pdf/PdfProcessor.cs
@@ -151,7 +151,7 @@ await Task.Run(() =>
//convert into skia format
using var originalBitmap = SKBitmap.Decode(bmpData);
- using var newImage = new SkiaImage(originalBitmap);
+ using var newImage = SKImage.FromBitmap(originalBitmap);
//process skia image into encoded image
returnValue = ImageProcessor.EncodeSkiaImage(newImage, actions).ToArray();
From 4aac96963d82db38172984fae8b41163a37bbcaa Mon Sep 17 00:00:00 2001
From: Dustin
Date: Sat, 17 May 2025 22:56:36 -0600
Subject: [PATCH 02/11] Fixed blurryness issue with filter quality paint
property
---
CommonImageActions.Core/ImageProcessor.cs | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/CommonImageActions.Core/ImageProcessor.cs b/CommonImageActions.Core/ImageProcessor.cs
index 6079608..1935e89 100644
--- a/CommonImageActions.Core/ImageProcessor.cs
+++ b/CommonImageActions.Core/ImageProcessor.cs
@@ -324,6 +324,12 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
rotationOffsetX = rotationOffsetY * -1;
}
+ var imagePaint = new SKPaint
+ {
+ IsAntialias = true,
+ FilterQuality = SKFilterQuality.High
+ };
+
//write to the canvas
switch (imageActions.Mode)
{
@@ -335,12 +341,12 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
if (isOddRotation)
{
var drawRect = new SKRect(rotationOffsetX, rotationOffsetY, imageActions.Height.Value, imageActions.Width.Value);
- canvas.DrawImage(newImage, drawRect);
+ canvas.DrawImage(newImage, drawRect, paint:imagePaint);
}
else
{
var drawRect = new SKRect(0, 0, imageActions.Width.Value, imageActions.Height.Value);
- canvas.DrawImage(newImage, drawRect);
+ canvas.DrawImage(newImage, drawRect, paint: imagePaint);
}
break;
@@ -357,7 +363,7 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
var fitOffsetY = (imageActions.Height.Value - fitScaledHeight) / 2;
var drawRect2 = new SKRect(fitOffsetX, fitOffsetY, fitScaledWidth, fitScaledHeight);
- canvas.DrawImage(newImage, drawRect2);
+ canvas.DrawImage(newImage, drawRect2, paint: imagePaint);
break;
//zoom in and fill canvas while maintaing aspect ratio
@@ -372,7 +378,7 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
var offsetX = (imageActions.Width.Value - scaledWidth) / 2;
var offsetY = (imageActions.Height.Value - scaledHeight) / 2;
var drawRect3 = new SKRect(offsetX, offsetY, scaledWidth, scaledHeight);
- canvas.DrawImage(newImage, drawRect3);
+ canvas.DrawImage(newImage, drawRect3, paint: imagePaint);
break;
}
From 0f27ca25bf3e59e67ca6ee361e5a8a4ad13c14eb Mon Sep 17 00:00:00 2001
From: Dustin
Date: Sat, 17 May 2025 23:03:20 -0600
Subject: [PATCH 03/11] Removed test that tested internal components
---
.../ImageProcessorTests.cs | 16 ----------------
1 file changed, 16 deletions(-)
diff --git a/CommonImageActions.Core.Tests/ImageProcessorTests.cs b/CommonImageActions.Core.Tests/ImageProcessorTests.cs
index 849f7a7..d634678 100644
--- a/CommonImageActions.Core.Tests/ImageProcessorTests.cs
+++ b/CommonImageActions.Core.Tests/ImageProcessorTests.cs
@@ -115,22 +115,6 @@ public async Task ProcessVirtualImageAsync_ShouldReturnProcessedImage()
Assert.NotEmpty(result);
}
- [Fact]
- public void EncodeSkiaImage_ShouldReturnEncodedImage()
- {
- // Arrange
- var bitmap = new SKBitmap(100, 100);
- using var canvas = new SKCanvas(bitmap);
- using var newImage = new SkiaImage(bitmap);
- var actions = new ImageActions();
-
- // Act
- var result = ImageProcessor.EncodeSkiaImage(newImage, actions);
-
- // Assert
- Assert.NotNull(result);
- }
-
[Fact]
public void GetInitials_ShouldReturnInitials()
{
From 60a2c037a972743a8bf73f8f2247c06c4fcc876e Mon Sep 17 00:00:00 2001
From: Dustin
Date: Sun, 18 May 2025 10:22:12 -0600
Subject: [PATCH 04/11] Removed unused function
---
CommonImageActions.Core/ImageProcessor.cs | 36 -----------------------
1 file changed, 36 deletions(-)
diff --git a/CommonImageActions.Core/ImageProcessor.cs b/CommonImageActions.Core/ImageProcessor.cs
index 1935e89..d15f9ab 100644
--- a/CommonImageActions.Core/ImageProcessor.cs
+++ b/CommonImageActions.Core/ImageProcessor.cs
@@ -488,42 +488,6 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
return encodedImage;
}
- public static float GetMaxFontSize(double sectorSize, SKTypeface typeface, string text, float degreeOfCertainty = 1f, float maxFont = 100f)
- {
- var max = maxFont; // The upper bound. We know the font size is below this value
- var min = 0f; // The lower bound, We know the font size is equal to or above this value
- var last = -1f; // The last calculated value.
- float value;
- while (true)
- {
- value = min + ((max - min) / 2); // Find the half way point between Max and Min
- using (SKFont ft = new SKFont(typeface, value))
- using (SKPaint paint = new SKPaint(ft))
- {
- if (paint.MeasureText(text) > sectorSize) // Measure the string size at this font size
- {
- // The text size is too large
- // therefore the max possible size is below value
- last = value;
- max = value;
- }
- else
- {
- // The text fits within the area
- // therefore the min size is above or equal to value
- min = value;
-
- // Check if this value is within our degree of certainty
- if (Math.Abs(last - value) <= degreeOfCertainty)
- return last; // Value is within certainty range, we found the best font size!
-
- //This font difference is not within our degree of certainty
- last = value;
- }
- }
- }
- }
-
public static UInt64 CalculateHash(string read)
{
UInt64 hashedValue = 3074457345618258791ul;
From cfdd3adc4fdce8aa9bbf0ff55b19630b6f6896da Mon Sep 17 00:00:00 2001
From: Dustin
Date: Sun, 18 May 2025 10:24:19 -0600
Subject: [PATCH 05/11] Thickened text to match old style
---
CommonImageActions.Core/ImageProcessor.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CommonImageActions.Core/ImageProcessor.cs b/CommonImageActions.Core/ImageProcessor.cs
index d15f9ab..77eba6b 100644
--- a/CommonImageActions.Core/ImageProcessor.cs
+++ b/CommonImageActions.Core/ImageProcessor.cs
@@ -392,7 +392,7 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
textToPrint = GetInitials(imageActions.Text);
}
- var myTypeface = SKTypeface.FromFamilyName("Arial", SKFontStyle.Bold);
+ var myTypeface = SKTypeface.FromFamilyName("Arial", SKFontStyleWeight.Black, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright);
var myFontSize = (int)(imageActions.Height.Value * 0.85);
// Set up paint for text
From d85332eadcd538100ed51fa0dbe5d62cd7aab995 Mon Sep 17 00:00:00 2001
From: Dustin
Date: Sun, 18 May 2025 10:34:32 -0600
Subject: [PATCH 06/11] Removed the ability to support named colors
---
CommonImageActions.Core/ImageProcessor.cs | 14 ++------------
.../wwwroot/index.html | 16 +++-------------
README.md | 4 ++--
3 files changed, 7 insertions(+), 27 deletions(-)
diff --git a/CommonImageActions.Core/ImageProcessor.cs b/CommonImageActions.Core/ImageProcessor.cs
index 77eba6b..267e8a8 100644
--- a/CommonImageActions.Core/ImageProcessor.cs
+++ b/CommonImageActions.Core/ImageProcessor.cs
@@ -95,13 +95,8 @@ await Task.Run(() =>
//set the text color
if (!string.IsNullOrEmpty(actions.ImageColor))
{
- //try regular
- if (SKColor.TryParse(actions.ImageColor, out var newColor))
- {
- virtualImageColor = newColor;
- }
//try hex
- else if (SKColor.TryParse($"#{actions.ImageColor}", out var newColorFromHex))
+ if (SKColor.TryParse($"#{actions.ImageColor}", out var newColorFromHex))
{
virtualImageColor = newColorFromHex;
}
@@ -423,13 +418,8 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
//set the text color
if (!string.IsNullOrEmpty(imageActions.TextColor))
{
- //try regular
- if (SKColor.TryParse(imageActions.TextColor, out var newColor))
- {
- paint.Color = newColor;
- }
//try hex
- else if (SKColor.TryParse($"#{imageActions.TextColor}", out var newColorFromHex))
+ if (SKColor.TryParse($"#{imageActions.TextColor}", out var newColorFromHex))
{
paint.Color = newColorFromHex;
}
diff --git a/CommonImageActions.SampleAspnetCoreProject/wwwroot/index.html b/CommonImageActions.SampleAspnetCoreProject/wwwroot/index.html
index b9b729b..4dd2819 100644
--- a/CommonImageActions.SampleAspnetCoreProject/wwwroot/index.html
+++ b/CommonImageActions.SampleAspnetCoreProject/wwwroot/index.html
@@ -132,16 +132,6 @@ Initials
-
-
-
-
-
-
Color Named
-
/test/thumbsUp.jpg?w=100&h=100&f=png&t=DustinG&in=true&tc=blue
-
-
-
@@ -155,10 +145,10 @@
Color Hex
-
+
-
Background Color (Manual)
-
/test/thumbsUp.jpg?w=100&h=100&f=png&t=DustinG&in=true&tc=00ff00&c=red
+
Background Color (Manual Hex)
+
/test/thumbsUp.jpg?w=100&h=100&f=png&t=DustinG&in=true&tc=00ff00&c=0000ff
diff --git a/README.md b/README.md
index 107ac49..c2803ce 100644
--- a/README.md
+++ b/README.md
@@ -160,8 +160,8 @@ app.UseCommonImageActions(
| corner, cr | Integer | The corner radius when shape is RoundedRectangle. Default is 10. |
| text, t | String | The text to display on the image |
| initials, in | Boolean | When true will only display initials of text. For example DustinG is displayed as DG. |
-| color, c | String (ffccff or blue) | Set a color for the image |
-| textColor, tc | String (ffccff or blue) | Set the color of the text |
+| color, c | String ffccff | Set a color for the image |
+| textColor, tc | String ffccff | Set the color of the text |
| colorFromText, ft | Boolean | When true a color will be generated based on a hash of the text. The list of colors can be updated in `ImageProcessor.BackgroundColours`. |
| format, f | Bmp, Gif, Ico, Jpeg, Png, Wbmp, Webp, Pkm, Ktx, Astc, Dng, Heif, Avif | What format to export the resulting image as. Default is png. |
| password, pw | String | (pdf only) password to open pdf |
From 10510ba6c9b736434529d39fe94abd2d5740ac93 Mon Sep 17 00:00:00 2001
From: Dustin
Date: Sun, 18 May 2025 10:36:26 -0600
Subject: [PATCH 07/11] Fixed typo in example
---
CommonImageActions.SampleAspnetCoreProject/wwwroot/index.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/CommonImageActions.SampleAspnetCoreProject/wwwroot/index.html b/CommonImageActions.SampleAspnetCoreProject/wwwroot/index.html
index 4dd2819..62434a5 100644
--- a/CommonImageActions.SampleAspnetCoreProject/wwwroot/index.html
+++ b/CommonImageActions.SampleAspnetCoreProject/wwwroot/index.html
@@ -27,7 +27,7 @@ Stretch (Default)
Max
- /test/thumbsUp.jpg?s=circle&w=100&h=100&m=zoom&f=png
+ /test/thumbsUp.jpg?s=circle&w=100&h=100&m=Max&f=png
@@ -37,7 +37,7 @@ Max
Fit
- /test/thumbsUp.jpg?s=ellipse&w=100&h=100&m=zoom&f=png
+ /test/thumbsUp.jpg?s=ellipse&w=100&h=100&m=Fit&f=png
From d37e39e79cc23c05da750eb633901e6db9242a24 Mon Sep 17 00:00:00 2001
From: Dustin
Date: Sun, 18 May 2025 11:00:48 -0600
Subject: [PATCH 08/11] Fixed a major calculation error with the conversion
---
CommonImageActions.Core/ImageProcessor.cs | 25 ++++++++++++++---------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/CommonImageActions.Core/ImageProcessor.cs b/CommonImageActions.Core/ImageProcessor.cs
index 267e8a8..e9c80e1 100644
--- a/CommonImageActions.Core/ImageProcessor.cs
+++ b/CommonImageActions.Core/ImageProcessor.cs
@@ -211,7 +211,7 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
// Create a new bitmap with the new dimensions
var skBmp = new SKBitmap(imageActions.Width.Value, imageActions.Height.Value);
var recorder = new SKPictureRecorder();
- var rect = new SKRect(0, 0, imageActions.Width.Value, imageActions.Height.Value);
+ var rect = GetSKRectByWidthAndHeight(0, 0, imageActions.Width.Value, imageActions.Height.Value);
var canvas = recorder.BeginRecording(rect);
//if no shape specified, but a corner radius is then set shape to rounded rectangle
@@ -244,14 +244,14 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
var a = new SKPath();
var centerX = imageActions.Width.Value / 2;
var centerY = imageActions.Height.Value / 2;
- var r = new SKRect(0, 0, imageActions.Width.Value, imageActions.Height.Value);
+ var r = GetSKRectByWidthAndHeight(0, 0, imageActions.Width.Value, imageActions.Height.Value);
a.AddOval(r);
canvas.ClipPath(a);
}
else if (imageActions.Shape == ImageShape.RoundedRectangle)
{
var a = new SKPath();
- var r = new SKRect(0, 0, imageActions.Width.Value, imageActions.Height.Value);
+ var r = GetSKRectByWidthAndHeight(0, 0, imageActions.Width.Value, imageActions.Height.Value);
if (imageActions.CornerRadius.HasValue)
{
@@ -335,12 +335,12 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
case ImageMode.Max:
if (isOddRotation)
{
- var drawRect = new SKRect(rotationOffsetX, rotationOffsetY, imageActions.Height.Value, imageActions.Width.Value);
+ var drawRect = GetSKRectByWidthAndHeight(rotationOffsetX, rotationOffsetY, imageActions.Height.Value, imageActions.Width.Value);
canvas.DrawImage(newImage, drawRect, paint:imagePaint);
}
else
{
- var drawRect = new SKRect(0, 0, imageActions.Width.Value, imageActions.Height.Value);
+ var drawRect = GetSKRectByWidthAndHeight(0, 0, imageActions.Width.Value, imageActions.Height.Value);
canvas.DrawImage(newImage, drawRect, paint: imagePaint);
}
break;
@@ -354,11 +354,11 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
}
var fitScaledWidth = (int)(newImage.Width * fitScale);
var fitScaledHeight = (int)(newImage.Height * fitScale);
- var fitOffsetX = (imageActions.Width.Value - fitScaledWidth) / 2;
- var fitOffsetY = (imageActions.Height.Value - fitScaledHeight) / 2;
- var drawRect2 = new SKRect(fitOffsetX, fitOffsetY, fitScaledWidth, fitScaledHeight);
+ var fitOffsetX = (imageActions.Width.Value - fitScaledWidth) / 2f;
+ var fitOffsetY = (imageActions.Height.Value - fitScaledHeight) / 2f;
+ var drawRect2 = GetSKRectByWidthAndHeight(fitOffsetX, fitOffsetY, fitScaledWidth, fitScaledHeight);
- canvas.DrawImage(newImage, drawRect2, paint: imagePaint);
+ canvas.DrawImage(newImage, drawRect2);
break;
//zoom in and fill canvas while maintaing aspect ratio
@@ -372,7 +372,7 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
var scaledHeight = (int)(newImage.Height * scale);
var offsetX = (imageActions.Width.Value - scaledWidth) / 2;
var offsetY = (imageActions.Height.Value - scaledHeight) / 2;
- var drawRect3 = new SKRect(offsetX, offsetY, scaledWidth, scaledHeight);
+ var drawRect3 = GetSKRectByWidthAndHeight(offsetX, offsetY, scaledWidth, scaledHeight);
canvas.DrawImage(newImage, drawRect3, paint: imagePaint);
break;
}
@@ -478,6 +478,11 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
return encodedImage;
}
+ public static SKRect GetSKRectByWidthAndHeight(float left, float top, float width, float height)
+ {
+ return new SKRect(left, top, width + left, top + height);
+ }
+
public static UInt64 CalculateHash(string read)
{
UInt64 hashedValue = 3074457345618258791ul;
From da4d8dad386506ea13b08b2ca9fcd39268ab29df Mon Sep 17 00:00:00 2001
From: Dustin
Date: Sun, 18 May 2025 18:02:49 -0600
Subject: [PATCH 09/11] Added ignore for local item
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index 6ef84b8..d10c047 100644
--- a/.gitignore
+++ b/.gitignore
@@ -365,3 +365,4 @@ FodyWeavers.xsd
/CommonImageActions/wwwroot/cache
/CommonImageActions/wwwroot/test/thumbsUp.jpg
/CommonImageActions.SampleAspnetCoreProject/wwwroot/cache
+/CommonImageActions.SampleAspnetCoreProject/wwwroot/test/ProjectsIcon.png
From bc001c02388389aadf5e173c4b77749707ff9d19 Mon Sep 17 00:00:00 2001
From: Dustin
Date: Sat, 24 May 2025 08:56:51 -0600
Subject: [PATCH 10/11] Added antialising to borders when masking
---
CommonImageActions.Core/ImageProcessor.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/CommonImageActions.Core/ImageProcessor.cs b/CommonImageActions.Core/ImageProcessor.cs
index e9c80e1..9ad201f 100644
--- a/CommonImageActions.Core/ImageProcessor.cs
+++ b/CommonImageActions.Core/ImageProcessor.cs
@@ -237,7 +237,7 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
var a = new SKPath();
a.AddCircle(centerX, centerY, radius);
- canvas.ClipPath(a);
+ canvas.ClipPath(a, antialias:true);
}
else if (imageActions.Shape == ImageShape.Ellipse)
{
@@ -246,7 +246,7 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
var centerY = imageActions.Height.Value / 2;
var r = GetSKRectByWidthAndHeight(0, 0, imageActions.Width.Value, imageActions.Height.Value);
a.AddOval(r);
- canvas.ClipPath(a);
+ canvas.ClipPath(a, antialias:true);
}
else if (imageActions.Shape == ImageShape.RoundedRectangle)
{
@@ -261,7 +261,7 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
{
a.AddRoundRect(r, CornerRadius, CornerRadius);
}
- canvas.ClipPath(a);
+ canvas.ClipPath(a, antialias:true);
}
}
From 9ef17536e30815eb10252c3f8451826851c3037a Mon Sep 17 00:00:00 2001
From: Dustin
Date: Sat, 24 May 2025 08:57:54 -0600
Subject: [PATCH 11/11] Removed antialising on image scale
---
CommonImageActions.Core/ImageProcessor.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/CommonImageActions.Core/ImageProcessor.cs b/CommonImageActions.Core/ImageProcessor.cs
index 9ad201f..f9d9f51 100644
--- a/CommonImageActions.Core/ImageProcessor.cs
+++ b/CommonImageActions.Core/ImageProcessor.cs
@@ -321,7 +321,6 @@ public static SKData EncodeSkiaImage(SKImage newImage, ImageActions imageActions
var imagePaint = new SKPaint
{
- IsAntialias = true,
FilterQuality = SKFilterQuality.High
};