Basic Image Manipulation using GDI+ and C#

GDI+ offers certain advantages over GDI when trying to manipulate images on Windows. One of the best is the ability to work with C#. This article will show you how to perform basic image manipulation with the GDI+ library in C#.

Image manipulation is considered one of the more difficult tasks in graphics programming. This is even more true if the operating system under consideration is Windows. The reason is that to achieve efficiency there is no better option than the Windows API.

The APIs provided by Windows comes under the GDI roof. GDI is short for Graphics Device Interface. However, GDI works with low level graphics. So to use it a good understanding of how Windows work is required. Even with MFC, GDI is a bit complicated.

But with the evolution of GDI+ the scenario is changing. The major change between GDI and GDI+ is that GDI exposes only APIs for unmanaged code whereas GDI+ provides for both managed as well as unmanaged code. Hence GDI+ is oriented towards .Net based languages. And in the world of .Net, one of the best options is C#.

So in this discussion, I will be focusing on how to use the basic image manipulations using the GDI+ library in C#. The first section will focus on the terminology used by GDI+ and image manipulation in general. In the second section I will detail the steps involved in image manipulation using GDI+. The last section will be about using the basic image manipulation within a real world application. That’s the outline for this discussion.

{mospagebreak title=Image Manipulation using GDI+: the Terminology}

Before understanding how to use GDI+ APIs for image manipulation, it is important to understand what GDI+ really is and what constitutes its vocabulary. If we consider basic image manipulation, there are four points that need to be understood, which are

  1. GDI+
  2. Vector Graphics
  3. Raster Graphics
  4. Imaging

The second, third and fourth are integral parts of the image manipulation vocabulary. The fourth term in itself consists of many terms, some of which will be discussed in the appropriate section.

GDI+

By definition “GDI+ is a library that provides an interface that allows programmers to write Windows and Web graphics applications that interact with graphical devices such as printers, monitors, or files.” In essence, it provides a layer of abstraction over various devices with which the GUI needs to work. This abstraction works by converting the data into a device compatible form. The device then turns the data into a human readable form. The implementation of GDI+ is in the form of C++ classes that can be used from a .Net environment. In the .Net library, GDI+ classes are exposed through the System.Drawing and its namespaces.

Vector Graphics

By definition this is “Graphics in which an image is stored as a series of numbers defining size, position, and shape.” In other words, in vector graphics the image contains position vectors describing the image, where a vector represents both quantity and direction. For example, instead of containing a bit in a file for a line being drawn, a vector graphics file describes a series of points to be connected. Since the file contains vector commands, the file size is small.

Raster Graphics

Raster is a grid of x- and y- co-ordinates on a display space which in this case is the display device. A Raster Graphics file contains information identifying which of these coordinates to illuminate using monochrome (black and white) or spectro-chrome (color) values. Raster images are also known as bit-mapped images or bitmaps because they contain information directly mapped to the display device’s grid. Raster graphics files are larger than Vector Graphic files.

Imaging

Imaging is the process of viewing and manipulating images. In managed GDI+, imaging has two facets, basic and advanced. The basic processes cover loading and saving, zooming, scaling and so forth, whereas the advanced ones cover color palette, metafiles and tagged images. The basic functionalities are encapsulated in the Image class. It provides methods to load, save and create images. The subclasses of the Image class i.e. Bitmap and Metafile provide the functionality for displaying and manipulating the images.

That was a bird’s eye view of the recurring terms in the world of GDI+ and image manipulation. In the next section I will discuss steps to take when loading and manipulating images; I will cover flipping as well as rotating the image.     

{mospagebreak title=Image Manipulation Using GDI+: Step By Step}

Now let’s have a look at the steps involved in using the GDI+ for image manipulation. There are four main steps:

  1. Overriding the Paint event of Form.
  2. Obtaining the Graphics object.
  3. Obtaining the Image object.
  4. Apply manipulation methods.

The first two steps are required whenever one has to work with GDI+. However, the last two come into the picture (pun not intended) only when image manipulation has to be done. So here are the details:

Overriding the Paint event of form

