`
sogotobj
  • 浏览: 653496 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

GDI+ 在Delphi程序的应用 -- Matrix应用心得

阅读更多

关于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提供的是一个3X 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就是实际的坐标点。下面是笔者写的一个计算函数和测试代码:

functionCalcTransRect(Origin:TGpRectF;e:TMatrixElements):TGpRectF;

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

var
R:TGpRectF;
pf:array[
0..3]ofTGpPointF;
I:Integer;
begin
R:
=Origin;
//分别计算四个角的相对坐标
pf[0]:=GetTransPoint(R.X,R.Y);
pf[
1]:=GetTransPoint(R.Width+R.X,R.Y);
pf[
2]:=GetTransPoint(R.X,R.Height+R.Y);
pf[
3]:=GetTransPoint(R.Width+R.X,R.Height+R.Y);
//取得左上角和右下角的坐标点
R:=GpRect(pf[0].X,pf[0].Y,0.0,0.0);
forI:=0to3do
begin
ifR.X>pf[I].XthenR.X:=pf[I].X
elseifR.Width<pf[I].XthenR.Width:=pf[I].X;
ifR.Y>pf[I].YthenR.Y:=pf[I].Y
elseifR.Height<pf[I].YthenR.Height:=pf[I].Y;
end;
//求出矩形尺寸
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:
=R;
end;

procedureTMainForm.Button1Click(Sender:TObject);
var
Image:TGpImage;
g:TGpGraphics;
m:TGpMatrix;
r:TGpRectF;
begin
Image:
=TGpImage.Create('....Mediamsn.jpg');
g:
=TGpGraphics.Create(Handle,False);
m:
=TGpMatrix.Create;
try
r:
=GpRect(20.0,20.0,Image.Width,Image.Height);
g.Clear(ARGBFromTColor(Color));
g.DrawImage(Image,r);

m.Rotate(
30);
m.Scale(
1.8,0.8);
m.Shear(
0.3,0.2);
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,20,20,Image.Width,Image.Height);//用绝对坐标画原图

m.Translate(
20,20);//坐标转换

m.Rotate(
30);
m.Scale(
1.8,0.8);
m.Shear(
0.3,0.2);
g.SetTransform(m);
g.DrawImage(Image,
0,0,Image.Width,Image.Height); //用相对坐标画图

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

这个问题似乎很简单,但是我们忽略了一个变换顺序问题,前面所有的变换操作都是以默认顺序moPrepend进行的,如果改为moAppend是否符合我们的要求呢?答案是否!因为moPrepend是在上一个变换操作完成前进行的,也就是说无论是图形形状还是坐标位置,都是和上一变换操作同步进行的;而moAppend则是在上一变换操作完成后进行的,这时,图形形状和坐标点都已经变了,在已经改变了形状和坐标位置的基础上继续当前变换,肯定的不到我们预想的效果。下面的图是改变上面三个变换操作的顺序为moAppend后的运行结果:

为此,我们不能再用坐标变换后的相对坐标进行操作,而是需要在每个变换操作前预置坐标位置和变换操作后还原坐标位置,以便当前和后续变换都是正确的。Matrix已经提供了一个RotateAt,我们只要再写ScaleAt和ShearAt就行了,这样一来,无论操作顺序如何,变换操作位置都在我们的预期范围内。下面是这2个过程和测试代码:

procedureScaleAt(m:TGpMatrix;ScaleX,ScaleY,x,y:Single;Order:TMatrixOrder=moPrepend);
begin
iforder=moAppendthen
begin
x:
=-x;
y:
=-y;
end;
m.Translate(x,y,Order);
m.Scale(ScaleX,ScaleY,Order);
m.Translate(
-x,-y,Order);
end;

procedureShearAt(m:TGpMatrix;ShearX,ShearY,x,y:Single;Order:TMatrixOrder
=moPrepend);
begin
iforder=moAppendthen
begin
x:
=-x;
y:
=-y;
end;
m.Translate(x,y,Order);
m.Shear(ShearX,ShearY,Order);
m.Translate(
-x,-y,Order);
end;

procedureTMainForm.Button2Click(Sender:TObject);
var
Image:TGpImage;
g:TGpGraphics;
m:TGpMatrix;
begin
Image:
=TGpImage.Create('....Mediamsn.jpg');
g:
=TGpGraphics.Create(Handle,False);
m:
=TGpMatrix.Create;
try
g.DrawImage(Image,
20,20,Image.Width,Image.Height);

m.RotateAt(
30,GpPoint(20.0,20.0),moAppend);
ScaleAt(m,
1.8,0.8,20,20,moAppend);
ShearAt(m,
0.3,0.2,20,20,moAppend);

g.SetTransform(m);
g.DrawImage(Image,
20,20,Image.Width,Image.Height);
finally
Image.Free;
g.Free;
m.Free;
end;
end;

运行结果如下图,如果改为默认操作顺序,则和前面平移坐标后的运行结果完全一样:

说明,本文所用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

分享到:
评论

相关推荐

    GDI+入门指导书------经典

    GDI+入门指导书------经典 非常适合于GDI+初学者

    GDI++ for DELPHI

    GDI++ for DELPHI是一个专为DELPHI开发者设计的图形设备接口(GDI)扩展库,它提供了丰富的图形绘制功能,使开发者能够利用更高级的图形处理技术来增强应用程序的界面美观度和交互性。GDI++是基于Windows API的GDI...

    GDI+_for_VCL基础

    GDI+ for VCL基础是关于在Delphi和C++Builder中使用GDI+图形库进行图形绘制和图像处理的专题。GDI+是微软在Windows XP系统中引入的一个增强图形设备接口,它扩展了传统的GDI(Graphics Device Interface),提供了更...

    在Delphi XE10.2版本可用的GDI+库

    在Delphi XE10.2版本中,开发者可以利用GDI+库来增强图形处理功能,提升应用程序的视觉效果。GDI+是Microsoft提供的一个图形设备接口,它基于GDI(Graphics Device Interface),但提供了更多的图形绘制和图像处理...

    GDI+图像程序设计(PDF & 源码 -电子工业出版社)

    ——在GDI+ Painter应用程序中添加颜色、钢笔和画笔 总结 第5章 颜色、字体和文本 5.1 访问Graphics对象 5.2 使用颜色 5.3 使用字体 5.4 使用文本和字符串 5.5 渲染文本的质量和性能 5.6 高级版式 5.7 一个...

    Delphi使用GDI+制作任意图片形状窗口

    为了实现上述功能,我们需要在Delphi中创建一个新的VCL Forms应用程序,然后导入GDI+的相关单元。在窗体的`OnCreate`事件中初始化GDI+,在`OnPaint`事件中绘制图片和处理透明度,在`OnNCCalcSize`事件中计算并设置...

    GDI+图形程序设计.zip

    GDI+提供了丰富的绘图功能,包括二维几何图形、曲线、文本、图像以及颜色管理等,使得开发者能够创建出具有高质量视觉效果的应用程序。 这本书《GDI+程序设计》显然是一个深入探讨GDI+技术的教程,它可能包含了GDI+...

    delphi gdi+遮罩动画字

    在本文中,我们将深入探讨如何在Delphi编程环境中利用GDI+库来创建遮罩动画文字效果。Delphi是一款强大的Windows应用程序...通过不断的实践和学习,可以更好地掌握GDI+在Delphi中的应用,为应用程序增添更多视觉魅力。

    GDI+程序设计 GDI+程序设计 GDI+程序设计 GDI+程序设计

    GDI+(Graphics Device Interface Plus)是微软Windows操作系统中用于图形设备接口的增强版本,它为开发者提供了一套丰富的绘图工具,使得在Windows应用程序中创建、管理和显示图形变得更加便捷和高效。GDI+不仅继承...

    Delphi GDI+

    Delphi GDI+是Microsoft图形设备接口(GDI)的一个增强版本,专为Delphi开发者设计,用于在Windows平台上创建更高效、更丰富的图形和图像处理应用。GDI+引入了面向对象的编程模型,提供了矢量图形、位图操作、文字...

    GDI+程序设计(清华大学)

    书中不仅介绍了GDI+的基础知识,还着重讲解了如何将GDI+技术应用于实际开发中,尤其适合那些希望在应用程序中实现高级图形处理和自定义控件开发的中高级程序员。 另外,书中提到了.NET Framework对编程的变革作用,...

    gdi++实现图像压缩-图像裁剪和缩放-图像格式转换-图像dpi修改.rar

    在Windows平台上,C++开发图形应用时,GDI++(也称为GDI+)是一个强大的图形库,它提供了丰富的功能,包括图像处理、绘制、文本渲染等。本压缩包文件包含的是利用GDI++实现的一些关键图像操作,如图像压缩、图像裁剪...

    GDI+图形程序设计

    通过阅读本书,读者不仅可以掌握GDI+的基本概念,还能学会如何在实际项目中应用这些技术,提升Windows应用程序的图形表现力。 《GDI+图形程序设计》的PDF文件包含了详细的章节结构,可能包括以下内容:GDI+概述、...

    GDI+开发包 GDI+ SDK

    GDI+(Graphics Device Interface Plus)是微软推出的一种图形设备接口的增强版本,它为Windows应用程序提供了丰富的2D图形、图像处理和文本渲染能力。GDI+开发包,即GDI+ SDK,是用于帮助开发者利用GDI+功能进行...

    ( Delphi 7 )使用GDI+进行图形缩放、拖动,多种图片格式支持,仅简单示例

    使用GDI+进行图形缩放、拖动,多种图片格式支持,仅简单示例。 问题源贴:http://bbs.csdn.net/topics/390638094

    WINDOWS GDI和GDI+编程实例剖析. - READ.doc

    示例程序中,通过MFC应用程序展示了GDI和GDI+的使用。GDI菜单下的“画线”功能演示了使用GDI进行线条绘制。GDI+菜单则包含了更多的功能,如“画线”使用GDI+绘制线条,“渐变画刷”展示了GDI+的色彩渐变效果,“基数...

    GDI+开发包 GDI+安装详解

    其中,ULONG_PTR是一个DWORD数据类型,该成员变量用来保存GDI+被初始化后在应用程序中的GDI+标识,以便能在应用程序退出后,引用该标识来调用Gdiplus:: GdiplusShutdown来关闭GDI+。 (2)在应用类中添加...

    GDI+程序设计 (中文版pdf)

    《GDI+程序设计》是由Eric White撰写的一本详细介绍了GDI+在.NET框架中图形编程应用的书籍,由清华大学出版社出版。GDI+是微软公司针对.NET环境所提供的图形设备接口,它取代了之前的GDI,并引入了大量新的命名空间...

    GDI+程序设计_GDI+程序设计_

    通过GDI+,你可以创建自定义的控件,实现复杂的用户界面,或者在应用程序中添加图形输出功能。 1. **Graphics类**:这是GDI+的核心类,用于实际的绘图操作。你可以从Graphics对象上绘制线条、曲线、矩形、椭圆、...

    delphi gdi+ 必要的 pas 文件

    通过 Delphi GDI+ 的 PAS 文件,你可以实现高质量的图形用户界面,创建出具有专业视觉效果的应用程序。但需要注意的是,虽然这些非官方的 PAS 文件解决了兼容性问题,但可能没有得到官方的支持,所以在使用过程中...

Global site tag (gtag.js) - Google Analytics