.NET and GDI+: Transforming Images on the Server - Introduction and Examples, Part I...

This article series focuses on the imaging elements of the GDI+ class available within the system.drawing namespace but also dips into the related graphics and typography facilities also available.


By: Chris Sully Date: March 4, 2004 Download the code.

Abstract

New to developers in the .NET Framework, and hence ASP.NET, is the ability to manipulate images through the GDI+ managed class interface (a set of wrappers) which is distributed as part of the Microsoft .NET Framework, allowing access to underlying operating system functionality that provides two-dimensional vector graphics, imaging, and typography. This article series focuses on the imaging elements of the GDI+ class available within the system.drawing namespace but also dips into the related graphics and typography facilities also available.

Introduction

New to developers in the .NET Framework, and hence to ASP.NET, is the ability to manipulate images through the GDI+ managed class interface (a set of wrappers) which is distributed as part of the Microsoft .NET Framework, allowing access to underlying operating system functionality that provides two-dimensional vector graphics, imaging, and typography. This article series focuses on the imaging elements of the GDI+ classes within the system.drawing namespace - particularly on manipulating bitmaps but also dips into the related graphics and typography facilities also available.

This series of articles shall proceed by introducing the core available classes and concepts then proceed by presenting and explaining a series of examples, introducing the various important related concepts along the way.

System Requirements

All code presented within this series of articles was developed using the .NET Framework version 1.0.3705 with Service Pack 1 applied (version 1.0 is available at http://www.asp.net/download.aspx, a text editor/ Microsoft ASP.NET Web Matrix and Microsoft Internet Explorer Version 6.0 (although no client side code is utilized explicitly that might cause issues with other browsers).

The pre-requisites for this series are a few months of experience with ASP.NET and a reasonable understanding of bitmaps. All examples are written in VB.NET.

Overview of GDI+

The acronym GDI stands for Graphics Device Interface, and GDI+ v1.0 is the latest version implemented as managed code within the .NET Framework. A graphics device interface, such as GDI+, is exactly what it says – an interface between the programmer and the underlying hardware allowing the programmer to focus on higher level graphics concepts rather than having to be concerned with how the hardware achieves the desired results. Further, this level of abstraction means that GDI+ code written for one display device will work on any other supported display device allowing the creation of device-independent applications.
The functionality of GDI+ falls within the following three areas:

1. 2-D vector graphics

GDI+ provides:

Further, you may store and manipulate a vector image created from these classes in a metafile, via the metafile class.

2. Imaging

Vector graphics techniques are suitable for rendering pictures that can be constructed from a number of simple (or complex) geometric elements. Photos cannot normally be rendered both accurately and easily with vector graphics. Images of this type are better stored as bitmaps: arrays of numbers that represent the colours of individual pixels on the screen. GDI+ provides the Bitmap class for displaying, manipulating, and saving bitmaps. This shall be the principal focus of this series of articles.

3. Typography

Typography is concerned with the display of text and the use of fonts, sizes, and styles to do so.

It is the imaging class, in particular the Bitmap derived class, that shall be the focus of this series of articles though inevitably we shall dip into the other related classes along the way to implement the presented examples.

The Image Class and Derived Classes

The focus of this series of articles is the System.Drawing.Imaging namespace which provides GDI+ imaging functionality and particularly the image class and its derived class, Bitmap. The Image class is an abstract base class that provides methods for working with raster images (bitmaps) and vector images (metafiles) as well as the Icon derived class. The Bitmap class and the Metafile class both inherit from the Image class. The Bitmap class encapsulates a GDI+ bitmap, which consists of the pixel data for a graphics image and its attributes. A Bitmap object is an object used to work with images defined by pixel data. The Bitmap class expands on the capabilities of the Image class by providing additional methods for loading, saving, and manipulating raster images. These shall be examined in further detail later. The Metafile class expands on the capabilities of the Image class by providing additional methods for recording and examining vector images.

Brief Introduction to Bitmaps

A bitmap is an array of bits that specify the colour of each pixel in a rectangular array of pixels. The number of bits devoted to an individual pixel determines the number of colours that can be assigned to that pixel. Files that store bitmaps usually contain metadata that represents information such as the number of bits per pixel, number of pixels in each row, and number of rows in the array. Included in this metadata might be a color table or color palette). This maps numbers in the bitmap data to specific colours. A bitmap that stores indexes in a colour table is called a palette-indexed bitmap. An example is the GIF format. Some bitmaps have no need for a colour table. If a bitmap uses 24 bits per pixel, that bitmap can store the colors themselves rather than indexes into a color table. An example is the 24bit PCX format.

