在调用Canvas.DrawBitmap之前对位图应用变换(Firemonkey)

3

下午好。

我正在开发一个绘图程序,允许用户在画布上拖放带有位图的TImage。(在RAD Studio XE2中的Firemonkey HD应用程序中)然后用户可以在保存图像之前更改x和y比例尺和旋转角度。所有的TImage都保存在列表中,然后使用这个简单的方法将此列表写入底层画布:

  for i := 0 to DroppedList.Count - 1 do
  begin
    AImage := DroppedList[i];
    SourceRect.Left := 0;
    SourceRect.Right := AImage.Bitmap.Width;
    SourceRect.Top := 0;
    Sourcerect.Bottom := AImage.Bitmap.Height;

    TargetRect.Left := AImage.Position.X;
    TargetRect.Right := AImage.Position.X + AImage.Bitmap.Width;
    TargetRect.Top := AImage.Position.Y;
    TargetRect.Bottom := AImage.Position.Y + AImage.Bitmap.Height;

    with FImage.Bitmap do
    begin
      Canvas.BeginScene;
      Canvas.DrawBitmap(AImage.Bitmap, SourceRect, TargetRect, 1, True);
      Canvas.EndScene;
      BitmapChanged
    end;
  end;

  FImage.Bitmap.SaveToFile('test.bmp');

这个问题在于DrawBitmap不能考虑窗口中可见的图像的缩放和旋转变换,在保存时会丢失。我正在寻找一种在将位图绘制到背景之前应用变换的方法。我无法找到任何关于此的信息,所以希望这里有人能够帮助。谢谢,Daniël。

1
你的代码并没有执行任何变换或旋转操作,只是将每个位图复制到不同的X、Y位置。你在应用程序的其他地方如何执行变换操作?你能重用那段代码吗?你需要一个图像处理库来实现你想要的效果吗? - Mike Sutton
1个回答

2
问题似乎在于缩放和旋转应用于源TImage。在这个“源TImage”中,变换不是针对位图而是在TImage级别上进行的(因为它是TControl,像所有TControl一样可以缩放和旋转)。稍后,您将源位图复制到其他地方,但实际上该位图从未更改。
所以必须根据源TImage中的设置在循环中旋转和缩放位图:
with FImage.Bitmap do
begin
  Canvas.BeginScene;     
  LBmp := TBitmap.Create;
  try
    // create a copy on which transformations will be applyed
    LBmp.Assign(AImage.Bitmap); 
    // rotate the local bmp copy according to the source TImage.
    if AImage.RotationAngle <> 0 then
      LBmp.Rotate( AImage.RotationAngle);
    // scale the local bmp copy...
    If AImage.Scale.X <> 1 
      then ;
    Canvas.DrawBitmap(LBmp, SourceRect, TargetRect, 1, True);
  finally
    LBmp.Free;
    Canvas.EndScene;
    BitmapChanged
  end;
end;

这个简单的代码示例很好地解释了问题。例如,RotatationAngle是AImage的属性,而不是AImage.Bitmap的属性。
避免实现变换的一种解决方法是使用TControl.MakeScreenshot()。(需要验证,可能会失败)
with FImage.Bitmap do
begin
  Canvas.BeginScene;
  LBmpInclTranformations := AImage.MakeScreenShot;
  Canvas.DrawBitmap(LBmpInclTranformations, SourceRect, TargetRect, 1, True);
  Canvas.EndScene;
  BitmapChanged
end;

嗨az01。 感谢您的帮助。现在一切都正常了。 如果其他人遇到这个问题: 您应该按照az01所述将旋转应用于BMP,并通过缩放TargetRect来缩放位图。 - Daniel
@Daniel,如果你认同这篇文章,请接受此回答。你也可以通过点击投票数上方的向上箭头来为该文章点赞;-) - TLama

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接