Rotate a TBitmap Image and Draw It on a Canvas (VCL & FMX) – Delphi Source Code Examples
In VCL, you can rotate and draw an image around any specified center point by using the coordinate transformation matrix (Direct2DCanvas matrix) of TCanvas.
In FMX, you can rotate and draw an image around any specified center point using the built‑in coordinate transformation matrix available in TCanvas.
Rotate an Image in VCL
Drag and drop two TImage components and two TButton components onto the form.
Assign event handlers to TForm1.OnCreate, Button1.OnClick, and Button2.OnClick, then enter the source code shown below.
By using the DrawRotationBitmap method in the code, you can rotate and draw a TBitmap image using Direct2DCanvas.
procedure DrawRotationBitmap( SourceBitmap:TBitmap; DestCanvas:TCanvas; Pt:TPoint; Rotation:Single; W, H:Integer; Opacity:Byte=255);
-
- SourceBitmap: TBitmap
- The bitmap to be drawn.
- DestCanvas: TCanvas
- The destination canvas where the bitmap will be drawn.
- Pt: TPoint
-
The drawing position and the center point of rotation.
Point(X, Y)
(Example) Point(50, 100) - Rotation: Single
- The rotation angle in degrees (clockwise is positive).
- W, H: Integer
- The width and height of the output image.
- Opacity: Byte
- Opacity value. 0 = transparent, 255 = fully opaque.
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;
// Draw SourceBitmap onto DestCanvas,
// rotated clockwise by Rotation degrees around Pt,
// with output size (W, H) and opacity (0–255).
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;
// Create a Direct2D canvas
D2Canvas := TDirect2DCanvas.Create(
DestCanvas, DestCanvas.ClipRect
);
// Begin drawing
D2Canvas.BeginDraw;
// Enable anti-aliasing
D2Canvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
// Create a translation matrix that moves to Pt2f
TranslationMatrix := TD2DMatrix3x2F.Translation(Pt2f);
// Create a rotation matrix with center Pt2f and angle Rotation
RotationMatrix := TD2DMatrix3x2F.Rotation(Rotation, Pt2f);
// Combine translation and rotation matrices
TranslationMatrix := TranslationMatrix * RotationMatrix;
// Apply the transform to the Direct2D canvas
D2Canvas.RenderTarget.SetTransform(TranslationMatrix);
// Draw the SourceBitmap
D2Canvas.StretchDraw(
Rect(-W div 2, -H div 2, W div 2, H div 2),
SourceBitmap,
Opacity // opacity (0–255)
);
// Reset the transform
D2Canvas.RenderTarget.SetTransform(TD2DMatrix3x2F.Identity);
// End drawing
D2Canvas.EndDraw;
// Free the Direct2D canvas
D2Canvas.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// Rotate Image2.Bitmap by 20 degrees clockwise,
// draw it at size (50,25) with opacity 100,
// centered at (150,100) on Image1.Bitmap.Canvas.
DrawRotationBitmap(
Image2.Picture.Bitmap, Image1.Picture.Bitmap.Canvas,
Point(150,100), 20, 50,25, 100
);
Image1.Refresh;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
// Rotate Image2.Bitmap by 20 degrees clockwise,
// draw it at size (50,25) with opacity 100,
// centered at (150,250) on Form1.Canvas.
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.
When you click "Button1", the image in "Image2" is rotated 20 degrees clockwise around the point (X=150, Y=100) on "Image1", then drawn at a size of 50×25 pixels with an opacity of 100/255.
When you click "Button2", the image in "Image2" is rotated 20 degrees clockwise around the point (X=150, Y=250) on "Form1", then drawn at a size of 50×25 pixels with an opacity of 100/255.
Rotate an Image in FMX
Drag and drop two TImage components and two TButton components onto the form.
Assign event handlers to TForm1.OnCreate, Button1.OnClick, and Button2.OnClick, then enter the source code shown below.
By using the DrawRotationBitmap method in the code, you can rotate and draw a TBitmap image in FMX by applying a transformation matrix through TCanvas.SetMatrix.
procedure DrawRotationBitmap( SourceBitmap:TBitmap; DestCanvas:TCanvas; Pt:TPoint; Rotation:Single; W,H:Integer; Opacity:Single=1);
-
- SourceBitmap: TBitmap
- The bitmap to be drawn.
- DestCanvas: TCanvas
- The destination canvas where the bitmap will be rendered.
- Pt: TPoint
-
The drawing position and the center point of rotation.
Point(X, Y)
(Example) Point(50, 100) - Rotation: Single
- The rotation angle in degrees (clockwise is positive).
- W, H: Integer
- The width and height of the output image.
- Opacity: Single
- Opacity value from 0.0 (transparent) to 1.0 (fully opaque).
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;
// Draw SourceBitmap onto DestCanvas,
// rotated clockwise by Rotation degrees around Pt,
// with output size (W, H) and opacity (0.0–1.0).
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;
// Create a translation matrix that moves to Pt
TranslationMatrix :=
System.Math.Vectors.TMatrix.CreateTranslation(
Pt.X, Pt.Y
);
// Create a rotation matrix for Rotation degrees
RotationMatrix :=
System.Math.Vectors.TMatrix.CreateRotation(
Rotation * Pi / 180
);
// Apply the combined rotation and translation matrix
DestCanvas.SetMatrix(RotationMatrix * TranslationMatrix);
DestCanvas.DrawBitmap(
SourceBitmap,
RectF(0,0,SourceBitmap.Width,SourceBitmap.Height),
RectF(-W/2, -H/2, W/2, H/2),
Opacity
);
// Restore the original matrix
DestCanvas.SetMatrix(Matrix);
DestCanvas.EndScene;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// Rotate Image2.Bitmap by 20 degrees clockwise,
// draw it at size (50,25) with opacity 0.7,
// centered at (150,100) on Image1.Bitmap.Canvas.
DrawRotationBitmap(
Image2.Bitmap, Image1.Bitmap.Canvas,
PointF(150,100), 20, 50,25, 0.7
);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
// Rotate Image2.Bitmap by 20 degrees clockwise,
// draw it at size (50,25) with opacity 0.7,
// centered at (150,250) on Form1.Canvas.
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.
When you click "Button1", the image in "Image2" is rotated 20 degrees clockwise around the point (X=150, Y=100) on "Image1", then drawn at a size of 50×25 pixels with an opacity of 0.7.
When you click "Button2", the image in "Image2" is rotated 20 degrees clockwise around the point (X=150, Y=250) on "Form1", then drawn at a size of 50×25 pixels with an opacity of 0.7.
