C#程序设计.唐大仕.08.绘图及图像

绘图及图像

1. GDI+及其基本类

  • GDI:Graphics Device Interface
  • GDI+:GDI的改进
    • 是 .NET 框架结构的重要组成部分
    • 和 GDI 一样它提供对二维图形图像文字排版处理的支持

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Graphics g = this.CreateGraphics();
Pen pen = new Pen(Color.Red, 2);
Brush brush = new SolidBrush(Color.Blue);
Font font = new Font("宋体", 24);
Rectangle rect = new Rectangle(20,120,100,160);

g.DrawLine(pen, 20, 100, 100, 100);
g.DrawRectangle(pen, rect);
g.DrawString("GDI+图形编程", font, brush, 20, 20);

brush.Dispose();
font.Dispose();
pen.Dispose();
g.Dispose();

  • Pen:画边框
  • Brush:填充

.NET 对 GDI+ 的封装

坐标系统

1
2
3
4
5
6
7
8
o---------------> x
|
|
|
|
v

y

System.Drawing 中常用的结构

Color

  • Color 封装了对颜色的定义
  • 该结构中封装了数百个分别对应与标准调色板色彩的静态成员
    • Color.Red:红色
    • Color.Purple:紫色
  • 有用的静态方法
    • FromArgb:通过三原色构建 Color 对象
    • FromKnownColor:通过已知颜色构建 Color 对象
    • FromName:通过颜色名称来构建 Color 对象
1
2
3
Color temp1 = Color.Black;
Color temp2 = Color.FromArgb(0,0,0);
Color temp3 = Color.FromName("Black");

Size 和 SizeF

  • 表示绘制平面上的一个尺寸
    • Size:整数
    • SizeF:浮点数
  • 属性
    • Width:表示宽度值
    • Height:表示高度值
  • 重载了加、减、比较、赋值操作

Point 和 PointF

  • 表示绘制平面上点的坐标,一个为整数,另外一个为浮点数
1
2
Point pt = new Point(20,20);
Point pt = new Point(new Size(10,10));
  • 重载了加、减、比较、赋值操作

Rectangle 和 RectangleF

  • 表示绘制平面上的一个矩形区域
  • 属性
属性 含义
Bottom 矩形底部的纵坐标
Top 矩形顶部的纵坐标
Left 矩形坐部的横坐标
Right 矩形右部的横坐标
Height 矩形的高度
Width 矩形的宽度
Size 矩形的尺寸
IsEmpty 矩形是否为空(高度和宽度是否都是0)
X 矩形左上角的横坐标
Y 矩形左上角的纵坐标

2. Graphics 对象及绘图方法

Graphics 对象

得到 Graphics 对象

  • OnPaint 事件中使用
1
2
3
4
5
Protected override void OnPaint(PaintEventArgse){
Graphics g = e.Graphics;
// 这里的 Graphics 对象不是我们的创建的
// 我们不要去 dispose 它
}
  • 在其他情况使用
1
2
Graphics g = this.CreateGraphics();
// 需要 dispose

关于 Graphics 的释放

  • 对于 CreateGraphics() 得到的 Graphics 对象

    • 系统会自动释放,也可以显式地释放

    1
    g.Dispose();

    • 也可以使用 using 的写法

    1
    2
    3
    using(Graphics g = this.CreateGraphics()) {
    // ...
    }

    • 这种写法相当于

    1
    2
    3
    4
    5
    try{
    // ...
    } finally{
    g.Dispose();
    }

Graphics 对象绘图方法

  • Draw:绘制边框
属性 含义
DrawArc 绘制圆弧
DrawBezier 绘制贝塞尔曲线
DrawBeziers 绘制贝塞尔曲线组
DrawClosedCurve 绘制封闭曲线
DrawCurve 绘制曲线
DrawEllipse 绘制椭圆
DrawIcon 绘制图标
DrawIconUnstretched 无缩放绘制图标
DrawImage 绘制图像
DrawImageUnscaled 无缩放绘制图像
DrawLine 绘制直线
DrawLines 绘制直线组
DrawPath 绘制 GraphicsPath 对象
DrawPie 绘制圆饼
DrawPolygon 绘制多边形
DrawRectangle 绘制矩形
DrawRectangles 绘制矩形组
DrawString 绘制文本
  • Fill:填充
属性 含义
FillClosedCurve 绘制实心封闭曲线
FillEllipe 封闭实心椭圆
FillPath GraphicsPath 对象
FillPie 绘制实心圆饼
FillPolygon 绘制实心多边形
FillRectangle 绘制实心矩形
FillRectangles 绘制实心矩形组
FillRegion 绘制实心 Region 对象

Pen 对象

  • System.Drawing 名称空间中
  • 用来指定图形的轮廓,如颜色宽度
1
2
3
4
5
// 画笔创建
Pen pen= new Pen(Color.Blue, 5);

