//Form.cs
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;
/*
彩色图像灰度化的转换公式有三种
1、Gray(i,j)=[R(i,j)+G(i,j)+B(i,j)]/3
2、Gray(i,j)=0.299*R(i,j)+0.587*G(i,j)+0.114*B(i,j)
3、Gray(i,j)=G(i,j)由2知G占的比重最大,所以可以这样
*/
namespace
colorToGray
{
public partial class Form1 : Form
{
private string curFileName;
private System.Drawing.Bitmap
curBitmap;
private HiPerfTimer myTimer;
public
Form1()
{
myTimer = new HiPerfTimer();
InitializeComponent();
}
private void btnOpen_Click(object sender, EventArgs e)
{
OpenFileDialog opnDlg = new OpenFileDialog();
//创建openFileDialog
//为图像选择一个筛选器
opnDlg.Filter =
"所有图像文件 | *.bmp; *.pcx; *.png; *.jpg; *.gif;" +
"*.tif;
*.ico; *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf|" +
"位图(*.bmp; *.jpg; *.png; ...) | *.bmp; *.pcx; *.png; *.jpg; *.gif; *.tif;
*.ico|" +
"矢量图( *.wmf; *.eps; *.emf;...) | *.dxf; *.cgm;
*.cdr; *.wmf; *.eps; *.emf";
opnDlg.Title = "打开图像文件";
//设置对话框标题
opnDlg.ShowHelp = true;
if
(opnDlg.ShowDialog() == DialogResult.OK) //如果结果为"打开",选定文件
{
curFileName = opnDlg.FileName;
//读取当前选中的文件名
//使用Image.FormFile创建对像
try
{
curBitmap =
(Bitmap)Image.FromFile(curFileName);
}
catch (Exception exp)
{
MessageBox.Show(exp.Message); //抛出异常
}
}
Invalidate(); //对窗体进行重新绘制,这钭强制执行paint事件处理程序
}
private void btnSave_Click(object sender, EventArgs e)
{
//如果没有创建图像,则退出
if (curBitmap ==
null)
{
return;
}
//调用SaveFileDialog
SaveFileDialog saveDlg = new
SaveFileDialog();
saveDlg.Title = "保存为";
saveDlg.OverwritePrompt = true;//改写已经存在文件时提示用户
saveDlg.Filter =
"BMP 文件 (*.bmp) | *.bmp|" + "Gif 文件 (*.gif) |*.gif|" +
"JPEG文件(*.jpg)|*.jpg|" + "PNG文件 (&.png)| *.png";
saveDlg.ShowHelp = true; //启用"帮助"按键
if (saveDlg.ShowDialog() ==
DialogResult.OK)
{
string fileName =
saveDlg.FileName;
string strFilExtn = fileName.Remove(0,
fileName.Length - 3); //获取选择文件的的扩展名
//保存文件
switch (strFilExtn)
{
case
"bmp":
curBitmap.Save(fileName,
System.Drawing.Imaging.ImageFormat.Bmp);
break;
case "jpg":
curBitmap.Save(fileName,System.Drawing.Imaging.ImageFormat.Jpeg
);
break;
case
"gif":
curBitmap.Save(fileName,System.Drawing.Imaging.ImageFormat.Gif);
break;
case "tif":
curBitmap.Save(fileName,System.Drawing.Imaging.ImageFormat.Tiff);
break;
case "png":
curBitmap.Save(fileName,System.Drawing.Imaging.ImageFormat.Tiff);
break;
default:
break;
}
}
}
private void btnClose_Click(object sender, EventArgs e)
{
this.Close();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
//获取Graphics对象
Graphics g =
e.Graphics;
if (curBitmap != null)
{
//使用DrawImage方法绘制图像
//160,20:显示主窗体内,图像左上角的坐标
//curBitmap.Width,curBitmap.Height:图像的宽度和高度
g.DrawImage(curBitmap, 160, 20, curBitmap.Width,
curBitmap.Height);
}
}
private void btnPixel_Click(object sender, EventArgs e)
{
myTimer.Start();
if (curBitmap !=
null)
{
Color curColor;
int
ret;
//二维图像数组循环
for
(int i = 0; i < curBitmap.Width; i++)
{
for (int j = 0; j < curBitmap.Height;
j++)
{
curColor =
curBitmap.GetPixel(i, j);
ret = (int)(curColor.R *
0.299 + curColor.G * 0.587 + curColor.B * 0.114);
curBitmap.SetPixel(i, j, Color.FromArgb(ret, ret, ret));
}
}
myTimer.Stop();
txtTimeBox.Text = myTimer.Duration.ToString("####.##") +
"毫秒";
Invalidate();
}
}
private void btnMemory_Click(object sender, EventArgs e)
{
/*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;
//24位Bmp位图字节数
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);
Invalidate();
}*/
//以上程序只适用于512 X 512的24位图像
//以下程序适用任意24位图
myTimer.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 =
bmpData.Stride * bmpData.Height;
//定义位图数组
byte[] rgbValues = new byte[bytes];
//复制被锁定的位图像素值到该数组内
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
//灰度化
double colorTemp =
0;
for (int i = 0; i < bmpData.Height;
i++)
{
//只处理每行中是图像像素的数据,舍弃未用空间
for (int j = 0; j <
bmpData.Width * 3; j += 3)
{
colorTemp = rgbValues[i * bmpData.Stride + j + 2] * 0.299 +
rgbValues[i * bmpData.Stride + j + 1] * 0.587
+
rgbValues[i * bmpData.Stride + j] *
0.114;
rgbValues[i * bmpData.Stride + j] =
rgbValues[i * bmpData.Stride + j + 1] =
rgbValues[i * bmpData.Stride + j + 2] = (byte)colorTemp;
}
}
//把数组复制回位图
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr,
bytes);
//解锁定位图像素
curBitmap.UnlockBits(bmpData);
myTimer.Stop();
txtTimeBox.Text =
myTimer.Duration.ToString("####.##") + "毫秒";
Invalidate();
}
}
private void btnPointer_Click(object sender, EventArgs e)
{
myTimer.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);
myTimer.Stop();
txtTimeBox.Text =
myTimer.Duration.ToString("####.##") + "毫秒";
Invalidate();
}
}
}
}
//HiPerfTimer.cs
using System;
using System.Collections.Generic;
using
System.Linq;
using System.Text;
using
System.Runtime.InteropServices;
using System.ComponentModel;
using
System.Threading;
namespace colorToGray
{
internal class HiPerfTimer
{
//引用Win32 API中的QueryPerformanceCounter()方法
//该方法用来查询任意时刻高精度计数器的实际值
[DllImport("Kernel32.dll")]
private static extern bool QueryPerformanceCounter(out long
lpPerformanceCount);
//引用Win32 API 中的QueryPerformanceFrequency()方法
//该方法返回高精度计数器每秒的计数值
[DllImport("Kernel32.dll")]
private
static extern bool QueryPerformanceFrequency(out long lpFrequency);
private long startTime, stopTime;
private long freq;
public HiPerfTimer()
{
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);
}
//返回计时结果(ms)
public double Duration
{
get
{
return (double)(stopTime - startTime) *
1000 / (double)freq;
}
}
}