//三种算法的时间比较
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;} } } }
C#实现彩色图像灰度处理
最新推荐文章于 2023-10-12 16:22:25 发布