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

 
 
 
 
 
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
 
Bitmap bmp = new Bitmap("rama.jpg");//加载图像
//填充窗体背景为白色
new Point(100, 0), // destination for upper-left point of original
new Point(0, 0)}; // destination for lower-left point of original
 
 
//旋转图像180°代码如下:
{
Graphics g = e.Graphics;
g.FillRectangle(Brushes.White, this.ClientRectangle);
new Point(0, 100), // destination for upper-left point of original
new Point(0, 0)}; // destination for lower-left point of original
 
 
//图像切变代码:
{
Graphics g = e.Graphics;
g.FillRectangle(Brushes.White, this.ClientRectangle);
new Point(0, 0), // destination for upper-left point of original
new Point(50, 100)};// destination for lower-left point of original
 
 
//图像截取:
{
Graphics g = e.Graphics;
g.FillRectangle(Brushes.White, this.ClientRectangle);
//要截取的矩形区域
//要显示到Form的矩形区域
 
 
//改变图像大小:
{
Graphics g = e.Graphics;
g.FillRectangle(Brushes.White, this.ClientRectangle);
int height = bmp.Height;
g.InterpolationMode = InterpolationMode.NearestNeighbor;
 
GraphicsUnit.Pixel);
//g.CompositingQuality = CompositingQuality.HighSpeed;
g.DrawImage(
new Rectangle(130, 10, 120, 120), 
GraphicsUnit.Pixel);
}
 
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
 
