Bitmap類、 Bitmapdata類和 Graphics類是C#圖像處理中最重要的3個類,如果要用C#
進行圖像處理,就一定要掌握它們。
1.1 Bitmap類
Bitmap對象封裝了GDI+中的一個位圖,此位圖由圖形圖像及其屬性的像素數據組成。
因此 Bitmap是用於處理由像素數據定義的圖像的對象。
Bitmap類類的主要方法和屬性如下:
Get Pixel方法和 Setpiⅸel方法:獲取和設置一個圖像的指定像素的顏色
Pixelformat屬性:返回圖像的像素格式。
Palette屬性:獲取或設置圖像所使用的顏色調色板。
Height屬性和 Width屬性:返回圖像的高度和寬度
Lockbits方法和 Unlockbits方法:分別鎖定和解鎖系統內存中的位圖像素。在基於
像素點的圖像處理方法中使用 Lockbits和 Unlockbits是一個很好的方式,這兩種方法可以使
我們通過指定像素的范圍來控制位圖的任意一部分,從而消除了通過循環對位圖的像素逐個
進行處理的需要。每次調用 Lockbits之后都應該調用一次 Unlockbits
Lockbits方法的定義如下:
public BitmapData LockBits(rectangle rect,ImageLockMode flag,PixelFormat format);
Lockbits矩形參數Rectangle定義了要在系統內存中鎖定的位圖的一部分;
Image Lockmode枚舉提供了對數據的訪問方式,表2.1所示是它的成員;
Pixelformat枚舉表示像素的格式,表2.2所示是它的主要成員。
Unlockbits方法使用一個由Lockbits返回的類型為BitmapData的參數,它定義為:
public void Unlockbits(BitmapData bitmapdata);
1.2 Bitmapdata類
Bitmapdata對象指定了位圖的屬性,如下所示。
Height屬性:被鎖定位圖的高度
Width屬性:被鎖定位圖的寬度
PixelFormat屬性:數據的實際像素格式
Scan0屬性:被鎖定數組的首字節地數組的地址。如果整個圖像被鎖定,則是圖像Height的第一個字節地址。
Stride屬性:步幅,也稱為掃描寬度
如圖所示,數組的寬度並不一定等於圖像像素數組的寬度,還有一部分未用區域。這是為了提高效率,系統要確定每行的字節數必須為4的倍數。例如一幅24位、寬為17個像素的圖像,它需要每行占有的空間為51(3×17)個字節,但51不是4的倍數,因此還需要補充1個字節,從而使每行的字節數擴展為52(4x13,即 Stride=52),這樣就滿足了每行字節數是4的倍數的條件。需要擴展多少個字節不僅是由圖像的寬度決定,而且還由圖像像素的格式決定。由於本書所選擇的圖像大小都為512×512,因此無論是24位彩色圖像,還是8位的灰度圖像,都滿足是4的倍數的條件,無需再擴展。如果處理的是任意寬度的圖像,那么在進行行掃描的時候,就需要把擴展字節去除掉。
1.3 Graphics類
raphics對象是GDH+的關鍵所在。許多對象都是由 Graphics類表示的,該類定義了繪
制和填充圖形對象的方法和屬性。一個應用程序只要需要進行繪制或着色,它就必須使用
Graphics對象。
1.4 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);
基礎代碼框架:
打開、保存、顯示圖像
//文件名 private string curFileName; //圖像對象 private Bitmap curBitmap; /// <summary> /// 打開圖像文件 /// </summary> private void open_Click(object sender, EventArgs e) { //創建OpenFileDialog OpenFileDialog opnDlg = new OpenFileDialog(); //為圖像選擇一個篩選器 opnDlg.Filter = "所有圖像文件|*.bmp;*.pcx;*.png;*.jpg;*.gif;" + "*.tif;*.ico;*.dxf;*.cgm;*.cdr;*.wmf;*.eps;*.emf|" + "位圖(*.bmp;*.jpg;*.png;...)|*.bmp;*.pcx;*.png;*.jpg;*.gif;*.tif;*.ico|" + "矢量圖(*.wmf;*.eps;*.emf;...)|*.dxf;*.cgm;*.cdr;*.wmf;*.eps;*.emf"; //設置對話框標題 opnDlg.Title = "打開圖像文件"; //啟用“幫助”按鈕 opnDlg.ShowHelp = true; //如果結果為“打開”,選定文件 if (opnDlg.ShowDialog() == DialogResult.OK) { //讀取當前選中的文件名 curFileName = opnDlg.FileName; //使用Image.FromFile創建圖像對象 try { curBitmap = (Bitmap)Image.FromFile(curFileName); } catch (Exception exp) { MessageBox.Show(exp.Message); } } //對窗體進行重新繪制,這將強制執行paint事件處理程序 Invalidate(); }
//在控件需要重新繪制時發生(窗體事件) private void Form1_Paint(object sender, PaintEventArgs e) { //獲取Graphics對象 Graphics g = e.Graphics; if (curBitmap != null) { //使用DrawImage方法繪制圖像 //180,20:顯示在主窗體內,圖像左上角的坐標 //curBitmap.Width, curBitmap.Height圖像的寬度和高度 g.DrawImage(curBitmap, 180, 20, curBitmap.Width, curBitmap.Height); } }
/// <summary> /// 保存圖像文件 /// </summary> private void save_Click(object sender, EventArgs e) { //如果沒有創建圖像,則退出 if (curBitmap == null) return; //調用SaveFileDialog SaveFileDialog saveDlg = new SaveFileDialog(); //設置對話框標題 saveDlg.Title = "保存為"; //改寫已存在文件時提示用戶 saveDlg.OverwritePrompt = true; //為圖像選擇一個篩選器 saveDlg.Filter = "BMP文件(*.bmp)|*.bmp|" + "Gif文件(*.gif)|*.gif|" + "JPEG文件(*.jpg)|*.jpg|" + "PNG文件(*.png)|*.png"; //啟用“幫助”按鈕 saveDlg.ShowHelp = true; //如果選擇了格式,則保存圖像 if (saveDlg.ShowDialog() == DialogResult.OK) { //獲取用戶選擇的文件名 string filename = saveDlg.FileName; string strFilExtn = filename.Remove(0, filename.Length - 3); //保存文件 switch (strFilExtn) { //以指定格式保存 case "bmp": curBitmap.Save(filename, ImageFormat.Bmp); break; case "jpg": curBitmap.Save(filename, ImageFormat.Jpeg); break; case "gif": curBitmap.Save(filename, ImageFormat.Gif); break; case "tif": curBitmap.Save(filename, ImageFormat.Tiff); break; case "png": curBitmap.Save(filename, ImageFormat.Png); break; default: break; } } }