在Visual C#下实现图像的透明处理
以前编程实现图像的透明处理是比较困难的,代码量多,工作又复杂。不过,现在随着微软VS.Net开发工具的逐渐普及,伴随而来的新兴开发语言C#以及GDI+等新的编程机制正为广大开发人员所接受。本文就向大家介绍在Visual C#中,如何运用GDI+中Alpha Blending技术实现图像的透明处理。
在各类有关.Net的技术论坛上常有人问如何实现透明的图像或图形效果,答案很简单,就是Alpha Blending技术。Alpha Blending技术是一个混合各种颜色值并产生透明效果的过程。具体的实现原理也很简单:在GDI+中,任何一种颜色由四种成分组成――Alpha,Red,Green和Blue。其中的Alpha成分则代表了一种颜色的透明程度,它的值在0到255之间变化。不言而喻,0代表完全透明而255则表示完全不透明。因此,你只要用透明效果创建一种颜色并用该颜色来画图像就可以完成图像的透明处理了。
原理虽然比较简单,但是要初学者实际操作起来可能也并不是那么容易。所以下面我就向大家展示一个很好的实例。在该实例中,我先在窗体上画了一些图形,这些图形包括直线、曲线、椭圆等,同时这些图形有的是不透明的、有的是半透明的、有的是强透明的(注:其中的"强透明"意思为非常透明,几乎为全透明,但是又隐约可见)。如果你有GDI+编程的一些基本知识,完成这些应该并不困难。然后,我在这些图形上覆盖了一幅图像,在正常情况(也就是不透明的情况)下,窗体上的图形为图像所遮盖,所以应该是看不见的。接着,我通过一个按钮的消息响应函数使得图像具有透明效果,这样一来的话,窗体上原来的那些图形就会浮现出来。
实现方法
首先,打开VS.net,新建一个Visual C#的项目,选择模板为"Windows应用程序",同时不妨命名为"TransparentImage",图示如下:
图1
接着,进行窗体布局。往窗体上添加三个按钮以完成用户输入控制。将窗体的Text属性设置为"图像的透明处理示例";将三个按钮的Text属性分别设置为"半透明"、"强透明"、"不透明";同时,为界面美观起见将三个按钮的FlatStyle属性均设置为Flat。最终,窗体布局的图示如下:
图2
完成了窗体布局,我们接着开始编写代码。首先,我们添加窗体的Paint消息响应函数。读者可以发现,我们在进行窗体布局的时候并没有在窗体上添加pictureBox控件,那么我们怎么显示图像并画出各种图形呢?这就要用到窗体的Paint消息响应函数了,函数实现如下:
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Graphics g = this.CreateGraphics();
g.Clear(this.BackColor);
DrawPerson();
//画一幅图像
Image curImage = Image.FromFile(@"e:\photo.jpg");
g.DrawImage(curImage, 0, 0, curImage.Width, curImage.Height);
g.Dispose();
}
(注:其中的e:\photo.jpg为笔者电脑上图像文件的路径,读者可以将它改为自己电脑上图像文件的路径,下同。该文件可在源代码文件夹中找到。)
在上面的函数中,我们先建立了一个Graphics
对象,该对象就是专门用来画图形和图像的。我们还调用了本类的一个私有成员函数DrawPerson()
,该函数实现的功能就是在窗体上画一些图形,这些图形包括了椭圆、曲线、三角形,而这些图形合在一起恰好构成了一个人的头部轮廓,所以我姑且将该函数命名为了DrawPerson()
。在调用完毕后,就在窗体上画出一幅图像(用一个图像文件完成)。最后就是Graphics
对象的Dispose
工作。其中,DrawPerson()
函数的具体实现如下:
private void DrawPerson()
{
Graphics g = this.CreateGraphics();
g.Clear(this.BackColor);
//画人头轮廓
Rectangle rect1 = new Rectangle(75, 0, 150, 200);
g.FillEllipse(new SolidBrush(Color.FromArgb(225, 155, 150, 25)), rect1);
//定义三支画笔,其中第一支为不透明,第二支为半透明,第三支为强透明
Pen opqPen = new Pen(Color.FromArgb(155, 120, 205, 190), 15);
Pen transPen = new Pen(Color.FromArgb(128, 25, 150, 25), 12);
Pen totTransPen = new Pen(Color.FromArgb(140, 120, 18, 10), 10);
//画人头的眼睛
Rectangle rect2 = new Rectangle(70, 0, 160, 80);
g.DrawArc( opqPen, rect2, 30, 40 );
g.DrawArc( opqPen, rect2, 110, 40 );
//画人头的鼻子
Point[] threePoints=new Point[]{new Point(140, 130), new Point(160, 130), new
Point(150, 80)};
g.DrawPolygon(transPen,threePoints);
//画人头的嘴巴
Rectangle rect3 = new Rectangle(110, 150, 80, 20);
g.DrawEllipse(totTransPen,rect3);
g.Dispose();
}
请读者注意,在上面的函数中,我们定义画笔的时候定义了三支透明程度不同的画笔:不透明、半透明、强透明,如此一来就可以完成图形的透明效果。不过,图像的透明效果实现起来相对复杂,我将会在后面介绍。
这样,我们就完成了窗体的初始化工作。在运行程序后,窗体上就不是空白一片,而是有具体的图像了。由于我们的图像比较大,所以窗体上的图形在最初的时候是看不见的,只有当图像为透明时,其中的人头图形才会显现,这就正好符合我们程序的初衷了。
接下来,我们就着手实现图像的透明效果。在实现图像的透明效果过程中,我们需要用到了ColorMatrix
和ImageAttributes
等类,而这些类包含在System.Drawing.Imaging
名字空间中,所以我们在源代码文件的开始处需添加:using System.Drawing.Imaging;
来实现对这些类的调用。还有,ImageAttributes
类是用来设置图像的一系列属性的,它被用作Graphics
类对象的DrawImage
方法的一个参数。而ImageAttributes
类对象的方法SetColorMatrix
则调用ColorMatrix
来设置图像的颜色值。而图像的透明效果正是又ColorMatrix
中部分值所决定的。下面就是具体的实现方法了。
添加三个按钮的消息响应函数如下:
"半透明"按钮:
private void button1_Click(object sender, System.EventArgs e)
{
Graphics g = this.CreateGraphics();
g.Clear(this.BackColor);
DrawPerson();
Bitmap bitmap = new Bitmap(@"e:\photo.jpg");
float[][] ptsArray ={
new float[] {1, 0, 0, 0, 0},
new float[] {0, 1, 0, 0, 0},
new float[] {0, 0, 1, 0, 0},
new float[] {0, 0, 0, 0.5f, 0}, //注意:此处为0.5f,图像为半透明
new float[] {0, 0, 0, 0, 1}};
ColorMatrix clrMatrix = new ColorMatrix(ptsArray);
ImageAttributes imgAttributes = new ImageAttributes();
//设置图像的颜色属性
imgAttributes.SetColorMatrix(clrMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
//画图像
g.DrawImage(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height),
0, 0, bitmap.Width, bitmap.Height,
GraphicsUnit.Pixel, imgAttributes);
g.Dispose();
}
"强透明"按钮:
private void button2_Click(object sender, System.EventArgs e)
{
Graphics g = this.CreateGraphics();
g.Clear(this.BackColor);
DrawPerson();
Bitmap bitmap = new Bitmap(@"e:\photo.jpg");
float[][] ptsArray ={
new float[] {1, 0, 0, 0, 0},
new float[] {0, 1, 0, 0, 0},
new float[] {0, 0, 1, 0, 0},
new float[] {0, 0, 0, 0.1f, 0}, //注意:此处为0.1f,图像为强透明
new float[] {0, 0, 0, 0, 1}};
ColorMatrix clrMatrix = new ColorMatrix(ptsArray);
ImageAttributes imgAttributes = new ImageAttributes();
//设置图像的颜色属性
imgAttributes.SetColorMatrix(clrMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
//画图像
g.DrawImage(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height),
0, 0, bitmap.Width, bitmap.Height,
GraphicsUnit.Pixel, imgAttributes);
g.Dispose();
}
"不透明"按钮:
private void button3_Click(object sender, System.EventArgs e)
{
Graphics g = this.CreateGraphics();
g.Clear(this.BackColor);
DrawPerson();
//画一幅图像
Image curImage = Image.FromFile(@"e:\photo.jpg");
g.DrawImage(curImage, 0, 0, curImage.Width, curImage.Height);
g.Dispose();
}
这样,我们就完成了三个按钮的消息响应函数,整个程序也完毕了。按下Ctll+F5运行程序,我们将得到如下所示的界面:
图3
上面的情况是最初始时的状态。所以我们只可以看到一幅图像却看不到后面的图形,为了验证后面的图形是否存在,我们点击"半透明"按钮。这样,上面的图像就呈半透明状态,我们可以通过该图像看到隐藏在图像后面的图形了,图形就是上面所说的人头啊。效果图示如下:
图4
不过这里的人头图形还不是那么明显,不用着急,最后还有一个"强透明"效果还没有试过呢,下面就看看效果如何吧。("不透明"就是恢复到原来的状态,不用解释了吧?呵呵!!)
图5
小结
本文通过一个实例向大家介绍了如何运用Visual C#实现图像的透明处理,其原理相对来说是比较简单的,这主要得归功于.Net框架中的类库,它们为我们提供了强大的功能,大大地简化了我们的编程工作。因此,要学习图像处理,就得掌握System.Drawing及其以下的各个命名空间中的类库。而要成为一名优秀的.Net程序员,学习整个.Net框架以及其类库才是最重要的,而并非是掌握那门编程语言的事。最后希望本文能对广大读者有所帮助。
源代码文件为TransparentImage.rar(下载)