您的位置:首页 > 编程语言 > C#

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

2012-06-04 11:14 696 查看
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;}
}
}
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