Bitmap bmp = new Bitmap("rama.jpg");
bmp.SetResolution(300f, 300f);
bmp.SetResolution(1200f, 1200f);
 
 
//用GDI+画图
{
Graphics gForm = e.Graphics;
for (int i = 1; i <= 7; ++i)
 
 
this.ClientRectangle.Height);
 
 
Bitmap bmp = new Bitmap(260, 260,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
gBmp.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
// 并将其画在内存的位图里面
Brush redBrush = new SolidBrush(red);
// 创建一个带有Alpha的绿色区域
Brush greenBrush = new SolidBrush(green);
//在窗体上面画出位图 now draw the bitmap on our window
// 清理资源
gBmp.Dispose();
greenBrush.Dispose();
}
 
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
 
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);
 
 
 
 
一. 底片效果
效果图: 
 
 
 
        {
            try
                int Height = this.pictureBox1.Image.Height;
                Bitmap newbitmap = new Bitmap(Width, Height);
                Color pixel;
                {
                    {
                        pixel = oldbitmap.GetPixel(x, y);
                        g = 255 - pixel.G;
                        newbitmap.SetPixel(x, y, Color.FromArgb(r, g, b));
                }
            }
            {
            }
 
 
 
 
 
 
 
 
 
 
 
       private void button1_Click(object sender, EventArgs e)
            //以浮雕效果显示图像
            {
                int Width = this.pictureBox1.Image.Width;
                Bitmap oldBitmap = (Bitmap)this.pictureBox1.Image;
                for (int x = 0; x < Width - 1; x++)
                    for (int y = 0; y < Height - 1; y++)
                        int r = 0, g = 0, b = 0;
                        pixel2 = oldBitmap.GetPixel(x + 1, y + 1);
                        g = Math.Abs(pixel1.G - pixel2.G + 128);
                        if (r > 255)
                        if (r < 0)
                        if (g > 255)
                        if (g < 0)
                        if (b > 255)
                        if (b < 0)
                        newBitmap.SetPixel(x, y, Color.FromArgb(r, g, b));
                }
            }
            {
            }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
        private void button1_Click(object sender, EventArgs e)
            //以黑白效果显示图像
            {
                int Width = this.pictureBox1.Image.Width;
                Bitmap oldBitmap = (Bitmap)this.pictureBox1.Image;
                for (int x = 0; x < Width; x++)
                    {
                        int r, g, b, Result = 0;
                        g = pixel.G;
                        //实例程序以加权平均值法产生黑白图像
                        switch (iType)
                            case 0://平均值法
                                break;
                                Result = r > g ? r : g;
                                break;
                                Result = ((int)(0.7 * r) + (int)(0.2 * g) + (int)(0.1 * b));
                        }
                    }
            }
            {
            }
 
 
 
 
 
 
 
 
 
 
 
        private void button1_Click(object sender, EventArgs e)
            //以柔化效果显示图像
            {
                int Width = this.pictureBox1.Image.Width;
                Bitmap MyBitmap = (Bitmap)this.pictureBox1.Image;
                //高斯模板
                for (int x = 1; x < Width - 1; x++)
                    {
                        int Index = 0;
                            for (int row = -1; row <= 1; row++)
                                pixel = MyBitmap.GetPixel(x + row, y + col);
                                g += pixel.G * Gauss[Index];
                                Index++;
                        r /= 16;
                        b /= 16;
                        r = r > 255 ? 255 : r;
                        g = g > 255 ? 255 : g;
                        b = b > 255 ? 255 : b;
                        bitmap.SetPixel(x - 1, y - 1, Color.FromArgb(r, g, b));
                this.pictureBox1.Image = bitmap;
            catch (Exception ex)
                MessageBox.Show(ex.Message, "信息提示");
        }
五.锐化效果
原理:突出显示颜色值大(即形成形体边缘)的像素点.
效果图:
 
 
 
 
 
实现代码:
 
        {
            try
                int Height = this.pictureBox1.Image.Height;
                Bitmap newBitmap = new Bitmap(Width, Height);
                Color pixel;
                int[] Laplacian ={ -1, -1, -1, -1, 9, -1, -1, -1, -1 };
                    for (int y = 1; y < Height - 1; y++)
                        int r = 0, g = 0, b = 0;
                        for (int col = -1; col <= 1; col++)
                            {
                                g += pixel.G * Laplacian[Index];
                                Index++;
                        //处理颜色值溢出
                        r = r < 0 ? 0 : r;
                        g = g < 0 ? 0 : g;
                        b = b < 0 ? 0 : b;
                    }
            }
            {
            }
 
 
 
 
 
 
 
 
实现代码:
 
        {
            try
                int Height = this.pictureBox1.Image.Height;
                Bitmap newBitmap = new Bitmap(Width, Height);
                Color pixel;
                    for (int y = 1; y < Height - 1; y++)
                        System.Random MyRandom = new Random();
                        //像素块大小
                        int dy = y + k % 19;
                            dx = Width - 1;
                            dy = Height - 1;
                        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控件来显示图片,如下:
        {
            ofd.Filter = "BMP Files(*.bmp)|*.bmp|JPG Files(*.jpg;*.jpeg)|*.jpg;*.jpeg|All Files(*.*)|*.*";
            ofd.CheckPathExists = true;
            {
                bmp = new Bitmap(ofd.FileName);
                {
                    return;
                pbxShowImage.Image = bmp;
            }
其中bmp为类的一个对象:private Bitmap bmp=null;
二、保存图像
        {
 
            sfd.Filter = "BMP Files(*.bmp)|*.bmp|JPG Files(*.jpg;*.jpeg)|*.jpg;*.jpeg|All Files(*.*)|*.*";
            {
                MessageBox.Show("保存成功!","提示");
            }
三、对像素的访问
using System;
using System.Linq;
using System.Drawing;
using System.Windows.Forms;
namespace ImageElf
    class GrayBitmapData
        public byte[,] Data;//保存像素矩阵
//图像的宽度
//图像的高度
        public GrayBitmapData()
            this.Width = 0;
            this.Data = null;
 
        {
            this.Width = bmpData.Width;
            Data = new byte[Height, Width];
            {
                for (int i = 0; i < Height; i++)
                    for (int j = 0; j < Width; j++)
    //将24位的RGB彩色图转换为灰度图
                        Data[i, j] = (byte)temp;
                    ptr += bmpData.Stride - Width * 3;//指针加上填充的空白空间
            }
        }
        public GrayBitmapData(string path)
        {
 
        {
            BitmapData bmpData=bmp.LockBits(new Rectangle(0,0,Width,Height),ImageLockMode.WriteOnly,PixelFormat.Format24bppRgb);
            {
                for(int i=0;i<Height;i++)
                    for(int j=0;j<Width;j++)
                        *(ptr++)=Data[i,j];
                        *(ptr++)=Data[i,j];
                    ptr+=bmpData.Stride-Width*3;
            }
            return bmp;
 
        {
            pbx.Image = b;
        }
        public void SaveImage(string path)
            Bitmap b=ToBitmap();
            //b.Dispose();
//均值滤波
        {
            {
            }
            for (int i = 0; i < Height; i++)
                for (int j = 0; j < Width; j++)
                    int sum = 0;
                    {
                        {
                            if (a < 0) a = 0;
                            if (b < 0) b = 0;
                            sum += Data[a, b];
                    }
                }
        }
        public void MidFilter(int windowSize)
            if (windowSize % 2 == 0)
                return;
 
            byte[,] newdata = new byte[Height, Width];
            {
                {
                    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 > Height - 1) a = Height - 1;
                            if (b > Width - 1) b = Width - 1;
                        }
                    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];
            }
//获得一个向量的中值
        {
            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[j] = temp;
                }
 
        }
        public void NewFilter(int windowSize)
            if (windowSize % 2 == 0)
                return;
 
            {
                {
                    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 > Height - 1) a = Height - 1;
                            if (b > Width - 1) b = Width - 1;
                        }
                    double avg = (sum+0.0) / (windowSize * windowSize);
                    {
                    }
                    {
                    }
            }
//直方图均衡
        {
            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];
            for (int i = 0; i < 256; i++)
                n += num[i];
            }
            for (int i = 0; i < Height; i++)
                for (int j = 0; j < Width; j++)
                    Data[i,j]=(byte)newGray[Data[i,j]];
            }
 
}
一个按钮来做各种调用:
        private void btnAvgFilter_Click(object sender, EventArgs e)
            if (bmp == null) return;
            gbmp.AverageFilter(3);
        }
        private void btnToGray_Click(object sender, EventArgs e)
            if (bmp == null) return;
            gbmp.ShowImage(pbxShowImage);
 
 
 
 
posted @ 2016-08-02 11:58  Net-Spider  阅读(268)  评论(0)    收藏  举报