Introduction: Microsoft's new .NET platform brings many new programming mechanisms such as GDI , Globalization to developers, and also invented a new programming language-C # similar to Java. For these new knowledge, we should understand and try to apply to practice projects as soon as possible, and the methods learned through instance are undoubtedly a very effective way. This article uses a simple example to show you how to use GDI and UNSAFE code classes in Visual C # to achieve simple digital image processing.
One. Overview:
The example of this paper is a digital image processing application. Its completion of its completion include the flipping of the image color, grayscale processing and lighting the image. The program is included in the image of the image in a dedicated Filters class, and we can implement the corresponding image processing function by calling the static member functions in this class. To achieve image processing, we have to process images one by one. We know that the image is composed of one one, and each pixel of an image has been processed, and finally the entire image is processed. In this process, we only need to process each pixel point, but do not need to consider the influence of the surrounding pixel points in the processing, so the implementation of the program is much simpler.
Since the BitMapData class in GDI does not provide direct access to image internal data, our unique way is to use pointers to get internal data of the image, then we have to use the Unsafe keyword to specify the internal data in the function. The code block. In the program, I also use options such as open files and save files to make our hard work.
two. Program implementation:
1. Open Visual Studio.NET, create a new Visual C # project, select "Windows Application" in the template, the project name can be customized (here ImageProcessor).
2. To make the form display images, we need to overload the onpaint () event function in this function, we draw an image on the main form of the program, in order to make the form display different sizes of size images, We also set the form of the AutoScroll property to TRUE. Thus, according to the size of the image, the corresponding scroll bar will appear on both sides. The implementation of this function is as follows:
Private void form1_paint (object sender, system.windows.Forms.PainteventArgs E)
{
Graphics g = E.Graphics;
g.drawImage (m_bitmap, new rectangle (this.autoscrollposition.x, this.autoscrollposition.y,
(int) (m_bitmap.width), (int)));
}
3. Add a main menu to the main form, the main menu completes some basic operations, including "Open File", "Save File", "Exit", "Flip Operation", "Gray Action", "Highlighting" Wait. The front three operations complete the opening and saving of the image file and the exit function of the program, the corresponding event processing function is as follows:
private void menuItemOpen_Click (object sender, System.EventArgs e) {OpenFileDialog openFileDialog = new OpenFileDialog (); openFileDialog.Filter = "Bitmap file (* .bmp) | * .bmp | Jpeg files (* .jpg) | * .jpg | All suitable documents (* .bmp / *. Jpg) | * .bmp / *. Jpg "; openfiledialog.filterindex = 2; OpenFileDialog.restRedirectory = true; if (DialogResult.ok == OpenFiledialog.ShowDialog ()) {m_bitmap = (Bitmap) Bitmap.FromFile (openFileDialog.FileName, false); this.AutoScroll = true; this.AutoScrollMinSize = new Size ((int) (m_Bitmap.Width), (int) m_Bitmap.Height)); this.Invalidate () ,}} Where M_bitmap is a data member of the main window body class, which is declared as private system.drawing.bitmap m_bitmap; (Note: Using the related class in the program, you should add USING SYSTEM. Drawing.Imaging;) At the same time, in the constructor of this class, we must first give it a Bitmap object: m_bitmap = new bitmap (2, 2); this code in the above code (); complete the main form Heavy painting, it calls the onpaint () function of the main form, and the open image file is displayed on the main form.
private void menuItemSave_Click (object sender, System.EventArgs e) {SaveFileDialog saveFileDialog = new SaveFileDialog (); saveFileDialog.Filter = "Bitmap file (* .bmp) | * .bmp | Jpeg files (* .jpg) | * .jpg | All suitable files (* .bmp / *. Jpg) | * .bmp / *. Jpg "; savefiledialog.filterindex = 1; SaveFileDialog.restRedirectory = true; if (DialogResult.ok == SaveFileDialog.showDialog ()) {m_bitmap. Save (SaveFileDialog.FileName);}}
Where m_bitmap.save (SaveFileDialog.FileName); a preservation of the image file is exactly the powerful function of GDI , we only need this simple statement to complete the task of the previous workload, so it is reasonable. The new mechanism in NET will greatly simplify our work.
Private Void MenuiteMexit_Click (Object Sender, System.EventArgs E) {this.close ();}
Next, the event handler of the three main operations is as follows:
private void menuItemInvert_Click (object sender, System.EventArgs e) {if (Filters.Invert (m_Bitmap)) this.Invalidate ();} private void menuItemGray_Click (object sender, System.EventArgs e) {if (Filters.Gray (m_Bitmap) this.invalidate ();} private void menuitembright_click (object sender, system.eventargs e) {parameter dlg = new parameter (); dlg.nvalue = 0; if (DialogResult.ok == DLG.ShowDialog ()) {IF (Filters.brightness (M_bitmap, Dlg.nValue) this.invalidate ();}}} The three functions of the corresponding image processing function invert (), gray (), brightness (), etc. are called in three functions. The three types in the three functions of the Filters class are the static function of public (containing Static Keywords), and their return value types are BOOL type, which we can decide whether to perform the redrawing of the main form according to the return value.
Invert (), gray (), both functions such as Brightness () are included in the Filters class, the INVERT () function algorithm is as follows:
public static bool Invert (Bitmap b) {BitmapData bmData = b.LockBits (new Rectangle (0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System. INTPTR scan0 = bmdata.scan0; unsafe {byte * p = (byte *) (void *) scan0; int noffset = stride - b.width * 3; int nwidth = B.Width * 3; for (int y = 0; Y This function and the parameters of the later functions are bitmap types, and their passages are the image files opened in the program. The BitMapData type of BitmapData in this function contains internal information of the image file. The Stride property of the BMDATA indicates the width of a line, and its scan0 property is a pointer to the internal information of the image. The function completed by this function is the flip of the image color, the implementation method is to use 255 to subtract the value of each pixel point in the image, and set the resulting value to the value at the original pixel point, for each pixel point To do this, only the entire image is processed. The unsafe code block in the function is the main part of the entire function. First we get the pointer of the image internal data, then set the offset, and set nwidth to B.Width * 3, because each pixel point contains three colors. Ingredients, three processing is performed when handling each pixel point. Next, use two nesting for loops to complete the processing of each pixel point, the core of processing is a sentence: p [0] = (byte) (255-p [0]) ;. After the UNSAFE code block, B. UlockBits (BMDATA) can be used to release the image resource. The function is executed, and finally returns the TRUE value. Note: Since it is necessary to compile unsafe code, you have to set the "Allow Unsafe Code Block" attribute in the project property page to True, which is shown below: The program effect implemented by this function is as follows: The algorithm of the gray () function is as follows: public static bool Gray (Bitmap b) {BitmapData bmData = b.LockBits (new Rectangle (0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System. INTPTR scan0 = bmdata.scan0; unsafe {byte * p = (byte *) (void *) scan0; int noffset = stride - b.Width * 3; Byte Red, Green, Blue; for (int y = 0; y < B.HEIGHT; Y) {for (int x = 0; x The function completed in this function is to gray the image, and our basic idea is the average value of the three color components of each pixel point. However, due to the sensitivity of the human eye, the effect of this complete mean is not good, so I took three effective parameters in the program: .299, .587, .114. However, it is intended here that the format stored in GDI is BGR instead of RGB, ie there is: Blue, Green, RED. Therefore, it is necessary to set the value of variables such as Red, Green, Blue in the FOR cycle, and cannot be reversed. After the function is executed, the TRUE value is also returned. The programs achieved by this function are as follows: The algorithm of the Brightness () function is as follows: Public Static Bool Brightness (Bitmap B, INT NBRIGHTNESS) {IF (Nbrightness <-255 || Nbrightness> 255) Return False; Bitmapdata Bmdata = B.Lockbits (New Rectangle (0, 0, B.Width, B.HEight), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; int nVal = 0; unsafe {byte * p = (byte *) (void *) Scan0; int nOffset = stride - B.Width * 3; int nwidth = B.Width * 3; for (int y = 0; y The programs achieved by this function are as follows: three. summary: This article shows you the basic way to complete digital image processing with Visual C # and GDI through a simple example. Through instance, we can not find reasonable application new technologies not only greatly simplify our programming work, but also improve programming efficiency. However, we have to use new technologies while understanding basic programming ideas is the most important, different languages, different mechanisms only achieve specific ways, and its inner thinking is also connected. For the above example, the algorithm for writing image processing functions is mastered, and it should be possible in other ways. At the same time, on the basis of the above, the reader may wish to try to raise a non-three to prepare more of the functions of image processing to enrich and improve this simple example.