Recipe 10.18. Speeding Up Image Processing


Problem

You want to implement some image-processing algorithms, and you want the operations to be reasonably fast.

Solution

Sample code folder: Chapter 10\LockImage

Use the InteropServices.Marshal.LockBits() method to prevent the operating system from moving the bitmap data around in memory. This greatly speeds up the program's access to the pixel data. This recipe presents a LockImage class that wraps the LockBits() functionality for easy use.

Discussion

The LockImage class presented in this recipe and the remaining recipes in this chapter contains several image-processing methods. (The full LockImage class is listed in Recipe 10.21.) The goal is to provide enough examples to enable you to design your own image-processing functionality.

The processing function demonstrated in this recipe is Mirror(), a method of the LockImage class that flips an image left and right. To see how it works, create a form with a PictureBox on it that has its Dock property set to Fill and its SizeMode property set to StretchImage. Load a picture into its Image property, and add the following code to its Click event:

 Private Sub PictureBox1_Click(ByVal sender As System.Object, _       ByVal e As System.EventArgs) Handles PictureBox1.Click    ' ----- Mirror-image the bitmap.    Dim mirrorIt As New LockImage    mirrorIt.Image = PictureBox1.Image    mirrorIt.Mirror( )    PictureBox1.Image = mirrorIt.Image End Sub 

When you click on the picture, this procedure creates an instance of the LockImage class, copies the PictureBox's image to it, calls the Mirror() method to process the image, and then copies the image back into the PictureBox. This is the pattern for using any of the processing methods of the LockImage class.

Now let's look at the portions of the LockImage class that relate to the mirroring processs.

First, you must import the requisite namespaces. InteropServices.Marshal is required for its LockBits() method. The class defines a few class-level variables:

 Imports System.Drawing.Imaging Imports System.Runtime.InteropServices.Marshal Public Class LockImage    Private BaseImage As Bitmap    Private BaseImageWidth As Integer    Private BaseImageHeight As Integer    Private TotalPixels As Integer    Private ImageAddress As IntPtr    Private ImageContent As BitmapData    Private ImageBuffer( ) As Integer 

The Image property stores or retrieves the bitmap image to be locked and processed:

 Public Property Image( ) As Bitmap    ' ----- User access to the relevant image.    Get       Return BaseImage    End Get    Set(ByVal Value As Bitmap)       Dim canvas As Graphics       BaseImage = New Bitmap(Value.Width, _          Value.Height, Value.PixelFormat)       canvas = Graphics.FromImage(BaseImage)       canvas.DrawImage(Value, 0, 0, _          Value.Width, Value.Height)       canvas.Dispose( )    End Set End Property 

The LockTheImage() method provides the important core functionality of this class; with it, you can lock down the bits of the bitmap and present the pixel data in an integer array for efficient processing. All pixel processing in the methods you create, such as the Mirror() method presented later, will process in place the integer pixel data stored in ImageBuffer().

Each 32-bit integer in ImageBuffer() represents a single pixel. The most significant byte is alpha, the opacity value. The next most significant byte is for red, then green, and the least significant byte is for blue. Each of these four values ranges from 0 to 255. Two other variables of importance for your image-processing methods are BaseImageWidth and BaseImageHeight. The ImageBuffer() array is one-dimensional, so these two values are required to determine the rectangular layout of the pixels:

 Private Sub LockTheImage( )    ' ----- Lock the image in memory. How much room    '       do we need?    BaseImageWidth = BaseImage.Width    BaseImageHeight = BaseImage.Height    TotalPixels = BaseImageWidth * BaseImageHeight    ' ----- Create a stable (locked) area in memory. It    '       will store 32-bit color images.    ReDim ImageBuffer(TotalPixels - 1)    ImageContent = BaseImage.LockBits( _       New Rectangle(0, 0, BaseImageWidth, _       BaseImageHeight), ImageLockMode.ReadWrite, _       PixelFormat.Format32bppRgb)    ImageAddress = ImageContent.Scan0    ' ----- Associate the buffer and the locked memory.    Copy(ImageAddress, ImageBuffer, 0, TotalPixels) End Sub 

The Mirror() method works by locating the first and last pixels of each row of the image, then swapping the pixels at those locations. The next and previous pixels in the row are swapped next, and this continues until all pixels in the row have been swapped. Here is the code for the Mirror() method:

 Public Sub Mirror( )    ' ----- Make a left-to-right mirror image.    Dim pixelIndex1 As Integer    Dim pixelIndex2 As Integer    Dim holdPixel As Integer    Dim down As Integer    ' ----- Lock the image for speed.    LockTheImage( )    ' ----- Process each row of the image.    For down = 0 To BaseImageHeight - 1       ' ----- Process each column,   up to halfway across.       pixelIndex1 = down * BaseImageWidth       pixelIndex2 = pixelIndex1 + BaseImageWidth - 1       Do While pixelIndex1 < pixelIndex2          ' ----- Swap two pixels.          holdPixel = ImageBuffer(pixelIndex1)          ImageBuffer(pixelIndex1) = _             ImageBuffer(pixelIndex2)          ImageBuffer(pixelIndex2) = holdPixel          pixelIndex1 += 1          pixelIndex2 -= 1       Loop    Next down    ' ----- Finished. Unlock the image.    UnlockTheImage( ) End Sub 

The UnlockTheImage( ) method restores the processed pixel data in ImageBuffer( ) to the bitmap, ready to be retrieved by the code that uses the class:

 Private Sub UnlockTheImage( )    ' ----- Unlock the memory area.    Copy(ImageBuffer, 0, ImageAddress, TotalPixels)    Image.UnlockBits(ImageContent)    ImageContent = Nothing    ReDim ImageBuffer(0) End Sub 

Figure 10-26 shows a sample picture just before being flipped; Figure 10-27 shows the picture immediately afterwards.

Figure 10-26. An image about to be flipped horizontally


See Also

Recipe 10.21 includes the full source code for the LockImage class.

Figure 10-27. The same image after the Mirror( ) method has worked its magic





Visual Basic 2005 Cookbook(c) Solutions for VB 2005 Programmers
Visual Basic 2005 Cookbook: Solutions for VB 2005 Programmers (Cookbooks (OReilly))
ISBN: 0596101775
EAN: 2147483647
Year: 2006
Pages: 400

Similar book on Amazon

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net