C#圖像處理――前奏(一) 轉載

 

一.Bitmap類

Bitmap對象封裝了GDI+中的一個位圖,此位圖由圖形圖像及其屬性的像素數據組成.因此Bitmap是用於處理由像素數據定義的圖像的對象.該類的主要方法和屬性如下:

1.       GetPixel方法和 SetPixel方法:獲取和設置一個圖像的指定像素的顏色.

2.       PixelFormat屬性:返回圖像的像素格式.

3.       Palette屬性:獲取和設置圖像所使用的顏色調色板.

4.       Height Width屬性:返回圖像的高度和寬度.

5.       LockBits 方法和UnlockBits方法:分別鎖定和解鎖系統內存中的位圖像素.在基於像素點的圖像處理方法中使用LockBits 和UnlockBits是一個很好的方式,這兩種方法可以使我們指定像素的範圍來控制位圖的任意一部分,從而消除了通過循環對位圖的像素逐個進行處理,每調用LockBits 之後都應該調用一次UnlockBits.

 

二.BitmapData類

BitmapData對象指定了位圖的屬性

1.       Height屬性:被鎖定位圖的高度.

2.       Width屬性:被鎖定位圖的高度.

3.       PixelFormat屬性:數據的實際像素格式.

4.       Scan0屬性:被鎖定數組的首字節地址,如果整個圖像被鎖定,則是圖像的第一個字節地址.

5.       Stride屬性:步幅,也稱爲掃描寬度.

如上圖所示,數組的長度並不一定等於圖像像素數組的長度,還有一部分未用區域,這涉及到位圖的數據結構,系統要保證每行的字節數必須爲4的倍數.

 

三.Graphics類

Graphics對象是GDI+的關鍵所在,許多對象都是由Graphics類表示的,該類定義了繪製和填充圖形對象的方法和屬性,一個應用程序只要需要進行繪製或着色,它就必須使用Graphics對象.

 

四.Image類

  這個類提供了位圖和元文件操作的函數.Image類被聲明爲abstract,也就是說Image類不能實例化對象,而只能做爲一個基類.

1.FromFile方法:它根據輸入的文件名產生一個Image對象,它有兩種函數形式:

public static Image FromFile(string filename);

public static Image FromFile(string filename, bool useEmbeddedColorManagement);

2.FromHBitmap方法:它從一個windows句柄處創建一個bitmap對象, 它也包括兩種函數形式:

public static bitmap fromhbitmap(intptr hbitmap);

public static bitmap fromhbitmap(intptr hbitmap, intptr hpalette);

3. FromStream方法:從一個數據流中創建一個image對象,它包含三種函數形式 :

public static image fromstream(stream stream);

public static image fromstream(stream stream, bool useembeddedcolormanagement);

fromstream(stream stream, bool useembeddedcolormanagement, bool validateimagedata);

 

 

有了上面的瞭解,我們便可以開始利用C#做圖像處理,下面介紹幾種方法:

一.   打開、保存、顯示圖像

         private Bitmap srcBitmap = null;

          private Bitmap showBitmap = null;

        //打開文件

        private void menuFileOpen_Click(object sender, EventArgs e)

        {

            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.Filter = @"Bitmap文件(*.bmp)|*.bmp|Jpeg文件(*.jpg)|*.jpg|所有合適文件(*.bmp,*.jpg)|*.bmp;*.jpg";

            openFileDialog.FilterIndex = 3;

            openFileDialog.RestoreDirectory = true;

            if (DialogResult.OK == openFileDialog.ShowDialog())

            {

                srcBitmap = (Bitmap)Bitmap.FromFile(openFileDialog.FileName, false);

                showBitmap = srcBitmap;

                this.AutoScroll = true;

                this.AutoScrollMinSize = new Size((int)(showBitmap.Width), (int)(showBitmap.Height));

                this.Invalidate();

                

               

            }

        }

        //保存圖像文件

        private void menuFileSave_Click(object sender, EventArgs e)

        {

            if (showBitmap != null)

            {

                SaveFileDialog saveFileDialog = new SaveFileDialog();

                saveFileDialog.Filter = @"Bitmap文件(*.bmp)|*.bmp|Jpeg文件(*.jpg)|*.jpg|所有合適文件(*.bmp,*.jpg)|*.bmp;*.jpg";

                saveFileDialog.FilterIndex = 3;

                saveFileDialog.RestoreDirectory = true;

                if (DialogResult.OK == saveFileDialog.ShowDialog())

                {  

                    ImageFormat format = ImageFormat.Jpeg;

                    switch (Path.GetExtension(saveFileDialog.FileName).ToLower())

                    {

                        case ".jpg":

                            format = ImageFormat.Jpeg;

                            break;

                        case ".bmp":

                            format = ImageFormat.Bmp;

                            break;

                        default:

                            MessageBox.Show(this, "Unsupported image format was specified", "Error",

                                MessageBoxButtons.OK, MessageBoxIcon.Error);

                            return;

                    }

                    try

                    {

                        showBitmap.Save(saveFileDialog.FileName,format );

                    }

                    catch (Exception)

                    {

                        MessageBox.Show(this, "Failed writing image file", "Error",

                            MessageBoxButtons.OK, MessageBoxIcon.Error);

                    }

                }

            }

 

        }

    //窗口重繪,在窗體上顯示圖像,重載Paint

        private void frmMain_Paint(object sender, System.Windows.Forms.PaintEventArgs e)

        {

            if (showBitmap != null)

            {

                Graphics g = e.Graphics;

                g.DrawImage(showBitmap, new Rectangle(this.AutoScrollPosition.X, this.AutoScrollPosition.Y ,

                (int)(showBitmap.Width), (int)(showBitmap.Height)));

            }

        }

         //灰度化

        private void menu2Gray_Click(object sender, EventArgs e)

        {

            if (showBitmap == null) return;

            showBitmap = RGB2Gray(showBitmap);//下面都以RGB2Gray爲例

            this.Invalidate();

        }

