正文

C#图像处理――前奏(一)2009-06-02 21:31:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/emath/44107.html

分享到:

一.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;           }//#

阅读(3602) | 评论(1)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册