Inc(Dir,10); jak obrócić timage
TImage
w VCL nie ma własnej właściwości Angle
– aby go obracać, trzeba obracać bitmapę znajdującą się w Image.Picture.Bitmap
.TAffineTransformation
). Inc(Dir, 10);
można wykorzystać w zdarzeniu timera, a przy każdej zmianie kąta wywoływać procedurę rotacji.Dir
) wygeneruj nową bitmapę i przypisz ją do TImage
. procedure Rotate90(const Src, Dst: TBitmap; CW: Boolean = True);
var x, y: Integer;
begin
Dst.PixelFormat := pf24bit;
Dst.SetSize(Src.Height, Src.Width);
for y := 0 to Src.Height-1 do
for x := 0 to Src.Width-1 do
if CW then
Dst.Canvas.Pixels[Src.Height-1-y, x] := Src.Canvas.Pixels[x, y]
else
Dst.Canvas.Pixels[y, Src.Width-1-x] := Src.Canvas.Pixels[x, y];
end;
uses Winapi.GDIPOBJ, Vcl.Imaging.GDIPlus, System.Math;
procedure RotateGDIPlus(const Src: TBitmap; Dst: TBitmap; Angle: Single);
var G: TGPGraphics; Img: TGPImage; CX, CY: Single;
begin
Dst.SetSize(Src.Width, Src.Height); // lub większy bufor
Dst.PixelFormat := pf32bit;
G := TGPGraphics.Create(Dst.Canvas.Handle);
Img := TGPImage.Create(Src);
G.SetSmoothingMode(SmoothingModeAntiAlias);
G.SetInterpolationMode(InterpolationModeHighQualityBicubic);
CX := Src.Width / 2; CY := Src.Height / 2;
G.TranslateTransform(CX, CY);
G.RotateTransform(Angle);
G.TranslateTransform(-CX, -CY);
G.DrawImage(Img, 0, 0, Src.Width, Src.Height);
Img.Free; G.Free;
end;
uses GR32, GR32_Transforms;
procedure RotateGR32(SrcBmp: TBitmap; DstBmp: TBitmap; Angle: Single);
var Src32, Dst32: TBitmap32; Tr: TAffineTransformation;
begin
Src32 := TBitmap32.Create; Dst32 := TBitmap32.Create; Tr := TAffineTransformation.Create;
try
Src32.Assign(SrcBmp);
Tr.SrcRect := FloatRect(0, 0, Src32.Width, Src32.Height);
Tr.Rotate(0, 0, Angle * PI / 180); // Graphics32 – radiany
Dst32.SetSize(Round(Src32.Width*1.5), Round(Src32.Height*1.5));
Tr.Transform(Dst32, Src32);
DstBmp.Assign(Dst32);
finally
Src32.Free; Dst32.Free; Tr.Free;
end;
end;
Inc
)var
SrcBmp: TBitmap; // oryginał
Dir : Integer = 0; // kąt w stopniach
procedure TForm1.FormCreate(Sender: TObject);
begin
SrcBmp := TBitmap.Create;
SrcBmp.LoadFromFile('obraz.png');
Image1.Picture.Bitmap.Assign(SrcBmp);
Timer1.Interval := 40; // ≈25 FPS
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var Dst: TBitmap;
begin
Inc(Dir, 10); // <-- fragment z pytania
if Dir >= 360 then Dir := Dir - 360;
Dst := TBitmap.Create;
try
RotateGDIPlus(SrcBmp, Dst, Dir);
Image1.Picture.Bitmap.Assign(Dst);
finally
Dst.Free;
end;
end;
TImage.RotationAngle
i akceleracja GPU. InterpolationModeLowQuality
dla płynności. pf32bit
, aby zachować przezroczystość. DstBitmap
i tylko go nadpisywać. https://github.com/skia4delphi/skia4delphi
) – pełny dostęp do GPU-accelerated Canvas. Obrót TImage
w klasycznym VCL wymaga obrotu bitmapy, nie samego komponentu.
Dla kątów 90/180/270 ° – wystarczy szybka zamiana współrzędnych pikseli.
Dla dowolnych kątów:
• GDI+ – łatwość implementacji, dobra jakość, średnia wydajność.
• Graphics32/Skia – najlepsza wydajność, antyaliasing i akceleracja sprzętowa.
Kod timera z Inc(Dir, 10);
cyklicznie zwiększa kąt i wywołuje procedurę rotacji, dając płynną animację.