1、各類旋轉、改變大小算法
注意:先要添加畫圖相關的using引用。c#
//向右旋轉圖像90°代碼以下:
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{windows
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);數組
}dom
//旋轉圖像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);ide
}函數
//圖像切變代碼:
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);oop
}
//圖像截取:
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, "信息提示");
}
}
1、讀入圖像
在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;
2、保存圖像
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();
}
}
3、對像素的訪問
咱們能夠來創建一個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);
}
4、總結
在Visual c#中對圖像進行處理或訪問,須要先創建一個Bitmap對象,而後經過其LockBits方法來得到一個BitmapData類的對象,而後經過得到其像素數據的首地址來對Bitmap對象的像素數據進行操做。固然,一種簡單可是速度慢的方法是用Bitmap類的GetPixel和SetPixel方法。其中BitmapData類的Stride屬性爲每行像素所佔的字節。
(轉自:http://blog.csdn.net/jiangxinyu/article/details/6222322/)
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 關聯的設備上下文的句柄。
實現
備註
設備上下文是一個基於 GDI 的 Windows 結構,它定義一組圖形對象及其關聯的特性,以及影響輸出的圖形模式。 此方法返回該設備上下文(字體除外)。因爲未選擇字體,使用 GetHdc 方法返回的句柄對 FromHdc 方法進行調用將會失敗。
GetHdc 方法調用和 ReleaseHdc 方法調用必須成對出現。 在 GetHdc 和 ReleaseHdc 方法對的範圍內,一般僅調用 GDI 函數。 在該範圍內對 Graphics(它產生 hdc 參數)的 GDI+ 方法的調用因 ObjectBusy 錯誤而失敗。 此外,GDI+ 忽略後續操做中對 hdc 參數的 Graphics 所作的全部狀態更改。
示例
下面的代碼示例設計爲與 Windows 窗體一塊兒使用,它須要 PaintEventArgse,即 Paint 事件處理程序的一個參數。 該示例演示如何調用 Windows GDI 函數以執行與 GDI+ Graphics 方法相同的任務。 代碼執行下列操做:
釋放由 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);
}()