C # Performance Comparison of common image processing methods

Source: Internet
Author: User

In. NET programming, due to the emergence of GDI +, the image processing function is greatly enhanced. This article introduces the common image processing methods and principles in. NET through a simple black/white processing instance and compares the performance of various methods.

 

Black and white processing principle: there are usually three algorithms for processing color images into black and white effects;

(1). Maximum Value Method: Make the R, G, and B values of each pixel equal to the largest one in the RGB (color value) of the original pixel;

(2). Average Method: The R, G, and B values of each pixel are equal to the average values of the RGB values of the original pixel;

(3). weighted average method: weighted the R, G, and B values of each pixel.

I think that the black and white images produced by the third method are "authentic ".

 

1. GetPixel Method

GetPixel (I, j) and SetPixel (I, j, Color) can directly obtain the Color structure of an image pixel, but the processing speed is relatively slow.

/// <Summary>
/// Pixel Method
/// </Summary>
/// <Param name = "curBitmap"> </param>
Private void PixelFun (Bitmap curBitmap)
{
Int width = curBitmap. Width;
Int height = curBitmap. Height;
For (int I = 0; I <width; I ++) // If I <curBitmap. Width is used as a loop, the performance will be affected.
{
For (int j = 0; j {
Color curColor = curBitmap. GetPixel (I, j );
Int ret = (int) (curColor. R * 0.299 + curColor. G * 0.587 + curColor. B * 0.114 );
CurBitmap. SetPixel (I, j, Color. FromArgb (ret, ret, ret ));
}
}
}

I <curBitmap. width is used as a loop condition, but should be retrieved and saved to a variable. In this way, the Width attribute is not retrieved from curBitmp every time during the loop, thus improving the performance.

However, the direct pixel extraction method cannot process large pixel images. It takes 2182ms to process a 1440*900 image:

Before processing:

After processing:

 

We can intuitively see that the time used for multiple tests has a slight fluctuation.

2. memory copy method
The memory copy method uses System. runtime. interopServices. marshal. copy Copies the image data to the array and then processes it. You do not need to directly operate the pointer without using unsafe. The processing speed is not much different from the pointer processing speed, processing a pair of 1440*900 images takes about 34 ms.

 
A class required for both the memory copy and pointer Methods: BitmapData
 

BitmapData class

 

The BitmapData object specifies the properties of the bitmap.

 

1. Height attribute: the Height of the locked bitmap.

 

2. Width attribute: the height of the locked bitmap.

 

3. PixelFormat attribute: the actual pixel format of the data.

 

4. Scan0 attribute: the first byte address of the locked array. If the entire image is locked, it is the first byte address of the image.

 

5. Stride attribute: Stride, also known as scan width.

As shown in, the length of the array is not necessarily equal to the length of the pixel array of the image. There are still some unused areas. This involves the bitmap data structure. The system must ensure that the number of bytes per line must be a multiple of 4.

Assume that the width of an image is 6, because the format is Format24bppRgb (3 bytes per pixel.Unless otherwise specifiedBitmapAre considered as 24Bit RGB)OfObviously, each row needs 6*3 = 18 bytes of storage. This is true for Bitmap. However, for BitmapData, although BitmapData. width is equal to Bitmap. width, but probably because of the display performance, the actual number of bytes in each line will be an integer greater than or equal to the 4 nearest to it, the actual number of bytes is Stride. In this example, 18 is not an integer multiple of 4, and the multiples of 4 closest to 18 are 20, so BitmapData. Stride = 20. Obviously, when the Width itself is a multiple of 4, BitmapData. Stride = Bitmap. Width * 3.

It may be better to draw a picture (this figure only applies when PixelFormat = PixelFormat. Format24bppRgb, each pixel occupies 24 bytes in total ). R, G, and B represent three primary color component bytes, respectively. BGR represents one pixel. To make it look convenient, I inserted a space between each pixel, which is actually none. X indicates the number of automatically inserted bytes that multiply by 4. In order to meet the reading habits of humans, I am a branch. In fact, it should be regarded as a continuous segment in the computer memory.

Scan0
|
| ------- Stride --------- |
| ------- Width --------- |
BGR XX
BGR XX
BGR XX
.
The Format24bppRgb format meets the following requirements:

BitmapData. Width * 3 +No space for each row (XX) = BitmapData. Stride

 

Similarly, for Format32bppRgb or Format32bppPArgb:

BitmapData. Width * 4 +No space for each row (XX) = BitmapData. Stride

/// <Summary>
/// Memory copy method
/// </Summary>
/// <Param name = "curBitmap"> </param>
Private unsafe void MemoryCopy (Bitmap curBitmap)
{
Int width = curBitmap. Width;
Int height = curBitmap. Height;

Rectangle rect = new Rectangle (0, 0, curBitmap. Width, curBitmap. Height );
System. Drawing. Imaging. BitmapData bmp data = curBitmap. LockBits (rect, System. Drawing. Imaging. ImageLockMode. ReadWrite, PixelFormat. Format24bppRgb); // curBitmap. PixelFormat

IntPtr = BMP data. Scan0;
Int bytesCount = BMP data. Stride * BMP data. Height;
Byte [] arrDst = new byte [bytesCount];
Marshal. Copy (ptr, arrDst, 0, bytesCount );

For (int I = 0; I <bytesCount; I + = 3)
{
Byte colorTemp = (byte) (arrDst [I + 2] * 0.299 + arrDst [I + 1] * 0.587 + arrDst [I] * 0.114 );
ArrDst [I] = arrDst [I + 1] = arrDst [I + 2] = (byte) colorTemp;

}
Marshal. Copy (arrDst, 0, ptr, bytesCount );
CurBitmap. UnlockBits (BMP data );
}

 3.Pointer Method

The pointer is an unsafe operation in c # And must be enclosed by unsafe for processing. The fastest speed is. It takes about 18 ms to process a 180*180 image.

 

Byte * ptr = (byte *) (BMP data. scan0); obtain the pointer to the root position of the image data, and then use BMP data. scan 0 to obtain the scanning width of the image, and then you can perform pointer operations.

 

/// <Summary>
/// Pointer Method
/// </Summary>
/// <Param name = "curBitmap"> </param>
Private unsafe void PointerFun (Bitmap curBitmap)
{
Int width = curBitmap. Width;
Int height = curBitmap. Height;

Rectangle rect = new Rectangle (0, 0, curBitmap. Width, curBitmap. Height );
System. Drawing. Imaging. BitmapData bmp data = curBitmap. LockBits (rect, System. Drawing. Imaging. ImageLockMode. ReadWrite, PixelFormat. Format24bppRgb); // curBitmap. PixelFormat
Byte temp = 0;
Int w = BMP data. Width;
Int h = BMP data. Height;
Byte * ptr = (byte *) (BMP data. Scan0 );
For (int I = 0; I {
For (int j = 0; j <w; j ++)
{
Temp = (byte) (0.299 * ptr [2] + 0.587 * ptr [1] + 0.114 * ptr [0]);
Ptr [0] = ptr [1] = ptr [2] = temp;
Ptr + = 3; // Format24bppRgb format each pixel occupies 3 bytes
}
Ptr + = BMP data. Stride-BMP data. Width * 3; // when each row reads the last "useful" data, skip unused space XX
}
CurBitmap. UnlockBits (BMP data );
}
The following are multiple groups of test data:
 
1920*1080
1440*900
1208*800
1024*768
500*544
200*169
Direct pixel Extraction
1705ms
1051ms
1710ms
1340ms
450ms
32ms
Memory copy method
54ms
33ms
26ms
20ms
7ms
0ms
Pointer Method
28ms
17ms
14ms
10ms
3ms
0ms
 
It can be seen that the efficiency of pointer and direct pixel extraction is two orders of magnitude!
Compare the advantages and disadvantages of the above method: 1. in general, the performance pointer method is slightly better than the memory copy method, and the direct pixel extraction method has the lowest performance. 2. the performance of big image processing pointer and memory copy methods has been significantly improved, and small images are relatively fast. 3. direct pixel extraction is easy to use and requires no attention to the image pixel format (PixelFormat), which is a secure code; if the memory copy method and pointer method do not change the pixel format of the original image, different processing needs to be performed for different pixel formats, which is unsafe code.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.