The code in the
ProcessImage_Click event handler launches
filterTask, which is a
Task<Bitmap> that calls the
ApplyFilterSobelHoriz method. Then, the code programs a continuation for
filterTask that shows the results of the Sobel horizontal filter applied to a JPEG image in the
ProcessedImage Image control. To keep this example simple, the code doesn't check for errors that could occur. Instead, the code uses tasks and continuations to run the Sobel vertical filter with an asynchronous execution and to keep the UI thread unblocked until it is necessary to display the resulting image. As you can see, it is possible to combine task-based programming introduced in .NET Framework 4 with IPP calls.
ApplyFilterSobelHoriz unsafe method runs a Sobel horizontal filter for the C:\YOURPICTUREFOLDER\YOURPICTURE.JPG bitmap. This method prepares the source and destination data and pointers to call the image processing IPP method that applies the filter
ipp.ip.ippiFilterSobelHoriz_8u_C3R. IPP uses the most appropriate SIMD instructions and the most convenient number of threads to optimize the execution of the image-processing algorithm based on the image size and the underlying hardware.
First, the C# method creates a new Bitmap (
originalImage) by reading the path specified in the
filename parameter and locks the bits into system memory by calling the
GetBitmapData method. The read-only bits are available through
sourceBitmapData. Because you need to have a destination bitmap, the method creates a new Bitmap called
destinationImage, with the same width and height as the original bitmap. Then, the code locks the bits into system memory by calling the
GetBitmapData method. These bits are available for reading and writing through
roi IppiSize structure specifies the region of interest, known as ROI, for the image. Then, the C# code defines the byte pointers
pDst, which access the pixel data for the source and destination bitmaps. The necessary parameters for the Sobel filter are available, and therefore, it is time to call the
ipp.ip.ippiFilterSobelHoriz_8u_C3R method that processes an image with three channels — red, green, and blue. So, the method is appropriate to use any photo taken with a digital camera and saved with the JPEG format.
This method applies the filter and stores the resulting pixels in the destination bitmap. Then, regardless of the results of the IPP filter, the code unlocks the bits for both source and destination bitmaps and returns
destinationImage. If something went wrong, the method should check the value for the status variable and throw the necessary exceptions.
filterTask task is a
Task<Bitmap>, and it returns the result of calling the
ApplyFilterSobelHoriz method. The continuation task chained to the
filterTask task receives this task as
antecedentTask and waits for it to propagate any exceptions. If an exception occurs, the code just catches it without taking additional actions. If the image-processing filter ran without problems, the code that runs in the same thread that created the UI controls shows the resulting bitmap in the
ProcessedImage control. When you use the code in a WPF application, you need to use the
System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap method to create a
BitmapSource from a GDI+
Of course, there is a penalty for calling IPP functions through a P/Invoke. However, IPP functions are highly optimized functions, and therefore, you can take advantage of the most modern instruction set available in any Intel CPU by calling IPP functions. In addition, you can combine these calls with task-based programming in order to create a responsive UI with simple code.
The main IPP DLL (ippi-x.x.dll, where x.x should be replaced by the different version numbers) includes references to other DLLs, so it is necessary to have the folder that includes the main DLL and its related DLLs in the path environment variable. Another option is to copy all the DLLs in the bin output folder for the project. In the "redist" folder for Intel Parallel Composer 2011, you will find two sub-folders, "ia32" and "intel64". You will find an "ipp" sub-folder in both the "ia32" and "intel64" folders with all the DLLs that you can redistribute according to the desired instruction set, IA-32 or EM64T. It is usually helpful to copy the appropriate DLLs to your bin output folder for your C# project if you receive errors when the C# wrappers try to load the main IPP DLL.
Intel IPP is a commercial product, but you can download a free trial version here.
If you want to dive deeper on the advantages of using performance libraries, you can read the excellent article about Performance Library Basics by Lori Matassa and Max Domeica.