LoginSignup
4
2

More than 3 years have passed since last update.

DelphiでGDI+を使って画像ファイルを回転させるサンプル

Last updated at Posted at 2020-04-14

参考元

アルファチャンネル(透明色・半透明色)にも対応しています

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;

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2