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

来源:互联网 发布:linux u盘挂载乱码 编辑:程序博客网 时间:2024/05/01 18:57

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, "信息提示");            }        } 

 

 


2 0