Online Book Reader

Home Category

Beautiful Code [22]

By Root 5020 0
with C# image processing, I began with some Windows Forms code from my book Programming Windows with C# (Microsoft Press). The ImageClip progam in Chapter 24 of that book incorporates code that will load, view, print, and save bitmaps of various popular formats, including JPEG, GIF, and PNG. That code, along with the code I wrote for this exercise, is available for downloading and contributes to a program named ImageFilterTest. The project file requires Visual Studio 2005 for compilation; the executable should run under the .NET Framework 2.0 and later. Perform the following steps to use the program:

In the File menu, select Open and load in a full-color bitmap. The filter-related code in the program only works with 24-bit-per-pixel or 32-bit-per-pixel bitmaps; it doesn't work with bitmaps that use color palette tables, including those where the palette table contains gray shades.

Select one of the filters in the Filter menu. The filter will be applied to the bitmap and the elapsed time will be reported. The first item in the Filter menu ("Use method that generates Intermediate Language") lets you select the method used to apply the filter. By default, the program uses a method called FilterMethodCS (short for "Filter Method using C#"). If you enable this menu item, the program uses FilterMethodIL ("Filter Method with Intermediate Language"). Both of these methods will be described later in this chapter.

Whenever you attempt to write C# code for best performance, one of the more interesting exercises is to examine the compiled file using a little utility included with the .NET Software Development Kit called IL Disassembler. The IL Disassembler shows you the Intermediate Language generated by the C# compiler. Although the program doesn't show you the final step—the conversion of the Intermediate Language into machine code by the just-in-time compiler—you can usually use it to locate some problem areas.

Very early on, I gave up on the idea of storing bitmap pixels in two-dimensional arrays. C# supports multidimensional arrays, but on the Intermediate Language level, getting elements in and out of multidimensional arrays requires method calls. Intermediate Language instructions do, however, support access to one-dimensional arrays. Furthermore, the standard (and fast) code for transferring pixels from a Bitmap object into an array and back into a Bitmap object involves a one-dimensional array. The code I wrote to transfer everything into a two-dimensional array involved a considerable amount of time just by itself.

To encapsulate image filters and the methods that apply these filters to bitmaps, I created a class named ImageFilter that contains three private fields and a constructor that sets the fields. The private field filter is a one-dimensional array that contains a two-dimensional filter, so the cxFilter and cyFilter fields are necessary to indicate the implicit number of columns and rows:

class ImageFilter

{

double[] filter;

int cxFilter;

int cyFilter;

public ImageFilter(int cxFilter, double[] filter)

{

this.filter = filter;

this.cxFilter = cxFilter;

this.cyFilter = filter.Length / cxFilter;

}

...

}

If only square filters were allowed, the cxFilter parameter to the constructor wouldn't be necessary, and the number of rows and columns could simply be calculated as the square root of the size of the filter array, which is available as filter.Length. The cxFilter parameter allows for rectangular filter arrays rather than just square ones. If cxFilter indicates the number of columns in the filter, the number of rows is filter.Length/cxFilter, which my code implicitly assumes is an integer.

The Filter class includes a method named ApplyFilter, which has a parameter of type Bitmap. I won't show you the ApplyFilter method here because it simply contains standard code to first access the pixels of the Bitmap object (using a method named LockBits), and then to transfer the pixels into a one-dimensional array. A second parameter of ApplyFilter is a Boolean named willGenerateCode.

Return Main Page Previous Page Next Page

®Online Book Reader