画像(TBitmap)を回転してCanvasに描画させる(VCL,FMX) ~Delphiソースコード集
VCLのTCanvasは「Direct2DCanvas」の座標変換マトリックス(行列)を使って画像を指定座標の中心を基準に回転表示させることが出来ます。
FMXのTCanvasは標準で使える座標変換マトリックス(行列)を使って画像を指定座標の中心を基準に回転表示させることが出来ます。
VCLで画像回転
フォームにTImage×2個、TButton×2個をドラッグ&ドロップします。
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で出力されます。
FMXで画像回転
フォームにTImage×2個、TButton×2個をドラッグ&ドロップします。
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で出力されます。