搜索
您的当前位置:首页正文

C#图像处理

来源:爱够旅游网
C#图像处理

C#图像处理

(各种旋转、改变⼤⼩、柔化、锐化、雾化、底⽚、浮雕、⿊⽩、滤镜效果)

⼀、各种旋转、改变⼤⼩

注意:先要添加画图相关的using引⽤。//向右旋转图像90°代码如下:

private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e){

Graphics g = e.Graphics;

Bitmap bmp = new Bitmap(\"rama.jpg\");//加载图像

g.FillRectangle(Brushes.White, this.ClientRectangle);//填充窗体背景为⽩⾊Point[] destinationPoints = {

new Point(100, 0), // destination for upper-left point of originalnew Point(100, 100),// destination for upper-right point of originalnew Point(0, 0)}; // destination for lower-left point of originalg.DrawImage(bmp, destinationPoints);}

//旋转图像180°代码如下:

private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e){

Graphics g = e.Graphics;

Bitmap bmp = new Bitmap(\"rama.jpg\");

g.FillRectangle(Brushes.White, this.ClientRectangle);Point[] destinationPoints = {

new Point(0, 100), // destination for upper-left point of originalnew Point(100, 100),// destination for upper-right point of originalnew Point(0, 0)}; // destination for lower-left point of originalg.DrawImage(bmp, destinationPoints);}

//图像切变代码:

private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e){

Graphics g = e.Graphics;

Bitmap bmp = new Bitmap(\"rama.jpg\");

g.FillRectangle(Brushes.White, this.ClientRectangle);Point[] destinationPoints = {

new Point(0, 0), // destination for upper-left point of originalnew Point(100, 0), // destination for upper-right point of originalnew Point(50, 100)};// destination for lower-left point of originalg.DrawImage(bmp, destinationPoints);}

//图像截取:

private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e){

Graphics g = e.Graphics;

Bitmap bmp = new Bitmap(\"rama.jpg\");

g.FillRectangle(Brushes.White, this.ClientRectangle);

Rectangle sr = new Rectangle(80, 60, 400, 400);//要截取的矩形区域

Rectangle dr = new Rectangle(0, 0, 200, 200);//要显⽰到Form的矩形区域g.DrawImage(bmp, dr, sr, GraphicsUnit.Pixel);}

//改变图像⼤⼩:

private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e){

Graphics g = e.Graphics;

Bitmap bmp = new Bitmap(\"rama.jpg\");

g.FillRectangle(Brushes.White, this.ClientRectangle);int width = bmp.Width;int height = bmp.Height;

// 改变图像⼤⼩使⽤低质量的模式

g.InterpolationMode = InterpolationMode.NearestNeighbor;

g.DrawImage(bmp, new Rectangle(10, 10, 120, 120), // source rectanglenew Rectangle(0, 0, width, height), // destination rectangleGraphicsUnit.Pixel);// 使⽤⾼质量模式

//g.CompositingQuality = CompositingQuality.HighSpeed;g.InterpolationMode = InterpolationMode.HighQualityBicubic;g.DrawImage(bmp,

new Rectangle(130, 10, 120, 120), new Rectangle(0, 0, width, height),GraphicsUnit.Pixel);}

//设置图像的分辩率:

private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e){

Graphics g = e.Graphics;

Bitmap bmp = new Bitmap(\"rama.jpg\");

g.FillRectangle(Brushes.White, this.ClientRectangle);bmp.SetResolution(300f, 300f);g.DrawImage(bmp, 0, 0);

bmp.SetResolution(1200f, 1200f);g.DrawImage(bmp, 180, 0);}

//⽤GDI+画图

private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e){

Graphics gForm = e.Graphics;

gForm.FillRectangle(Brushes.White, this.ClientRectangle);for (int i = 1; i <= 7; ++i){

//在窗体上⾯画出橙⾊的矩形

Rectangle r = new Rectangle(i*40-15, 0, 15,this.ClientRectangle.Height);

gForm.FillRectangle(Brushes.Orange, r);}

//在内存中创建⼀个Bitmap并设置CompositingModeBitmap bmp = new Bitmap(260, 260,

System.Drawing.Imaging.PixelFormat.Format32bppArgb);Graphics gBmp = Graphics.FromImage(bmp);

gBmp.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;// 创建⼀个带有Alpha的红⾊区域// 并将其画在内存的位图⾥⾯

Color red = Color.FromArgb(0x60, 0xff, 0, 0);Brush redBrush = new SolidBrush(red);

gBmp.FillEllipse(redBrush, 70, 70, 160, 160);// 创建⼀个带有Alpha的绿⾊区域

Color green = Color.FromArgb(0x40, 0, 0xff, 0);Brush greenBrush = new SolidBrush(green);

gBmp.FillRectangle(greenBrush, 10, 10, 140, 140);

//在窗体上⾯画出位图 now draw the bitmap on our windowgForm.DrawImage(bmp, 20, 20, bmp.Width, bmp.Height);// 清理资源

bmp.Dispose();gBmp.Dispose();redBrush.Dispose();greenBrush.Dispose();}

//在窗体上⾯绘图并显⽰图像

private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e){

Graphics g = e.Graphics;

Pen blackPen = new Pen(Color.Black, 1);if (ClientRectangle.Height / 10 > 0){

for (int y = 0; y < ClientRectangle.Height; y += ClientRectangle.Height / 10){

g.DrawLine(blackPen, new Point(0, 0), new Point(ClientRectangle.Width, y));}}

blackPen.Dispose();}

C# 使⽤Bitmap类进⾏图⽚裁剪

在Mapwin(⼿机游戏地图编辑器)⽣成的地图txt⽂件中添加⾃⼰需要处理的数据后转换成可在⼿机(Ophone)开发环境中使⽤的字节流地图⽂件的⼩⼯具,其中就涉及到图⽚的裁剪和⽣成了。有以下⼏种⽅式。

⽅法⼀:拷贝像素。

当然这种⽅法是最笨的,效率也就低了些。

在Bitmap类中我们可以看到这样两个⽅法:GetPixel(int x, int y)和SetPixel(int x, int y, Color color)⽅法。从字⾯的含以上就知道前者是获取图像某点像素值,是⽤Color对象返回的;后者是将已知像素描画到制定的位置。下⾯就来做个实例检验下:

1.⾸先创建⼀个Windows Form窗体程序,往该窗体上拖放7个PictureBox控件,第⼀个⽤于放置并显⽰原始的⼤图⽚,其后6个⽤于放置并显⽰裁剪后新⽣成的6个⼩图;2.放置原始⼤图的PictureBox控件name属性命名为pictureBoxBmpRes,其后pictureBox1到pictureBox6依次命名,并放置在合适的位置;3.双击Form窗体,然后在Form1_Load事件中加⼊下⾯的代码即可。//导⼊图像资源

Bitmap bmpRes = null;

String strPath = Application.ExecutablePath; try{

int nEndIndex = strPath.LastIndexOf('//');

strPath = strPath.Substring(0,nEndIndex) + \"//Bmp//BmpResMM.bmp\"; bmpRes = new Bitmap(strPath);

//窗体上显⽰加载图⽚

pictureBoxBmpRes.Width = bmpRes.Width; pictureBoxBmpRes.Height = bmpRes.Height; pictureBoxBmpRes.Image = bmpRes; }

catch(Exception ex) {

System.Windows.Forms.MessageBox.Show(\"图⽚资源加载失败!/r/n\" + ex.ToString()); }

//裁剪图⽚(裁成2⾏3列的6张图⽚) int nYClipNum = 2, nXClipNum = 3;

Bitmap[] bmpaClipBmpArr = new Bitmap[nYClipNum * nXClipNum];

for (int nYClipNumIndex = 0; nYClipNumIndex < nYClipNum; nYClipNumIndex++) {

for (int nXClipNumIndex = 0; nXClipNumIndex < nXClipNum; nXClipNumIndex++) {

int nClipWidth = bmpRes.Width / nXClipNum; int nClipHight = bmpRes.Height / nYClipNum;

int nBmpIndex = nXClipNumIndex + nYClipNumIndex * nYClipNum + (nYClipNumIndex > 0?1:0); bmpaClipBmpArr[nBmpIndex] = new Bitmap(nClipWidth, nClipHight);

for(int nY = 0; nY < nClipHight; nY++) {

for(int nX = 0; nX < nClipWidth; nX++) {

int nClipX = nX + nClipWidth * nXClipNumIndex; int nClipY = nY + nClipHight * nYClipNumIndex;

Color cClipPixel = bmpRes.GetPixel(nClipX, nClipY);

bmpaClipBmpArr[nBmpIndex].SetPixel(nX, nY, cClipPixel); }

} } }

PictureBox[] picbShow = new PictureBox[nYClipNum * nXClipNum]; picbShow[0] = pictureBox1; picbShow[1] = pictureBox2; picbShow[2] = pictureBox3; picbShow[3] = pictureBox4; picbShow[4] = pictureBox5; picbShow[5] = pictureBox6;

for (int nLoop = 0; nLoop < nYClipNum * nXClipNum; nLoop++) {

picbShow[nLoop].Width = bmpRes.Width / nXClipNum; picbShow[nLoop].Height = bmpRes.Height / nYClipNum;

picbShow[nLoop].Image = bmpaClipBmpArr[nLoop]; }

现在看看那些地⽅需要注意的了。其中int nBmpIndex =

nXClipNumIndex + nYClipNumIndex * nYClipNum + (nYClipNumIndex > 0?1:0);

这句定义了存储裁剪图⽚对象在数组中的索引,需要注意的就是后⾯的(nYClipNumIndex > 0?1:0)——因为只有当裁剪的对象处于第⼀⾏以外的⾏时需要将索引加1;另外,因为这种⽅法的效率不⾼,程序运⾏起来还是顿了下。如果有兴趣的话,可以将以上的代码放到⼀个按钮Click事件函数中,当单击该按钮时就可以感觉到了。

⽅法⼆:运⽤Clone函数局部复制。

同样在Bitmap中可以找到Clone()⽅法,该⽅法有三个重载⽅法。Clone(),Clone(Rectangle, PixelFormat)和Clone(RectangleF, PixelFormat)。第⼀个⽅法将创建并返回⼀个精确的实例对象,后两个就是我们这⾥需要⽤的局部裁剪了(将上⾯的程序稍稍改进下——将裁剪的处理放到⼀个按钮事件函数中,然后再托⼀个按钮好窗体上,最后将下⾯的代码复制到该按钮的事件函数中。for (int nYClipNumIndex = 0; nYClipNumIndex < nYClipNum; nYClipNumIndex++){

for (int nXClipNumIndex = 0; nXClipNumIndex < nXClipNum; nXClipNumIndex++) {

int nClipWidth = bmpRes.Width / nXClipNum;

int nClipHight = bmpRes.Height / nYClipNum; int nBmpIndex =

nXClipNumIndex + nYClipNumIndex * nYClipNum + (nYClipNumIndex > 0 ? 1 : 0);

Rectangle rClipRect = new Rectangle(nClipWidth * nXClipNumIndex, nClipHight * nYClipNumIndex, nClipWidth, nClipHight);

bmpaClipBmpArr[nBmpIndex] = bmpRes.Clone(rClipRect, bmpRes.PixelFormat); }}

运⾏程序,单击按钮检验下,发现速度明显快可很多。

其实这种⽅法较第⼀中⽅法不同的地⽅仅只是变换了for循环中的拷贝部分的处理,Rectangle rClipRect = new Rectangle(nClipWidth * nXClipNumIndex, nClipHight * nYClipNumIndex, nClipWidth, nClipHight);

bmpaClipBmpArr[nBmpIndex] = bmpRes.Clone(rClipRect, bmpRes.PixelFormat);

⼀. 底⽚效果

原理: GetPixel⽅法获得每⼀点像素的值, 然后再使⽤SetPixel⽅法将取反后的颜⾊值设置到对应的点.效果图:

代码实现:

private void button1_Click(object sender, EventArgs e) {

//以底⽚效果显⽰图像 try {

int Height = this.pictureBox1.Image.Height; int Width = this.pictureBox1.Image.Width;

Bitmap newbitmap = new Bitmap(Width, Height); Bitmap oldbitmap = (Bitmap)this.pictureBox1.Image; Color pixel;

for (int x = 1; x < Width; x++) {

for (int y = 1; y < Height; y++) {

int r, g, b;

pixel = oldbitmap.GetPixel(x, y); r = 255 - pixel.R; g = 255 - pixel.G; b = 255 - pixel.B;

newbitmap.SetPixel(x, y, Color.FromArgb(r, g, b)); } }

this.pictureBox1.Image = newbitmap; }

catch (Exception ex) {

MessageBox.Show(ex.Message, \"信息提⽰\", MessageBoxButtons.OK, MessageBoxIcon.Information); } }

⼆. 浮雕效果

原理: 对图像像素点的像素值分别与相邻像素点的像素值相减后加上128, 然后将其作为新的像素点的值.效果图:

代码实现:

private void button1_Click(object sender, EventArgs e) {

//以浮雕效果显⽰图像 try {

int Height = this.pictureBox1.Image.Height; int Width = this.pictureBox1.Image.Width;

Bitmap newBitmap = new Bitmap(Width, Height); Bitmap oldBitmap = (Bitmap)this.pictureBox1.Image; Color pixel1, pixel2;

for (int x = 0; x < Width - 1; x++) {

for (int y = 0; y < Height - 1; y++) {

int r = 0, g = 0, b = 0;

pixel1 = oldBitmap.GetPixel(x, y);

pixel2 = oldBitmap.GetPixel(x + 1, y + 1); r = Math.Abs(pixel1.R - pixel2.R + 128); g = Math.Abs(pixel1.G - pixel2.G + 128); b = Math.Abs(pixel1.B - pixel2.B + 128); if (r > 255) r = 255; if (r < 0) r = 0; if (g > 255) g = 255; if (g < 0) g = 0; if (b > 255) b = 255; if (b < 0) b = 0;

newBitmap.SetPixel(x, y, Color.FromArgb(r, g, b)); } }

this.pictureBox1.Image = newBitmap; }

catch (Exception ex) {

MessageBox.Show(ex.Message, \"信息提⽰\", MessageBoxButtons.OK, MessageBoxIcon.Information); } }

三. ⿊⽩效果

原理: 彩⾊图像处理成⿊⽩效果通常有3种算法;

(1).最⼤值法: 使每个像素点的 R, G, B 值等于原像素点的 RGB (颜⾊值) 中最⼤的⼀个;(2).平均值法: 使⽤每个像素点的 R,G,B值等于原像素点的RGB值的平均值;(3).加权平均值法: 对每个像素点的 R, G, B值进⾏加权 ---⾃认为第三种⽅法做出来的⿊⽩效果图像最 \"真实\".效果图:

代码实现:

private void button1_Click(object sender, EventArgs e) {

//以⿊⽩效果显⽰图像 try {

int Height = this.pictureBox1.Image.Height; int Width = this.pictureBox1.Image.Width;

Bitmap newBitmap = new Bitmap(Width, Height); Bitmap oldBitmap = (Bitmap)this.pictureBox1.Image; Color pixel;

for (int x = 0; x < Width; x++) for (int y = 0; y < Height; y++) {

pixel = oldBitmap.GetPixel(x, y); int r, g, b, Result = 0;

r = pixel.R; g = pixel.G; b = pixel.B;

//实例程序以加权平均值法产⽣⿊⽩图像 int iType =2; switch (iType) {

case 0://平均值法

Result = ((r + g + b) / 3); break;

case 1://最⼤值法

Result = r > g ? r : g;

Result = Result > b ? Result : b; break;

case 2://加权平均值法

Result = ((int)(0.7 * r) + (int)(0.2 * g) + (int)(0.1 * b)); break; }

newBitmap.SetPixel(x, y, Color.FromArgb(Result, Result, Result)); }

this.pictureBox1.Image = newBitmap; }

catch (Exception ex) {

MessageBox.Show(ex.Message, \"信息提⽰\"); } }

四. 柔化效果

原理: 当前像素点与周围像素点的颜⾊差距较⼤时取其平均值.效果图:

代码实现:

private void button1_Click(object sender, EventArgs e) {

//以柔化效果显⽰图像 try {

int Height = this.pictureBox1.Image.Height; int Width = this.pictureBox1.Image.Width; Bitmap bitmap = new Bitmap(Width, Height);

Bitmap MyBitmap = (Bitmap)this.pictureBox1.Image; Color pixel; //⾼斯模板

int[] Gauss ={ 1, 2, 1, 2, 4, 2, 1, 2, 1 }; for (int x = 1; x < Width - 1; x++) for (int y = 1; y < Height - 1; y++) {

int r = 0, g = 0, b = 0; int Index = 0;

for (int col = -1; col <= 1; col++) for (int row = -1; row <= 1; row++) {

pixel = MyBitmap.GetPixel(x + row, y + col); r += pixel.R * Gauss[Index]; g += pixel.G * Gauss[Index]; b += pixel.B * Gauss[Index]; Index++; } r /= 16; g /= 16; b /= 16;

//处理颜⾊值溢出 r = r > 255 ? 255 : r; r = r < 0 ? 0 : r;

g = g > 255 ? 255 : g; g = g < 0 ? 0 : g;

b = b > 255 ? 255 : b; b = b < 0 ? 0 : b;

bitmap.SetPixel(x - 1, y - 1, Color.FromArgb(r, g, b)); }

this.pictureBox1.Image = bitmap; }

catch (Exception ex) {

MessageBox.Show(ex.Message, \"信息提⽰\"); } }

五.锐化效果

原理:突出显⽰颜⾊值⼤(即形成形体边缘)的像素点.效果图:

实现代码:

private void button1_Click(object sender, EventArgs e) {

//以锐化效果显⽰图像 try {

int Height = this.pictureBox1.Image.Height; int Width = this.pictureBox1.Image.Width;

Bitmap newBitmap = new Bitmap(Width, Height); Bitmap oldBitmap = (Bitmap)this.pictureBox1.Image; Color pixel; //拉普拉斯模板

int[] Laplacian ={ -1, -1, -1, -1, 9, -1, -1, -1, -1 }; for (int x = 1; x < Width - 1; x++) for (int y = 1; y < Height - 1; y++) {

int r = 0, g = 0, b = 0; int Index = 0;

for (int col = -1; col <= 1; col++) for (int row = -1; row <= 1; row++) {

pixel = oldBitmap.GetPixel(x + row, y + col); r += pixel.R * Laplacian[Index]; g += pixel.G * Laplacian[Index]; b += pixel.B * Laplacian[Index]; Index++; }

//处理颜⾊值溢出 r = r > 255 ? 255 : r; r = r < 0 ? 0 : r;

g = g > 255 ? 255 : g; g = g < 0 ? 0 : g;

b = b > 255 ? 255 : b; b = b < 0 ? 0 : b;

newBitmap.SetPixel(x - 1, y - 1, Color.FromArgb(r, g, b)); }

this.pictureBox1.Image = newBitmap; }

catch (Exception ex) {

MessageBox.Show(ex.Message, \"信息提⽰\"); } }

六. 雾化效果

原理: 在图像中引⼊⼀定的随机值, 打乱图像中的像素值效果图:

实现代码:

private void button1_Click(object sender, EventArgs e) {

//以雾化效果显⽰图像 try {

int Height = this.pictureBox1.Image.Height; int Width = this.pictureBox1.Image.Width;

Bitmap newBitmap = new Bitmap(Width, Height); Bitmap oldBitmap = (Bitmap)this.pictureBox1.Image; Color pixel;

for (int x = 1; x < Width - 1; x++) for (int y = 1; y < Height - 1; y++) {

System.Random MyRandom = new Random(); int k = MyRandom.Next(123456); //像素块⼤⼩

int dx = x + k % 19; int dy = y + k % 19; if (dx >= Width) dx = Width - 1; if (dy >= Height) dy = Height - 1;

pixel = oldBitmap.GetPixel(dx, dy); newBitmap.SetPixel(x, y, pixel); }

this.pictureBox1.Image = newBitmap; }

catch (Exception ex) {

MessageBox.Show(ex.Message, \"信息提⽰\"); } }

浅谈Visual C#进⾏图像处理

作者:彭军 http://pengjun.org.cn

这⾥之所以说“浅谈”是因为我这⾥只是简单的介绍如何使⽤Visual C#进⾏图像的读⼊、保存以及对像素的访问。⽽不涉及太多的算法。⼀、读⼊图像

在Visual C#中我们可以使⽤⼀个Picture Box控件来显⽰图⽚,如下: private void btnOpenImage_Click(object sender, EventArgs e) {

OpenFileDialog ofd = new OpenFileDialog();

ofd.Filter = \"BMP Files(*.bmp)|*.bmp|JPG Files(*.jpg;*.jpeg)|*.jpg;*.jpeg|All Files(*.*)|*.*\"; ofd.CheckFileExists = true; ofd.CheckPathExists = true;

if (ofd.ShowDialog() == DialogResult.OK) {

//pbxShowImage.ImageLocation = ofd.FileName; bmp = new Bitmap(ofd.FileName); if (bmp==null) {

MessageBox.Show(\"加载图⽚失败!\", \"错误\"); return; }

pbxShowImage.Image = bmp; ofd.Dispose(); } }

其中bmp为类的⼀个对象:private Bitmap bmp=null;

在使⽤Bitmap类和BitmapData类之前,需要使⽤using System.Drawing.Imaging;⼆、保存图像

private void btnSaveImage_Click(object sender, EventArgs e) {

if (bmp == null) return;

SaveFileDialog sfd = new SaveFileDialog();

sfd.Filter = \"BMP Files(*.bmp)|*.bmp|JPG Files(*.jpg;*.jpeg)|*.jpg;*.jpeg|All Files(*.*)|*.*\"; if (sfd.ShowDialog() == DialogResult.OK) {

pbxShowImage.Image.Save(sfd.FileName); MessageBox.Show(\"保存成功!\",\"提⽰\"); sfd.Dispose(); } }

三、对像素的访问

我们可以来建⽴⼀个GrayBitmapData类来做相关的处理。整个类的程序如下:using System;

using System.Collections.Generic;using System.Linq;using System.Text;using System.Drawing;

using System.Drawing.Imaging;using System.Windows.Forms;namespace ImageElf{

class GrayBitmapData {

public byte[,] Data;//保存像素矩阵 public int Width;//图像的宽度 public int Height;//图像的⾼度

public GrayBitmapData() {

this.Width = 0; this.Height = 0; this.Data = null; }

public GrayBitmapData(Bitmap bmp) {

BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); this.Width = bmpData.Width; this.Height = bmpData.Height; Data = new byte[Height, Width]; unsafe {

byte* ptr = (byte*)bmpData.Scan0.ToPointer(); for (int i = 0; i < Height; i++) {

for (int j = 0; j < Width; j++) {

//将24位的RGB彩⾊图转换为灰度图

int temp = (int)(0.114 * (*ptr++)) + (int)(0.587 * (*ptr++))+(int)(0.299 * (*ptr++)); Data[i, j] = (byte)temp; }

ptr += bmpData.Stride - Width * 3;//指针加上填充的空⽩空间 } }

bmp.UnlockBits(bmpData); }

public GrayBitmapData(string path) : this(new Bitmap(path)) { }

public Bitmap ToBitmap() {

Bitmap bmp=new Bitmap(Width,Height,PixelFormat.Format24bppRgb);

BitmapData bmpData=bmp.LockBits(new Rectangle(0,0,Width,Height),ImageLockMode.WriteOnly,PixelFormat.Format24bppRgb); unsafe {

byte* ptr=(byte*)bmpData.Scan0.ToPointer(); for(int i=0;ifor(int j=0;j*(ptr++)=Data[i,j]; *(ptr++)=Data[i,j]; *(ptr++)=Data[i,j]; }

ptr+=bmpData.Stride-Width*3; } }

bmp.UnlockBits(bmpData); return bmp; }

public void ShowImage(PictureBox pbx) {

Bitmap b = this.ToBitmap(); pbx.Image = b; //b.Dispose(); }

public void SaveImage(string path) {

Bitmap b=ToBitmap(); b.Save(path); //b.Dispose(); }//均值滤波

public void AverageFilter(int windowSize) {

if (windowSize % 2 == 0) {

return; }

for (int i = 0; i < Height; i++) {

for (int j = 0; j < Width; j++) {

int sum = 0;

for (int g = -(windowSize - 1) / 2; g <= (windowSize - 1) / 2; g++) {

for (int k = -(windowSize - 1) / 2; k <= (windowSize - 1) / 2; k++) {

int a = i + g, b = j + k; if (a < 0) a = 0;

if (a > Height - 1) a = Height - 1; if (b < 0) b = 0;

if (b > Width - 1) b = Width - 1; sum += Data[a, b]; } }

Data[i,j]=(byte)(sum/(windowSize*windowSize)); } } }//中值滤波

public void MidFilter(int windowSize) {

if (windowSize % 2 == 0) {

return; }

int[] temp = new int[windowSize * windowSize]; byte[,] newdata = new byte[Height, Width]; for (int i = 0; i < Height; i++) {

for (int j = 0; j < Width; j++) {

int n = 0;

for (int g = -(windowSize - 1) / 2; g <= (windowSize - 1) / 2; g++) {

for (int k = -(windowSize - 1) / 2; k <= (windowSize - 1) / 2; k++) {

int a = i + g, b = j + k; if (a < 0) a = 0;

if (a > Height - 1) a = Height - 1; if (b < 0) b = 0;

if (b > Width - 1) b = Width - 1; temp[n++]= Data[a, b]; } }

newdata[i, j] = GetMidValue(temp,windowSize*windowSize); } }

for (int i = 0; i < Height; i++)

{

for (int j = 0; j < Width; j++) {

Data[i, j] = newdata[i, j]; } } }

//获得⼀个向量的中值

private byte GetMidValue(int[] t, int length) {

int temp = 0;

for (int i = 0; i < length - 2; i++) {

for (int j = i + 1; j < length - 1; j++) {

if (t[i] > t[j]) {

temp = t[i]; t[i] = t[j]; t[j] = temp; } } }

return (byte)t[(length - 1) / 2]; }

//⼀种新的滤波⽅法,是亮的更亮、暗的更暗 public void NewFilter(int windowSize) {

if (windowSize % 2 == 0) {

return; }

for (int i = 0; i < Height; i++) {

for (int j = 0; j < Width; j++) {

int sum = 0;

for (int g = -(windowSize - 1) / 2; g <= (windowSize - 1) / 2; g++) {

for (int k = -(windowSize - 1) / 2; k <= (windowSize - 1) / 2; k++) {

int a = i + g, b = j + k; if (a < 0) a = 0;

if (a > Height - 1) a = Height - 1; if (b < 0) b = 0;

if (b > Width - 1) b = Width - 1; sum += Data[a, b]; } }

double avg = (sum+0.0) / (windowSize * windowSize); if (avg / 255 < 0.5) {

Data[i, j] = (byte)(2 * avg / 255 * Data[i, j]); } else {

Data[i,j]=(byte)((1-2*(1-avg/255.0)*(1-Data[i,j]/255.0))*255); } } } }

//直⽅图均衡

public void HistEqual() {

double[] num = new double[256] ; for(int i=0;i<256;i++) num[i]=0; for (int i = 0; i < Height; i++) {

for (int j = 0; j < Width; j++) {

num[Data[i, j]]++; } }

double[] newGray = new double[256]; double n = 0;

for (int i = 0; i < 256; i++) {

n += num[i];

newGray[i] = n * 255 / (Height * Width); }

for (int i = 0; i < Height; i++) {

for (int j = 0; j < Width; j++) {

Data[i,j]=(byte)newGray[Data[i,j]]; } } }}}

在GrayBitmapData类中,只要我们对⼀个⼆维数组Data进⾏⼀系列的操作就是对图⽚的操作处理。在窗⼝上,我们可以使⽤⼀个按钮来做各种调⽤://均值滤波

private void btnAvgFilter_Click(object sender, EventArgs e) {

if (bmp == null) return;

GrayBitmapData gbmp = new GrayBitmapData(bmp); gbmp.AverageFilter(3);

gbmp.ShowImage(pbxShowImage); }

//转换为灰度图

private void btnToGray_Click(object sender, EventArgs e) {

if (bmp == null) return;

GrayBitmapData gbmp = new GrayBitmapData(bmp); gbmp.ShowImage(pbxShowImage); }

四、总结

在Visual c#中对图像进⾏处理或访问,需要先建⽴⼀个Bitmap对象,然后通过其LockBits⽅法来获得⼀个BitmapData类的对象,然后通过获得其像素数据的⾸地址来对Bitmap对象的像素数据进⾏操作。当然,⼀种简单但是速度慢的⽅法是⽤Bitmap

C# colorMatrix 对图⽚的处理 : 亮度调整 抓屏 翻转 随⿏标画矩形

1.图⽚亮度处理

private void btn_Grap_Click(object sender, EventArgs e) {

//亮度百分⽐ int percent = 50;

Single v = 0.006F * percent; Single[][] matrix = {

new Single[] { 1, 0, 0, 0, 0 }, new Single[] { 0, 1, 0, 0, 0 }, new Single[] { 0, 0, 1, 0, 0 }, new Single[] { 0, 0, 0, 1, 0 }, new Single[] { v, v, v, 0, 1 } };

System.Drawing.Imaging.ColorMatrix cm = new System.Drawing.Imaging.ColorMatrix(matrix);

System.Drawing.Imaging.ImageAttributes attr = new System.Drawing.Imaging.ImageAttributes(); attr.SetColorMatrix(cm); //Image tmp

Image tmp = Image.FromFile(\"1.png\");

this.pictureBox_Src.Image = Image.FromFile(\"1.png\");

Graphics g = Graphics.FromImage(tmp); try {

Rectangle destRect = new Rectangle(0, 0, tmp.Width, tmp.Height);

g.DrawImage(tmp, destRect, 0, 0, tmp.Width, tmp.Height, GraphicsUnit.Pixel, attr); }

finally {

g.Dispose(); }

this.pictureBox_Dest.Image = (Image)tmp.Clone(); }

2.抓屏将⽣成的图⽚显⽰在pictureBox

private void btn_Screen_Click(object sender, EventArgs e) {

Image myImage = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); Graphics g = Graphics.FromImage(myImage);

g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)); //IntPtr dc1 = g.GetHdc(); //此处这两句多余,具体看最后GetHdc()定义 //g.ReleaseHdc(dc1); g.Dispose();

this.pictureBox_Src.SizeMode = PictureBoxSizeMode.StretchImage; this.pictureBox_Src.Image = myImage;

myImage.Save(\"Screen\", ImageFormat.Png); }

3.翻转

private void btn_RotateFlip_Click(object sender, EventArgs e) {

this.pictureBox_Src.Image = Image.FromFile(\"1.png\");

Image tmp = Image.FromFile(\"1.png\");

tmp.RotateFlip(RotateFlipType.Rotate90FlipNone); this.pictureBox_Dest.Image = tmp; }

4.跟随⿏标在 pictureBox的图⽚上画矩形 private int intStartX = 0; private int intStartY = 0;

private bool isMouseDraw = false;

private void pictureBox_Src_MouseDown(object sender, MouseEventArgs e) {

isMouseDraw = true;

intStartX = e.X; intStartY = e.Y; }

private void pictureBox_Src_MouseMove(object sender, MouseEventArgs e) {

if (isMouseDraw) {

try {

//Image tmp = Image.FromFile(\"1.png\");

Graphics g = this.pictureBox_Src.CreateGraphics(); //清空上次画下的痕迹

g.Clear(this.pictureBox_Src.BackColor); Brush brush = new SolidBrush(Color.Red); Pen pen = new Pen(brush, 1); pen.DashStyle = DashStyle.Solid;

g.DrawRectangle(pen, new Rectangle(intStartX > e.X ? e.X : intStartX, intStartY > e.Y ? e.Y : intStartY, Math.Abs(e.X - intStartX), Math.Abs(e.Y - intStartY))); g.Dispose();

//this.pictureBox_Src.Image = tmp; }

catch (Exception ex) {

ex.ToString(); } } }

private void pictureBox_Src_MouseUp(object sender, MouseEventArgs e) {

isMouseDraw = false;

intStartX = 0; intStartY = 0; }5.取灰度

private void btn_GetGray_Click(object sender, EventArgs e) {

this.pictureBox_Src.Image = Image.FromFile(\"1.png\");

Bitmap currentBitmap = new Bitmap(this.pictureBox_Src.Image); Graphics g = Graphics.FromImage(currentBitmap); ImageAttributes ia = new ImageAttributes(); float[][] colorMatrix = {

new float[] {0.299f, 0.299f, 0.299f, 0, 0}, new float[] {0.587f, 0.587f, 0.587f, 0, 0}, new float[] {0.114f, 0.114f, 0.114f, 0, 0}, new float[] {0, 0, 0, 1, 0}, new float[] {0, 0, 0, 0, 1}

};

ColorMatrix cm = new ColorMatrix(colorMatrix);

ia.SetColorMatrix(cm, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

g.DrawImage(currentBitmap, new Rectangle(0, 0, currentBitmap.Width, currentBitmap.Height), 0, 0, currentBitmap.Width, currentBitmap.Height, GraphicsUnit.Pixel, ia); this.pictureBox_Dest.Image = (Image)(currentBitmap.Clone()); g.Dispose(); }

Graphics.GetHdc ⽅法.NET Framework 4

获取与此 Graphics 关联的设备上下⽂的句柄。命名空间: System.Drawing

程序集: System.Drawing(在 System.Drawing.dll 中)语法

[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags =SecurityPermissionFlag.UnmanagedCode)]public IntPtr GetHdc()返回值

类型:System.IntPtr

与此 Graphics 关联的设备上下⽂的句柄。实现

IDeviceContext.GetHdc()备注

设备上下⽂是⼀个基于 GDI 的 Windows 结构,它定义⼀组图形对象及其关联的特性,以及影响输出的图形模式。 此⽅法返回该设备上下⽂(字体除外)。由于未选择字体,使⽤ GetHdc ⽅法返回的句柄对 FromHdc ⽅法进⾏调⽤将会失败。GetHdc ⽅法调⽤和 ReleaseHdc ⽅法调⽤必须成对出现。 在 GetHdc 和 ReleaseHdc ⽅法对的范围内,通常仅调⽤ GDI 函数。 在该范围内对 Graphics(它产⽣ hdc 参数)的 GDI+ ⽅法的调⽤因 ObjectBusy 错误⽽失败。 此外,GDI+⽰例

下⾯的代码⽰例设计为与 Windows 窗体⼀起使⽤,它需要 PaintEventArgse,即 Paint 事件处理程序的⼀个参数。 该⽰例演⽰如何调⽤ Windows GDI 函数以执⾏与 GDI+ Graphics ⽅法相同的任务。 代码执⾏下列操作:为 Windows DLL ⽂件 gdi32.dll 定义互操作性 DllImportAttribute 特性。 此 DLL 包含所需的 GDI 函数。将该 DLL 中的 Rectangle 函数定义为外部函数。创建⼀⽀红⾊钢笔。

利⽤该钢笔,使⽤ GDI+ DrawRectangle ⽅法将矩形绘制到屏幕。

定义内部指针类型变量 hdc 并将它的值设置为窗体的设备上下⽂句柄。使⽤ GDI Rectangle 函数将矩形绘制到屏幕。释放由 hdc 参数表⽰的设备上下⽂。

public class GDI{

[System.Runtime.InteropServices.DllImport(\"gdi32.dll\")] internal static extern bool Rectangle( IntPtr hdc,

int ulCornerX, int ulCornerY, int lrCornerX, int lrCornerY);}

[System.Security.Permissions.SecurityPermission(

System.Security.Permissions.SecurityAction.LinkDemand, Flags =

System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)] private void GetHdcForGDI1(PaintEventArgs e){

// Create pen.

Pen redPen = new Pen(Color.Red, 1);

// Draw rectangle with GDI+.

e.Graphics.DrawRectangle(redPen, 10, 10, 100, 50);

// Get handle to device context. IntPtr hdc = e.Graphics.GetHdc();

// Draw rectangle with GDI using default pen. GDI.Rectangle(hdc, 10, 70, 110, 120);

// Release handle to device context. e.Graphics.ReleaseHdc(hdc);}

因篇幅问题不能全部显示,请点此查看更多更全内容

Top