Thumbnails and Zooming with GDI+ and C#

In the last part I gave you a bird’s eye view of what GDI+ is and showed you how to set up an application for using GDI+. However, without knowing more about the facilitator (i.e. GDI+), going forward would be counterproductive. Hence, in this part, along with different image manipulation techniques, the focus will be on the essentials of GDI+.

Contributed by
Rating: 4 stars4 stars4 stars4 stars4 stars / 14
October 31, 2006
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement

In the first section of this article, I will discuss GDI+ in brief, including the differences from its predecessor, that is GDI. The second section will focus on the manipulation techniques such as zooming and creating thumbnails. In the third and fourth sections I will extend the application created in the last part to include the techniques introduced in this discussion. That is the outline of this discussion.

More About GDI+

GDI+ essentially refers to the library that helps developers to interact with various devices such as monitors, printers, and others that have graphical capabilities without going into low-level details of these devices. The essence of GDI+ is that it can interact with peripherals such as monitors and present data in human readable form. From the point of view of a developer, it's a monumental task to interact directly with these devices. 

This is where GDI+ comes into picture. It acts as a conduit and a translator for the data being passed between devices and applications. Even controlling the command line terminals comes under GDI+. It does everything from printing a "Hello World" program on the console to drawing lines, rectangles and so forth and printing a form. Pictorially it can be shown thus:

The next question that arises is how does GDI+ work? To make it crystal clear, let's look at an example of drawing a line. A line, in essence, is a sequence of pixels from a starting location (X­­0, Y0) to an ending location (Xn, Yn). To draw such a line the devices (the monitor in this case) need to know the device coordinates or physical coordinates.

However, instead of directly telling the device, the call is made to the drawLine() method of GDI+, and GDI+ draws the line from point A to point B in the memory, also known as video memory. GDI+ reads the point A and point B locations, converts them to a sequence of pixels, and tells the monitor to display the sequence of pixels. In short, GDI+ converts device independent calls to a device understandable form and vice versa.

So that’s an overview of how GDI+ works. Let's now move on to the topic of image manipulation.

Image Manipulation: Thumbnail, Zooming and Saving

In the last part, I discussed simple manipulations such as flipping and rotating. Lets tackle some topics that are a bit more complex in concept if not in implementation. They are:

  1. Creating thumbnails.
  2. Zooming a loaded image.
  3. Saving a manipulated image.

Of these the first two come under the category of image manipulation (strictly speaking) whereas the last is a generic image-based task along the lines of a file operation.

Creating Thumbnails

Thumbnails are reduced versions of images. The dimensions of a thumbnail image are typically of 80 to 200 pixels in length. In GDI+, a thumbnail of an image can be created by GetThumbnailImage() of Image class. It takes four parameters. 

The first parameter corresponds to the width. The second parameter is for the height of the thumbnail to be generated. The third parameter is Image.GetThumbnailImageAbort, which needs to be passed for compatibility, though it is not being used in the current version. The fourth parameter is likewise not used, but needs to be passed for compatibility. The fourth parameter must be IntPtr.Zero.

If the first two parameters, namely width and height, are 0, then GDI+ returns an embedded thumbnail (some images contain thumbnails embedded into them). Otherwise the thumbnail is created using system-defined dimensions. For example if img is an instance of the Image class and the width and height to be used are system defined, the statement to create a thumbnail would be:

Image thumbNailImage = img.GetThumbnailImage(0, 0,tnCallBack,
IntPtr.Zero);

where thumbNailImage contains the returned thumbnail, and the tnCallback is a function corresponding to Image.GetThumbnailImageAbort which is defined as:

// Must be called, but not used style='font-size:10.0pt;font-family:Verdana'>public bool tnCallbackMethod() { return false; }

Zooming a loaded image

Zooming is the process of enlarging an image by multiplying it with a number called the zoom factor. By definition, “The zoom factor is the ratio of the current size of the image to the desired new size of the image.” By dividing the current size of the image with the desired size of the image, we get the zoom factor. For example, to zoom in on an image by 200%, the current size must be multiplied by 200% or by 2 (200%= 200/100=2). To zoom out an image by 25 percent, the size must be multiplied by 25 percent, or 0.25 (25/100 = 0.25 times). It is one of those areas of image manipulation where GDI+ doesn’t provide methods to achieve the result.

Saving a manipulated image

Saving is one of the primary operations done on an image. While saving an image, the type into which the image has to be saved, or in other words the extension of the image, plays a major role. Each type corresponds to a particular format. In essence, while saving an image, writing out the data according to the format is necessary. However, since the API that is being used is GDI+, a single call to the Save() method of the Image class abstracts out all the details of writing out the data according to the format. It takes two parameters, the name as which the image is to be saved and the format into which the image has to be saved. The format can be specified using the types provided by the ImageFormat class. The following table specifies the various formats supported by GDI+.

Property

Description

Bmp

Specifies BMP format.

Emf

Specifies EMF (Enhanced Metafile Format).

Exif

Specifies EXIF format.

Gif

Specifies GIF format.

Guid

Specifies a GUID structure that represents the ImageFormatobject.

Icon

Specifies Windows icon format.

Jpeg

Specifies JPEG format.

MemoryBmp

Specifies memory bitmap format.

Png

Specifies PNG format.

Tiff

Specifies TIFF format.

Wmf

Specifies WMF (Windows Metafile Format).

Of these, Emf and Wmf are specific to Windows. I will be discussing these in detail in the future.

To give you an example, if you wanted to save an image with the name “checker.gif” in GIF format, the statement would be:

