トップへ(mam-mam.net/)

画像(TBitmap)を回転してCanvasに描画させる(VCL,FMX) ~Delphiソースコード集

検索:

画像(TBitmap)を回転してCanvasに描画させる(VCL,FMX) ~Delphiソースコード集

VCLのTCanvasは「Direct2DCanvas」の座標変換マトリックス(行列)を使って画像を指定座標の中心を基準に回転表示させることが出来ます。
FMXのTCanvasは標準で使える座標変換マトリックス(行列)を使って画像を指定座標の中心を基準に回転表示させることが出来ます。

VCLで画像回転

フォームにTImage×2個、TButton×2個をドラッグ&ドロップします。

画像(TBitmap)を回転してCanvasに描画させる(VCL,FMX)

TForm1.OnCreateとButton1.OnClick、Button2.OnClickにイベントを割り当てて以下ソースコードを記述します。
procedure DrawRotationBitmap(SourceBitmap:TBitmap;DestCanvas:TCanvas;Pt:TPoint;Rotation:Single; W,H:Integer; Opacity:Byte=255);
が「Direct2DCanvas」を使ったTBitmap画像回転メソッドです。

SourceBitmap:TBitmap
出力したいビットマップ
DestCanvas:TCanvas
出力先Canvas
Pt:TPoint
出力及び回転中心座標 Point(X,Y)
(例)Point(50,100)
Rotation:Single
回転角度(右回りが正の度単位)
W:Integer
画像を出力する幅
H:Integer
画像を出力する高さ
Opacity:Byte
不透明度で0(透明)~255(完全に不透明)の値で指定します。
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Image2: TImage;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
uses Vcl.Direct2D, Winapi.D2D1;

//SourceBitmapビットマップをDestCanvasに座標Ptを中心として
//  時計回りにRotation度回転して座標Ptを中心に幅W,高さHで不透明度Opacityで描画する
procedure DrawRotationBitmap(SourceBitmap:TBitmap; DestCanvas:TCanvas;
  Pt:TPoint; Rotation:Single; W,H:Integer; Opacity:Byte=255);
var D2Canvas:TDirect2DCanvas;
    Pt2f:TD2DPoint2f;
    TranslationMatrix,RotationMatrix:TD2DMatrix3X2F;
begin
  Pt2f.x:=Pt.X;
  Pt2f.y:=Pt.Y;
  //Direct2Dキャンバスの作成
  D2Canvas:=TDirect2DCanvas.Create(
    DestCanvas, DestCanvas.ClipRect
  );
  //描画の開始
  D2Canvas.BeginDraw;
  //アンチエイリアス有効
  D2Canvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
  //中心点(Pt2f.x,Pt2f.y)で時計回りに20度回転に変換を設定する
  //座標Pt2fに移動する変換行列の作成
  TranslationMatrix:=TD2DMatrix3x2F.Translation(Pt2f);
  //座標Pt2f、回転角度Rotation度の変換行列の作成
  RotationMatrix:=TD2DMatrix3x2F.Rotation(Rotation,Pt2f);
  //移動と回転の変換行列を掛けた変換行列を作成
  TranslationMatrix:=TranslationMatrix*RotationMatrix;
  //Direct2DCanvasに変換行列を適用する
  D2Canvas.RenderTarget.SetTransform(TranslationMatrix);

  //SourceBitmapの描画を行う
  D2Canvas.StretchDraw(
    Rect(-W div 2, -H div 2, W div 2, H div 2),
    SourceBitmap,
    Opacity //不透明度(0~255)
  );
  //Direct2DCanvasの変換行列を元に戻す
  D2Canvas.RenderTarget.SetTransform(TD2DMatrix3x2F.Identity);
  //描画の終了
  D2Canvas.EndDraw;
  //Direct2Dキャンバスの破棄
  D2Canvas.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  //Image2.Bitmapを右20度回転して、
  //サイズ(50,25)で不透明度100でImage1.Bitmap.Canvasに座標(150,100)を中心として描画する
  DrawRotationBitmap(
    Image2.Picture.Bitmap, Image1.Picture.Bitmap.Canvas,
    Point(150,100), 20, 50,25, 100
  );
  Image1.Refresh;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  //Image2.Bitmapを右20度回転して、
  //サイズ(50,25)で不透明度100でForm1.Canvasに座標(150,250)を中心として描画する
  DrawRotationBitmap(
    Image2.Picture.Bitmap, Form1.Canvas,
    Point(150,250), 20, 50,25, 100
  );
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Width:=300;
  Image1.Height:=200;
  Image1.Picture.Bitmap.SetSize(300,200);
  Image1.Picture.Bitmap.Canvas.Brush.Color:=clWhite;
  Image1.Picture.Bitmap.Canvas.FillRect(Rect(0,0,300,200));
  Image1.Picture.Bitmap.Canvas.Pen.Color:=clRed;
  Image1.Picture.Bitmap.Canvas.MoveTo(0,100);
  Image1.Picture.Bitmap.Canvas.LineTo(300,100);
  Image1.Picture.Bitmap.Canvas.MoveTo(150,0);
  Image1.Picture.Bitmap.Canvas.LineTo(150,200);

  Image2.Width:=100;
  Image2.Height:=50;
  Image2.Picture.Bitmap.SetSize(100,50);
  Image2.Picture.Bitmap.Canvas.Brush.Color:=clBlue;
  Image2.Picture.Bitmap.Canvas.FillRect(Rect(0,0,100,50));