// 使用 Pens 类,直接用系统定义好的 Pen
Pen p = Pens.Red;
属性 描述 取值
Alignment 指定相对于理论上、零宽度的线条的 Pen 对象的对齐方式 PenAlignment.Center:位于所绘制线条的中央
PenAlignment.Insert:位于所绘制线条的嵌入内部
PenAlignment.Left:位于所绘制线条的左侧
PenAlignment.OutSet:位于所绘制线条的嵌入外部
PenAlignment.Right:位于所绘制线条的右侧
DashStyle 绘制线条的虚线类型 DashStyle.Custom:用户自定义
DashStyle.Dash:线段
DashStyle.DashDot:线段和点
DashStyle.DashDotDot:线段、点和点
DashStyle.Dot:点
DashStyle.Solid:实线
StartCap
EndCap
绘制线条的起点和终点类型 LineCap LAnchorMask 用于检查线帽是否为锚头帽的掩码
ArrowAnchor 箭头状锚头帽
Custom 自定义线帽
DiamondAnchor 菱形锚头帽
Flat 平线帽
NoAnchor 没有锚
Round 圆线帽
RoundAnchor 圆锚头帽
Square 方线帽
SquareAnchor 方锚头帽
Triangle 三角线帽

Brush 对象

  • Brush 是一个抽象类,不能被直接 new 实例化
  • 它有5个派生类,分别实行不同类型的画刷
    • SolidBrush:实心画刷(最简单)
    • HatchBrush:带阴影线的画刷
    • LinearGradientBrush:填充颜色线性渐变的画刷
    • PathGradientBrush:填充颜色沿路径渐变的画刷
    • TextureBrush:使用图像进行填充的画刷
  • 使用 Brushes 类
    • Brushes.Red

文本绘制

  • Font 类
    • FontFamiliy、字体大小、字体风格(Bold、Italic、Regular、Strikeout、Underline)
1
Font myFont = new Font("宋体", 16, FontStyle.Bold|FontStyle.Italic);
  • DrawString() 函数各种重载

Transform

  • 3x3 矩阵

示例代码片段

绘制应用

一些笔记

  • 在图片上绘制文字得一种方法
  • 将图片复制到剪切板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Graphics g = Graphics.FromImage(image);
Font font = new System.Drawing.Font("微软雅黑", 12, (System.Drawing.FontStyle.Bold));
LinearGradientBrush brush = new LinearGradientBrush(
new Rectangle(0, 0, image.Width, image.Height),
Color.White,
Color.FromArgb(100,100,100),
1.2f,
true);
g.DrawString(textBox1.Text, font, brush, 100, 184);
g.DrawString(textBox2.Text, font, brush, 100, 417);
g.DrawString(textBox3.Text, font, brush, 100, 650);
g.Dispose();
pictureBox1.Image = image;
// 将图片复制到剪切板
Clipboard.SetDataObject(pictureBox1.Image);
  • 屏保程序编程方式
    • LuminousClock.sln

3. 控件与绘图

控件重绘

  • paint 事件发生情况
    • 窗体 A 覆盖了窗体 B,当窗体 A 移开的时候,窗体 B 得 paint 事件会被触发
  • 强制程序进行重绘
1
2
3
4
5
6
7
8
9
// 使控件的特定区域无效并向控件发送绘制消息
void Invalidate();
void Invalidate(Rectangle);

// 使控件重绘其工作区内的无效区域
void Update();

// 相当于 this.Invalidate(true); this.Update();
void Refresh();

双缓冲技术

  • Double Buffer
  • 预先在内存中绘制好图像,然后再一次性绘制到屏幕上
1
2
3
4
5
6
7
8
9
10
11
// 1. 在内存中建立一块虚拟画布
Bitmap bmp = new Bitmap(600, 600);

// 2.获取这块内存画布的 Graphics 引用
Graphics g = Graphics.FromImage(bmp);

// 3. 在这块内存画布上绘图
g.FillEllipse(brush, i* 10, j * 10, 10, 10);

// 4. 将内存画布画到窗口中
this.CreateGraphics().DrawImage(bmp, 0, 0);
  • 直接设置控件的 DoubleBuffered 属性为 true

4. Bitmap 类及图像处理

  • GDI+ 中对图像处理提供了以下支持:
    • 支持 BMP、GIF、JPEG、PNG、TIFF、ICON 等等广泛格式的图像文件
    • 提供了用于多种光栅图像格式进行编码和解码的公共接口
    • 支持为图像格式添加动态格式
    • 支持对图像的像素进行多种处理,包括亮度、对比度、颜色平衡、模糊、消弱等
    • 支持对图像进行旋转、剪切等操作
  • 主要通过 Image类 实现

Bitmap类

  • Image 是抽象类,Bitmap 从 Image 派生
  • 可以处理 BMP、JPEG、GIF、PNG 等格式
1
2
3
4
Bitmap bt1 = new Bitmap("c:\\1.bmp");
Bitmap bt2 = new Bitmap(bt1, 200, 300);
Bitmap bt3;
bt3.FromFile("文件名称");

针对图像像素的处理

  • 图像文件bmp的格式
  • 慢速方法
1
bitmap.GetPixel(x,y);
  • 使用指针(快)
    • 因为使用了unsafe,所以编译的时候需要设置 “允许不安全的代码”
      • /unsafe
1
2
3
4
5
6
7
bitmapData = bitmap.LockBits(
bounds, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
// 起始位置
pBase = (Byte*)bitmapData.Scan0.ToPointer();
// 任意位置
// stride: 一行的像素点占据的字节数
(PixelData*)(pBase + y * stride + x * sizeof(PixelData));

图像处理