【笔记】【C# 二维三维图形绘制工程实例宝典】 第03章 坐标系统和颜色变换

3.1 坐标系统

GDI+定义了三种形式的坐标系统:世界坐标系统页面坐标系统设备坐标系统

测量相对于文档区域左上角的位置和测量相对于屏幕(桌面)左上角的位置之间的区别非常重要,GDI+为它们指定了不同的名称:

  • 世界坐标:用来绘制自然模型的坐标(以像素为单位)。Graphics.Draw*使用的坐标就是该坐标系下的坐标。
  • 页面坐标:要测量的点距离客户区域左上角的位置(以像素为单位)。
  • 设备坐标:设备坐标类似于页面坐标,但其测量单位不一定是像素,而是用户通过调用Graphics.PageUnit属性指定的单位。

GDI+在设备绘图表面(如屏幕,打印机)绘制图形之前,图形的坐标系统要经过几步变换

  • 第一步变换世界坐标到页面坐标,这一变换过程称为世界变换。
  • 第二步变换页面坐标到设备坐标,这一变换过程称为页面变换。设备坐标代表绘制的图形时怎样显示在设备上的。

在GDI+中,所有三种坐标系统的起始原点均是客户区左上角原点(0,0)。当画一条从点A(0,0)到点B(120,80)的直线时,该直线的起始点是左上角X方向的0像素点和Y方向的0像素点,终点是X方向的120像素点和Y方向的80像素点。以下程序展示了应用世界坐标系统在窗体上绘制一条从点A(0,0)到点B(120,80)的直线。此时,世界坐标系统与页面坐标系统重合。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;

namespace Example
{
    public partial class Form1 : Form
    {
        private System.ComponentModel.IContainer components = null;

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(332, 266);
            this.Name = "Form1";
            this.Text = "Form1";
            
            this.ResumeLayout(false);

        }
		
        public Form1()
        {
            InitializeComponent();

            this.AutoScaleDimensions = new Size(5, 13);
            this.ClientSize = new Size(392, 373);
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 
        }


        protected override void OnPaint(PaintEventArgs e)
        {
            // 获取绘图对象
            Graphics g = e.Graphics;

            // 设置垂直方向字体
            Font vertFont = new Font("Verdana", 10, FontStyle.Regular);
            // 设置水平方向字体
            Font horzFont = new Font("Verdana", 10, FontStyle.Regular);
            // 设置画刷
            SolidBrush blackBrush = new SolidBrush(Color.Black);
            // 设置黑色画笔
            Pen blackPen = new Pen(Color.Black, 1);
            // 设置蓝色画笔
            Pen bluePen = new Pen(Color.Blue, 1);

            //页面坐标
            //绘制X轴标签

            g.DrawString("200", horzFont, blackBrush, 200, 5);
            g.DrawString("100", horzFont, blackBrush, 100, 5);
            g.DrawString("X", horzFont, blackBrush, 250, 0);

            //Drawing vertical string
            StringFormat vertStrFormat= new StringFormat();
            vertStrFormat.FormatFlags = StringFormatFlags.DirectionVertical;
            //绘制Y轴标签
            g.DrawString("100", vertFont, blackBrush, 0, 100);
            g.DrawString("200", vertFont, blackBrush, 0, 200);
            g.DrawString("Y", vertFont, blackBrush, 0, 250);
			
            //绘制坐标轴
            g.DrawLine(blackPen, 0, 0, 0, 250);
            g.DrawLine(blackPen, 0, 0, 250, 0);

            // 绘制直线
            Point A = new Point(0, 0);
            Point B = new Point(120, 80);
            g.DrawLine(bluePen, A, B);
        }
    }
}

现将世界坐标系统的原点从点(0,0)偏移到点(50,40),应用Graphics类中的TranslateTransform方法实现原点的偏移。

  • 世界坐标系统中,该直线仍是起始于点(0,0)终止于点(120,80),
  • 页面坐标系统中该直线是起始于点(50,40)终止于点(120 + 50 = 170, 80 + 40 = 120)
protected override void OnPaint(PaintEventArgs e)
{
    Graphics g = e.Graphics;
    g.PageUnit = GraphicsUnit.Inch;
    g.DrawLine(Pens.Black, 0,0,2,1);
}

在上述的代码段中,首先将PageUnit属性值设置为英寸,然后画一条从点(0,0)到点(2,1)的直线。这条直线在世界和页面坐标系统中起始于点(0,0)终止于点(2,1),但是在设备坐标中,该直线起始于点(0,0)终止于点(192,96)(假设屏幕的解析度是每英寸96个点)。注意,画笔此时的默认宽度为1个页面单位,即1个英寸宽。当然,也可重新定义笔的宽度。

protected override void OnPaint(PaintEventArgs e)
{
    Graphics g = e.Graphics;
    Pen redPen = new Pen(Color.Red, 1/g.Dpix);
    g.PageUnit = GraphicsUnit.Inch;
    g.DrawLine(redPen, 0,0,2,1);
}

3.2 颜色变换

GDI+提供用于存储和处理图形图像的Image类和Bitmap类,Image对象和Bitmap对象将每个像素的颜色都存储为32位的数:红色、绿色、蓝色和Alpha个占8位。这四个分量的值都是0到255。在红色、绿色、蓝色分量中,0标识没有亮度,255标识最大亮度。Alpha分量指定颜色的透明度,0表示完全透明,255表示完全不透明。颜色矢量采用四元组形式(红色、绿色、蓝色、Alpha)。因此可用以下颜色矩阵来修改该颜色分量。

             | Red    0       0       0     |
             | 0      Green   0       0     |
             | 0      0       Blue    0     |
             | 0      0       0       Alpha |

表示颜色的另一种管理是用数字1表示亮度达到最大,GDI+在进行颜色变换时使用以1表示最大亮度的管理。例如,改变颜色(0,255,0,255)到半透明,方法就是用50%替代上述4x4颜色变换矩阵中的Alpha的初始值。相关的计算矩阵如下所示:

                 | 1    0   0    0   |
                 | 0    1   0    0   |
|0 255 0 255| x  |                   | = |0 255 0 127.5|
                 | 0    0   1    0   |
                 | 0    0   0    0.5 |

上述是通过4x4的颜色变换矩阵进行线性变换。要支持非线性变换,需要将4x4的线性颜色变换矩阵扩展为5x5的仿射颜色变换矩阵。

             | Red    0       0       0      0 |
             | 0      Green   0       0      0 |
             | 0      0       Blue    0      0 |
             | 0      0       0       Alpha  0 |
             | 0      0       0       0      1 |

例如,假设颜色适量为(25,100,100,255),须同事完成两个操作:

  • 将红色元素的值加倍
  • 将绿色元素的值加100
                     | 2   0    0    0  0 |
                     | 0   1    0    0  0 |
|25 100 100 255 1| x | 0   0    1    0  0 | = |50 200 100 255 1|
                     | 0   0    0    1  0 |
                     | 0   100  0    0  1 |

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhy29563

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值