二.   提取像素法

       這種方法簡單易懂,但相當耗時,完全不可取.

public static Bitmap RGB2Gray(Bitmap srcBitmap)

        {

            Color srcColor;

            int wide = srcBitmap.Width;

            int height = srcBitmap.Height;

            for (int y = 0; y < height; y++)

                for (int x = 0; x < wide; x++)

                {

                    //獲取像素的RGB顏色值

                    srcColor = srcBitmap.GetPixel(x, y);

                    byte temp = (byte)(srcColor.R * .299 + srcColor.G * .587 + srcColor.B * .114);

                    //設置像素的RGB顏色值

                    srcBitmap.SetPixel(x, y, Color.FromArgb(temp, temp, temp));

                }

            return srcBitmap ;

 

        }//#

 

三.   內存法

這是比較常用的方法

public static Bitmap RGB2Gray(Bitmap srcBitmap)

        {

            int wide = srcBitmap.Width;

            int height = srcBitmap.Height;

            Rectangle rect = new Rectangle(0, 0, wide, height);

            // 將Bitmap鎖定到系統內存中, 獲得BitmapData

            BitmapData srcBmData = srcBitmap.LockBits(rect,

                      ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            //創建Bitmap

             Bitmap dstBitmap = CreateGrayscaleImage(wide, height);//這個函數在後面有定義

            BitmapData dstBmData = dstBitmap.LockBits(rect,

                      ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);

            // 位圖中第一個像素數據的地址。它也可以看成是位圖中的第一個掃描行

            System.IntPtr srcPtr = srcBmData.Scan0;

            System.IntPtr dstPtr = dstBmData.Scan0;

            // 將Bitmap對象的信息存放到byte數組中

            int src_bytes = srcBmData.Stride * height;

            byte[] srcValues = new byte[src_bytes];

            int dst_bytes = dstBmData.Stride * height;

            byte[] dstValues = new byte[dst_bytes];

            //複製GRB信息到byte數組

            System.Runtime.InteropServices.Marshal.Copy(srcPtr, srcValues, 0, src_bytes);

            System.Runtime.InteropServices.Marshal.Copy(dstPtr, dstValues, 0, dst_bytes);

            // 根據Y=0.299*R+0.114*G+0.587B,Y爲亮度

            for (int i = 0; i < height; i++)

                for (int j = 0; j < wide; j++)

                {

                  //只處理每行中圖像像素數據,捨棄未用空間

                  //注意位圖結構中RGB按BGR的順序存儲

                    int k = 3 * j;

                    byte temp = (byte)(srcValues[i * srcBmData.Stride + k + 2] * .299

                         + srcValues[i * srcBmData.Stride + k + 1] * .587 + srcValues[i * srcBmData.Stride + k] * .114);

                    dstValues[i * dstBmData.Stride + j] = temp;

                }

            //將更改過的byte[]拷貝到原位圖

            System.Runtime.InteropServices.Marshal.Copy(dstValues, 0, dstPtr, dst_bytes);

           

            // 解鎖位圖

            srcBitmap.UnlockBits(srcBmData);

            dstBitmap.UnlockBits(dstBmData);

            return dstBitmap;

 

        }//#

 

轉載源:http://blog.csdn.net/xinshi9608/article/details/5725299

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章