Visual Studio .NET 2003 (Image Processing)

All of the source code for the Windows C++ applications accompanying this topic were built using Microsoft Visual Studio .NET 2003. Visual Studio is the standard bearer when it comes to PC IDEs, and has been the most popular Windows compiler since the release of Visual Studio 5 in the mid-90s. Beginning in 1998, Visual Studio version 6 cemented its place as the dominant C/C++ compiler and this compiler remained fairly static until .NET arrived. The next generation of Visual Studio, deemed "Visual Studio .NET" was released in 2002 and came with compilers for various .NET languages, most notably C#, Visual Basic .NET, and of course C/C++. This was followed a year later with Visual Studio .NET 2003, which fixed numerous bugs and added many improvements to the compilers for all of the various languages. As this topic was going to press, the next version of Visual Studio, Visual Studio 2005 (code-named "Whidbey") was in beta release.

With the advent of Microsoft’s .NET initiative, there are now two distinct flavors of C++: so-called "managed" C++, and "unmanaged" or "native" C++. The difference between the two is that managed C++ is a .NET-compliant language fully aware of the .NET environment and the virtual machine that the environment is predicated on, the common language runtime or CLR. All of the C++ applications in this topic use the more traditional unmanaged C++, so that the source code should be portable to other PC compilers like Borland’s C++ Builder or Intel’s C++ Compiler for Windows. The knock on previous versions of Microsoft’s C++ compilers have been their lack of compliance to the ISO C++ standard, and Microsoft’s lackadaisical attitude towards rectifying the situation. With the 2003 edition of Visual Studio however, this problem seems to have been solved, and the C++ compiler is now one of the more standard compliant on the market. Furthermore, Microsoft appears to remain committed to maintaining this compliance.


One of the reasons why application development on the PC can sometimes appear daunting is the overwhelming array of class libraries, frameworks, and Application Programming Interfaces (APIs) made available to users to Visual Studio. From the Win32 API to DirectDraw and DirectShow, the number of libraries can be simply dizzying. Visual Studio .NET 2003 applications in this topic draw on three major libraries: Microsoft Foundation Classes (MFC), Graphics Device Interface Plus (GDI+), and the Intel Integrated Performance Primitives (Intel IPP) package. Figure 2-5 shows the relationship between these three libraries, and in this topic the implementation of a class that facilitates the interactions between the MFC, GDI+, and Intel IPP triumvirate is fully detailed. The remainder of this section briefly introduces each of these three libraries.

Microsoft Foundation Classes (MFC)

Prior to the advent of MFC, building Windows GUIs in Visual Studio or other compilers was done using the raw Win32 API, which consists of literally hundreds, perhaps even thousands, of functions littered all over the Windows programming landscape21. As C++ began to attain more popularity in the early 1990s, Microsoft released MFC, which is a collection of classes that constitute a "thin wrapper" around the various C functions and data structures that make up the Win32 API. Essentially, MFC is implemented as a thin object-oriented veneer around Win32, and if you understand the basics of Win32, MFC should be reasonably easy to pick up.

The GUI applications featured in this topic are rather simplistic, as our goal is embedded deployment. However, there are cases where we either desire a reference implementation in C/C++ closer to the eventual DSP implementation than MATLAB prototypes, or we need front-end interfaces for DSP-based image processing systems (residing on the EVM or DSK). To be useful, in both instances we require some minimal GUI facilities as well as visualization capabilities. Rendering of images can be done in MFC, but in this topic we use the more modern GDI+ (discussed below) to perform these duties. However, MFC is utilized for the rest of the GUI portion of these applications. All of the Windows GUIs in this topic are built as so-called "dialog" applications, meaning which they are composed of a single modal dialog whose implementation is entirely encapsulated within a single C++ class that inherits from the MFC base class CDialog.

Diagram depicting the general software structure of the Windows applications developed in this topic. They are MFC applications, with an MFC application class (left) responsible for instantiating a main dialog object. The dialog (middle) typically contains numerous child controls, and the callbacks that deal with reading image files and displaying monochrome 8-bit images use GDI+. The image processing algorithms call on Intel IPP functions (right).

