アルファチャンネル(透明色・半透明色)にも対応しています
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
GDIPAPI, GDIPOBJ, Math, GDIPUTIL;
procedure RotateBMP(var bmp: TGPBitmap; angle: single);
function GetRect(bmp: TGPBitmap): TGPRectF;
var
path: TGPGraphicsPath;
mtrx: TGPMatrix;
begin
path := TGPGraphicsPath.Create;
mtrx := TGPMatrix.Create;
try
path.AddRectangle(MakeRect(0, 0, bmp.GetWidth, bmp.GetHeight));
mtrx.Rotate(angle); //ワールド座標を回転
path.Transform(mtrx);
path.GetBounds(Result); //ワールド座標をページ座標に変換
finally
mtrx.Free;
path.Free;
end;
end;
var
dst: TGPBitmap;
gr: TGPGraphics;
r: TGPRectF;
begin
//回転後のページ座標のRectを取得する
r := GetRect(bmp);
//回転後のサイズでBitmapオブジェクトを作成(小数以下切上)
dst := TGPBitmap.Create(Ceil(r.Width), Ceil(r.Height), PixelFormat32bppARGB);
dst.SetResolution(96,96); //標準のDPIに設定(PNGファイル対策)
gr := TGPGraphics.Create(dst);
try
//画像がすべて収まるように中心点の座標(0,0)を移動する
gr.TranslateTransform(-r.X, -r.Y);
gr.RotateTransform(angle); //ワールド座標を回転
gr.DrawImage(bmp,0,0);
finally
gr.Free;
end;
bmp.Free;
bmp := dst;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
bmp: TGPBitmap;
LImgGUID : TGUID;
begin
bmp := TGPBitmap.Create('z:Sample.png');
bmp.SetResolution(96,96); //標準のDPIに設定(PNGファイル対策)
//図形を45°回転させる
RotateBMP(bmp, 45);
if GetEncoderClsid('image/png', LImgGUID) >= 0 then begin
bmp.Save('z:Rotate.png', LImgGUID);
end;
bmp.Free;
end;
end.
以下の変更で、拡大率の変更も可能です
gr.RotateTransform(angle: Single)
mtrx.Rotate(angle: Single)
↓
gr.ScaleTransform(scaleX, scaleY: Single)
mtrx.Scale(scaleX, scaleY: Single)
//例:mtrx.Scale(1.5,1.5) 1.5倍
//例:mtrx.Scale(1,-1) 上下反転
//例:mtrx.Scale(-1,1) 左右反転
2020.4.17 加筆 また、RotateBMP関数を以下の用に書き直せば、```gr.RotateTransform```は不要になります。
procedure RotateBMP(var bmp: TGPBitmap; angle: single);
var
mtrx: TGPMatrix;
path: TGPGraphicsPath;
dst : TGPBitmap;
gr : TGPGraphics;
r : TGPRectF;
begin
mtrx := TGPMatrix.Create;
try
mtrx.Rotate(angle); //ワールド座標を回転
// mtrx.Scale(1,-1);
path := TGPGraphicsPath.Create;
try
//回転後のページ座標のRectを取得する
path.AddRectangle(MakeRect(0, 0, bmp.GetWidth, bmp.GetHeight));
path.Transform(mtrx);
path.GetBounds(r); //ワールド座標をページ座標に変換
finally
path.Free;
end;
//回転後のサイズでBitmapオブジェクトを作成(小数以下切上)
dst := TGPBitmap.Create(Ceil(r.Width), Ceil(r.Height), PixelFormat32bppARGB);
dst.SetResolution(96,96); //標準のDPIに設定(PNGファイルの対策)
gr := TGPGraphics.Create(dst);
try
//画像がすべて収まるように中心点の座標(0,0)を移動する
gr.TranslateTransform(-r.X, -r.Y);
gr.MultiplyTransform(mtrx); //ページ座標をワールド座標に変換
gr.DrawImage(bmp,0,0);
finally
gr.Free;
end;
finally
mtrx.Free;
end;
bmp.Free;
bmp := dst;
end;