delphi – 如何在FireMonkey中将图像绘制到旋转的矩形?
在FireMonkey中,将位图绘制到源矩形很简单:
Canvas.DrawBitmap(FBitmap,ImageSrcRect,ImageDstRect,1); 我在TPaintBox的画布上做这个.我想改为绘制旋转的位图(并缩放,因为目标大小可能与源大小不同.) 特别: >我有两点 如下图所示: 左边一个是我目前可以做的;在右边是我想做的. 最好的方法是什么? 我试过的 为了保持现有代码简单(例如,绘制到目标矩形,从而缩放结果),我一直在尝试在调用现有的DrawBitmap代码之前向画布的矩阵添加旋转矩阵.例如, OldMatrix := Canvas.Matrix; // Original,to restore W := PointB.X - PointA.X; H := PointA.Y - PointB.Y; RotationMatrix := TMatrix.CreateRotation(-ArcTan2(H,W)); Canvas.SetMatrix(OldMatrix * RotationMatrix); Canvas.DrawBitmap(FImage,1); Canvas.SetMatrix(OldMatrix); 并且有几个变化与现有矩阵相乘,创建了一个全新的矩阵,包括平移和旋转等等.所有这些部分都有效:旋转角度是正确的,但我在使位置保持一致方面遇到了很多麻烦 – 例如,围绕中心点旋转(这甚至不是围绕点旋转位图的顶部,而不是围绕中心旋转.)我发现旋转的图像在底部偏移很好右边象限,但在其他三个中偏移/平移不正确,例如偏得太远,或者剪裁到两点的最左边或最顶端的X或Y位置.我不知道为什么会这样,而且就此而言,我正在寻求帮助. 细节 >德尔福10西雅图 解决方法
据我所知,主要问题是在新的旋转坐标系中找到图片角的坐标.这可以通过以下方式解决:
procedure DrawRotatedBitmap(const Canvas : TCanvas; const Bitmap : TBitmap; const PointA,PointB : TPointF; const Offset : TPointF; const Scale : Single); var OldMatrix,TranslationAlongLineMatrix,RotationMatrix,TranslationMatrix,ScaleMatrix,FinalMatrix: TMatrix; W,H : Single; SrcRect,DestRect: TRectF; Corner: TPointF; LineLength : Single; LineAngleDeg : Integer; begin OldMatrix := Canvas.Matrix; // Original,to restore try {$ifdef DRAW_HELPERS} Canvas.Fill.Color := TAlphaColorRec.Black; Canvas.DrawLine(PointA,PointB,0.5); {$endif} W := PointB.X - PointA.X; H := PointA.Y - PointB.Y; LineLength := abs(PointA.Distance(PointB)); // Looking for the middle of the task line // and the coordinates of the image left upper angle // solving the proportion width/linelength=xo/0.5requireddimensions Corner := TPointF.Create((PointB.X + PointA.X) / 2,(PointA.Y + PointB.Y) / 2);// Middle {$ifdef DRAW_HELPERS} Canvas.Stroke.Color := TAlphaColorRec.Red; Canvas.DrawEllipse(TRectF.Create(Corner,2,2),1); {$endif} Corner.X := Corner.X - Bitmap.Width / 2 * W / LineLength; Corner.Y := Corner.Y + Bitmap.Width / 2 * H / LineLength; {$ifdef DRAW_HELPERS} Canvas.Stroke.Color := TAlphaColorRec.Green; Canvas.DrawEllipse(TRectF.Create(Corner,1); {$endif} // Account for scale (if the FMX control is scaled / zoomed); translation // (the control may not be located at (0,0) in its parent form,so its canvas // is offset) and rotation ScaleMatrix := TMatrix.CreateScaling(Scale,Scale); TranslationMatrix := TMatrix.CreateTranslation(Offset.X,Offset.Y); RotationMatrix := TMatrix.CreateRotation(-ArcTan2(H,W)); TranslationAlongLineMatrix := TMatrix.CreateTranslation(Corner.X,Corner.Y); FinalMatrix := ((RotationMatrix * ScaleMatrix) * TranslationMatrix) * TranslationAlongLineMatrix; // If in the top left or top right quadrants,the image will appear // upside down. So,rotate the image 180 degrees // This is useful when the image contains text,ie is an annotation or similar,// or needs to always appear "under" the line LineAngleDeg := Round(RadToDeg(-Arctan2(H,W))); case LineAngleDeg of -180..-90,90..180 : FinalMatrix := TMatrix.CreateRotation(DegToRad(180)) * TMatrix.CreateTranslation(Bitmap.Width,0) * FinalMatrix; end; Canvas.SetMatrix(FinalMatrix); // And finally draw the bitmap DestRect := TRectF.Create(PointF(0,0),Bitmap.Width,Bitmap.Height); SrcRect := TRectF.Create(0,Bitmap.Height); {$ifdef DRAW_HELPERS} Canvas.DrawBitmap(Bitmap,SrcRect,DestRect,0.5); {$else} Canvas.DrawBitmap(Bitmap,1); {$endif} finally // Restore the original matrix Canvas.SetMatrix(OldMatrix); end; end; 有ifdef-ed画线的线条和点也可以帮助你 – 这些画线和一些有用的点(线条中心和图像左上角),这对调试很有用. 由DavidM编辑:此外,还有翻译和缩放矩阵.绘制框绘制父窗体的画布(最终),但可能不位于(0,因此需要考虑目标画布的偏移位置.此外,控件可以具有缩放,因此也需要构建到最终旋转矩阵中. 此代码经过大量编辑,无论方向/ quadrant the line angle is in如何都可以工作.也就是说,当线条完全水平或垂直时,以及在右下角的象限中,它应该工作. 一个有趣的调整是识别示例中的位图包含文本.当线条位于左上角或右上角时 – 也就是说,从其原点向上或向左或向右 – 位图显示在人眼上方.调整识别并旋转位图,使位图的“顶部”始终面向线条,位图的“底部”通常指向下方,使图像看起来正确.如果您不需要表示可识别内容的图像(例如符号,文本,标签等),则可以删除此调整 插图 具有不同的角度和缩放. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |