C#实现彩色图像灰度处理

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ImageGray
{
    public partial class Form1 : Form
    {
        private TimePerform myperform;
        public Form1()
        {
            InitializeComponent();
            myperform = new TimePerform();

        }

       
        private string curFileName;
        private System.Drawing.Bitmap curBitmap;

//打开图像
        private void open_Click(object sender, EventArgs e)
        {
            OpenFileDialog opdlg = new OpenFileDialog();
            opdlg.Filter = "所有图像文件|*.bmp;*.pcx;*.png;*.jpg;*.gif" + "*.tif;*.ico;*.dxf;*.wmf;*.eps;*.emf|" + "位图(*.bmp;*.jpg;*.png;...)|*.bmp;*.pcx;*.jpg;*.png;*.jpg;*.gif;*.tif;*.ico|"
                + "矢量图(*.wmf;*.eps;*.emf...)|*.dxf;*.cgm;*.cgr;*.wmf;*.eps;*.emf";
            opdlg.Title = "打开图像文件";
            opdlg.ShowHelp = true;
            if (opdlg.ShowDialog() == DialogResult.OK)
            {
                curFileName = opdlg.FileName;
                try { curBitmap = (Bitmap)Image.FromFile(curFileName); }
                catch(Exception ee){
                    MessageBox.Show(ee.Message);
                }
            }
           
            Invalidate();
        }
//保存图像
        private void save_Click(object sender, EventArgs e)
        {
            if (curBitmap == null) return;
            SaveFileDialog savedlg = new SaveFileDialog();
            savedlg.Title = "保存为";
            savedlg.ShowHelp = true;
            savedlg.Filter = "bmp文件(*.bmp)|*.bmp|"+"gif文件(*.gif)|*.gif|"+"jpeg文件(*.jpg)|*.jpg|"+"png文件(*.png)|*.png";
            if (savedlg.ShowDialog() ==DialogResult.OK)
            {
                string filename = savedlg.FileName;
                string suffix = filename.Remove(0, filename.Length - 3);
                switch(suffix)
                {
                    case "bmp": curBitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Bmp); break;
                    case "gif": curBitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Gif); break;
                    case "jpg": curBitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Jpeg); break;
                    case "png": curBitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Png); break;
                    default: break;
                }
            
            }
        
        
        }
//关闭窗体
        private void close_Click(object sender, EventArgs e)
        {
            this.Close();
        }
//利用与窗体相关联的Graphics对象绘制图像
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            if (curBitmap != null)
            { g.DrawImage(curBitmap,160,20,curBitmap.Width,curBitmap.Height); }

        }
        /// <summary>
        /// 彩色图像灰度化 在图像处理算法中,要把彩色图像转换成灰度图像
        /// 24位彩色图象用3个字节表示,每个字节对应着R,G,B分量的亮度。当R G B 不同时表现为彩色图像
        /// 当R G B相同时表现为灰度图像
        /// Gray(i,j)=[0.299*R(i,j)+0.587*G(i,j)+0.114*B(i,j)]/3
        /// 变换后的灰度图像仍然用24位图像表示
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
  /// 方法一:提取像素法 使用GDI+中的Bitmap.GetPixel和Bitmap.SetPixel
        private void pixel_Click(object sender, EventArgs e)
        {
            myperform.Start();
            if (curBitmap != null)
            { Color color;
            int ret;
                for(int i=0;i<curBitmap.Width;i++)
                {
                    for (int j = 0; j < curBitmap.Height;j++ )
                    {
                        color = curBitmap.GetPixel(i, j);
                        ret=(int)(color.R*0.299+color.G*0.587+color.B*0.114);
                        curBitmap.SetPixel(i, j, Color.FromArgb(ret, ret, ret));
                    }
                }
                myperform.Stop();
                textBox1.Text = myperform.Duration.ToString("####.##" + "毫秒");
                Invalidate();//对窗体进行重新绘制,这将强制执行Paint事件处理程序
            }


        }
  // 方法二:内存法,把图像数据直接复制到内存中,提高程序的运行速度
        private void memory_Click(object sender, EventArgs e)
        {
            myperform.Start();
            if (curBitmap != null) {
                Rectangle rect = new Rectangle(0,0,curBitmap.Width,curBitmap.Height);
                System.Drawing.Imaging.BitmapData bmpdata = curBitmap.LockBits(rect,System.Drawing.Imaging.ImageLockMode.ReadWrite,curBitmap.PixelFormat);
                IntPtr ptr = bmpdata.Scan0;
                int bytes = curBitmap.Width * curBitmap.Height * 3;
                byte[] rgbValues = new byte[bytes];
                System.Runtime.InteropServices.Marshal.Copy(ptr,rgbValues,0,bytes);
                double colorTemp = 0;
                for (int i = 0; i < rgbValues.Length;i+=3 )
                { colorTemp = rgbValues[i + 2] * 0.299 + rgbValues[i + 1] * 0.587 + rgbValues[i] * 0.114;
                rgbValues[i]=rgbValues[i+1]=rgbValues[i+2]=(byte)colorTemp;
                }
                System.Runtime.InteropServices.Marshal.Copy(rgbValues,0,ptr,bytes);
                curBitmap.UnlockBits(bmpdata);
                myperform.Stop();
                textBox1.Text = myperform.Duration.ToString("####.##" + "毫秒");
                Invalidate();
            }
        }
