Draw Images in ASP.NET Core 5
access_time 3 months ago languageEnglish
more_vert

Draw Images in ASP.NET Core 5

visibility 161 comment 0

System.Drawing package is added back to .NET 5. It provides common GDI+ graphics to draw images: System.Drawing.Bitmap, System.Drawing.BitmapData, System.Drawing.Brush, System.Drawing.Font, System.Drawing.Graphics, System.Drawing.Icon and etc. Previously we have to use third-party libraries to draw images in .NET Core 2.x/3.x as article Graphics Programming and Image Processing in .NET Core 2.x shows. This article provides detailed steps to implement the same in ASP.NET 5 applications. 

Prerequisites

.NET 5 SDK is required to create projects through command line. Refer to page .NET 5 is Officially Released for more details about .NET.

Create sample ASP.NET project

Use the following commands to create a sample project:

mkdir dotnet5-drawing
cd dotnet5-drawing
dotnet new webapp

The project structure looks like the following screenshot:

Add package reference 

The package required is available here NuGet Gallery | System.Drawing.Common 5.0.1.

Use the following command to add reference to the package:

dotnet add package System.Drawing.Common --version 5.0.1

After this, the project file will be updated accordingly:

  <ItemGroup>
    <PackageReference Include="System.Drawing.Common" Version="5.0.1" />
  </ItemGroup>

Add a controller

Let's add a controller class to draw images. Follow these steps:

1) Add package reference

dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design  

Or upgrade it already exists:

dotnet tool update --global dotnet-aspnet-codegenerator 

2) Add a controller class

Generate a controller class using template:

dotnet aspnet-codegenerator --project . controller  -name CaptchaController

A new class file named CaptchaController.cs will be generated. 

Update controller

Update the controller implementation to draw a captcha image in the response.

Replace the content with the following:

using System;
using System.Drawing;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace dotnet5_drawing
{
    [Route("/api/[controller]")]
    public class CaptchaController : Controller
    {
        // Background color 
        private readonly Color bgColor = Color.FromArgb(0xe9, 0xec, 0xef);
        // Code color 
        private readonly Color codeColor = Color.FromArgb(0x00, 0x69, 0xd9);
        // Obstruction color 
        private readonly Color obsColor = Color.FromArgb(0x28, 0xa7, 0x45);

        [HttpGet]
        [AllowAnonymous]
        public async Task IndexAsync()
        {
            var (content, contentType) = GenerateCaptchaImage();
            HttpContext.Response.ContentType = contentType;
            await HttpContext.Response.BodyWriter.WriteAsync(content);
        }

        private (byte[] content, string contentType) GenerateCaptchaImage()
        {
            // Setup output format
            var contentType = "image/png";
            // Image width
            const int imageWidth = 150;
            // Image height
            const int imageHeight = 50;
            // Captcha code length
            const int captchaCodeLength = 4;
            // Captcha code string, all the possible chars that can appear in the image.
            const string captchaCodeString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

            Random random = new Random();
            // Generate random characters
            StringBuilder s = new StringBuilder();
            using var ms = new MemoryStream();

            // Create the image
            using Bitmap bitmap = new Bitmap(imageWidth, imageHeight);
            // Create the graphics 
            using Graphics graphics = Graphics.FromImage(bitmap);
            // Write bg color
            graphics.FillRectangle(new SolidBrush(bgColor), 0, 0, imageWidth, imageHeight);

            // Add obstructions
            using (Pen pen = new Pen(new SolidBrush(obsColor), 2))
            {
                for (int i = 0; i < 10; i++)
                {
                    graphics.DrawLine(pen, new Point(random.Next(0, imageWidth - 1), random.Next(0, imageHeight - 1)), new Point(random.Next(0, imageWidth - 1), random.Next(0, imageHeight - 1)));
                }
            }
            for (int i = 0; i < 100; i++)
            {
                bitmap.SetPixel(random.Next(imageWidth), random.Next(imageHeight), Color.FromArgb(random.Next()));
            }

            // Font
            using (Font font = new Font(FontFamily.GenericMonospace, 32, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Pixel))
            {
                for (int i = 0; i < captchaCodeLength; i++)
                {
                    s.Append(captchaCodeString.Substring(random.Next(0, captchaCodeString.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));
                }
            }
            // Save image, image format type is consistent with response content type.
            bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
            return (ms.ToArray(), contentType);
        }
    }
}

The controller will be exposed via route /api/captcha.

The most important logic is implemented in function GenerateCaptchaImage. This function does the following:

  • Use namespace System.Drawing.
  • Instantiate a Bitmap object which is then used to instantiate Graphics object.
  • The Graphics object is used to draw lines, dots and characters. The characters are randomly selected from a predefined string. The color and formats of these drawings are defined by the pens/brushes.  The position of the characters are randomly decided too.
  • At last the bitmap binary content is save to a memory stream which is eventually output to the HTTP response stream. 

Update Startup.cs

We need to update Startup.cs file to ensure controller routes are mapped and exposed:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            //...

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
                endpoints.MapControllers();
            });
        }

Build and run the application

Now we can build and run the application using the following command:

dotnet build
dotnet run

The output of the last command looks something like the following:

Building...
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: F:\Projects\dotnet5-drawing

The image can be viewed via opening the following URL in your browser:

https://localhost:5001/api/captcha

The captcha image looks like the following screenshot:

Add image to Razor pages

You can also add the image in other pages. For example, the following code snippet displays the image in Index page:

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
    <p><img src="/api/captcha" /></p>
</div>
The index page looks like the following screenshot:


Summarize

It's very easy to use System.Drawing.Common package to draw images in ASP.NET Core or .NET core. For more information about GDI+, refer to GDI+ - Win32 apps | Microsoft Docs.

info Last modified by Raymond 3 months ago copyright This page is subject to Site terms.
Like this article?
Share on

Please log in or register to comment.

account_circle Log in person_add Register

Log in with external accounts

Follow Kontext

Get our latest updates on LinkedIn.

Want to contribute on Kontext to help others?

Learn more

More from Kontext

visibility 971
thumb_up 0
access_time 2 years ago
Introduction to C# Interactive
visibility 903
thumb_up 0
access_time 8 months ago
visibility 33
thumb_up 0
access_time 7 months ago
visibility 885
thumb_up 0
access_time 6 years ago