Image Processing with .NET Core

WEBINAR: On-demand webcast

How to Boost Database Development Productivity on Linux, Docker, and Kubernetes with Microsoft SQL Server 2017 REGISTER >

If you're new to .NET Core, and familiar with the full .NET Framework, you may or may not have noticed that the System.Drawing namespace—which is very useful for image processing and manipulation—is not available to .NET Core. Because the full framework runs on Windows machines, .NET Core is cross platform; and to quote MSDN 'The System.Drawing namespace provides access to GDI+ basic graphics functionality.' We begin to see the problem here.

There is a good chance .NET Core will not be running on Windows, so we need to consider alternatives when looking to process images with .NET Core.

For this article, we'll look at one such project, named ImageSharp, which has reached the alpha stage. You can find the project here.

This project has seen some outstanding progress from the team, and I'm sure they'll be grateful for any help you may be able to provide in seeing this project to release. However, because this project is currently in alpha, it isn't for use in production environments just yet.

All that aside, let's look at using ImageSharp to do some simple image processing. I'm going to download and compile the project manually, and then include the projects needed in a new solution along with a .NET Core console application.

To clone the ImageSharp project; you may use this link…

git clone https://github.com/JimBobSquarePants/ImageSharp

Once cloned and opened, you should have an ImageSharp solution that looks like what we see in Figure 1.

The ImageSharp solution
Figure 1: The ImageSharp solution

Following this, we'll then create another solution that we'll use for the remainder of this article. This solution setup looks like this…

Our example solution including ImageSharp with a console application
Figure 2: Our example solution including ImageSharp with a console application

From your console application, reference the other two projects. Note that, to process an image of a particular format, you'll need to include the relevant project, too. From Figure 2, observe that the ImageSharp.Formats.Jpeg project has been included, along with ImageSharp.

Given the format project included, we'll be processing JPEG images for this article. To begin, we'll create an empty image.

At a location of your choosing, let's create a directory to hold our images. If you prefer, you can simply store these at the root of your application. I've created a directory on one of my flash drives, called 'ImageSharpExampleImages', and put together some code that looks similar to this…

public static void Main(string[] args)
{
   CreateImage();
}

static void CreateImage()
{
   var directory = Path.GetDirectoryName("G:\\
      ImageSharpExampleImages'\\");
   var imageName = "codeguruimage.jpg";

   using (FileStream fileStream = File.OpenWrite
      (Path.Combine(directory, imageName)))
   {
      Image newImage = new Image(400, 400);
      newImage.SaveAsJpeg(fileStream);
   }
}

If you run the console application, executing the preceding code, you should find a JPEG in your designated directory. This image should be 400 by 400 pixels and all black because we haven't specified any colors yet.

A black image isn't very interesting, so let's add some color to it. ImageSharp allows you to extract the image's pixels, and presents them in a very handy struct named Color. This value type allows us to take a pixel and do a number of operations on it, such as returning a hex string and much more. If you have the time, I would suggest studying Color, but for now, let's create a bitmap with some added color.

With the following code, we'll turn our image to all red.

using (FileStream fileStream =
   File.OpenWrite(Path.Combine(directory, imageName)))
{
   Image newImage = new Image(400, 400);

   Color[] pixels = newImage.Pixels;

   for(int i = 0; i < pixels.Length; i++)
   {
      pixels[i].R = 0xff;
   }

   newImage.SetPixels(400, 400, pixels);
   newImage.SaveAsJpeg(fileStream);
}

And the output from the code above…

The image with pixels manipulated to coloured red
Figure 3: The image with pixels manipulated to coloured red

From that simple action above, we can also see how to do something like extracting the pixels from one image, and placing them on another image in a given position. I'll leave that piece of fun for you to explorer in your good time, and move in to looking at some other processing options available to us.

If you're following along with the code, go ahead and include the ImageSharp.Processing project in your solution and add a reference to it. If all is well, you'll find that this Processing project gives us actions such as:

Resizing our image:

newImage.Resize(600, 600);

Changing saturation levels:

newImage.Saturation(-50);

Rotating the hue:

newImage.Hue(180);

We also have included, out of the box, some of the good old classic effects like Oil Painting, Gaussian blur/sharpen, and converting the image to Greyscale.

I'll leave this here with your good self, and happy image processing to you and a round of applause for the team behind ImageSharp. If you have any questions about this article, you may find me on Twitter @GLanata.



About the Author

Gavin Lanata

Gavin has been building front-ends to software applications; desktop, web, and mobile, for several years now. Gavin often attends developer events, expanding his own knowledge in the fast paced world of IT, and lending a helping hand to developers needing a little direction navigating the world of design. Gavin has dedicated his time to the study of the many factors influencing human usage and reaction to software application. Art, design and coding name a few but certainly not the least of his tools to find the truths behind why we like and use the things we do.

Related Articles

Comments

  • James Jackson-South

    Posted by James Jackson-South on 02/01/2017 06:30pm

    Hi Gavin, Thanks for the writeup, it's great to see people sharing our work! Just a quick not to say that while using the Pixel array works, it's better to use the PixelAccessor class to do you manipulation. That way you can use [x,y] indexer to get your pixel rather than doing the maths. It's way faster too! Cheers James

    • Great stuff!

      Posted by Gavin lanata on 02/12/2017 02:14am

      Awesome, thanks for the tip James!

      Reply
    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date