In .Net applications, drawing is done on a Form’s surface. This is same for both web and desktop applications. The function where the actual drawing code can be hooked in is the Paint method. So, the first step is to override this method to get a foothold into the draw process within the application. This can be achieved either by supplying a Paint handler to the Form’s paint method or by overriding the OnPaint method. It is better to provide a Paint handler.

Obtaining the Graphics object

The next step is to obtain the object of the Graphics class, because it is only through the Graphics object that the drawing methods can be called. To show an image it has to be drawn onto the Form. That can only be done using the DrawImage method of an object of the Graphics class. An object of the Graphics class is associated with a form. So it can be obtained by one of three methods:

  • Using PaintEventArgs argument passed into the Paint handler.
  • Using PaintArgs argument passed into the OnPaint method.
  • Using CreateGraphics method of a Form.

An example of the first method would be thus:

private void form1_Paint(object sender, PaintEventArgs e)

{

	Graphics g = e.Graphics;

}

where form1_Paint is the handler for Paint event of Form form1. The Graphics property of the PaintEventArgs returns a Graphics object associated with the Form object.  The second way can be exemplified as:

protected override void OnPaint(PaintEvent { Graphics g = e.Graphics; }

The main difference between the first and second examples is that in the second way, the OnPaint method is overridden. The example for the third way would be:

Graphics g = this.CreateGraphics();

Where this refers to the Form in which this statement has been embedded. The CreateGraphics() method returns a method object of the Form. The only drawback of this approach is that the Graphics object would have to be disposed of manually using the dispose method of the Graphics object. I prefer the first method; therefore I will be using it henceforth.

Obtaining the Image object

The image object can be obtained in three different ways using the static methods provided by the Image class:

  1. The FromFile method returns an Image from the file specified as an argument.
  2. FromHbitmap creates and returns an Image object from a window handle to a bitmap.
  3. FromStream creates an Image object from a stream of bytes (in a file or a database).

Among these, the first method is the most commonly used if the image is available as a file, whereas the third method comes handy in web applications where the images would be stored as a column value of a table. The following statement creates an object of the Image class using the first method:

 Image curImage = Image.FromFile(“flower.bmp”);

Apply manipulation methods

For the sole purpose of imaging, the Image class provides many methods. The most common in imaging are Flip and Rotate. The Image class provides for these by the following method – RotateFlip. The parameter to this method defines whether flipping as well as rotating both have to be done or only a flip or rotation must be applied. It also defines through what degrees flipping or rotating must be done. The following table provides the most common arguments to the RotateFlip method as well as their descriptions. The arguments being passed are the members of the RotateFlipType.

 

Member

Description

Rotate180FlipNone

180-degree rotation without flipping

Rotate180FlipX

180-degree rotation with a horizontal flip

Rotate180FlipXY

180-degree rotation with horizontal and vertical flips

Rotate180FlipY

180-degree rotation with a vertical flip

Rotate270FlipNone

270-degree rotation without flipping

Rotate270FlipX

270-degree rotation with a horizontal flip

Rotate270FlipXY

270-degree rotation with horizontal and vertical flips

Rotate270FlipY

270-degree rotation with a vertical flip

Rotate90FlipNone

90-degree rotation without flipping

Rotate90FlipX

90-degree rotation with a horizontal flip

Rotate90FlipXY

90-degree rotation with horizontal and vertical flips

Rotate90FlipY

90-degree rotation with a vertical flip

RotateNoneFlipNone

No rotation and no flipping

RotateNoneFlipX

No rotation, with a horizontal flip

RotateNoneFlipXY

No rotation, with horizontal and vertical flips

RotateNoneFlipY

No rotation, with a vertical flip

For example, to flip and rotate an image through 90 degrees on both the X- and Y- axes the statement would be:

curImage.RotateFlip(RotateFlipType.Rotate90FlipXY);

where curImage is an object of the type Image and the argument tells the RotateFlip method that the image has to be rotated through 90 degrees and needs to be flipped both vertically and horizontally.

That brings us to the end of this section. In the next section I will develop an application that will load, flip and rotate the loaded image.

{mospagebreak title=Image Manipulation in the Real World}

Starting from this part onwards, I will be developing an image manipulation application using C# and GDI+. The basic version that will be developed now will provide the following capabilities:

  • Loading an image file.
  • Rotating the loaded image 90 degrees.
  • Flipping the image along its X-axis.

First the menus must be set up as shown in the figure below.

The names of the menus are:

  • mnuLoad – the submenu that will show the Open dialog box and loads the file.
  • mnu90rotate – rotates the image by 90 degrees.
  • mnuXfilp- flips the image along X-axis.

Here is the handler for loading the image:

private void mnuLoad_Click(object sender,     System.EventArgs e) {     // Create OpenFileDialog     OpenFileDialog opnDlg = new OpenFileDialog();     // Set a filter for images     opnDlg.Filter =         "All Image files|*.bmp;*.gif;*.jpg;*.ico;"+        "*.emf;,*.wmf|Bitmap Files(*.bmp;*.gif;*.jpg;"+         "*.ico)|*.bmp;*.gif;*.jpg;*.ico|"+         "Meta Files(*.emf;*.wmf;*.png)|*.emf;*.wmf;*.png";     opnDlg.Title = "ImageViewer: Open Image File";     opnDlg.ShowHelp = true;     // If OK, selected     if(opnDlg.ShowDialog() == DialogResult.OK)     {         // Read current selected file name         curFileName = opnDlg.FileName;         // Create the Image object using         // Image.FromFile         try         {             curImage = Image.FromFile(curFileName);         }         catch(Exception exp)        {            MessageBox.Show(exp.Message);         }     }     // Repaint the form, which forces the paint     // event handler     Invalidate(); }

The name of the file returned by the open file dialog is set as the current file name. Then it is used to load the file using the FromFile function of the Image class. The returned image is assigned to the curImage variable, which is of type Image, and its scope is of class level. The Next Invalidate() method is called so that a paint event is fired. Following the code, embedded in the Form’s Paint method handler is this piece, which actually draws the image:

private void Form1_Paint(object sender,     System.Windows.Forms.PaintEventArgs e) {           Graphics g = e.Graphics;           if(curImage != null)           {              // Draw image using the DrawImage method               g.DrawImage(curImage,                     AutoScrollPosition.X,                     AutoScrollPosition.Y,                     curImage.Width,                     curImage.Height );           } }

The logic checks whether the current image is null or not. If it is not null, the DrawImage method of the Graphics class is given the curImage as the Image to be loaded. The Graphics object is obtained from the Graphics property of PaintEventArgs object. Next is the handler for rotating the image; it is embedded in the handler for the mnu90rotate menu item. Here is the code:

// Rotate 90 degrees private void mnu90rotate_Click(object sender,     System.EventArgs e) {     if(curImage != null)     {        curImage.RotateFlip(             RotateFlipType.Rotate90FlipNone);         Invalidate();     } }

The image is rotated using the RotateFlip method of the Image class. Since curImage is of the Image class type, the method can be directly called on the Image object. Next it calls the Invalidate() method to redraw the image.

Last comes the flip logic. It is embedded in the handler for the mnuXflip menu item.

// Flip X private void mnuXflip_Click(object sender,     System.EventArgs e) {     if(curImage != null)     {         curImage.RotateFlip(             RotateFlipType.RotateNoneFlipX);         Invalidate();     } }

That’s all for the example. This sets up the stage for image manipulation using GDI+ in C#. However certain aspects of the problem of image manipulation have been left out, including saving the image and how GDI+ works. These will be the topics that will be tackled in the next part of this series. Till then…

3 thoughts on “Basic Image Manipulation using GDI+ and C#

  1. GDI+ is a great progress over GDI in terms of API calls. In this article I have discussed the GDI+ APIs in context of basic image manipulations. Please do comment.

  2. Hi,

    I’ve application to capture video of image and grab the still image. It runs well untill I put loop to regrab the still images many times automatically.. and the error (generic error occured GDI+) happend.
    For your information, I also run different code of application that have similar function which to capture the image repeatedly that I found from internet. However, it give the same error message.
    I think maybe I’ve to setup something in the configuration but I still blur about it. I’m using C# Express edition. Could anybody help me please…

[gp-comments width="770" linklove="off" ]