Figure 2-5. Diagram depicting the general software structure of the Windows applications developed in this topic. They are MFC applications, with an MFC application class (left) responsible for instantiating a main dialog object. The dialog (middle) typically contains numerous child controls, and the callbacks that deal with reading image files and displaying monochrome 8-bit images use GDI+. The image processing algorithms call on Intel IPP functions (right).

The behavior of the GUI comes from what happens when the user interacts with the various controls that lie within the main dialog. When the user interacts with such controls, the MFC framework calls the appropriate callback methods in the CDialog-derived class. These callback methods are hooked into the application using the Visual Studio .NET 2003 GUI designer (previous versions of Visual Studio used something called the "class wizard" to a similar effect). The Visual Studio GUI designer takes care of inserting all of the infrastructure code that maps button clicks to method invocations. MFC does this through a well-defined command update mechanism via a process known as dynamic data exchange.

GDI+

GDI+ is an object-oriented extension to Microsoft’s venerable Graphical Device Interface API, and frankly has been sorely needed for quite some time. GDI is a C library of functions and type definitions used for 2D graphics, providing exactly the type of graphics functionality needed for visualizing the results of image processing algorithms – namely the rendering of bitmapped images. DirectDraw, which is a subset of DirectX, is a COM-based API that can provide similar functionality but is more complicated than GDI and more suited to streaming video and the type of 3D graphics prevalent in games and CAD applications. OpenGL is another option (in the Windows world, there is no dearth of options when it comes to programming libraries) but integration with MFC and Win32 in general is less straightforward than with GDI.

The historic problem with GDI has been its verbosity and vulnerability to resource leaks (the programmer must be diligent in explicitly freeing GDI resources), both of which can be traced back to the library’s C heritage. GDI+ corrects many of these problems, by providing convenient wrapper classes around core GDI types like bitmap and hdc (a handle to a device context). Of course, there is no such thing as a free lunch, and the cost of increased simplicity is performance – there is a slight performance hit when using GDI+, when compared to coding against the raw GDI API.

For the most part, the image processing applications in this topic use GDI+ classes and functionality to accomplish two distinct tasks: parsing image files and displaying bitmapped images. Reading in and parsing a Windows BMP or JPEG file used to be a tedious, mind-numbing chore with GDI. Now with GDI+, an image object can be constructed with nothing more than just the image file pathname, as so:

tmp6-38_thumb

The ‘L’ in front of the pathname string denotes a wide-character (16-bit) string literal. Saving an image using GDI+ is equally straightforward:

tmp6-39_thumb

Likewise, prior to the introduction of GDI, rendering a bitmap onto a Windows GUI was quite a bit more difficult than it should have been. Essentially, efficient display of a bitmap image boils down to an operation known as a "bit-block transfer", for which the legacy Bit Bit GDI function could be used. This function accepts eight input parameters and moreover, the simple act of rendering an image required a multitude of related GDI functions for initializing the device context, setting up the coordinate system, and so on. Finally, all resource handles must be managed very carefully and explicitly deallocated using appropriate GDI function calls, or else insidious and hard-to-track down memory leaks end up plaguing the application. With the object-oriented GDI+ library, all of the above and more are elegantly encapsulated by the Bitmap object. Both GDI and GDI+ come standard with Visual Studio .NET 2003.

Intel Integrated Performance Primitives (IPP)

The Intel IPP library is a collection of optimized C-callable functions targeting multimedia operations such as audio processing, video processing, data compression, and most importantly to us, image processing. You would be hard pressed to find faster implementations of the hundreds of basic operations that the Intel IPP library provides for the IA-32 and ItaniumĀ® architectures. The Windows applications in this topic use the latest version of the library (4.1), although all of the code has also been tested with the earlier 4.0 version and some with the earlier 3.0 version.


The IPP library can be purchased and downloaded from the Intel web site at http://www.intel.com/software/products/ipp/index.htm. In addition, a trial version of the library can also be downloaded for the purposes of building and using the code that accompanies this topic. By default, the IPP installation places the header files, static libraries, and DLLs within C: \Program Files\Intel\IPP, and the Visual Studio projects on the CD-ROM assume this location. If you install the IPP library to a different location, you will need to modify the projects to point to the correct location.

Next post:

Previous post: