程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# (GDI+相關) 圖像處理(各種旋轉、改變大小、柔化、銳化、霧化、底片、浮雕、黑白、濾鏡效果) (轉),

C# (GDI+相關) 圖像處理(各種旋轉、改變大小、柔化、銳化、霧化、底片、浮雕、黑白、濾鏡效果) (轉),

編輯:C#入門知識

C# (GDI+相關) 圖像處理(各種旋轉、改變大小、柔化、銳化、霧化、底片、浮雕、黑白、濾鏡效果) (轉),


 

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屬性為每行像素所占的字節。
 
 

排列組合A幾幾的 C幾幾的怎算

A32 是排列 C32 是組合
比如A32 就是3乘以2 等於6
A 6 3 就是6*5*4
就是從大數開始乘後面那個數表示有多少個數 A 7 2 等於 7*6* 2就有兩位 A 5 2 =5*4
那麼C 3 2 就是還要除以一個 數 比如 C 3 2 就是 A 3 2 再除以 A 22
C 5 3 就是 A 5 3 除以 A 3 3
相當清楚了嗎 樓主 手打字 求給分
 

排列組合A幾幾的 C幾幾的怎算

A32 是排列 C32 是組合
比如A32 就是3乘以2 等於6
A 6 3 就是6*5*4
就是從大數開始乘後面那個數表示有多少個數 A 7 2 等於 7*6* 2就有兩位 A 5 2 =5*4
那麼C 3 2 就是還要除以一個 數 比如 C 3 2 就是 A 3 2 再除以 A 22
C 5 3 就是 A 5 3 除以 A 3 3
相當清楚了嗎 樓主 手打字 求給分
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved