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++)

                {

                  //只处理每行中图像像素数据,舍弃未用空间

                  //注意位图结构中RGBBGR的顺序存储

                    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;

 

        }//#

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值