转 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 original new Point(100, 100),// destination for upper-right point of original new Point(0, 0)}; // destination for lower-left point of original g.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 original new Point(100, 100),// destination for upper-right point of original new Point(0, 0)}; // destination for lower-left point of original g.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 original new Point(100, 0), // destination for upper-right point of original new Point(50, 100)};// destination for lower-left point of original g.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 rectangle

new Rectangle(0, 0, width, height), // destination rectangle GraphicsUnit.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并设置CompositingMode Bitmap 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 window gForm.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;i<Height;i++)                 {                     for(int j=0;j<Width;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类的GetPixel和SetPixel方法。其中BitmapData类的Stride属性为每行像素所占的字节。

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+ 忽略后续操作中对 hdc 参数的 Graphics 所做的所有状态更改。

示例


下面的代码示例设计为与 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);

}

原文链接 http://blog.csdn.net/jiangxinyu/article/details/6222322/

时间: 2024-10-13 08:28:42

转 C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)的相关文章

C# (GDI+相关) 图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)

原文:C# (GDI+相关) 图像处理(各种旋转.改变大小.柔化.锐化.雾化.底片.浮雕.黑白.滤镜效果) C#图像处理   (各种旋转.改变大小.柔化.锐化.雾化.底片.浮雕.黑白.滤镜效果)     一.各种旋转.改变大小   注意:先要添加画图相关的using引用.   //向右旋转图像90°代码如下: private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) {   Graphics g

C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)

C#图像处理(各种旋转.改变大小.柔化.锐化.雾化.底片.浮雕.黑白.滤镜效果) 标签: c#图像处理gdi 2014-08-14 09:09 441人阅读 评论(0) 收藏 举报 本文章已收录于: .NET知识库 分类: C#(78) 作者同类文章X 一.各种旋转.改变大小 注意:先要添加画图相关的using引用. [csharp] view plain copy print? //向右旋转图像90°代码如下: private void Form1_Paint(object sender, S

黄聪: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.ClientRectangl

动画效果-基础动画设置(改变大小,改变透明度,翻转,旋转,复原)

在可视化编程下 #import "BaseViewController.h" @interface BaseViewController () @property (weak, nonatomic) IBOutlet UIImageView *imageView; @end @implementation BaseViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)didReceiveMemoryWar

图片各种旋转、改变大小

1.各种旋转.改变大小 注意:先要添加画图相关的 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.Cli

【转】C# 控件的自定义拖动、改变大小方法

在用VS的窗体设计器时,我们可以发现控件都是可以拖动的,并且还可以调整大小.怎么在自己的程序中可以使用上述功能呢? 下面的方法值得借鉴! using System; using System.Windows.Forms; using System.Drawing; namespace ControlSizeChangeEx { /// <summary> /// This class implements sizing and moving functions for /// runtime

Qt:无标题栏无边框程序的拖动和改变大小

From: http://blog.csdn.net/kfbyj/article/details/9284923 最近做项目遇到的问题,总结下. 有时候我们觉得系统的标题栏和按钮太丑太呆板,想做自己的标题栏以及最大化.最小化.关闭,菜单按钮,我们就需要 [cpp] view plaincopyprint? setWindowFlags(Qt::FramelessWindowHint); 但是这样过后,我们就不能拖动窗口改变位置,以及拖动边缘改变窗口大小了. 有两种方案处理这种情况: 1.自己对m

设置textarea文本框不可以拖动改变大小

设置textarea文本框不可以拖动改变大小:在默认状态下,textarea文本框可以使用鼠标拖动调整大小,可能在某些情况下需要禁止此功能.代码如下: <!DOCTYPE html> <html> <head> <meta charset=" utf-8"> <meta name="author" content="http://www.softwhy.com/" /> <titl

UITableVIewcell中图片不能改变大小的原因

你有没没有发现,有时候把图片放进cell.imageView中时无法顺利改变大小呢? 其实根本原因是要在layoutSubviews重新配置一下,cell的布局里面默认有一个imageiView,同时,我们如果自己定义的话也需要在layoutSubviews中布局控件. - (void)layoutSubviews { //改变系统cell.imageView大小的方法 [super layoutSubviews]; self.imageView.bounds =CGRectMake(10,5,