在Delphi中旋转TImage

Ave*_*oes 2 delphi image-processing rotation

我只是为了一个有趣的虚拟桌面与朋友一起玩Magic The Gathering.我正在使用Delphi 2010.这些卡在应用程序中由TImage组件表示(加载从数据库加载的卡的PNG文件).这里的要点是,在MTG中,一个非常常见的事情是点击一张卡片(向右旋转90度).有一个简单的方法可以做到这一点?我真的不需要"动画",只需点击一次旋转的卡片(虽然动画会很好).游戏应该与许多卡同时工作,它们可以移动到表单中的任何位置.我正在考虑在数据库中轻拍和未打开卡片的图像,但如果有一种漂亮而有效的方式来旋转卡片,这可能是一种过度杀伤力.

有任何想法吗?

TLa*_*ama 6

或者你可以离开TImage并使用eg TPaintBox和GDI +库.GDI + RotateFlip直接用这个方法.使用GDI+ Library for Delphi它看起来像:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ActiveX, GDIPOBJ, GDIPAPI;

type
  TForm1 = class(TForm)
    Button1: TButton;
    PaintBox1: TPaintBox;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure PaintBox1Paint(Sender: TObject);
  private
    FImage: TGPImage;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  Stream: IStream;
  BlobStream: TMemoryStream;
begin
  BlobStream := TMemoryStream.Create;
  try
    // assuming the BlobStream here has a valid image loaded from a database
    Stream := TStreamAdapter.Create(BlobStream);
    FImage := TGPImage.Create(Stream);
  finally
    BlobStream.Free;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FImage.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  FImage.RotateFlip(Rotate90FlipNone);
  PaintBox1.Invalidate;
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  with TGPGraphics.Create(PaintBox1.Canvas.Handle) do
  try
    DrawImage(FImage, 0, 0);
  finally
    Free;
  end;
end;

end.
Run Code Online (Sandbox Code Playgroud)

这样的矫枉过正,不是吗? - ?


Uli*_*rdt 5

您可以使用TPaintBox而不是TImage,并使用带旋转矩阵的SetWorldTransform来绘制抽头卡.我使用StretchDrawRotated:

procedure XForm_SetRotation(out AXForm: TXForm; AAngle: Extended; ACenter: TPoint);
var
  SinA, CosA: Extended;
begin
  SinCos(AAngle, SinA, CosA);
  AXForm.eM11 := CosA;
  AXForm.eM12 := SinA;
  AXForm.eM21 := -SinA;
  AXForm.eM22 := CosA;
  AXForm.eDx := (ACenter.X - (CosA * ACenter.X)) + ((SinA * ACenter.Y));
  AXForm.eDy := (ACenter.Y - (SinA * ACenter.X)) - ((CosA * ACenter.Y));
end;

procedure StretchDrawRotated(ACanvas: TCanvas; const ARect: TRect; AAngle: Extended; ACenter: TPoint; AGraphic: TGraphic);
var
  XForm, XFormOld: TXForm;
  GMode: Integer;
begin
  GMode := SetGraphicsMode(ACanvas.Handle, GM_ADVANCED);
  try
    if GetWorldTransform(ACanvas.Handle, XFormOld) then
      try
        XForm_SetRotation(XForm, AAngle, ACenter);
        SetWorldTransform(ACanvas.Handle, XForm);
        ACanvas.StretchDraw(ARect, AGraphic);
      finally
        SetWorldTransform(ACanvas.Handle, XFormOld);
      end;
  finally
    SetGraphicsMode(ACanvas.Handle, GMode);
  end;
end;
Run Code Online (Sandbox Code Playgroud)


Sti*_*ers 5

这种做法的老方法是使用PlgBlt.

procedure RotateBitmap90CW(b1,b2:TBitmap);
var
  x,y:integer;
  p:array[0..2] of TPoint;
begin
  x:=b1.Width;
  y:=b1.Height;
  b2.Width:=y;
  b2.Height:=x;
  p[0].X:=y;
  p[0].Y:=0;
  p[1].X:=y;
  p[1].Y:=x;
  p[2].X:=0;
  p[2].Y:=0;
  PlgBlt(b2.Canvas.Handle,p,b1.Canvas.Handle,0,0,x,y,0,0,0);
end;
Run Code Online (Sandbox Code Playgroud)

  • 我建议您将卡位图传递为b1,并将您创建的临时TBitmap实例仅用于调用此过程,然后使用它在目标Canvas上绘制.您还可以稍微更改过程以接受画布句柄和目标坐标以直接传递到PlgBlt. (2认同)