画像(TBitmap)を回転してCanvasに描画させる(VCL,FMX) ~Delphiソースコード集
VCLのTCanvasは「Direct2DCanvas」の座標変換マトリックス(行列)を使うと画像を指定座標を中心に回転描画させることが出来ます。
FMXのTCanvasは標準で使える座標変換マトリックス(行列)を使って画像を指定座標を中心に回転描画させることが出来ます。
VCLで画像回転
フォームにTImage×2個、TButton×2個をドラッグ&ドロップします。
TForm1.OnCreateとButton1.OnClick、Button2.OnClickにイベントを割り当てて以下ソースコードを記述します。
ソースコード中の「DrawRotationBitmap」メソッドを使うと「Direct2DCanvas」を使ってTBitmap画像回転描画が可能です。
procedure DrawRotationBitmap( SourceBitmap:TBitmap; DestCanvas:TCanvas; Pt:TPoint; Rotation:Single; W, H:Integer; Opacity:Byte=255);
-
- SourceBitmap:TBitmap
- 出力したいビットマップ
- DestCanvas:TCanvas
- 出力先Canvas
- Pt:TPoint
- 出力及び回転中心座標 Point(X,Y)
(例)Point(50,100) - Rotation:Single
- 回転角度(右回りが正の 度 単位)
- W, 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度回転して幅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に移動する変換行列の作成
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で出力されます。
FMXで画像回転
フォームにTImage×2個、TButton×2個をドラッグ&ドロップします。
TForm1.OnCreateとButton1.OnClick、Button2.OnClickにイベントを割り当てて以下ソースコードを記述します。
ソースコード中の「DrawRotationBitmap」メソッドを使うと「Direct2DCanvas」を使ってTBitmap画像回転描画が可能です。
procedure DrawRotationBitmap( SourceBitmap:TBitmap; DestCanvasTCanvas; Pt:TPoint; Rotation:Single; W,H:Integer; Opacity:Single=1);
-
- SourceBitmap:TBitmap
- 出力したいビットマップ
- DestCanvas:TCanvas
- 出力先Canvas
- Pt:TPoint
- 出力及び回転中心座標 Point(X,Y)
(例)Point(50,100) - Rotation:Single
- 回転角度(右回りが正の度単位)
- W, 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度回転して幅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;
//座標Ptに移動する変換行列の作成
TranslationMatrix :=
System.Math.Vectors.TMatrix.CreateTranslation(
Pt.X,Pt.Y
);
//回転角度Rotation度の変換行列の作成
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で出力されます。