curImage.Save(“checker.gif”, ImageFormat.Gif);

where curImage is the instance of the Image class.

That brings us to the end of this section. In the next section, I will be extending the application developed in the first part by embedding the operations discussed in this section.

Image Manipulation in the Real World

It is time to put the theory into practice. I will do this by enhancing the application developed in the last part by adding the following functionalities:

  1. Save the image in the format specified by user.
  2. Zoom in according to the percentage selected from the menu.
  3. Create a thumbnail of a loaded image.

The menus corresponding to the operations are:

  • mnuSave – the submenu of File menu to save the image.
  • mnu200Zoom – zooms the image by 200%.
  • mnuThumbNail- creates a thumbnail of the image.

Here is the method that handles the click event of mnuSave:

private void mnuSave_Click(object sender,     System.EventArgs e) { // If image is created     if(curImage == null)         return;     // Call SaveFileDialog     SaveFileDialog saveDlg = new SaveFileDialog();     saveDlg.Title = "Save Image As";     saveDlg.OverwritePrompt = true;     saveDlg.CheckPathExists = true;     saveDlg.Filter =         "Bitmap File(*.bmp)|*.bmp|" +         "Gif File(*.gif)|*.gif|" +         "JPEG File(*.jpg)|*.jpg|" +         "PNG File(*.png)|*.png" ;     saveDlg.ShowHelp = true;     // If selected, save     if(saveDlg.ShowDialog() == DialogResult.OK)     {         // Get the user-selected file name         string fileName = saveDlg.FileName;         // Get the extension         string strFilExtn =             fileName.Remove(0, fileName.Length - 3);         // Save file         switch(strFilExtn)         {            case "bmp":                 curImage.Save(fileName, ImageFormat.Bmp);                 break;             case "jpg":                 curImage.Save(fileName, ImageFormat.Jpeg);                 break;             case "gif":                 curImage.Save(fileName, ImageFormat.Gif);                 break;             case "tif":                 curImage.Save(fileName, ImageFormat.Tiff);                 break;             case "png":                 curImage.Save(fileName, ImageFormat.Png);                 break;             default:                 break;             }     } }

First the save dialog box is shown with acceptable extensions. Then, from the file name returned by the dialog box, the extension is retrieved. Finally, according to the extension, the Save() method is called with the corresponding image format parameter.

Image Manipulation in the Real World, continued

Next comes the handler for mnu200Zoom. But before that certain things have to be done. First add the following line to the class at the application level:

private double curZoom = 1.0;

Then the mnuLoad (from previous part) has to be changed slightly. The added code is shown in bold:

private void mnuLoad_Click(object sender,     System.EventArgs e) {    //Change the AutoScrollMinSize property this.AutoScrollMinSize = new Size ((int)(curImage.Width * curZoom), (int)(curImage.Height * curZoom)); // 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 added code multiples the image width and height with the zoom factor to render an image with the appropriate zoom setting. Next the paint event handler has to be changed. The DrawImage() method has to be changed into the following:

g.DrawImage(curImage, new Rectangle     (this.AutoScrollPosition.X,     this.AutoScrollPosition.Y,     (int)(curRect.Width * curZoom),     (int)(curRect.Height * curZoom)));

The image should have the correct height and width according to the zoom factor. For that the current width and height is multiplied with the current zoom factor represented by curZoom variable. The last step in zooming is the event handler for mnu200Zoom:

private void mnu200_Click(object sender,

    System.EventArgs e)

{

   if(curImage != null)

    {
        curZoom = (double)200/100;

        Invalidate();

    }

}

Finally we have the event handler for the mnuThumbNail:

private void mnuThumbNail_Click(object sender,     System.EventArgs e) {     if(curImage != null)     {        // Callback         Image.GetThumbnailImageAbort tnCallBack =             new Image.GetThumbnailImageAbort(tnCallbackMethod);         // Get the thumbnail image         Image thumbNailImage = curImage.GetThumbnailImage             (100, 100, tnCallBack, IntPtr.Zero);         // Create a Graphics object         Graphics tmpg = this.CreateGraphics();         tmpg.Clear(this.BackColor);         // Draw thumbnail image         tmpg.DrawImage(thumbNailImage, 40, 20);         // Dispose of Graphics object         tmpg.Dispose();     } } // Must be called, but not used public bool tnCallbackMethod() {     return false; }

It first creates a variable of type GetThumbnailImageAbort and assigns the tnCallbackMethod() to it by passing the method to the GetThumbnailImageAbort. Then it creates a new instance of the Image class to hold the image returned by the GetThumbnailImage method, which is then used to draw the thumbnail onto the screen.

This brings us to the end of this discussion. In this part I discussed more advanced features of GDI+. I will continue along the same lines in next part. Till then…

blog comments powered by Disqus
C# ARTICLES

- Beginning C#
- ASP.NET RedirectPermanent Method using C# an...
- C Programming Language and UNIX Pioneer Pass...
- Using Facebook JavaScript SDK in ASP.NET wit...
- ASP.NET Export to Excel and Word using VB.NE...
- WAV and MP3 Streaming with ASP.Net and C#
- Game Programming using SDL: the File I/O API
- C# and Java Developer Jobs on the Rise
- The Future Evolution of C# and VB.NET
- C# If and Else-if Statements
- How To Use the C# String Replace Method
- 5 Ways to Parse XML in C#
- C# Meets Design Patterns
- Coding a CRC-Generating Algorithm in C
- Cyclic Redundancy Check

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 3 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials