Graphics Programming and Image Processing in .NET Core 2.x
In .NET Core 2.x, Windows Forms or WPF are not implemented since they are based on GDI+ and DirectX respectively in Windows. In .NET Core 3.0, there is plan to add Desktop Packs which includes UWP. WPF and Windows Forms. However, they will still be Windows-only. In .NET Core applications, you may need to generate or process images. To do that, there are quite a few third party libraries you can use even they don’t implement all the functionalities in .NET Framework. For example, the following open source projects are available to use:
- CoreCompat.System.Drawing
- ImageSharp
- Magick.NET
- SkiaSharp
- FreeImage-dotnet-core
- MagicScaler
- …
In Microsoft official .NET blog, there is a post summarizes these core features of these libraries and performance comparisons.
In this page, I am going to show you how to draw a captcha image using CoreCompat.System.Drawing.
Sample code
The following code snippet shows how to create a bitmap image and save to HTTP response stream.
The main steps used are listed below:
- Instantiate a Bitmap object
- Use the Bitmap object to create a Graphics object
- Use the Graphics object to draw strings and lines. Font style and colour brushes can be applied. For these .NET core libraries, not all the .NET Framework brushes or fonts are implemented.
- Save the Bitmap object as file or into streams.
The code is very similar to the one I created in one of the previous posts.
private void ProcessRequest(HttpContext context)
{
// Setup output format
context.Response.ContentType = "image/gif";
Random random = new Random();
// Generate random characters
StringBuilder s = new StringBuilder();
// Create the image
using (Bitmap bitmap = new Bitmap(captchaOptions.ImageWidth, captchaOptions.ImageHeight))
{
// Create the graphics
using (Graphics graphics = Graphics.FromImage(bitmap))
{
// Write bg color
graphics.FillRectangle(new SolidBrush(bgColor), 0, 0, captchaOptions.ImageWidth, captchaOptions.ImageHeight);
// Font
using (Font font = new Font(FontFamily.GenericSerif, 32, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Pixel))
{
for (int i = 0; i < captchaOptions.CodeLength; i++)
{
s.Append(captchaOptions.CaptchaString.Substring(random.Next(0, captchaOptions.CaptchaString.Length - 1), 1));
// Write char to the graphic
graphics.DrawString(s[s.Length - 1].ToString(), font, new SolidBrush(codeColor), i * 32, random.Next(0, 24));
}
}
// Add obstructions
using (Pen pen = new Pen(new SolidBrush(this.obsColor), 1))
{
for (int i = 0; i < 10; i++)
{
graphics.DrawLine(pen, new Point(random.Next(0, captchaOptions.ImageWidth - 1), random.Next(0, captchaOptions.ImageHeight - 1)), new Point(random.Next(0, captchaOptions.ImageWidth - 1), random.Next(0, captchaOptions.ImageHeight - 1)));
}
}
for (int i = 0; i < 100; i++)
{
bitmap.SetPixel(random.Next(captchaOptions.ImageWidth), random.Next(captchaOptions.ImageHeight), Color.FromArgb(random.Next()));
}
context.Session.Set(captchaOptions.SessionName, Encoding.UTF8.GetBytes(s.ToString().ToLower()));
// Save image
bitmap.Save(context.Response.Body, System.Drawing.Imaging.ImageFormat.Gif);
}
}
}
Sample output
The following is a sample captcha image in this website.