end;

end.

「Button1」をクリックすると「Image2」の画像が「Image1」の座標(X=150,Y=100)を中心に右20度回転して幅50px、高さ25pxで不透明度100÷255で出力されます。
「Button2」をクリックすると「Image2」の画像が「Form1」の座標(X=150,Y=250)を中心に右20度回転して幅50px、高さ25pxで不透明度100÷255で出力されます。

画像(TBitmap)を回転してCanvasに描画させる(VCL)

FMXで画像回転

フォームにTImage×2個、TButton×2個をドラッグ&ドロップします。

画像(TBitmap)を回転してCanvasに描画させる(FMX)

TForm1.OnCreateとButton1.OnClick、Button2.OnClickにイベントを割り当てて以下ソースコードを記述します。
procedure DrawRotationBitmap(SourceBitmap:TBitmap;DestCanvas:TCanvas;Pt:TPoint;Rotation:Single; W,H:Integer; Opacity:Single=1);
が「Direct2DCanvas」を使ったTBitmap画像回転メソッドです。

SourceBitmap:TBitmap
出力したいビットマップ
DestCanvas:TCanvas
出力先Canvas
Pt:TPoint
出力及び回転中心座標 Point(X,Y)
(例)Point(50,100)
Rotation:Single
回転角度(右回りが正の度単位)
W:Integer
画像を出力する幅
H:Integer
画像を出力する高さ
Opacity:Single
不透明度で0.0(透明)~1.0(完全に不透明)の値で指定します。

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.Controls.Presentation, FMX.StdCtrls, FMX.Objects;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Image2: TImage;
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { private 宣言 }
  public
    { public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

uses System.Math.Vectors;

//SourceBitmapビットマップをDestCanvasに座標Ptを中心として
//  時計回りにRotation度回転して座標Ptを中心に幅W,高さHで不透明度Opacityで描画する
procedure DrawRotationBitmap(SourceBitmap:TBitmap; DestCanvas:TCanvas;
  Pt:TPointF; Rotation:Single; W,H:Integer; Opacity:Single=1);
var Matrix,TranslationMatrix,RotationMatrix:TMatrix;
begin
  DestCanvas.BeginScene();
  Matrix:=DestCanvas.Matrix;
  TranslationMatrix :=
    System.Math.Vectors.TMatrix.CreateTranslation(
      Pt.X,Pt.Y
    );
  RotationMatrix:=
    System.Math.Vectors.TMatrix.CreateRotation(
      Rotation*Pi/180
    );
  DestCanvas.SetMatrix(RotationMatrix*TranslationMatrix);
  DestCanvas.DrawBitmap(
    SourceBitmap,
    RectF(0,0,SourceBitmap.Width,SourceBitmap.Height),
    RectF(-W/2,-H/2,W/2,H/2),
    Opacity
  );
  DestCanvas.SetMatrix(Matrix);
  DestCanvas.EndScene;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  //Image2.Bitmapを右20度回転して、
  //サイズ(50,25)で不透明度0.7でImage1.Bitmap.Canvasに座標(150,100)を中心として描画する
  DrawRotationBitmap(
    Image2.Bitmap, Image1.Bitmap.Canvas,
    PointF(150,100), 20, 50,25, 0.7
  );
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  //Image2.Bitmapを右20度回転して、
  //サイズ(50,25)で不透明度0.7でForm1.Canvasに座標(150,250)を中心として描画する
  DrawRotationBitmap(
    Image2.Bitmap, Form1.Canvas,
    PointF(150,250), 20, 50,25, 0.7
  );
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Width:=300;
  Image1.Height:=200;
  Image1.Bitmap.SetSize(300,200);
  Image1.Bitmap.Canvas.BeginScene();
  Image1.Bitmap.Canvas.Fill.Color:=TAlphaColorRec.White;
  Image1.Bitmap.Canvas.FillRect(RectF(0,0,300,200),0,0,[],1);
  Image1.Bitmap.Canvas.Stroke.Color:=TAlphaColorRec.Red;
  Image1.Bitmap.Canvas.DrawLine(PointF(0,100),PointF(300,100),1);
  Image1.Bitmap.Canvas.DrawLine(PointF(150,0),PointF(150,200),1);
  Image1.Bitmap.Canvas.EndScene;

  Image2.Width:=100;
  Image2.Height:=50;
  Image2.Bitmap.SetSize(100,50);
  Image2.Bitmap.Canvas.BeginScene();
  Image2.Bitmap.Canvas.Fill.Color:=TAlphaColorRec.Blue;
  Image2.Bitmap.Canvas.FillRect(RectF(0,0,100,50),0,0,[],1);
  Image2.Bitmap.Canvas.EndScene;
end;

end.

「Button1」をクリックすると「Image2」の画像が「Image1」の座標(X=150,Y=100)を中心に右20度回転して幅50px、高さ25pxで不透明度0.7で出力されます。
「Button2」をクリックすると「Image2」の画像が「Form1」の座標(X=150,Y=250)を中心に右20度回転して幅50px、高さ25pxで不透明度0.7で出力されます。

画像(TBitmap)を回転してCanvasに描画させる(FMX)