Several ways of using C # for image processing

Source: Internet
Author: User

This article discusses the use of bitmap classes, bitmapdata classes and unsafe code in C # image processing, and byte alignment issues.

Bitmap class

Namespaces: System.Drawing

Encapsulates a GDI + bitmap that consists of pixel data for a graphic image and its properties. Bitmap is an object that is used to process images defined by pixel data.

With the C # class for image processing, it is most convenient to use the bitmap class, using the class's GetPixel () and SetPixel () to access each pixel point of the image. The following is the sample code in MSDN:

public void Getpixel_example ( PaintEventArgs e)   {     //Create a Bitmap object from an image file.      Bitmap Mybitmap = new Bitmap ("Grapes.jpg");     //Get The color of a pixel within mybitmap.  &N bsp;   Color Pixelcolor = Mybitmap.getpixel (a);     //Fill a rectangle with Pixelcolo r.      SolidBrush pixelbrush = new SolidBrush (pixelcolor);      E. Graphics.FillRectangle (pixelbrush, 0, 0, +); }

It can be seen that the bitmap class uses an elegant way to manipulate the image, but the performance reduction is not negligible. For example, a 800*600 color image grayscale, the time spent in seconds to calculate. The speed of image processing in a real project is absolutely intolerable.

BitmapData class

Namespaces: System.Drawing.Imaging

Refers to the properties of the location map image. The BitmapData class is used by the LockBits and Unlockbits methods of the Bitmap class. Cannot be inherited.

Fortunately we also have the BitmapData class, through BitmapData BitmapData LockBits () can lock Bitmap into system memory. The public properties of this class are:

    • Width Gets or sets the pixel width of the Bitmap object. This can also be seen as a number of pixels in a scan line.
    • Height Gets or sets the pixel height of the Bitmap object. This is sometimes referred to as the number of scanned rows.
    • PixelFormat Gets or sets the format of the pixel information in the Bitmap object that returns this BitmapData object.
    • Scan0 Gets or sets the address of the first pixel data in a bitmap. It can also be seen as the first scan line in a bitmap.
    • Stride Gets or sets the span width (also known as the sweep width) of the Bitmap object.

The sample code in the following MSDN demonstrates how to use the PixelFormat, Height, Width, and Scan0 properties, LockBits and Unlockbits methods, and ImageLockMode enumerations.

private void Lockunlockbitsexample (PaintEventArgs e) {

Create a new bitmap. Bitmap bmp = New Bitmap ("c:\\fakephoto.jpg");

Lock the bitmap ' s bits. Rectangle rect = new Rectangle (0, 0, BMP. Width, BMP.      Height); System.Drawing.Imaging.BitmapData bmpdata = bmp. LockBits (Rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, BMP.      PixelFormat);     Get the address of the first line. IntPtr ptr = bmpdata.scan0;

Declare an array to hold the bytes of the bitmap. int bytes = bmpdata.stride * bmp.      Height; byte[] rgbvalues = new Byte[bytes];

Copy the RGB values into the array. System.Runtime.InteropServices.Marshal.Copy (PTR, rgbvalues, 0, bytes);

Set every red value to 255.      for (int counter = 0; counter < rgbvalues.length; counter+=3) rgbvalues[counter] = 255; Copy the RGB values back to the bitmap System.Runtime.InteropServices.Marshal.Copy (rgbvalues, 0, ptr, bytes);

Unlock the bits. Bmp. Unlockbits (Bmpdata);

Draw the modified image. E.graphics.drawimage (BMP, 0, 150);

}

The code above demonstrates how to access an image in an array, rather than using inefficient getpixel () and SetPixel ().

Unsafe code

In fact, the above approach still does not meet our requirements, image processing is a large number of operations, different from the general application we write. What we need is an image processing program that is comparable in performance to a C + + program. C + + is how to improve efficiency, answer Yue: pointer. Fortunately, it is. NET also allows us to use pointers only in non-secure blocks of code. What is a non-security code?

In order to maintain type safety, C # does not support pointer arithmetic by default. However, by using the unsafe keyword, you can define an unsafe context in which pointers can be used. In the common language runtime (CLR), unsafe code refers to code that cannot be verified. Unsafe code in C # is not necessarily dangerous, but code whose security cannot be validated by the CLR. Therefore, the CLR only performs operations on unsafe code in fully trusted assemblies. If you use unsafe code, you are responsible for ensuring that your code does not cause security risks or pointer errors. Unsafe code has the following properties:

    • methods, types, and code blocks that can be defined as unsafe.
    • In some cases, unsafe code can improve the performance of an application by removing an array boundary check.
    • Unsafe code is required when calling a native function that requires pointers.
    • Using unsafe code will cause security risks and stability risks.
    • In C #, in order to compile unsafe code, the application must be compiled with/unsafe.

As the C # language specification says, unsafe code is in fact a "security" feature, both from the developer and from the user's point of view. Unsafe code must be explicitly marked with the modifier unsafe, so that the developer does not misuse unsafe functionality, and the execution engine will ensure that unsafe code is not executed in an untrusted environment.

The following code shows how to traverse an image with a pointer to the BitmapData class, where the code in the unsafe code block is the non-secure code.

Create images   BITMAP image =  new Bitmap ("C:\\images\\image.gif"); //Get images of BitmapData pairs like   BitmapData data = Image. LockBits (New Rectangle (0, 0, image. Width, image. Height), imagelockmode.readwrite , pixelformat.format24bpprgb );  //cyclic processing   unsafe  {& nbsp;         byte* ptr = (byte*) (data. Scan0);          for (int i = 0; i < data. Height; i + +)          {            for (int j = 0;  J < data.) Width;  J + +)              {               /write the logic implementation here                ptr + = 3;               }&nbsp          ptr + = data. Stride-data. Width * 3;        } }

There is no doubt that this approach is the fastest, so in the actual project is the use of pointers to the way to access the image pixels.

The byte alignment problem is in the above example ptr + = data. Stride-data. Width * 3, which means crossing useless areas because the image data is stored in memory as 4-byte aligned, as explained below:

Suppose there is a picture with a width of 6, which is assumed to be in Format24bpprgb format (3 bytes per pixel, in the following discussion, unless otherwise noted, bitmap are considered 24-bit RGB). Obviously, each row needs to be 6*3=18 bytes of storage. This is true for bitmap. But for BitmapData, though data. Width is still equal to image.width, but presumably for display performance considerations, the actual number of bytes per line will become greater than or equal to its nearest 4 of the full multiples, at which point the actual number of bytes is stride. In this case, 18 is not an integer multiple of 4, and a multiple of the nearest 4 to 18 is 20, so this data is greater than 18. Stride = 20. Obviously, when the width itself is a multiple of 4, data. Stride = image. Width * 3.

Drawing a picture may be better understood. R, G, and B represent 3 primary component bytes respectively, and BGR represents one pixel. To make it look convenient, I've inserted a space between each pixel, and there's actually no. X is the byte that is automatically inserted to complement the multiple of 4. In order to conform to human reading habits I branch, in fact, in computer memory should be seen as a continuous large segment.

|-------stride-----------| |-------width---------| | scan0:bgr bgr bgr BGR bgr bgr xx bgr bgr bgr bgr bgr BGR xx BGR  BGR BGR BGR BGR BGR xx.  . .

First use data. Scan0 found the address of the No. 0 component of the No. 0 pixel, which pointed to a byte type, so it was defined as byte* ptr. When a row is scanned, the current pointer position (as the No. 0 color component of the current pixel) is continuously removed with three values (3 primaries components). Note that 0 1 2 represents the order of B G R. When taking the value pointed to by the pointer, it looks like p[n] and P + = N and then fetch p[0] is equivalent), and then move down 3 positions (ptr + = 3, as refers to the next pixel of the No. 0 color component). After doing the bitmap.width operation, reached the position of Bitmap.width * 3, you should skip the byte labeled X in the graph (a total of Stride-width * 3 bytes), the code is PTR + = DATAIN.STRIDE-DATAIN.W Idth * 3.

By reading this article, I believe you have an understanding of several ways in which you might use C # for image processing. The way you use it depends on your performance requirements. The first is the most elegant, the third is the fastest, but not the security code, and the second is a compromise that guarantees security code while improving efficiency. People who are familiar with C + + programming may be more inclined to the third way, and I personally prefer the third way.

Several methods for image processing using C # (GO)

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.