Please note that you do need a reasonable understanding of bitmaps and the differences between the different image formats to utilize the related GDI+ image functionality to the full. For example, due to the nature of their internal representations some methods that work with JPEGs will not work with GIFs. The .NET SDK documentation contains an introduction to Bitmaps (ms-help://MS.NETFrameworkSDK/cpguidenf/html/_gdiplus_types_of_bitmaps_about.htm) (which is where the first paragraph of this section largely originates) as well as the common formats and I would suggest you review this information if you intend to do further work with the various image types and do not have a great deal of previous experience in this area. We’ll be dealing largely with GIFs and JPEGs in this series of articles.

The Image and Bitmap Classes

As already stated the Bitmap class encapsulates a GDI+ bitmap, which consists of the pixel data for a graphics image and its attributes. A Bitmap object is an object used to work with images defined by pixel data.

Before we delve into code let's take a quick look at some of the properties and methods of the Bitmap object, most of which are inherited from the parent Image class.

Public Properties

Picking out a subset of the available properties based on their relevance to the rest of this article

NameDescription
FrameDimensionsListGets an array of GUIDs that represent the dimensions of frames within this Image object.
HeightGets the height of this Image object.
HorizontalResolutionGets the horizontal resolution, in pixels-per-inch, of this Image object.
PaletteGets or sets the color palette used for this Image object.
PhysicalDimensionGets the width and height of this Image object.
PixelFormatGets the pixel format for this Image object.
RawFormatGets the image format of this Image object (see the ImageFormat class)
SizeGets the width and height of this Image object.
VerticalResolutionGets the vertical resolution, in pixels-per-inch, of this Image object.
WidthGets the width of this Image object.

Note that all of these properties are inherited from the Image class.

Points from the above:

A frame is an individual bitmap, of which there can be several in an image. For example, in an animated gif.

Note that you can also access the color palette of the image in the above. In fact there is a distinct colorpalette class. The colours in the palette are limited to 32-bit ARGB colors. A 32-bit ARGB color has 8 bits each for alpha, red, green, and blue values. The lowest 8 bits make up the blue bit, the next 8 bits are green, the next 8 bits are red, and the most significant 8 bits are alpha. This means each component can vary from 0 to 255. Fully on is 255 and fully off is 0. Alpha is used to make the colour value transparent (alpha = 0) or opaque (alpha = 255). We’ll return to this in one of the examples later. The number of intensity levels in the image can be increased without increasing the number of colours used. This process creates what is called a halftone, and it offers increased contrast at a cost of decreased resolution.

Public Methods

NameDescription
Clone (Overloaded)Creates a copy of the section of this Bitmap defined with a specified PixelFormat.
Dispose (Overloaded)*Releases all resources used by the bitmap object
FromHiconCreates a Bitmap from a Windows handle to an icon.
FromResourceCreates a Bitmap object from the specified Windows resource: for example from a DLL that contain a bitmap as a named resource.
GetBounds*Gets a bounding rectangle in the specified units for this Image object.
GetEncoderParameterList*Returns information about the parameters supported by the specified image encoder.
GetFrameCount*Returns the number of frames of the specified dimension.
GetHbitmap OverloadedCreates a Windows HBITMAP from the image.
GetHiconReturns the handle to an icon.
GetPixelGets the color of the specified pixel in this Bitmap.
GetThumbnailImage*Returns the thumbnail for this Image object.
MakeTransparent OverloadedMakes the default transparent color transparent for this Bitmap.
RemovePropertyItem*Removes the specified property item from this Image object.
RotateFlip*This method rotates, flips, or rotates and flips the Image object.
Save (inherited from Image) OverloadedSaves this Image object to the specified Stream object in the specified format.
SaveAdd (inherited from Image) OverloadedAdds the information in the specified Image object to this Image object. The specified EncoderParameters object determines how the new information is incorporated into the existing image.
SelectActiveFrame*Selects the frame specified by the dimension and index.
SetPixelSets the color of the specified pixel in this Bitmap object.
SetResolutionSets the resolution for this Bitmap.

* (inherited from Image)

Points from the above:

The pixel format is an enumeration defining the number of bits of memory associated with one pixel of data. The format also defines the order of the color components within a single pixel of data. There are approximately 20 members to this enumeration – see the .NET SDK Documentation.

For the rest of this series of articles we'll present a set of examples starting with the most simple example we could think of and gradually exploring more complex areas of GDI+.

1. Displaying an Image

Almost all of the code examples follow a similar pattern with code presented being positioned to execute in the Page_Load sub of the <script> section of the page with the content type of the resulting output being set to an image format. The namespaces generally imported will be:

<%@ import namespace="system.drawing" %>
<%@ import namespace="system.drawing.imaging" %>

Though this varies by example.

Here's an equivalent of the 'hello world' example for the bitmap class. We'll load an image into a bitmap object from a file via one of the 12 overloaded bitmap object constructors. We'll then simply stream the resultant image for display on the user's browser.

gdi1.aspx code snippet:

dim bmpBitmap1 as New system.drawing.bitmap(server.mappath("images/alima.jpg"))

'Set the content type
response.contenttype="image/jpeg"
'send the bitmap to the outputstream
bmpBitmap1.save(response.outputstream, imageformat.jpeg)

'tidy up
bmpBitmap1.dispose()

You'll thus see alima.jpg (a member of my extended family who'll you'll see in several forms in subsequent examples) in your browser:

The other constructors allow instantiation of a bitmap object from an image object, a data stream and another bitmap object with the ability to specify size and resolution among other parameters. Combinations of these make up the remaining 11 constructors.

The dispose method, which will be present in all the examples, releases the resources used to represent the Bitmap.

That concludes our first 'hello world' example. In the second article of this series we'll continue to look at GDI+ via further examples.

References

ASP.NET: Tips, tutorials and code
Mitchell et al.
Sams Publishing
ISBN 0-672-32143-2

.NET SDK Documentation

Various online articles, notably:

The Code Project - An ASP.NET thumbnail solution - ASP.NET
http://www.codeproject.com/aspnet/ThumbTools.asp

Chris Garretts ASPAlliance Column:
http://www.aspalliance.com/chrisg/

Bob Powell’s GDI+ FAQ
http://www.bobpowell.net/

http://www.c-sharpcorner.com/Code/2002/April/DrawTransparentImageUsingAB.asp
C# Corner: C# and .NET Developer's Network: transparent images
Mahesh Chand

http://www.c-sharpcorner.com/Code/2002/Dec/WorkWithPNG.asp
Working with the Portable Network Graphics (PNG) Format: Part 1
Tom Curry

http://www.c-sharpcorner.com/graphics/transforms_101.asp
Using Transforms with GDI+ in C#
Mike Gold

You may download example code here.