网站公告列表

  没有公告

加入收藏
设为首页
联系站长
您现在的位置: 网络学院 >> 程序设计 >> Delphi编程 >> 文章正文
  GDI+ 在Delphi程序的应用 -- Matrix应用心得            【字体:
GDI+ 在Delphi程序的应用 -- Matrix应用心得
作者:佚名    文章来源:不详    点击数:    更新时间:2007-8-3    

        关于GDI+的几何变换类Matrix的理论和应用有很多书籍和文章介绍,本文只是谈一点自己的应用心得。
正在装载数据……

        使用GDI+的Matrix类,可以很方便的进行提供了Rotate(旋转)、Scale( 缩放)、Shear(切变)等线性变换和Translate(平移),还可以通过这几个基本的变换组成更复杂的复合变换。通过变换后的图形及原点坐标变化很大,如下面的语句:

  g.DrawEllipse(Pens.Blue, 0, 0, 100, 50);
  g.ScaleTransform(1.0, 0.5);
  g.TranslateTransform(50.0, 0.0, moAppend);
  g.RotateTransform(30, moAppend);
  g.DrawEllipse(Pens.Blue, 0, 0, 100, 50);

将产生下面的图像:

但是,我们有时需要知道变换后的图形尺寸及坐标,如果通过编程计算求得,可能很麻烦,特别是一些复杂的组合变换。利用Matrix提供的变换后的矩阵数据,可以很简单的得到变换后的图形矩形。

        Matrix提供的是一个3 X 2 仿射矩阵,上面的2 X 2 矩阵是Rotate、Scale和Shear等线性变换后的数据,分别用m11,m21,m12,m22表示,可以用x = m11 * xi+ m21 * yi,y = m21 * xi + m22 * yi求得线性变换后图形的任意一点的相对坐标,我们只要计算四个角的坐标就行了;下面一行则是平移数据,用dx,dy表示,前面计算出的坐标点分别加上dx和dy就是实际的坐标点。下面是笔者写的一个计算函数和测试代码:

function CalcTransRect(Origin: TGpRect; e: TMatrixElements): TGpRect;

  function GetTransPoint(x, y: Single): TGpPointF;
  begin
    Result.X :
= e.m11 * x + e.m21 * y;
    Result.Y :
= e.m12 * x + e.m22 * y;
  end;

  procedure GetMinMax(var AMin, AMax: Single; vs: array of Single);
  var
    I: Integer;
  begin
    AMin :
= vs[0];
    AMax :
= vs[0];
    
for I := Low(vs) to High(vs) do
    begin
      
if vs[I] < AMin then AMin := vs[I];
      
if vs[I] > AMax then AMax := vs[I];
    end;
  end;
var
  R: TGpRectF;
  B: TGpRect;
  LT, RT, LB, RB: TGpPointF;
begin
  B :
= Origin;
  
// 分别计算四个角的相对坐标
  LT := GetTransPoint(B.X, B.Y);
  RT :
= GetTransPoint(B.Width + B.X, B.Y);
  LB :
= GetTransPoint(B.X, B.Height + B.Y);
  RB :
= GetTransPoint(B.Width + B.X, B.Height + B.Y);
  
// 取得左上角和右下角的坐标点
  GetMinMax(R.X, R.Width, [LT.X, RT.X, LB.X, RB.X]);
  GetMinMax(R.Y, R.Height, [LT.Y, RT.Y, LB.Y, RB.Y]);
  
// 求出矩形尺寸
  R.Width := R.Width - R.X;
  R.Height :
= R.Height - R.Y;
  
// 求得左上角实际坐标
  R.X := R.X + e.dx;
  R.Y :
= R.Y + e.dy;

  Result.X :
= Trunc(R.X);
  Result.Y :
= Trunc(R.Y);
  Result.Width :
= Round(R.Width);
  Result.Height :
= Round(R.Height);
end;

procedure TMainForm.Button1Click(Sender: TObject);
var
  Image: TGpImage;
  g: TGpGraphics;
  m: TGpMatrix;
  r: TGpRect;
begin
  Image :
= TGpImage.Create('....Mediamsn.jpg');
  g :
= TGpGraphics.Create(Handle, False);
  m :
= TGpMatrix.Create;
  
try
    r :
= GpRect(2020, Image.Width, Image.Height);
    m.Rotate(
30);
    m.Scale(
1.80.8);
    m.Shear(
0.30.2);
    g.DrawImage(Image, r);
    g.SetTransform(m);
    g.DrawImage(Image, r);
    r :
= CalcTransRect(r, m.Elements);
    g.ResetTransform;
    g.DrawRectangle(Pens.Red, r);
  
finally
    Image.Free;
    g.Free;
    m.Free;
  end;
end;

运行结果如下图,红色的矩形是计算出的变换后的坐标,与变换后的图像完全吻合:

        还有的时候,我们需要精确控制图形的变换,比如,以图形左上角为原点缩放、以图形中心点进行旋转等。由于GDI+的几何变换是以Graphics画布原点,而不是以图形左上角为原点进行的,所以必须使用平移进行坐标变换,然后采用相对坐标画图。比如,我们希望上面的例子以画布20,20为原点(即无论怎样变换,左上角坐标不变)进行线性变换:

    g.DrawImage(Image, 2020, Image.Width, Image.Height); //用绝对坐标画原图

    m.Translate(
2020);    // 坐标转换

    m.Rotate(
30);
    m.Scale(
1.80.8);
    m.Shear(
0.30.2);
    g.SetTransform(m);
    g.DrawImage(Image, 
00, Image.Width, Image.Height);  //用相对坐标画图

其结果为下图,完全符合要求:

        说明,本文所用GDI+代码与网上流通的不兼容,如上面例子中的TMatrixElements,定义为:

  TMatrixElements = packed record
    case Integer of
      0: (Elements: array[0..5] of  Single);
      1: (m11, m12, m21, m22, dx, dy: Single);
  end;

而网上流通的则定义为一个数组:

TMatrixArray = array[0..5] of Single;

        如有错误,请来信指正:maozefa@hotmail.com




本文来源:http://blog.csdn.net/maozefa/archive/2007/07/10/1684129.aspx
站内文章搜索 高级搜索
文章录入:admin    责任编辑:admin 
  • 上一篇文章:

  • 下一篇文章:
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
     在delphi中使用xml文档有…
     初探delphi 7 中的插件编…
     delphi 2006(dexter) & …
     获得windows的版本信息。
     “序列号输入助手”源代…
     rs232串口通讯模块
     ado方式下判断数据表是否…
  • Java的网络编程(TCP/IP)

  • Ant入门-配置和使用     选…

  • 浅析Spring框架下PropertyPl…

  • jsp重定向forward和sendRedi…

  • MVP——Model-Viewer-Presen…

  • C++ Object Model

  • Solaris10下,使用SunStudio…

  • 内存管理内幕--Jonathan Bar…

  • constructor and destructor

  • delegate C#关键字 (委托类型…

  •   网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    网络学院©2007 www.23book.net
    为您提供web编程,vb编程,vc编程,服务器架设管理,数据库设计等方面的知识 站长:David