//方法三:指针法,直接使用指针对位图进行操作,使用unsafe关键字时,需在项目-属性-生成-允许不安全代码进行勾选
        private void pointer_Click(object sender, EventArgs e)
        {
            myperform.Start();
            if (curBitmap != null)
            {
                Rectangle rect = new Rectangle(0,0,curBitmap.Width,curBitmap.Height);
                System.Drawing.Imaging.BitmapData bmpdata = curBitmap.LockBits(rect,System.Drawing.Imaging.ImageLockMode.ReadWrite,curBitmap.PixelFormat);
                byte temp=0;
                unsafe
                {
                    byte* ptr = (byte*)(bmpdata.Scan0);
                    for (int i = 0; i < bmpdata.Height;i++ )
                    {
                        for (int j = 0; j < bmpdata.Width; j++)
                        { temp = (byte)(0.299 * ptr[2] + 0.587 * ptr[1] + 0.114 * ptr[0]);
                        ptr[0]=ptr[1]=ptr[2]=temp;
                        ptr += 3;
                        }
                          ptr += bmpdata.Stride - bmpdata.Width * 3;
                    }
                  
                }
                curBitmap.UnlockBits(bmpdata);
                myperform.Stop();
                textBox1.Text = myperform.Duration.ToString("####.##" + "毫秒");
                Invalidate();
            }
           
        }
    }
}
//三种算法的时间比较
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
using System.ComponentModel;
namespace ImageGray
{
    class TimePerform
    {[DllImport("Kernel32.dll")]
        //这叫引入kernel32.dll这个动态连接库。这个动态连接库里面包含了很多WindowsAPI函数,如果你想使用这面的函数,就需要这么引入。
        //举个例子://[DllImport("kernel32.dll")]
        //private static extern void 函数名(参数,[参数]); 函数名就是一个属于kernel32.dll里的一个函数。完了你就可以用那个函数了
        //extern 修饰符用于声明在外部实现的方法。 extern 修饰符的常见用法是在使用 Interop 服务调入非托管代码时与 DllImport 特性一起使用。 在这种情况下,还必须将方法声明为 static
        private static extern bool QueryPerformanceCounter(out long lpPerformanceCount) ;
        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceFrequency(out long lpFrequency);
        private long startTime, stopTime;
        private long freq;
        public TimePerform()
        {
            startTime = 0;
            stopTime = 0;
            if (QueryPerformanceFrequency(out freq)==false)
            { throw new Win32Exception(); }

        }

        public void Start() 
        {
            Thread.Sleep(0);
            QueryPerformanceCounter(out startTime);
        }

        public void Stop()
        {
            QueryPerformanceCounter(out stopTime);

        }
        public double Duration { 
        get{return (double)(stopTime-startTime)*1000/ (double)freq;}
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值