diff --git a/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs b/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs
index 05ad7a1..0f82370 100644
--- a/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs
+++ b/IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs
@@ -14,6 +14,30 @@ public partial class AnyBitmap
{
private byte[] Binary { get; set; }
+ ///
+ /// Width of the image.
+ ///
+ public int Width
+ {
+ get
+ {
+ SkiaSharp.SKBitmap sKBitmap = SkiaSharp.SKBitmap.Decode(Binary);
+ return sKBitmap.Width;
+ }
+ }
+
+ ///
+ /// Height of the image.
+ ///
+ public int Height
+ {
+ get
+ {
+ SkiaSharp.SKBitmap sKBitmap = SkiaSharp.SKBitmap.Decode(Binary);
+ return sKBitmap.Height;
+ }
+ }
+
///
/// Number of raw image bytes stored
///
diff --git a/IronSoftware.Drawing/IronSoftware.Drawing.Common/Color.cs b/IronSoftware.Drawing/IronSoftware.Drawing.Common/Color.cs
new file mode 100644
index 0000000..a37e413
--- /dev/null
+++ b/IronSoftware.Drawing/IronSoftware.Drawing.Common/Color.cs
@@ -0,0 +1,915 @@
+using System;
+using System.Globalization;
+using System.Linq;
+
+namespace IronSoftware.Drawing
+{
+ public partial class Color
+ {
+
+ ///
+ /// Gets the alpha component value of this System.Drawing.Color structure.
+ ///
+ /// The alpha component value of this IronSoftware.Drawing.Color.
+ public byte A { get; internal set; }
+
+ ///
+ /// Gets the green component value of this System.Drawing.Color structure.
+ ///
+ /// The green component value of this IronSoftware.Drawing.Color.
+ public byte G { get; internal set; }
+
+ ///
+ /// Gets the blue component value of this System.Drawing.Color structure.
+ ///
+ /// The blue component value of this IronSoftware.Drawing.Color.
+ public byte B { get; internal set; }
+
+ ///
+ /// Gets the red component value of this System.Drawing.Color structure.
+ ///
+ /// The red component value of this IronSoftware.Drawing.Color.
+ public byte R { get; internal set; }
+
+ internal Color(string colorcode)
+ {
+ colorcode = colorcode.TrimStart('#');
+
+ if (colorcode.Length == 8)
+ {
+ this.A = (byte)int.Parse(colorcode.Substring(0, 2), NumberStyles.HexNumber);
+ this.R = (byte)int.Parse(colorcode.Substring(2, 2), NumberStyles.HexNumber);
+ this.G = (byte)int.Parse(colorcode.Substring(4, 2), NumberStyles.HexNumber);
+ this.B = (byte)int.Parse(colorcode.Substring(6, 2), NumberStyles.HexNumber);
+ }
+ else if (colorcode.Length == 6)
+ {
+ this.A = 255;
+ this.R = (byte)int.Parse(colorcode.Substring(0, 2), NumberStyles.HexNumber);
+ this.G = (byte)int.Parse(colorcode.Substring(2, 2), NumberStyles.HexNumber);
+ this.B = (byte)int.Parse(colorcode.Substring(4, 2), NumberStyles.HexNumber);
+ }
+ else if (colorcode.Length == 3)
+ {
+ this.A = 255;
+ this.R = (byte)int.Parse(string.Join("", Enumerable.Repeat(colorcode.Substring(0, 1), 2)), NumberStyles.HexNumber);
+ this.G = (byte)int.Parse(string.Join("", Enumerable.Repeat(colorcode.Substring(1, 1), 2)), NumberStyles.HexNumber);
+ this.B = (byte)int.Parse(string.Join("", Enumerable.Repeat(colorcode.Substring(2, 1), 2)), NumberStyles.HexNumber);
+ }
+ else
+ {
+ throw NoConverterException(colorcode, null);
+ }
+ }
+
+ internal Color(int alpha, int red, int green, int blue)
+ {
+ this.A = (byte)alpha;
+ this.R = (byte)red;
+ this.G = (byte)green;
+ this.B = (byte)blue;
+ }
+
+ internal Color(int red, int green, int blue)
+ {
+ this.A = 255;
+ this.R = (byte)red;
+ this.G = (byte)green;
+ this.B = (byte)blue;
+ }
+
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color AliceBlue = new Color("#F0F8FF");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color AntiqueWhite = new Color("#FAEBD7");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Aqua = new Color("#00FFFF");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Aquamarine = new Color("#7FFFD4");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Azure = new Color("#F0FFFF");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Beige = new Color("#F5F5DC");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Bisque = new Color("#FFE4C4");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Black = new Color("#000000");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color BlanchedAlmond = new Color("#FFEBCD");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Blue = new Color("#0000FF");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color BlueViolet = new Color("#8A2BE2");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Brown = new Color("#A52A2A");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color BurlyWood = new Color("#DEB887");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color CadetBlue = new Color("#5F9EA0");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Chartreuse = new Color("#7FFF00");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Chocolate = new Color("#D2691E");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Coral = new Color("#FF7F50");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color CornflowerBlue = new Color("#6495ED");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Cornsilk = new Color("#FFF8DC");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Crimson = new Color("#DC143C");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Cyan = new Color("#00FFFF");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkBlue = new Color("#00008B");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkCyan = new Color("#008B8B");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkGoldenrod = new Color("#B8860B");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkGray = new Color("#A9A9A9");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkGreen = new Color("#006400");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkKhaki = new Color("#BDB76B");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkMagenta = new Color("#8B008B");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkOliveGreen = new Color("#556B2F");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkOrange = new Color("#FF8C00");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkOrchid = new Color("#9932CC");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkRed = new Color("#8B0000");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkSalmon = new Color("#E9967A");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkSeaGreen = new Color("#8FBC8B");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkSlateBlue = new Color("#483D8B");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkSlateGray = new Color("#2F4F4F");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkTurquoise = new Color("#00CED1");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DarkViolet = new Color("#9400D3");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DeepPink = new Color("#FF1493");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DeepSkyBlue = new Color("#00BFFF");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DimGray = new Color("#696969");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color DodgerBlue = new Color("#1E90FF");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Firebrick = new Color("#B22222");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color FloralWhite = new Color("#FFFAF0");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color ForestGreen = new Color("#228B22");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Fuchsia = new Color("#FF00FF");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Gainsboro = new Color("#DCDCDC");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color GhostWhite = new Color("#F8F8FF");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Gold = new Color("#FFD700");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Goldenrod = new Color("#DAA520");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Gray = new Color("#808080");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Green = new Color("#008000");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color GreenYellow = new Color("#ADFF2F");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Honeydew = new Color("#F0FFF0");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color HotPink = new Color("#FF69B4");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color IndianRed = new Color("#CD5C5C");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Indigo = new Color("#4B0082");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Ivory = new Color("#FFFFF0");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Khaki = new Color("#F0E68C");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Lavender = new Color("#E6E6FA");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LavenderBlush = new Color("#FFF0F5");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LawnGreen = new Color("#7CFC00");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LemonChiffon = new Color("#FFFACD");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LightBlue = new Color("#ADD8E6");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LightCoral = new Color("#F08080");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LightCyan = new Color("#E0FFFF");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LightGoldenrodYellow = new Color("#FAFAD2");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LightGray = new Color("#D3D3D3");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LightGreen = new Color("#90EE90");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LightPink = new Color("#FFB6C1");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LightSalmon = new Color("#FFA07A");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LightSeaGreen = new Color("#20B2AA");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LightSkyBlue = new Color("#87CEFA");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LightSlateGray = new Color("#778899");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LightSteelBlue = new Color("#B0C4DE");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LightYellow = new Color("#FFFFE0");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Lime = new Color("#00FF00");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color LimeGreen = new Color("#32CD32");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Linen = new Color("#FAF0E6");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Magenta = new Color("#FF00FF");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Maroon = new Color("#800000");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color MediumAquamarine = new Color("#66CDAA");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color MediumBlue = new Color("#0000CD");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color MediumOrchid = new Color("#BA55D3");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color MediumPurple = new Color("#9370DB");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color MediumSeaGreen = new Color("#3CB371");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color MediumSlateBlue = new Color("#7B68EE");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color MediumSpringGreen = new Color("#00FA9A");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color MediumTurquoise = new Color("#48D1CC");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color MediumVioletRed = new Color("#C71585");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color MidnightBlue = new Color("#191970");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color MintCream = new Color("#F5FFFA");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color MistyRose = new Color("#FFE4E1");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Moccasin = new Color("#FFE4B5");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color NavajoWhite = new Color("#FFDEAD");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Navy = new Color("#000080");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color OldLace = new Color("#FDF5E6");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Olive = new Color("#808000");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color OliveDrab = new Color("#6B8E23");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Orange = new Color("#FFA500");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color OrangeRed = new Color("#FF4500");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Orchid = new Color("#DA70D6");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color PaleGoldenrod = new Color("#EEE8AA");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color PaleGreen = new Color("#98FB98");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color PaleTurquoise = new Color("#AFEEEE");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color PaleVioletRed = new Color("#DB7093");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color PapayaWhip = new Color("#FFEFD5");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color PeachPuff = new Color("#FFDAB9");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Peru = new Color("#CD853F");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Pink = new Color("#FFC0CB");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Plum = new Color("#DDA0DD");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF0F8FF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color PowderBlue = new Color("#B0E0E6");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #800080.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Purple = new Color("#800080");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #663399.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color RebeccaPurple = new Color("#663399");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FF0000.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Red = new Color("#FF0000");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #BC8F8F.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color RosyBrown = new Color("#BC8F8F");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #4169E1.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color RoyalBlue = new Color("#4169E1");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #8B4513.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color SaddleBrown = new Color("#8B4513");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FA8072.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Salmon = new Color("#FA8072");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #F4A460.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color SandyBrown = new Color("#F4A460");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #2E8B57.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color SeaGreen = new Color("#2E8B57");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFF5EE.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color SeaShell = new Color("#FFF5EE");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #A0522D.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Sienna = new Color("#A0522D");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #C0C0C0.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Silver = new Color("#C0C0C0");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #87CEEB.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color SkyBlue = new Color("#87CEEB");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #6A5ACD.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color SlateBlue = new Color("#6A5ACD");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #708090.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color SlateGray = new Color("#708090");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFFAFA.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Snow = new Color("#FFFAFA");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #00FF7F.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color SpringGreen = new Color("#00FF7F");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #4682B4.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color SteelBlue = new Color("#4682B4");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #D2B48C.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Tan = new Color("#D2B48C");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #008080.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Teal = new Color("#008080");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #D2B48C.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Thistle = new Color("#D8BFD8");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FF6347.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Tomato = new Color("#FF6347");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #40E0D0.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Turquoise = new Color("#40E0D0");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #EE82EE.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Violet = new Color("#EE82EE");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #F5DEB3.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Wheat = new Color("#F5DEB3");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFFFFF.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color White = new Color("#FFFFFF");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #F5F5F5.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color WhiteSmoke = new Color("#F5F5F5");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #FFFF00.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color Yellow = new Color("#FFFF00");
+ ///
+ /// Gets a system-defined color that has an ARGB value of #9ACD32.
+ ///
+ /// A IronSoftware.Drawing.Color representing a system-defined color.
+ public static Color YellowGreen = new Color("#9ACD32");
+
+ ///
+ /// Creates a System.Drawing.Color structure from the specified 8-bit color values
+ /// (red, green, and blue). The alpha value is implicitly 255 (fully opaque). Although
+ /// this method allows a 32-bit value to be passed for each color component, the
+ /// value of each component is limited to 8 bits.
+ ///
+ /// The red component value for the new System.Drawing.Color. Valid values are 0 through 255.
+ /// The green component value for the new System.Drawing.Color. Valid values are 0 through 255.
+ /// The blue component value for the new System.Drawing.Color. Valid values are 0 through 255.
+ ///
+ public static Color FromArgb(int red, int green, int blue)
+ {
+ return new Color(red, green, blue);
+ }
+
+ ///
+ /// Creates a System.Drawing.Color structure from the specified 8-bit color values
+ /// (red, green, and blue). The alpha value is implicitly 255 (fully opaque). Although
+ /// this method allows a 32-bit value to be passed for each color component, the
+ /// value of each component is limited to 8 bits.
+ ///
+ /// The alpha value for the new System.Drawing.Color. Valid values are 0 through 255.
+ /// The red component value for the new System.Drawing.Color. Valid values are 0 through 255.
+ /// The green component value for the new System.Drawing.Color. Valid values are 0 through 255.
+ /// The blue component value for the new System.Drawing.Color. Valid values are 0 through 255.
+ ///
+ public static Color FromArgb(int alpha, int red, int green, int blue)
+ {
+ return new Color(alpha, red, green, blue);
+ }
+
+ ///
+ /// Creates a IronSoftware.Drawing.Color structure from a 32-bit ARGB value.
+ ///
+ /// A value specifying the 32-bit ARGB value.
+ /// IronSoftware.Drawing.Color
+ public static Color FromArgb(int argb)
+ {
+ return new Color(argb.ToString("X"));
+ }
+
+ ///
+ /// L* is a value from 0 (black) to 100 (white) where 50 is the perceptual "middle grey".
+ /// L* = 50 is the equivalent of Y = 18.4, or in other words an 18% grey card, representing the middle of a photographic exposure(Ansel Adams zone V).
+ ///
+ /// Preceived Lightness
+ public double GetLuminance()
+ {
+ int vR = R / 255;
+ int vG = G / 255;
+ int vB = B / 255;
+
+ double Y = (0.2126 * SRGBtoLin(vR) + 0.7152 * SRGBtoLin(vG) + 0.0722 * SRGBtoLin(vB));
+
+ if (Y <= (216 / 24389))
+ { // The CIE standard states 0.008856 but 216/24389 is the intent for 0.008856451679036
+ return Y * (24389 / 27); // The CIE standard states 903.3, but 24389/27 is the intent, making 903.296296296296296
+ }
+ else
+ {
+ return Math.Pow(Y, (1 / 3)) * 116 - 16;
+ }
+ }
+
+ ///
+ /// Implicitly casts System.Drawing.Color objects to .
+ /// When your .NET Class methods to use as parameters and return types, you now automatically support Color as well.
+ ///
+ /// System.Drawing.Color will automatically be cast to
+ public static implicit operator Color(System.Drawing.Color Color)
+ {
+ return new Color(Color.A, Color.R, Color.G, Color.B);
+ }
+
+ ///
+ /// Implicitly casts System.Drawing.Color objects from .
+ /// When your .NET Class methods to use as parameters and return types, you now automatically support SKColor as well.
+ ///
+ /// is explicitly cast to an System.Drawing.Rectangle
+ static public implicit operator System.Drawing.Color(Color Color)
+ {
+ return System.Drawing.Color.FromArgb(Color.A, Color.R, Color.G, Color.B);
+ }
+
+ ///
+ /// Implicitly casts SkiaSharp.SKColor objects to .
+ /// When your .NET Class methods to use as parameters and return types, you now automatically support SKColor as well.
+ ///
+ /// System.Drawing.Color will automatically be cast to
+ public static implicit operator Color(SkiaSharp.SKColor Color)
+ {
+ return new Color(Color.Alpha, Color.Red, Color.Green, Color.Blue);
+ }
+
+ ///
+ /// Implicitly casts SkiaSharp.SKColor objects from .
+ /// When your .NET Class methods to use as parameters and return types, you now automatically support SKColor as well.
+ ///
+ /// is explicitly cast to an SkiaSharp.SKColor
+ static public implicit operator SkiaSharp.SKColor(Color Color)
+ {
+ return new SkiaSharp.SKColor(Color.A, Color.R, Color.G, Color.B);
+ }
+
+ #region Private Method
+
+ private static InvalidOperationException NoConverterException(string color, Exception innerException)
+ {
+ return new InvalidOperationException($"{color} is unable to convert to {typeof(Color)} because it requires a suitable length of string.", innerException);
+ }
+
+ private static double SRGBtoLin(int colorChannel)
+ {
+ // Send this function a decimal sRGB gamma encoded color value
+ // between 0.0 and 1.0, and it returns a linearized value.
+
+ if (colorChannel <= 0.04045)
+ {
+ return colorChannel / 12.92;
+ }
+ else
+ {
+ return Math.Pow(((colorChannel + 0.055) / 1.055), 2.4);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/IronSoftware.Drawing/IronSoftware.Drawing.Common/IronBitmap.cs b/IronSoftware.Drawing/IronSoftware.Drawing.Common/IronBitmap.cs
new file mode 100644
index 0000000..27b556e
--- /dev/null
+++ b/IronSoftware.Drawing/IronSoftware.Drawing.Common/IronBitmap.cs
@@ -0,0 +1,295 @@
+using SkiaSharp;
+using System;
+
+namespace IronSoftware.Drawing
+{
+ public static class IronBitmap
+ {
+ ///
+ /// Resize an image with scale.
+ ///
+ /// Original bitmap to resize.
+ /// Scale of new image 0 - 1.
+ /// IronSoftware.Drawing.AnyBitmap.
+ public static AnyBitmap Resize(this AnyBitmap bitmap, float scale)
+ {
+ SKBitmap originalBitmap = bitmap;
+ SKBitmap toBitmap = new SKBitmap((int)(originalBitmap.Width * scale), (int)(originalBitmap.Height * scale), originalBitmap.ColorType, originalBitmap.AlphaType);
+
+ using (SKCanvas canvas = new SKCanvas(toBitmap))
+ {
+ // Draw a bitmap rescaled
+ canvas.SetMatrix(SKMatrix.MakeScale(scale, scale));
+ canvas.DrawBitmap(originalBitmap, 0, 0);
+ canvas.ResetMatrix();
+ canvas.Flush();
+ }
+
+ return toBitmap;
+ }
+
+ ///
+ /// Resize an image with width and height.
+ ///
+ /// Original bitmap to resize.
+ /// Width ot the new resized image.
+ /// Height ot the new resized image.
+ /// IronSoftware.Drawing.AnyBitmap.
+ public static AnyBitmap Resize(this AnyBitmap bitmap, int width, int height)
+ {
+ SKBitmap originalBitmap = bitmap;
+ SKBitmap toBitmap = new SKBitmap(width, height, originalBitmap.ColorType, originalBitmap.AlphaType);
+ originalBitmap.ExtractSubset(toBitmap, new CropRectangle(0, 0, width, height));
+
+ return toBitmap;
+ }
+
+ ///
+ /// Resize an image with width and height.
+ ///
+ /// Original bitmap to resize.
+ /// Width ot the new resized image.
+ /// Height ot the new resized image.
+ /// Ratio of new image 0 - 1.
+ /// IronSoftware.Drawing.AnyBitmap.
+ public static AnyBitmap Resize(this AnyBitmap bitmap, int width, int height, float ratio)
+ {
+ SKBitmap originalBitmap = bitmap;
+ SKBitmap toBitmap = new SKBitmap(width, height, originalBitmap.ColorType, originalBitmap.AlphaType);
+
+ using (SKCanvas canvas = new SKCanvas(toBitmap))
+ {
+ // Draw a bitmap rescaled
+ canvas.SetMatrix(SKMatrix.MakeScale(ratio, ratio));
+ canvas.DrawBitmap(originalBitmap, 0, 0);
+ canvas.ResetMatrix();
+ canvas.Flush();
+ }
+
+ return toBitmap;
+ }
+
+ ///
+ /// Resize an image with width and height.
+ ///
+ /// Original bitmap to resize.
+ /// CropArea to crop an image.
+ /// IronSoftware.Drawing.AnyBitmap.
+ public static AnyBitmap CropImage(this AnyBitmap bitmap, CropRectangle cropRect)
+ {
+ if (cropRect != null)
+ {
+ CropRectangle dest = ValidateCropArea(bitmap, cropRect);
+ SKBitmap croppedBitmap = new SKBitmap((int)dest.Width, (int)dest.Height);
+ try
+ {
+ using (SKCanvas canvas = new SKCanvas(croppedBitmap))
+ {
+ canvas.DrawBitmap(bitmap, cropRect, dest);
+ canvas.Flush();
+ }
+
+ return croppedBitmap;
+ }
+ catch (OutOfMemoryException)
+ {
+ try { croppedBitmap.Dispose(); } catch { }
+ throw new Exception("Crop Rectangle is larger than the input image.");
+ }
+ }
+ else
+ {
+ return bitmap;
+ }
+ }
+
+ ///
+ /// Rotate an image.
+ ///
+ /// Original bitmap to resize.
+ /// Angle for rotate image. Default (null): Try to find the image angle.
+ /// IronSoftware.Drawing.AnyBitmap.
+ public static AnyBitmap RotateImage(this AnyBitmap bitmap, double? angle = null)
+ {
+ double skewAngle = angle ?? SkewImageLib.GetSkewAngle(bitmap);
+ double radians = Math.PI * skewAngle / 180;
+ float sine = (float)Math.Abs(Math.Sin(radians));
+ float cosine = (float)Math.Abs(Math.Cos(radians));
+
+ int originalWidth = ((SKBitmap)bitmap).Width;
+ int originalHeight = ((SKBitmap)bitmap).Height;
+ int rotatedWidth = (int)(cosine * originalWidth + sine * originalHeight);
+ int rotatedHeight = (int)(cosine * originalHeight + sine * originalWidth);
+
+ SKBitmap rotatedBitmap = new SKBitmap(rotatedWidth, rotatedHeight);
+
+ using (SKCanvas canvas = new SKCanvas(rotatedBitmap))
+ {
+ canvas.Clear(SKColors.LightPink);
+ canvas.Translate(rotatedWidth / 2, rotatedHeight / 2);
+ canvas.RotateDegrees((float)angle);
+ canvas.Translate(-originalWidth / 2, -originalHeight / 2);
+ canvas.DrawBitmap(bitmap, new SKPoint());
+ }
+
+ return rotatedBitmap;
+ }
+
+ ///
+ /// Find angle of the image.
+ ///
+ /// Original bitmap to resize.
+ /// Angle of the image in double.
+ public static double GetSkewAngle(this AnyBitmap bitmap)
+ {
+ return SkewImageLib.GetSkewAngle(bitmap);
+ }
+
+ ///
+ /// Trim white space of the image.
+ ///
+ /// Original bitmap to trim.
+ /// IronSoftware.Drawing.AnyBitmap.
+ public static SKBitmap Trim(this AnyBitmap bitmap)
+ {
+
+ try
+ {
+ SKBitmap originalBitmap = bitmap;
+ int[] rgbValues = new int[originalBitmap.Height * originalBitmap.Width];
+
+ // Determine Left
+ int newLeft = -1;
+ for (int x = 0; x < originalBitmap.Width; x++)
+ {
+ for (int y = 0; y < originalBitmap.Height; y++)
+ {
+ SKColor color = originalBitmap.GetPixel(x, y);
+ if (color != SKColors.White)
+ {
+ newLeft = x;
+ break;
+ }
+ }
+ if (newLeft != -1)
+ break;
+ }
+ // Determine Right
+ int newRight = -1;
+ for (int x = originalBitmap.Width - 1; x >= 0; x--)
+ {
+ for (int y = 0; y < originalBitmap.Height; y++)
+ {
+ SKColor color = originalBitmap.GetPixel(x, y);
+ if (color != SKColors.White)
+ {
+ newRight = x;
+ break;
+ }
+ }
+ if (newRight != -1)
+ break;
+ }
+ // Determine Bottom
+ int newBottom = -1;
+ for (int y = 0; y < originalBitmap.Height; y++)
+ {
+ for (int x = 0; x < originalBitmap.Width; x++)
+ {
+ SKColor color = originalBitmap.GetPixel(x, y);
+ if (color != SKColors.White)
+ {
+ newBottom = x;
+ break;
+ }
+ }
+ if (newBottom != -1)
+ break;
+ }
+ // Determine Top
+ int newTop = -1;
+ for (int y = originalBitmap.Height - 1; y >= 0; y--)
+ {
+ for (int x = 0; x < originalBitmap.Width; x++)
+ {
+ SKColor color = originalBitmap.GetPixel(x, y);
+ if (color != SKColors.White)
+ {
+ newTop = x;
+ break;
+ }
+ }
+ if (newTop != -1)
+ break;
+ }
+
+ return CropImage(bitmap, new SKRect(newLeft, newTop, newRight, newBottom));
+ }
+ catch
+ {
+ return bitmap.Clone();
+ }
+ }
+
+ ///
+ /// Add border to the image.
+ ///
+ /// Original bitmap to trim.
+ /// Background color of the border.
+ /// Size of the border in pixel.
+ /// IronSoftware.Drawing.AnyBitmap.
+ public static AnyBitmap AddBorder(this AnyBitmap bitmap, IronSoftware.Drawing.Color color, int size)
+ {
+ SKBitmap originalBitmap = bitmap;
+ int maxWidth = originalBitmap.Width + size * 2;
+ int maxHeight = originalBitmap.Height + size * 2;
+ SKBitmap toBitmap = new SKBitmap(maxWidth, maxHeight);
+
+ var ratioX = (double)maxWidth / originalBitmap.Width;
+ var ratioY = (double)maxHeight / originalBitmap.Height;
+ var ratio = (float)Math.Min(ratioX, ratioY);
+
+ using (SKCanvas canvas = new SKCanvas(toBitmap))
+ {
+ canvas.SetMatrix(SKMatrix.MakeScale(ratio, ratio));
+ canvas.Clear(color);
+ int x = (toBitmap.Width - originalBitmap.Width) / 2;
+ int y = (toBitmap.Height - originalBitmap.Height) / 2;
+ canvas.DrawBitmap(bitmap, x, y);
+ canvas.ResetMatrix();
+ canvas.Flush();
+ }
+
+ return toBitmap;
+ }
+
+ #region Private Method
+
+ private static CropRectangle ValidateCropArea(SKBitmap img, CropRectangle CropArea)
+ {
+ int maxWidth = img.Width;
+ int maxHeight = img.Height;
+
+ int cropAreaX = CropArea.X > 0 ? CropArea.X : 0;
+ int cropAreaY = CropArea.Y > 0 ? CropArea.Y : 0;
+ int cropAreaWidth = CropArea.Width > 0 ? CropArea.Width : img.Width;
+ int cropAreaHeight = CropArea.Height > 0 ? CropArea.Height : img.Height;
+
+ int croppedWidth = cropAreaX + cropAreaWidth;
+ int croppedHeight = cropAreaY + cropAreaHeight;
+
+ int newWidth = cropAreaWidth;
+ int newHeight = cropAreaHeight;
+ if (croppedWidth > maxWidth)
+ {
+ newWidth = maxWidth - cropAreaX;
+ }
+ if (croppedHeight > maxHeight)
+ {
+ newHeight = maxHeight - cropAreaY;
+ }
+ return new CropRectangle(cropAreaX, cropAreaY, newWidth, newHeight);
+ }
+ #endregion
+ }
+}
diff --git a/IronSoftware.Drawing/IronSoftware.Drawing.Common/SkewImageLib.cs b/IronSoftware.Drawing/IronSoftware.Drawing.Common/SkewImageLib.cs
new file mode 100644
index 0000000..54badb5
--- /dev/null
+++ b/IronSoftware.Drawing/IronSoftware.Drawing.Common/SkewImageLib.cs
@@ -0,0 +1,181 @@
+using SkiaSharp;
+using System;
+
+namespace IronSoftware.Drawing
+{
+ internal class SkewImageLib
+ {
+ // Representation of a line in the image.
+ private class HougLine
+ {
+ // Count of points in the line.
+ public int Count;
+ // Index in Matrix.
+ public int Index;
+ // The line is represented as all x,y that solve y*cos(alpha)-x*sin(alpha)=d
+ public double Alpha;
+ }
+
+
+ // The Bitmap
+ private static SKBitmap _internalBmp;
+
+ // The range of angles to search for lines
+ const double ALPHA_START = -20;
+ const double ALPHA_STEP = 0.2;
+ const int STEPS = 40 * 5;
+ const double STEP = 1;
+
+ // Precalculation of sin and cos.
+ private static double[] _sinA;
+ private static double[] _cosA;
+
+ // Range of d
+ private static double _min;
+
+
+ private static int _count;
+ // Count of points that fit in a line.
+ private static int[] _hMatrix;
+
+ // Calculate the skew angle of the image cBmp.
+ internal static double GetSkewAngle(SKBitmap bitmap)
+ {
+ _internalBmp = bitmap;
+
+ // Hough Transformation
+ Calc();
+
+ // Top 20 of the detected lines in the image.
+ HougLine[] hl = GetTop(20);
+
+ // Average angle of the lines
+ double sum = 0;
+ int count = 0;
+ for (int i = 0; i <= 19; i++)
+ {
+ sum += hl[i].Alpha;
+ count += 1;
+ }
+ return sum / count;
+ }
+
+ // Calculate the Count lines in the image with most points.
+ private static HougLine[] GetTop(int count)
+ {
+ HougLine[] hl = new HougLine[count];
+
+ for (int i = 0; i <= count - 1; i++)
+ {
+ hl[i] = new HougLine();
+ }
+ for (int i = 0; i <= _hMatrix.Length - 1; i++)
+ {
+ if (_hMatrix[i] > hl[count - 1].Count)
+ {
+ hl[count - 1].Count = _hMatrix[i];
+ hl[count - 1].Index = i;
+ int j = count - 1;
+ while (j > 0 && hl[j].Count > hl[j - 1].Count)
+ {
+ HougLine tmp = hl[j];
+ hl[j] = hl[j - 1];
+ hl[j - 1] = tmp;
+ j -= 1;
+ }
+ }
+ }
+
+ for (int i = 0; i <= count - 1; i++)
+ {
+ int dIndex = hl[i].Index / STEPS;
+ int alphaIndex = hl[i].Index - dIndex * STEPS;
+ hl[i].Alpha = GetAlpha(alphaIndex);
+ //hl[i].D = dIndex + _min;
+ }
+
+ return hl;
+ }
+
+
+ // Hough Transforamtion:
+ private static void Calc()
+ {
+ int hMin = _internalBmp.Height / 4;
+ int hMax = _internalBmp.Height * 3 / 4;
+
+ Init();
+ for (int y = hMin; y <= hMax; y++)
+ {
+ for (int x = 1; x <= _internalBmp.Width - 2; x++)
+ {
+ // Only lower edges are considered.
+ if (IsBlack(x, y))
+ {
+ if (!IsBlack(x, y + 1))
+ {
+ Calc(x, y);
+ }
+ }
+ }
+ }
+ }
+
+ // Calculate all lines through the point (x,y).
+ private static void Calc(int x, int y)
+ {
+ int alpha;
+
+ for (alpha = 0; alpha <= STEPS - 1; alpha++)
+ {
+ double d = y * _cosA[alpha] - x * _sinA[alpha];
+ int calculatedIndex = (int)CalcDIndex(d);
+ int index = calculatedIndex * STEPS + alpha;
+ try
+ {
+ _hMatrix[index] += 1;
+ }
+ catch (Exception ex)
+ {
+ System.Diagnostics.Debug.WriteLine(ex.ToString());
+ }
+ }
+ }
+ private static double CalcDIndex(double d)
+ {
+ return Convert.ToInt32(d - _min);
+ }
+ private static bool IsBlack(int x, int y)
+ {
+ SKColor c = _internalBmp.GetPixel(x, y);
+ double luminance = (c.Red * 0.299) + (c.Green * 0.587) + (c.Blue * 0.114);
+ return luminance < 140;
+ }
+
+ private static void Init()
+ {
+ // Precalculation of sin and cos.
+ _cosA = new double[STEPS];
+ _sinA = new double[STEPS];
+
+ for (int i = 0; i < STEPS; i++)
+ {
+ double angle = GetAlpha(i) * Math.PI / 180.0;
+ _sinA[i] = Math.Sin(angle);
+ _cosA[i] = Math.Cos(angle);
+ }
+
+ // Range of d:
+ _min = -_internalBmp.Width;
+ _count = (int)(2 * (_internalBmp.Width + _internalBmp.Height) / STEP);
+ _hMatrix = new int[_count * STEPS];
+
+
+ }
+
+ private static double GetAlpha(int index)
+ {
+ return ALPHA_START + index * ALPHA_STEP;
+ }
+ }
+}