C#GDI+编程教程
第7章C#图形图像编程基础
本章主要介绍使用C#进行图形图像编程基础~其中包括GDI+绘图基础、C#图
像处理基础以及简单的图像处理技术。
7.1GDI+绘图基础
编写图形程序时需要使用GDI(GraphicsDeviceInterface,图形设备接口),
从程序设计的角度看,GDI包括两部分:一部分是GDI对象,另一部分是GDI函
数。GDI对象定义了GDI函数使用的工具和环境变量,而GDI函数使用GDI对象绘
制各种图形,在C#中,进行图形程序编写时用到的是GDI+(GraphiceDevice
InterfacePlus图形设备接口)版本,GDI+是GDI的进一步扩展,它使我们编程更
加方便。7.1.1GDI+概述
GDI+是微软在Windows2000以后操作系统中提供的新的图形设备接口,其通
过一套部署为托管代码的类来展现,这套类被称为GDI+的“托管类接口”,GDI+
主要提供了以下三类服务:
(1)二维矢量图形:GDI+提供了存储图形基元自身信息的类(或结构体)、存储
图形基元绘制方式信息的类以及实际进行绘制的类。
(2)图像处理:大多数图片都难以划定为直线和曲线的集合,无法使用二维矢
量图形方式进行处理。因此,GDI+为我们提供了Bitmap、Image等类,它们可用于
显示、操作和保存BMP、JPG、GIF等图像格式。
(3)文字显示:GDI+支持使用各种字体、字号和样式来显示文本。
我们要进行图形编程,就必须先讲解Graphics类,同时我们还必须掌握Pen、
Brush和Rectangle这几种类。
GDI+比GDI优越主要表现在两个方面:第(一)GDI+通过提供新功能(例如:渐变
画笔和alpha混合)扩展了GDI的功能;第(二)修订了编程模型,使图形编程更加简
易灵活。
7.1.2Graphics类
Graphics类封装一个GDI+绘图图面,提供将对象绘制到显示设备的方法,
Graphics与特定的设备上下文关联。画图方法都被包括在Graphics类中,在画任
何对象(例如:
Circle,Rectangle)时,我们首先要创建一个Graphics类实例,这个实例相当
于建立
了一块画布,有了画布才可以用各种画图方法进行绘图。
绘图程序的设计过程一般分为两个步骤:(一)创建Graphics对象;(二)使用
Graphics
对象的方法绘图、显示文本或处理图像。
通常我们使用下述三种方法来创建一个Graphics对象。
方法一、利用控件或窗体的Paint事件中的PainEventArgs
在窗体或控件的Paint事件中接收对图形对象的引用,作为
PaintEventArgs(PaintEventArgs指定绘制控件所用的Graphics)的一部分,在为
控件创建绘制代码时,通常会使用此方法来获取对图形对象的引用。
例如:
//窗体的Paint事件的响应方法
privatevoidform1_Paint(objectnder,PaintEventArg)
{
Graphicsg=cs;
}
也可以直接重载控件或窗体的OnPaint方法,具体代码如下所示:protected
overridevoidOnPaint(PaintEventArg){
Graphicsg=cs;
}
Paint事件在重绘控件时发生。
方法二、调用某控件或窗体的CreateGraphics方法
调用某控件或窗体的CreateGraphics方法以获取对Graphics对象的引用,该
对象表示
该控件或窗体的绘图图面。如果想在已存在的窗体或控件上绘图,通常会使用
此方法。例如:
Graphicsg=Graphics();
方法三、调用Graphics类的FromImage静态方法
由从Image继承的任何对象创建Graphics对象。在需要更改已存在的图像
时,通常会
使用此方法。
例如:
//名为“”的图片位于当前路径下
Imageimg=le("");//建立Image对象
Graphicsg=age(img);//创建Graphics对象
,(Graphics类的方法成员
有了一个Graphics的对象引用后,就可以利用该对象的成员进行各种各样图
形的
绘制,表7.1列出了Graphics类的常用方法成员。
表7.1Graphics类常用方法
名称说明
DrawArc画弧。
DrawBezier画立体的贝尔塞曲线。
DrawBeziers画连续立体的贝尔塞曲线。
DrawClodCurve画闭合曲线。
DrawCurve画曲线。
DrawEllip画椭圆。
DrawImage画图像。
DrawLine画线。
DrawPath通过路径画线和曲线。
DrawPie画饼形。
DrawPolygon画多边形。
DrawRectangle画矩形。
DrawString绘制文字。
FillEllip填充椭圆。
FillPath填充路径。
FillPie填充饼图。
FillPolygon填充多边形。
FillRectangle填充矩形。
FillRectangles填充矩形组。
FillRegion填充区域。
在中,GDI+的所有绘图功能都包括在System、g、
g、g2D和
等命名
空间中,因此在开始用GDI+类之前,需要先引用相应的命名空间。2(引用命
名空间
在C#应用程序中使用using命令已用给定的命名空间或类,下面是一个C#应
用程
序引用命名空间的例子:
usingSystem;
c;;
entModel;g;
g2D;g;
7.1.3常用画图对象
在创建了Graphics对象后,就可以用它开始绘图了,可以画线、填充图形、
显示
文本等等,其中主要用到的对象还有:
,Pen:用来用patterns、colors或者bitmaps进行填充。,Color:用来画线
和多边形,包括矩形、圆和饼形。,Font:用来给文字设置字体格式。
,Brush:用来描述颜色。
,Rectangle:矩形结构通常用来在窗体上画矩形。,Point:描述一对有序的
x,y两个坐标值。
1(Pen类
Pen用来绘制指定宽度和样式的直线。使用DashStyle属性绘制几种虚线,可
以使用各
种填充样式(包括纯色和纹理)来填充Pen绘制的直线,填充模式取决于画笔或
用作填充对
象的纹理。
使用画笔时,需要先实例化一个画笔对象,主要有以下几种方法。用指定的
颜色实例化一只画笔的方法如下:
publicPen(Color);
用指定的画刷实例化一只画笔的方法如下:
publicPen(Brush);
用指定的画刷和宽度实例化一只画笔的方法如下:
publicPen(Brush,float);
用指定的颜色和宽度实例化一只画笔的方法如下:
publicPen(Color,float);
实例化画笔的语句格式如下:
Penpn=newPen();
或者Penpn=newPen(,100);Pen常用的属性有以下几个,如表
7.2所示:
表7.2Pen常用属性
名称说明
Alignment获得或者设置画笔的对齐方式。
Brush获得或者设置画笔的属性。
Color获得或者设置画笔的颜色。
Width获得或者设置画笔的宽度。
2(Color结构
在自然界中,颜色大都由透明度(A)和三基色(R,G,B)所组成。在GDI+中,通过
Color结构封装对颜色的定义,Color结构中,除了提供(A,R,G,B)以外,还提
供许多
系统定义的颜色,如Pink(粉颜色),另外,还提供许多静态成员,用于对颜色
进行操作。Color结构的基本属性如表7.3所示。
表7.3颜色的基本属性
名称说明
A获取此Color结构的alpha分量值,取值(0,255)。B获取此Color结构的
蓝色分量值,取值(0,255)。G获取此Color结构的绿色分量值,取值(0,255)。
R获取此Color结构的红色分量值,取值(0,255)。
获取此Color结构的名称,这将返回用户定义的颜色的名称Name或已知颜色
的名称(如果该颜色是从某个名称创建的),对于
自定义的颜色,将返回RGB值。
Color结构的基本(静态)方法如表7.4所示
表7.4颜色的基本方法
名称说明
FromArgb从四个8位ARGB分量(alpha、红色、绿色和蓝色)值创建Color
结构。
FromKnowColor从指定的预定义颜色创建一个Color结构。
FromName从预定义颜色的指定名称创建一个Color结构。Color结构变量可
以通过已有颜色构造,也可以通过RGB建立,例如:Colorclr1=
gb(122,25,255);Colorclr2=
owColor();//KnownColor为枚举类型Colorclr3
=me("SlateBlue");在图像处理中一般需要获取或设置像素的颜色
值,获取一幅图像的某个像素颜色值
的具体步骤如下:
(1)定义Bitmap
BitmapmyBitmap=newBitmap("c:");
(2)定义一个颜色变量把在指定位置所取得的像素值存入颜色变量中
Colorc=newColor();
c=el(10,10);//获取此Bitmap中指定像素的颜色。(3)将
颜色值分解出单色分量值
intr,g,b;
r=c.R;
g=c.G;
b=c.B;
3(Font类
Font类定义特定文本格式,包括字体、字号和字形属性。Font类的常用构造
函数
是publicFont(string字体名,float字号,FontStyle字形),其中字号和
字体
为可选项和publicFont(string字体名,float字号),其中“字体名”为
Font的
FontFamily的字符串表示形式。下面是定义一个Font对象的例子代码:
FontFamilyfontFamily=newFontFamily("Arial");Fontfont=new
Font(fontFamily,16,r,);
字体常用属性如表7.5所示。
表7.5字体的常用属性
名称说明
Bold是否为粗体。
FontFamily字体成员。
Height字体高。
Italic是否为斜体。
Name字体名称。
Size字体尺寸。
SizeInPoints获取此Font对象的字号,以磅为单位。
Strikeout是否有删除线。
Style字体类型。
Underline是否有下划线。
Unit字体尺寸单位。
4(Brush类
Brush类是一个抽象的基类,因此它不能被实例化,我们总是用它的派生类进
行实
例化一个画刷对象,当我们对图形内部进行填充操作时就会用到画刷,关于画
刷在7.1.5
中有详细讲解。
5(Rectangle结构
存储一组整数,共四个,表示一个矩形的位置和大小。矩形结构通常用来在窗
体上
画矩形,除了利用它的构造函数构造矩形对象外,还可以使用Rectangle结构
的属性成
员,其属性成员如表7.6所示。
表7.6Rectangle结构属性
名称说明
Bottom底端坐标
Height矩形高
IsEmpty测试矩形宽和高是否为0
Left矩形左边坐标
Location矩形的位置
Right矩形右边坐标
Size矩形尺寸.
Top矩形顶端坐标
Width矩形宽
X矩形左上角顶点X坐标
Y矩形左上角顶点Y坐标Retangle结构的构造函数有以下两个:
//用指定的位置和大小初始化Rectangle类的新实例。
publicRetangle(Point,Size);//Size结构存储一个有序整数对,通常为矩形
的宽度和高度。
和
publicRectangle(int,int,int,int);
6(Point结构
用指定坐标初始化Point类的新实例。这个结构很像C++中的Point结构,它
描述了一对有序的x,y两个坐标值,其构造函数为:publicPoint(intx,inty);
其中x为该点的水平位置;y为该点的水垂直位置。下面是构造Point对象的例子
代码:
Pointpt1=newPoint(30,30);
Pointpt2=newPoint(110,100);
7.1.4基本图形绘制举例
1(画一个矩形
【例7.1】建立一个项目,在窗体上画一个矩形,通过直接在Form1类中重载
OnPaint函数的方法来实现。
图7.1画一个矩形
protectedoverridevoidOnPaint(PaintEventArg)
{
Graphicsg=cs;
Rectanglerect=newRectangle(50,30,100,100);
LinearGradientBrushlBrush=newLinearGradientBrush(rect,
,,rdDiagonal);
ctangle(lBrush,rect);
}
运行结果如图7.1所示。
2(画一个弧
【例7.2】画一个弧形。
弧形函数格式如下:
publicvoidDrawArc(Penpen,Rectanglerect,FloatstartArgle,Float
sweepAngle);
直接在Form1类中重载OnPaint函数
protectedoverridevoidOnPaint(PaintEventArg)
{
Graphicsg=cs;
Penpn=newPen();
Rectanglerect=newRectangle(50,50,200,100);
c(pn,rect,12,84);
}
运行结果如图7.2所示。
图7.2画一个弧
3(画线
【例7.3】画一条线。
protectedoverridevoidOnPaint(PaintEventArg)
{
Graphicsg=cs;
Penpn=newPen();
Pointpt1=newPoint(30,30);Pointpt2=newPoint(110,100);
ne(pn,pt1,pt2);}
运行结果如图7.3所示。
图7.3画一条线
4(画椭圆
【例7.4】画一个椭圆。
图7.4画一个椭圆
protectedoverridevoidOnPaint(PaintEventArg){
Graphicsg=cs;
Penpn=newPen(,100);
Rectanglerect=newRectangle(50,50,200,100);lip(pn,
rect);
}
运行结果如图7.4所示。
5(输出文本
【例7.5】输出文本。
protectedoverridevoidOnPaint(PaintEventArg){
Fontfnt=newFont("Verdana",16);
Graphicsg=cs;
ring("GDI+World",fnt,newSolidBrush(),14,10);
}
运行结果如图7.5所示。
图7.5输出文本
6(填充路径
【例7.6】填充路径。
protectedoverridevoidOnPaint(PaintEventArg){
Graphicsg=cs;
ctangle(newSolidBrush(),ClientRectangle);
GraphicsPathpath=newGraphicsPath(newPoint[]{
newPoint(40,140),newPoint(275,200),
newPoint(105,225),newPoint(190,300),
newPoint(50,350),newPoint(20,180),},
newbyte[]{
(byte),
(byte),
(byte),
(byte),
(byte),
(byte),
});
PathGradientBrushpgb=newPathGradientBrush(path);
ndColors=newColor[]
{
,,,,
,,
};
th(pgb,path);
}
运行结果如图7.6所示。
图7.6填充路径
注意:GraphicsPath类位于命名空间g2D中~表示一系
列相互连接的直线和曲线。
7.1.5画刷和画刷类型
Brush类型是一个抽象类,所以它不能被实例化,也就是不能直接应用,但是
我们可以利用它的派生类,如:HatchBrush、SolidBrush和TextureBrush等。画
刷类型一般在g命名空间中,如果应用HatchBrush和
GradientBrush画刷,需要在程序中引入g2D命名空间。
1(SolidBrush(单色画刷)
它是一种一般的画刷,通常只用一种颜色去填充GDI+图形,例如:
protectedoverridevoidOnPaint(PaintEventArg)
{
Graphicsg=cs;
SolidBrushsdBrush1=newSolidBrush();
SolidBrushsdBrush2=newSolidBrush();
SolidBrushsdBrush3=newSolidBrush();
lip(sdBrush2,20,40,60,70);
Rectanglerect=newRectangle(0,0,200,100);
e(sdBrush3,0,0,200,40,0.0f,30.0f);
PointFpoint1=newPointF(50.0f,250.0f);
PointFpoint2=newPointF(100.0f,25.0f);
PointFpoint3=newPointF(150.0f,40.0f);
PointFpoint4=newPointF(250.0f,50.0f);
PointFpoint5=newPointF(300.0f,100.0f);
PointF[]curvePoints={point1,point2,point3,point4,point5};
lygon(sdBrush1,curvePoints);
}
运行结果如图7.7所示。
图7.7SolidBrush应用
2(HatchBrush(阴影画刷)
HatchBrush类位于g2D命名空间中。阴影画刷有两种
颜色:
前景色和背景色,以及6种阴影。前景色定义线条的颜色,背景色定各线条之
间间隙的
颜色。HatchBrush类有两个构造函数:
,publicHatchBrush(HatchStyle,Colorforecolor);
,publicHatchBrush(HatchStyle,Colorforecolor,Colorbackcolor);
HatchStyle枚举值指定可用于HatchBrush对象的不同图案。HatchStyle的主要
成员如表7.7所示。
表7.7HatchStyle主要成员
名称说明
BackwardDiagonal从右上到左下的对角线的线条图案。Cross指定交叉的水
平线和垂直线。
DarkDownwardDiagonal指定从顶点到底点向右倾斜的对角线,其两边夹角
比ForwardDiagonal小50%,宽度是其两倍。此阴影
图案不是锯齿消除的。
DarkHorizontal指定水平线的两边夹角比Horizontal小50%并且宽
度是Horizontal的两倍。
DarkUpwardDiagonal指定从顶点到底点向左倾斜的对角线,其两边夹角
比BackwardDiagonal小50%,宽度是其两倍,但这
些直线不是锯齿消除的。
DarkVertical指定垂直线的两边夹角比Vertical小50%并且宽度
是其两倍。
DashedDownwardDiagonal指定虚线对角线,这些对角线从顶点到底点向右倾
斜。
DashedHorizontal指定虚线水平线。
DashedUpwardDiagonal指定虚线对角线,这些对角线从顶点到底点向左倾
斜。
DashedVertical指定虚线垂直线。
DiagonalBrick指定具有分层砖块外观的阴影,它从顶点到底点向
左倾斜。
DiagonalCross交叉对角线的图案。
Divot指定具有草皮层外观的阴影。
ForwardDiagonal从左上到右下的对角线的线条图案。Horizontal水平线的
图案。
HorizontalBrick指定具有水平分层砖块外观的阴影。LargeGrid指定阴影
样式Cross。
LightHorizontal指定水平线,其两边夹角比Horizontal小50%。
LightVertical指定垂直线的两边夹角比Vertical小50%。Max指定阴影样式
SolidDiamond。
Min指定阴影样式Horizontal。
NarrowHorizontal指定水平线的两边夹角比阴影样式Horizontal小
75%(或者比LightHorizontal小25%)。NarrowVertical指定垂直线的两边夹
角比阴影样式Vertical小75%
(或者比LightVertica小25%)。OutlinedDiamond指定互相交叉的正向对角
线和反向对角线,但这些
对角线不是锯齿消除的。
Percent05指定5%阴影。前景色与背景色的比例为5:100。Percent90指定
90%阴影。前景色与背景色的比例为90:100。Plaid指定具有格子花呢材料外观
的阴影。Shingle指定带有对角分层鹅卵石外观的阴影,它从顶点到
底点向右倾斜。
SmallCheckerBoard指定带有棋盘外观的阴影。
SmallConfetti指定带有五彩纸屑外观的阴影。
SolidDiamond指定具有对角放置的棋盘外观的阴影。Sphere指定具有球体
彼此相邻放置的外观的阴影。Trellis指定具有格架外观的阴影。
Vertical垂直线的图案。
Wave指定由代字号“~”构成的水平线。
Weave指定具有织物外观的阴影。
下面代码显示了HatchBrush画刷的使用。
protectedoverridevoidOnPaint(PaintEventArg){
Graphicsg=cs;
HatchBrushhBrush1=newHatchBrush(alCross,
ate,);
HatchBrushhBrush2=newHatchBrush(Horizontal,
,);
HatchBrushhBrush3=newHatchBrush(,
olet,);
lip(hBrush1,20,80,60,20);
Rectanglerect=newRectangle(0,0,200,100);
e(hBrush3,0,0,200,40,0.0f,30.0f);
PointFpoint1=newPointF(50.0f,250.0f);
PointFpoint2=newPointF(100.0f,25.0f);
PointFpoint3=newPointF(150.0f,40.0f);
PointFpoint4=newPointF(250.0f,50.0f);
PointFpoint5=newPointF(300.0f,100.0f);
PointF[]curvePoints={point1,point2,point3,point4,point5};
lygon(hBrush2,curvePoints);
}
运行结果如图7.8所示。
图7.8HatchBrush应用
3(TextureBrush(纹理画刷)
纹理画刷拥有图案,并且通常使用它来填充封闭的图形。为了对它初始化,可
以使用一个已经存在的别人设计好了的图案,或使用常用的设计程序设计的自己的
图案,同时应该使图案存储为常用图形文件格式,如BMP格式文件。这里有一个设
计好的位图,被存储为文件。
privatevoidForm1_Paint(objectnder,PaintEventArg){
Graphicsg=cs;
//根据文件名创建原始大小的bitmap对象
Bitmapbitmap=newBitmap("D:");
//将其缩放到当前窗体大小
bitmap=newBitmap(bitmap,);
TextureBrushmyBrush=newTextureBrush(bitmap);
lip(myBrush,Rectangle);}
运行结果如图7.9所示。
图7.9TextTureBursh应用
4(LinearGradientBrush和PathGradientBrush(渐变画刷)
渐变画刷类似与实心画刷,因为它也是基于颜色的,与实心画刷不同的是:渐
变画刷使用两种颜色;它的主要特点是:在使用过程中,一种颜色在一端,而另外一
种颜色在另一端,在中间,两种颜色融合产生过渡或衰减的效果。
渐变画刷有两种:线性画刷和路径画刷(LinearGradientBrush和
PathGradientBrush)。
其中LinearGradientBrush可以显示线性渐变效果,而PathGradientBrush是
路径渐变的可以显示比较具有弹性的渐变效果。
(1)LinearGradientBrush类
LinearGradientBrush类构造函数如下:
publicLinearGradientBrush(Pointpoint1,Pointpoint2,Color
color1,Color
color2)
参数说明:
point1:表示线性渐变起始点的Point结构。
point2:表示线性渐变终结点的Point结构。
color1:表示线性渐变起始色的Color结构。
color2:表示线性渐变结束色的Color结构。
代码如下:
privatevoidForm1_Paint(objectnder,PaintEventArg)
{
Graphicsg=cs;
LinearGradientBrushmyBrush=new
LinearGradientBrush(Rectangle,,,
al);
ctangle(myBrush,Rectangle);}
运行结果如图7.10所示。
图7.10LinearGradientBrush的应用
(2)PathGradientBrush类
PathGradientBrush类的构造函数如下:
publicPathGradientBrush(GraphicsPathpath);
参数说明:
path:GraphicsPath,定义此PathGradientBrush填充的区域。
例子代码如下:
privatevoidForm1_Paint(objectnder,PaintEventArg){
Graphicsg=cs;
PointcenterPoint=newPoint(150,100);
intR=60;
GraphicsPathpath=newGraphicsPath();
ip(centerPoint.X-R,centerPoint.Y-R,2*R,2*R);
PathGradientBrushbrush=newPathGradientBrush(path);
//指定路径中心点
Point=centerPoint;
//指定路径中心的颜色
Color=;
//Color类型的数组指定与路径上每个顶点的颜色
ndColors=newColor[]{};
lip(brush,centerPoint.X-R,centerPoint.Y-R,2*R,2*R);
centerPoint=newPoint(350,100);
R=20;
path=newGraphicsPath();
ip(centerPoint.X-R,centerPoint.Y-R,2*R,2*R);
ip(centerPoint.X-2*R,centerPoint.Y-2*R,4*R,4*R);
ip(centerPoint.X-3*R,centerPoint.Y-3*R,6*R,6*R);brush=
newPathGradientBrush(path);
Point=centerPoint;
Color=;
ndColors=newColor[]{,,
};
th(brush,path);
}
运行结果如图7.11所示。
图7.11PathGradientBrush应用
7.2C#图像处理基础
本节主要介绍C#图像处理基础知识以及对图像的基本处理方法和技巧,主要包
括图像的加载、变换和保存等操作。
7.2.1C#图像处理概述
1(图像文件的类型
GDI+支持的图像格式有BMP、GIF、JPEG、EXIF、PNG、TIFF、ICON、WMF、EMF
等,几乎涵盖了所有的常用图像格式,使用GDI+可以显示和处理多种格式的图像
文件。
2(图像类
GDI+提供了Image、Bitmap和Metafile等类用于图像处理,为用户进行图像
格式的加载、变换和保存等操作提供了方便。
(1)Image类
Image类是为Bitmap和Metafile的类提供功能的抽象基类。
(2)Metafile类
定义图形图元文件,图元文件包含描述一系列图形操作的记录,这些操作可以
被记录(构造)和被回放(显示)。
(3)Bitmap类
封装GDI+位图,此位图由图形图像及其属性的像素数据组成,Bitmap是用于
处理由像素数据定义的图像的对象,它属于g命名空间,该命名空
间提供了对GDI+基本图形功能的访问。Bitmap类常用方法和属性如表7.8所示。
表7.8Bitmap常用属性和方法
名称说明
公共属性
Height获取此Image对象的高度。
RawFormat获取此Image对象的格式。
Size获取此Image对象的宽度和高度。
Width获取此Image对象的宽度。
公共方法
GetPixel获取此Bitmap中指定像素的颜色。
MakeTransparent使默认的透明颜色对此Bitmap透明。
RotateFlip旋转、翻转或者同事旋转和翻转Image对象。
Save将Image对象以指定的格式保存到指定的
Stream对象。
SetPixel设置Bitmap对象中指定像素的颜色。
SetPropertyItem将指定的属性项设置为指定的值。
SetResolution设置此Bitmap的分辨率。
Bitmap类有多种构造函数,因此可以通过多种形式建立Bitmap对象,例如:
从指定的现有图像建立Bitmap对象
Bitmapbox1=newBitmap();
从指定的图像文件建立Bitmap对象,其中“C:”已
存在的图像文件
Bitmapbox2=newBitmap("C:");
从现有的Bitmap对象建立新的Bitmap对象
Bitmapbox3=newBitmap(box1);
7.2.2图像的输入和保存
1(图像的输入
在窗体或图形框内输入图像有两种方式:(一)在窗体设计时使用图形框对象的
Image属性输入;(二)在程序中通过打开文件对话框输入。
方法(一)、窗体设计时使用图形框对象的Image属性输入
窗体设计时使用对象的Image属性输入图像的操作如下:
(1)在窗体上,建立一个图形框对象(pictureBox1),选择图形框对象属性中的
Image属性,如图7.12所示。
(2)单击Image属性右侧的【„】,弹出一个“选择资源”窗口,在该窗口中选
择“本地资源”,单击【导入(M)...】将弹出一个“打开”对话框,如图7.13所
示。
图7.12Image属性
图7.13“打开”对话框
(3)选择图像文件后,单击【打开】按钮。
方法(二)、使用“打开文件”对话框输入图像
在窗体上添加一个命令按钮(button1)和一个图形框对象(pictureBox1),双击
命令按钮,在响应方法中输入如下代码:
privatevoidbutton1_Click(objectnder,EventArg)
{
OpenFileDialogofdlg=newOpenFileDialog();
="BMPFile(*.bmp)|*.bmp";
if(alog()==)
{
Bitmapimage=newBitmap(me);
=image;
}
}
执行该程序时,使用“打开文件”对话框,选择图像文件,该图像将会被打
开,并显示在pictureBox1图像框中。
【例7.7】图像输入。
采用方法(二)来实现图像的输入。
设计步骤如下:
(1)建立如图7.14所示的项目界面,在窗体上加入【打开图像】命令按钮和一
个PictureBox控件。
(2)双击【打开图像】命令按钮,编辑按钮的单击事件响应函数,其代码同方
法(二)中所写代码,在此不再重复。
图7.14图像输入
(3)运行后单击【打开图像】按钮,弹出一个“打开文件”对话框,选择图象
文件名,运行结果如图7.15所示。
图7.15运行结果
2(图像的保存
保存图像的步骤如下:
(1)当使用按钮和保存对话框保存文件时,加入保存按钮和PictureBox控件,
窗体设计如图7.16所示。
(2)保存命令钮的单击事件的响应函数代码如下:
privatevoidbutton2_Click(objectnder,EventArg)
{
stringstr;
Bitmapbox1=newBitmap();
SaveFileDialogsfdlg=newSaveFileDialog();
="bmp文件(*.BMP)|*.BMP|AllFile(*.*)|*.*";
alog();
str=me;
(str);
}
执行该过程时,将打开“另存为”对话框,如图7.17所示。
图7.16保存图像
图7.17“另存为”对话框
选择图像文件的保存路径。
3(图像格式的转换
使用Bitmap对象的Save方法,可以把打开的图像保存为不同的文件格式,从
而实现图像格式的转换。在上述例子中添加一个命令按钮,双击该命令按钮,编辑
其相应代码如下:privatevoidbutton3_Click(objectnder,EventArg)
{
stringstr;
Bitmapbox1=newBitmap();
SaveFileDialogsfdlg=newSaveFileDialog();
="bmp文件(*.jpeg)|*.jpeg|AllFile(*.*)|*.*";
alog();
str=me;
(str,);
}
Bitmap对象的Save方法中的第二个参数指定了图像保存的格式。
ormat支持的格式如表7.9所示:
表ormat支持的格式
名称说明
Bmp获取位图图像格式(BMP)。
Emf获取增强型Windows图元文件图像格式(EMF)。
Exif获取可交换图像文件(Exif)格式。
Gif获取图形交换格式(GIF)图像格式。
Guid获取表示此ImageForma对象的Guid结构。
Icon获取Windows图标图像格式。
Jpeg获取联合图像专家组(JPEG)图像格式。
MemoryBmp获取内存位图图像格式。
Png获取W3C可移植网络图形(PNG)图像格式。
Tiff获取标签图像文件格式(TIFF)图像格式。
Wmf获取Windows图元文件(WMF)图像格式。
7.2.3图像的拷贝和粘贴
图像拷贝和粘贴是图像处理的基本操作之一,通常有两种方法来完成图像的拷
贝和粘贴:一种可以使用剪贴板拷贝和粘贴图像,一种使用AxPictureClip控件拷
贝和粘贴图像。
1(使用剪贴板拷贝和粘贴图像
剪贴板是在Windwos系统中单独预留出来的一块内存,它用来暂时存放在
Windwos应用程序间要交换的数据,使用剪贴板对象可以轻松实现应用程序间的数
据交换,这些数据包括图像或文本。在C#中,剪贴板通过Clipboard类来实现,
Clipboard类的常用方法如表7.10所示。
表7.10Clipboard类常用方法
名称说明
Clear从剪贴板中移除所有数据。
ContainsData指示剪贴板中是否存在指定格式的数据,或
可转换成此格式的数据。
ContainsImage指示剪贴板中是否存在Bitmap格式或可转
换成此格式的数据。
ContainsText已重载。指示剪贴板中是否存在文本数据。
GetData从剪贴板中检索指定格式的数据。
GetDataObject检索当前位于系统剪贴板中的数据。
GetFileDropList从剪贴板中检索文件名的集合。
GetImage检索剪贴板上的图像。
GetText已重载。从剪贴板中检索文本数据。
SetAudio已重载。将WaveAudio格式的数据添加到剪
贴板中。
SetData将指定格式的数据添加到剪贴板中。
SetDataObject已重载。将数据置于系统剪贴板中。
SetImage将Bitmap格式的Image添加到剪贴板中。
SetText已重载。将文本数据添加到剪贴板中。
剪贴板的使用主要有一下两个步骤:
,将数据置于剪贴板中。
,从剪贴板中检索数据。
下面简要介绍剪贴板的使用。
(1)将数据置于剪贴板中
可以通过SetDataObject方法将数据置于剪贴板中,SetDataObject方法有以
下三种形式的定义:
,aObject(Object):将非持久性数据置于系统剪贴板中。
由
CompactFramework支持。
,aObject(Object,Boolean):将数据置于系统剪贴板中,并
指定在退出应用程序后是否将数据保留在剪贴板中。
,aObject(Object,Boolean,Int32,Int32):尝试指定的次数,
以将数据置于系统剪贴板中,且两次尝试之间具有指定的延迟,可以选择在退出应
用程序后将数据保留在剪贴板中。
将字符串置于剪贴板中的语句如下所示:
stringstr="MaheshwritingdatatotheClipboard";
aObject(str)
(2)从剪贴板中检索数据
可以通过GetDataObject方法从剪贴板中检索数据,它将返回IdataObject,
其定义如下:
publicstaticIDataObjectGetDataObject();
首先使用IdataObject对象的GetDataPrent方法检测剪贴板上存放的是什
么类型的数据,然后是使用IdataObject对象的GetData方法获取剪贴板上相应的
数据类型的数据。下面使用GetDataObject方法从剪贴板中检索出字符串数据。
例如:
IDataObjectiData=aObject();
if(aPrent())
{
stringstr=(String)a();
}
【例7.8】使用剪贴板拷贝和粘贴图像。
(1)建立如图7.18所示的窗体。在窗体上天加两个图片框控件和两个命令按钮
控件。利用第一个图片框的属性窗口为其输入图像。
(2)双击【复制】命令按钮,输入如下代码,将图像置于剪贴板中。
privatevoidbutton1_Click(objectnder,EventArg)
{
aObject();
}
(3)双击【粘贴】命令按钮,输入如下代码,从剪贴板中检索出图像,并显示
于第二个图片框中。
privatevoidbutton2_Click(objectnder,EventArg)
{
IDataObjectiData=aObject();
if(aPrent())
{
=(Bitmap)a();
}
}
(4)运行程序,首先单击【复制】命令按钮,然后单击【粘贴】命令按钮,运
行结果如图7.19所示。
图7.18剪贴板窗体设计
图7.19剪贴板图像复制
2(使用AxPictureClip控件拷贝和粘贴图像
AxPictureClip控件不是常规控件,而是一个ActiveX控件。因此,工具箱中
没有该控件,要想使用该控件,必须把该控件添加到工具箱中,具体步骤如下:
(1)右键单击工具箱的空白处,在弹出的快捷菜单中选择【选择项】菜单项,
则弹出“选择工具箱项”对话框,如图7.20所示。
图7.20添加AxPictureClip控件
(2)在该对话框中的【COM组件】选项卡中选择【MicrosoftPictureClip
Control,version6】项,并单击【确定】按钮,该控件就添加到工具箱中了。
AxPictureClip控件可用于随机访问方法或者枚举访问方法指定源位图中剪切
区域如下:
,使用随机访问方法来作为剪切区域选择源位图的任何部分。通过使用ClipX
和ClipY属性指定的剪切区域左上角,ClipHeight和ClipWidth属性确定剪切区
域的区域。当想要查看位图的一部分此方法很有用。
,使用枚举访问方法可以分成的行和列数指定源位图。结果是图片的统一矩阵
单元编号0、1、2和等等,通过使用GraphicCell属性来访问单个单元。当源位图
图像与要访问单独的调色板包含这种方法非常有用。
【例7.9】使用AxPictureClip控件剪切和粘贴图像。
(1)建立如图7.21示的窗体。在窗体上天加两个图片框控件和两个命令按钮控
件。
(2)双击【打开】命令按钮,输入如下代码,将图像打开。
privatevoidbutton1_Click(objectnder,EventArg)
{
OpenFileDialogofdlg=newOpenFileDialog();
="BMPFile(*.bmp)|*.bmp";
if(alog()==)
{
Bitmapimage=newBitmap(me);
=image;
}
}
(3)双击【复制与粘贴】命令按钮,输入如下代码,将图像复制到第二个图片
框中。
privatevoidbutton2_Click(objectnder,EventArg)
{
//使用枚举访问方法
e=;
=6;//将图片分成6列
=3;//将图片分成3行
try
{
=_GraphicCell(0);//取出第一个图
像块
}
catch(Exceptionex)
{
(ng());
}
}
(4)运行程序,单击【打开】命令按钮,选择一个图像文件打开,如图7.21所
示,然后单击【复制与粘贴】命令按钮,运行结果如图7.22所示。
图7.21打开图片后效果
(5)使用随机访问方法。
也可以使用随机访问方法,只需将上述例子中的【复制与粘贴】命令按钮的响
应方法改为如下代码即可:
privatevoidbutton2_Click(objectnder,EventArg)
{
//使用随机访问方法
e=;
=15;
=15;
ight=50;
dth=50;
=;//
}
图7.22粘贴后效果
注意:如果没有控件~需要自行下载或复制到本
机~并通过注册程序REGSVR32注册该组件。例如~如果该文件在
C:WINDOWSsystem32路径下~可以通过如下命令行语句实现注册:REGSVR32
C:
7.2.4彩色图像处理
1(图像的分辨率
所谓分辨率就是指画面的解析度,由多少像素构成,数值越大,图像也就越清
晰。我们通常所看到的分辨率都以乘法形式表现的,例如800*600,其中“800”
表示屏幕上水平方向显示的点数,“600”表示垂直方向的点数。图像分辨率越
大,越能表现更丰富的细节。图像的分辨率决定了图像与原物的逼进程度,对同一
大小的图像,其像素数越多,即将图像分割的越细,图像越清晰,称之为分辨率
高,反之为分辨率低,分辨率的高低取决于采样操作。例如,对于一幅256*256分
辨率的图像,采用变换的方法可以实现不同分辨率显示。
【例7.10】将256*256分辨率的图像变换为64*64分辨率。
算法说明:将256*256分辨率的图像变换为64*64分辨率方法是将源图像分成
4*4的子图像块,然后将该4*4子图像块的所有像素的颜色按F(i,j)的颜色值进行
设定,达到降低分辨率的目的。
建立一个如图7.23所示界面的项目,【分辨率】命令按钮的响应方法的代码
设计如
下:
privatevoidbutton3_Click(objectnder,EventArg)
{
Colorc=newColor();
//把图片框中的图片给一个Bitmap类型
Bitmapbox1=newBitmap();
Bitmapbox2=newBitmap();
intr,g,b,size,k1,k2,xres,yres,i,j;
xres=;
yres=;
size=4;
for(i=0;i<=xres-1;i+=size)
{
for(j=0;j<=yres-1;j+=size)
{
c=el(i,j);
r=c.R;
g=c.G;
b=c.B;
//用FromArgb把整型转换成颜色值
Colorcc=gb(r,g,b);
for(k1=0;k1<=size-1;k1++)
{
for(k2=0;k2<=size-1;k2++)
{
if(i+k1<)
el(i+k1,j+k2,cc);
}
}
}
}
h();//刷新
=box2;//图片赋到图片框中
}
输入图像分辨率为256*256像素,转换为64*64分辨率图像如图7.23所示。
图7.23分辨率
2(彩色图像变换灰度图像
(1)彩色位图图像的颜色
图像像素的颜色是由三种基本色颜色,即红(R)、绿(G)、蓝(B)有机组合而成
的,称为三基色。每种基色可取0,255的值,因此由三基色可组合成
(256*256*256)1677万种颜色,每种颜色都有其对应的R、G、B值。例如,常见的
7种颜色及其对应的R、G、B值如表7.11所示。
表7.11常见的7种颜色及其对应的R、G、B值
颜色名R值G值B值
红25500
蓝00255
绿02550
白255255255
黄2552550
黑000
青0255255
品红2550255
(2)彩色图像颜色值的获取
在使用C#系统处理彩色图像时,使用Bitmap类的GetPixel方法获取图像上指
定像素的颜色值,格式为:
Colorc=newColor();
c=el(i,j);
其中,(i,j)为获得颜色的坐标位置。GetPixel方法取得指定位置的颜色值并
返回
一个长整型的整数。例如,求图片框1中图像在位置(i,j)的像素颜色值c
时,可写为:
Colorc=newColor();
c=el(i,j);
(3)彩色位图颜色值分解
像素颜色值c是一个长整型的数值,占4个字节,最上位字节的值为“0”,
其它3个下位字节依次为B、G、R,值为0,255。
从从值分解出R、G、B值可直接使用:
Colorc=newColor();
c=el(i,j);
r=c.R;
g=c.G;
b=c.B;
(4)图像像素颜色的设定
设置像素可使用SetPixel方法。用法如下:
Colorc1=gb(rr,gg,bb);
el(i+k1,j+k2,c1);
【例7.11】彩色图像生成灰度图像。
算法说明:将彩色图像像素的颜色值分解为三基色R、G、B,求其和的平均值,
然后使用SetPixel方法以该平均值参数生成图像。
其相应的代码设计如下:
c=el(i,j);
r=c.b;
g=c.G;
b=c.B;
cc=(int)((r+g+b)/3);
if(cc<0)cc=0;
f(cc>255)cc=255;
Colorc1=gb(cc,cc,cc);
el(i,j,c1);
(1)在上例中增加一个【灰度图像】命令按钮。
(2)双击该按钮,编辑其响应方法的代码如下:
privatevoidbutton4_Click(objectnder,EventArg)
{
Colorc=newColor();
//把图片框1中的图片给一个Bitmap类型
Bitmapb=newBitmap();
Bitmapb1=newBitmap();
intrr,gg,bb,cc;
for(inti=0;i<;i++)
{
for(intj=0;j<;j++)
{
c=el(i,j);
rr=c.R;
gg=c.G;
bb=c.B;
cc=(int)((rr+gg+bb)/3);
if(cc<0)cc=0;
if(cc>255)cc=255;
//用FromArgb把整型转换成颜色值
Colorc1=gb(cc,cc,cc);
el(i,j,c1);
}
h();//刷新
=b1;//图片赋给图片框2
}
}
(3)运行程序,程序运行结果如图7.24所示。
图7.24灰度图像
3(灰度图像处理
【例7.12】改善对比度。
算法说明:本例根据特定的输入输出灰度转换关系,增强了图像灰度,处理后
图像
的中等灰度值增大,图像变亮。
注意:本例中描述对比度改善的输入、输出灰度值对应关系的程序段为:lev=
80;
wid=100;
for(x=0;x<256;x+=1)
{
lut[x]=255;
}
for(x=lev;x<(lev+wid);x++)
{
dm=((double)(x-lev)/(double)wid)*255f;lut[x]=(int)(dm);
}
(1)在窗体上添加一个“对比度”命令按钮。
(2)双击“对比度”命令按钮,编辑代码如下:
privatevoidbutton5_Click(objectnder,EventArg)
{
Colorc=newColor();
Bitmapbox1=newBitmap();
Bitmapbox2=newBitmap();
intrr,x,m,lev,wid;
int[]lut=newint[256];
int[,,]pic=newint[600,600,3];
doubledm;
lev=80;
wid=100;
for(x=0;x<256;x+=1)
{
lut[x]=255;
}
for(x=lev;x<(lev+wid);x++)
{
dm=((double)(x-lev)/(double)wid)*255f;
lut[x]=(int)dm;
}
for(inti=0;i<-1;i++)
{
for(intj=0;j<;j++)
{
c=el(i,j);
pic[i,j,0]=c.R;
pic[i,j,1]=c.G;
pic[i,j,2]=c.B;
}
}
for(inti=0;i<-1;i++)
{
for(intj=0;j<;j++)
{
m=pic[i,j,0];
rr=lut[m];
Colorc1=gb(rr,rr,rr);
el(i,j,c1);
}
h();
=box2;
}
}
(3)运行程序,运行结果如图7.25所示。
图7.25改善对比度
本章小结
本章主要讲述了C#下的图形图像基础知识,对图形的绘制,图像的处理和音频
视频等多媒体的使用方法;在图片处理方面提供了一个GDI+,功能十分强大,
能完成对图像的全方位处理。
思考与练习(习题)1(绘制一个图形需要哪些基本步骤,
2(在窗体上绘制图形有哪些方法,
3(如何构造一个颜色对象,
4(打开图像有哪些方法,
5(如何转换图像格式,
本文发布于:2022-11-23 12:42:02,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/5743.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |