Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2012年12月14日] [更新 2012年12月14日] GDI+ 関係サンプル
   
GDI+ 関係サンプル 
G100_TGPMatrix による座標変換
動作確認等 Windows 7 U64(SP1) + Delphi XE(UP1) Pro
G100_GDIPlus_TGPMatrix.zip [3,705 KB] 2012年12月14日版 (EXE 同梱)







TGPMatrix による座標変換


TGPMatrix クラスは,3 行 3 列のマトリックス (行列) を扱うクラスです.座標値に対して次のような演算を実行します.1 列目は X 座標値に対する,2 列目は Y 座標値に対する変換で,3 列目はダミーの列です.
第 3 行目を追加することにより,座標値の線形変換と平行移動を組み合わせたアフィン変換を可能にしています.そのために第 3 例目が追加されています.
  
例えば,RotateAt 関数は,回転中心座標を指定しての回転ができますが,内部では次のような演算を実行していることになります.ここで,θは回転角度で,Xc, Yc が回転の中心座標値です.
 
TGPMatrix では,複数の行列に対して同時に演算させることもできますが,注意が必要です.線形代数を学習された方にとっては,既知のことですが,行列 A, B があった場合,A * B と B * A の結果は特別な行例でない限り違います.

このページのサンプルは,行列の要素ごとのサンプルとなっていますが,実際にはこれらを組み合わせて使用することになるでしょう.
行列の要素の代入は,SetElements 関数で行います.行列の要素は,3 X 3 ですが,1 列目と 2 列目だけを代入します.1, 2, 3 行目の順にセットします.





01_TGPMatrix による平行移動


次の行列の演算をして,描画位置の座標を移動するサンプルです.
  


図1
設計時画面
図2
実行開始画面
図3
X 軸方向への移動例
図4
Y 軸方向への移動例
図5
X 軸と Y 軸方向の移動例

リスト1
TGPMatrix による平行移動
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ, ComCtrls;

type
  TMyPanel = class(TPanel)
  private
    FXValue : Single;
    FYValue : Single;
    procedure SetXValue(const Value: Single);
    procedure SetYValue(const Value: Single);
  protected
    procedure Paint; override;
  public
    constructor Create(AOwner: TComponent); override;
    property XValue : Single read FXValue write SetXValue;
    property YValue : Single read FYValue write SetYValue;
  end;

  TForm1 = class(TForm)
    TrackBar1: TTrackBar;
    TrackBar2: TTrackBar;
    Label1: TLabel;
    Label2: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure TrackBar1Change(Sender: TObject);
    procedure TrackBar2Change(Sender: TObject);
  private
    { Private 宣言 }
    MyPanel : TMyPanel;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  Caption := 'GDI+  TGPMatrix 平行移動';

  //描画するコントロールを生成
  MyPanel := TMyPanel.Create(Self);
  with MyPanel do begin
    Parent := Self;
    SetBounds(5, 70, Self.ClientWidth - 10, Self.ClientHeight - 75);
    DoubleBuffered   := True;
    ControlStyle     := MyPanel.ControlStyle + [csOpaque];
    BevelOuter       := bvNone;
    Visible          := True;
    Color            := clWhite;
    ParentBackground := False;
    Anchors          := [akLeft, akTop, akRight, akBottom];
  end;

  //水平方向への移動量
  with TrackBar1 do begin
    ShowSelRange := False;
    TickStyle    := tsNone;
    Height   := 26;
    Min      := -200;
    Max      := 200;
    Position := 0;
  end;

  //垂直方向への移動量
  with TrackBar2 do begin
    ShowSelRange := False;
    TickStyle    := tsNone;
    Height   := 26;
    Min      := -200;
    Max      := 200;
    Position := 0;
  end;
end;

//=============================================================================
//  TrackBar1のOnClickイベント処理
//  X軸方向の移動量
//=============================================================================
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
  if not Assigned(MyPanel) then exit;
  MyPanel.XValue := TrackBar1.Position;
end;

//=============================================================================
//  TrackBar2のOnClickイベント処理
//  Y軸方向の移動量
//=============================================================================
procedure TForm1.TrackBar2Change(Sender: TObject);
begin
  if not Assigned(MyPanel) then exit;
  MyPanel.YValue :=  TrackBar2.Position;
end;

{ TMyPanel }

//-----------------------------------------------------------------------------
//  コンストラクタ
//  各種プロパティの初期化
//-----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
  inherited;

  FXValue := 0.0;
  FYValue := 0.0;
end;

//-----------------------------------------------------------------------------
//  XValueプロパティ設定用メソッド
//  X軸方向の移動量
//-----------------------------------------------------------------------------
procedure TMyPanel.SetXValue(const Value: Single);
begin
  if not Assigned(Parent) then exit;

  if FXValue <> Value then begin
     FXValue := Value;
     Invalidate;
  end;
end;

//-----------------------------------------------------------------------------
//  YValueプロパティ設定用メソッド
//  Y軸方向の移動量
//-----------------------------------------------------------------------------
procedure TMyPanel.SetYValue(const Value: Single);
begin
  if not Assigned(Parent) then exit;

  if FYValue <> Value then begin
     FYValue := Value;
     Invalidate;
  end;
end;

//-----------------------------------------------------------------------------
//  TMyPanelクラスのPaintメソッド
//  実際の描画コード
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
  LObjWidth     : Integer;
  LObjHeight    : Integer;
  LObjRect      : TGPRect;
  LXLocation    : Integer;
  LYLocation    : Integer;
  LGPGraphic    : TGPGraphics;
  LGPBrush      : TGPHatchBrush;
  LGPFontFamily : TGPFontFamily;
  LGPStrFormat  : TGPStringFormat;
  LGPPath       : TGPGraphicsPath;
  LGPMatrix     : TGPMatrix;
  LGPPen        : TGPPen;
  LColor        : Cardinal;
begin
  inherited;

  //描画する四角形と楕円の領域とサイズ
  LObjWidth  := 130;
  LObjHeight := 100;
  LObjRect   := MakeRect(0, 0, LObjWidth, LObjHeight);

  //座標原点位置の値
  LXLocation := Width  div 2;
  LYLocation := Height div 2;

  //このTMyPanelのCanvasを描画先にしてTGPGraphicsのインスタンスを生成
  LGPGraphic := TGPGraphics.Create(Canvas.Handle);

  //座標の原点を (FXLocation, FYLocation) に移動する
  LGPGraphic.TranslateTransform(LXLocation, LYLocation);

  //ブラシを生成
  LColor   := ColorRefToARGB($804000);
 LGPPen   := TGPPen.Create(LColor, 1);
 LGPBrush := TGPHatchBrush.Create(HatchStyle30Percent, aclWhite, LColor);

 //文字列の書式等を設定
  LGPFontFamily := TGPFontFamily.Create('Arial Black');
 LGPStrFormat  := TGPStringFormat.Create;
 LGPStrFormat.SetAlignment(StringAlignmentCenter);
 LGPStrFormat.SetLineAlignment(StringAlignmentCenter);

 //パスを生成して四角形と楕円と文字列を追加
 LGPPath := TGPGraphicsPath.Create;
 LGPPath.AddRectangle(LObjRect);
 LGPPath.AddEllipse(LObjRect);
 LGPPath.AddString('DELPHI',
                    -1,
                    LGPFontFamily,
                    FontStyleRegular,
                    25,
                    LObjRect,
                    LGPStrFormat);


 //TGPMatrixを生成して要素を代入
  LGPMatrix := TGPMatrix.Create;
 LGPMatrix.SetElements(1.0, 0.0,
              0.0, 1.0,
              FXValue, FYValue);
  //マトリックスの情報をパスに渡して,パスを描画
 LGPPath.Transform(LGPMatrix);
 LGPGraphic.FillPath(LGPBrush, LGPPath);
 LGPGraphic.DrawPath(LGPPen, LGPPath);


  //座標原点を交差する座標軸を描く
  LGPPen.SetColor(aclBlack);
  LGPPen.SetWidth(1.0);
  LGPPen.SetDashStyle(DashStyleDash);
  LGPGraphic.DrawLine(LGPPen, 0, -LYLocation, 0, LYLocation);
  LGPGraphic.DrawLine(LGPPen, -LXLocation, 0, LXLocation, 0);

  //Createしたオブジェクトは解放する
  LGPGraphic.Free;
  LGPBrush.Free;
  LGPFontFamily.Free;
  LGPStrFormat.Free;
  LGPPath.Free;
  LGPMatrix.Free;
  LGPPen.Free;
end;

end.




02_TGPMatrix による軸方向の倍率


次のマトリックスを使用して,X 軸方向と Y 軸方向の倍率を変更するサンプルです.
  


図6
設計時画面
図7
実行開始画面
図8
実行結果例

リスト2
TGPMatrix による軸方向の倍率
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ, ComCtrls;

type
  TMyPanel = class(TPanel)
  private
    FXScale : Single;
    FYScale : Single;
    procedure SetXScale(const Value: Single);
    procedure SetYScale(const Value: Single);
  protected
    procedure Paint; override;
  public
    constructor Create(AOwner: TComponent); override;
    property XScale : Single read FXScale write SetXScale;
    property YScale : Single read FYScale write SetYScale;
  end;

  TForm1 = class(TForm)
    TrackBar1: TTrackBar;
    TrackBar2: TTrackBar;
    Label1: TLabel;
    Label2: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure TrackBar1Change(Sender: TObject);
    procedure TrackBar2Change(Sender: TObject);
  private
    { Private 宣言 }
    MyPanel : TMyPanel;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  Caption := 'GDI+  TGPMatrix  X 軸と Y 軸方向の倍率';

  //描画するコントロールを生成
  MyPanel := TMyPanel.Create(Self);
  with MyPanel do begin
    Parent := Self;
    SetBounds(5, 70, Self.ClientWidth - 10, Self.ClientHeight - 75);
    DoubleBuffered   := True;
    ControlStyle     := MyPanel.ControlStyle + [csOpaque];
    BevelOuter       := bvNone;
    Visible          := True;
    Color            := clWhite;
    ParentBackground := False;
    Anchors          := [akLeft, akTop, akRight, akBottom];
  end;

  //X軸方向の倍率設定用
  //-3.0~3.0とするために100倍の値としている
  with TrackBar1 do begin
    ShowSelRange := False;
    TickStyle    := tsNone;
    Height   := 26;
    Min      := -300;
    Max      := 300;
    Position := 100;
  end;

  //Y軸方向の倍率設定用
  //-3.0~3.0とするために100倍の値としている
  with TrackBar2 do begin
    ShowSelRange := False;
    TickStyle    := tsNone;
    Height   := 26;
    Min      := -300;
    Max      := 300;
    Position := 100;
  end;
end;

//=============================================================================
//  TrackBar1のOnClickイベント処理
//  X軸方向の倍率の設定
//=============================================================================
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
  if not Assigned(MyPanel) then exit;
  MyPanel.XScale := TrackBar1.Position / 100.0;
end;

//=============================================================================
//  TrackBar2のOnClickイベント処理
//  Y軸方向の倍率の設定
//=============================================================================
procedure TForm1.TrackBar2Change(Sender: TObject);
begin
  if not Assigned(MyPanel) then exit;
  MyPanel.YScale :=  TrackBar2.Position / 100.0;
end;

{ TMyPanel }

//-----------------------------------------------------------------------------
//  コンストラクタ
//  各種プロパティの初期化
//-----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
  inherited;

  FXScale := 0.0;
  FYScale := 0.0;
end;

//-----------------------------------------------------------------------------
//  XScaleプロパティ設定用メソッド
//  X軸方向の倍率の設定
//-----------------------------------------------------------------------------
procedure TMyPanel.SetXScale(const Value: Single);
begin
  if not Assigned(Parent) then exit;

  if FXScale <> Value then begin
     FXScale := Value;
     Invalidate;
  end;
end;

//-----------------------------------------------------------------------------
//  YScaleプロパティ設定用メソッド
//  Y軸方向の倍率の設定
//-----------------------------------------------------------------------------
procedure TMyPanel.SetYScale(const Value: Single);
begin
  if not Assigned(Parent) then exit;

  if FYScale <> Value then begin
     FYScale := Value;
     Invalidate;
  end;
end;

//-----------------------------------------------------------------------------
//  TMyPanelクラスのPaintメソッド
//  実際の描画コード
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
  LObjWidth     : Integer;
  LObjHeight    : Integer;
  LObjRect      : TGPRect;
  LXLocation    : Integer;
  LYLocation    : Integer;
  LGPGraphic    : TGPGraphics;
  LGPBrush      : TGPHatchBrush;
  LGPFontFamily : TGPFontFamily;
  LGPStrFormat  : TGPStringFormat;
  LGPPath       : TGPGraphicsPath;
  LGPMatrix     : TGPMatrix;
  LGPPen        : TGPPen;
  LColor        : Cardinal;
begin
  inherited;

  //描画する四角形と楕円の領域とサイズ
  LObjWidth  := 130;
  LObjHeight := 100;
  LObjRect   := MakeRect(0, 0, LObjWidth, LObjHeight);

  //座標原点位置の値
  LXLocation := Width  div 2;
  LYLocation := Height div 2;

  //このTMyPanelのCanvasを描画先にしてTGPGraphicsのインスタンスを生成
  LGPGraphic := TGPGraphics.Create(Canvas.Handle);

  //座標の原点を (FXLocation, FYLocation) に移動する
  LGPGraphic.TranslateTransform(LXLocation, LYLocation);

  //ブラシを生成
  LColor   := ColorRefToARGB($804000);
 LGPPen   := TGPPen.Create(LColor, 1);
 LGPBrush := TGPHatchBrush.Create(HatchStyle30Percent, aclWhite, LColor);

 //文字列の書式等を設定
 LGPFontFamily := TGPFontFamily.Create('Arial Black');
 LGPStrFormat  := TGPStringFormat.Create;
 LGPStrFormat.SetAlignment(StringAlignmentCenter);
 LGPStrFormat.SetLineAlignment(StringAlignmentCenter);

 //パスを生成して四角形と楕円と文字列を追加
 LGPPath := TGPGraphicsPath.Create;
 LGPPath.AddRectangle(LObjRect);
 LGPPath.AddEllipse(LObjRect);
 LGPPath.AddString('DELPHI',
                    -1,
                    LGPFontFamily,
                    FontStyleRegular,
                    25,
                    LObjRect,
                    LGPStrFormat);

 //TGPMatrixを生成して要素を代入
 LGPMatrix := TGPMatrix.Create;
 LGPMatrix.SetElements(FXScale, 0.0,
              0.0, FYScale,
              0.0, 0.0);
  //マトリックスの情報をパスに渡して,パスを描画
 LGPPath.Transform(LGPMatrix);
 LGPGraphic.FillPath(LGPBrush, LGPPath);
 LGPGraphic.DrawPath(LGPPen, LGPPath);


  //座標原点を交差する座標軸を描く
  LGPPen.SetColor(aclBlack);
  LGPPen.SetWidth(1.0);
  LGPPen.SetDashStyle(DashStyleDash);
  LGPGraphic.DrawLine(LGPPen, 0, -LYLocation, 0, LYLocation);
  LGPGraphic.DrawLine(LGPPen, -LXLocation, 0, LXLocation, 0);

  //Createしたオブジェクトは解放する
  LGPGraphic.Free;
  LGPBrush.Free;
  LGPFontFamily.Free;
  LGPStrFormat.Free;
  LGPPath.Free;
  LGPMatrix.Free;
  LGPPen.Free;
end;

end.




03_TGPMatrix による平行四辺形の描画領域


行列の次の要素を変えると,描画領域が平行四辺形となります.対象のオブジェクトが画像であれば,傾斜した画像 (傾斜イメージ) ということになります.
  


図9
設計時画面
図10
実行開始画面
図11
実行結果例

リスト3
TGPMatrix による平行四辺形の描画領域
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ, ComCtrls;

type
  TMyPanel = class(TPanel)
  private
    FXAddValue : Single;
    FYAddValue : Single;
    procedure SetXAddValue(const Value: Single);
    procedure SetYAddValue(const Value: Single);
  protected
    procedure Paint; override;
  public
    constructor Create(AOwner: TComponent); override;
    property XAddValue : Single read FXAddValue write SetXAddValue;
    property YAddValue : Single read FYAddValue write SetYAddValue;
  end;

  TForm1 = class(TForm)
    TrackBar1: TTrackBar;
    TrackBar2: TTrackBar;
    Label1: TLabel;
    Label2: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure TrackBar1Change(Sender: TObject);
    procedure TrackBar2Change(Sender: TObject);
  private
    { Private 宣言 }
    MyPanel : TMyPanel;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  Caption := 'GDI+  TGPMatrix  平行四辺形の描画領域';

  //描画するコントロールを生成
  MyPanel := TMyPanel.Create(Self);
  with MyPanel do begin
    Parent := Self;
    SetBounds(5, 70, Self.ClientWidth - 10, Self.ClientHeight - 75);
    DoubleBuffered   := True;
    ControlStyle     := MyPanel.ControlStyle + [csOpaque];
    BevelOuter       := bvNone;
    Visible          := True;
    Color            := clWhite;
    ParentBackground := False;
    Anchors          := [akLeft, akTop, akRight, akBottom];
  end;

  //X軸方向の値に加算する値の設定
  with TrackBar1 do begin
    ShowSelRange := False;
    TickStyle    := tsNone;
    Height   := 26;
    Min      := -300;
    Max      := 300;
    Position := 0;
  end;

  //Y軸方向の値に加算する値の設定
  with TrackBar2 do begin
    ShowSelRange := False;
    TickStyle    := tsNone;
    Height   := 26;
    Min      := -300;
    Max      := 300;
    Position := 0;
  end;
end;

//=============================================================================
//  TrackBar1のOnClickイベント処理
//  X軸方向の値に加算する値の設定
//=============================================================================
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
  if not Assigned(MyPanel) then exit;
  MyPanel.XAddValue := TrackBar1.Position / 100.0;
end;

//=============================================================================
//  TrackBar2のOnClickイベント処理
//  Y軸方向の値に加算する値の設定
//=============================================================================
procedure TForm1.TrackBar2Change(Sender: TObject);
begin
  if not Assigned(MyPanel) then exit;
  MyPanel.YAddValue :=  TrackBar2.Position / 100.0;
end;

{ TMyPanel }

//-----------------------------------------------------------------------------
//  コンストラクタ
//  各種プロパティの初期化
//-----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
  inherited;

  FXAddValue := 0.0;
  FYAddValue := 0.0;
end;

//-----------------------------------------------------------------------------
//  XAddValueプロパティ設定用メソッド
//  X軸方向の値に加算する値の設定
//-----------------------------------------------------------------------------
procedure TMyPanel.SetXAddValue(const Value: Single);
begin
  if not Assigned(Parent) then exit;

  if FXAddValue <> Value then begin
     FXAddValue := Value;
     Invalidate;
  end;
end;

//-----------------------------------------------------------------------------
//  YAddValueプロパティ設定用メソッド
//  Y軸方向の値に加算する値の設定
//-----------------------------------------------------------------------------
procedure TMyPanel.SetYAddValue(const Value: Single);
begin
  if not Assigned(Parent) then exit;

  if FYAddValue <> Value then begin
     FYAddValue := Value;
     Invalidate;
  end;
end;

//-----------------------------------------------------------------------------
//  TMyPanelクラスのPaintメソッド
//  実際の描画コード
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
  LObjWidth     : Integer;
  LObjHeight    : Integer;
  LObjRect      : TGPRect;
  LXLocation    : Integer;
  LYLocation    : Integer;
  LGPGraphic    : TGPGraphics;
  LGPBrush      : TGPHatchBrush;
  LGPFontFamily : TGPFontFamily;
  LGPStrFormat  : TGPStringFormat;
  LGPPath       : TGPGraphicsPath;
  LGPMatrix     : TGPMatrix;
  LGPPen        : TGPPen;
  LColor        : Cardinal;
begin
  inherited;

  //描画する四角形と楕円の領域とサイズ
  LObjWidth  := 130;
  LObjHeight := 100;
  LObjRect   := MakeRect(0, 0, LObjWidth, LObjHeight);

  //座標原点位置の値
  LXLocation := Width  div 2;
  LYLocation := Height div 2;

  //このTMyPanelのCanvasを描画先にしてTGPGraphicsのインスタンスを生成
  LGPGraphic := TGPGraphics.Create(Canvas.Handle);

  //座標の原点を (FXLocation, FYLocation) に移動する
  LGPGraphic.TranslateTransform(LXLocation, LYLocation);

  //ブラシを生成
  LColor   := ColorRefToARGB($804000);
 LGPPen   := TGPPen.Create(LColor, 1);
 LGPBrush := TGPHatchBrush.Create(HatchStyle30Percent, aclWhite, LColor);

 //文字列の書式等を設定
 LGPFontFamily := TGPFontFamily.Create('Arial Black');
 LGPStrFormat  := TGPStringFormat.Create;
 LGPStrFormat.SetAlignment(StringAlignmentCenter);
 LGPStrFormat.SetLineAlignment(StringAlignmentCenter);

 //パスを生成して四角形と楕円と文字列を追加
 LGPPath := TGPGraphicsPath.Create;
 LGPPath.AddRectangle(LObjRect);
 LGPPath.AddEllipse(LObjRect);
 LGPPath.AddString('DELPHI',
                    -1,
                    LGPFontFamily,
                    FontStyleRegular,
                    25,
                    LObjRect,
                    LGPStrFormat);

 //TGPMatrixを生成して要素を代入
 LGPMatrix := TGPMatrix.Create;
  //マトリックスの情報をパスに渡して,パスを描画
 LGPMatrix.SetElements(1.0, FYAddValue,
              FXAddValue, 1.0,
              0.0, 0.0);
 LGPPath.Transform(LGPMatrix);
 LGPGraphic.FillPath(LGPBrush, LGPPath);
 LGPGraphic.DrawPath(LGPPen, LGPPath);


  //座標原点を交差する座標軸を描く
  LGPPen.SetColor(aclBlack);
  LGPPen.SetWidth(1.0);
  LGPPen.SetDashStyle(DashStyleDash);
  LGPGraphic.DrawLine(LGPPen, 0, -LYLocation, 0, LYLocation);
  LGPGraphic.DrawLine(LGPPen, -LXLocation, 0, LXLocation, 0);

  //Createしたオブジェクトは解放する
  LGPGraphic.Free;
  LGPBrush.Free;
  LGPFontFamily.Free;
  LGPStrFormat.Free;
  LGPPath.Free;
  LGPMatrix.Free;
  LGPPen.Free;
end;

end.




04_TGPMatrix による画像の平行四辺形領域描画


上のサンプルと同じ行列演算によって,画像を傾斜して,平行四辺形の描画領域とした例です.


図12
設計時画面
図13
実行開始画面
図14
実行結果例

リスト4
TGPMatrix による画像の平行四辺形領域描画
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ, ComCtrls;

type
  TMyPanel = class(TPanel)
  private
    FXAddValue : Single;
    FYAddValue : Single;
    procedure SetXAddValue(const Value: Single);
    procedure SetYAddValue(const Value: Single);
  protected
    procedure Paint; override;
  public
    constructor Create(AOwner: TComponent); override;
    property XAddValue : Single read FXAddValue write SetXAddValue;
    property YAddValue : Single read FYAddValue write SetYAddValue;
  end;

  TForm1 = class(TForm)
    TrackBar1: TTrackBar;
    TrackBar2: TTrackBar;
    Label1: TLabel;
    Label2: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure TrackBar1Change(Sender: TObject);
    procedure TrackBar2Change(Sender: TObject);
  private
    { Private 宣言 }
    MyPanel : TMyPanel;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  Caption := 'GDI+  TGPMatrix  平行四辺形の描画領域画像';

  //描画するコントロールを生成
  MyPanel := TMyPanel.Create(Self);
  with MyPanel do begin
    Parent := Self;
    SetBounds(5, 70, Self.ClientWidth - 10, Self.ClientHeight - 75);
    DoubleBuffered   := True;
    ControlStyle     := MyPanel.ControlStyle + [csOpaque];
    BevelOuter       := bvNone;
    Visible          := True;
    Color            := clWhite;
    ParentBackground := False;
    Anchors          := [akLeft, akTop, akRight, akBottom];
  end;

  //X軸方向の値に加算する値の設定
  with TrackBar1 do begin
    ShowSelRange := False;
    TickStyle    := tsNone;
    Height   := 26;
    Min      := -500;
    Max      := 500;
    Position := 0;
  end;

  //Y軸方向の値に加算する値の設定
  with TrackBar2 do begin
    ShowSelRange := False;
    TickStyle    := tsNone;
    Height   := 26;
    Min      := -500;
    Max      := 500;
    Position := 0;
  end;
end;

//=============================================================================
//  TrackBar1のOnClickイベント処理
//=============================================================================
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
  if not Assigned(MyPanel) then exit;
  MyPanel.XAddValue := TrackBar1.Position / 100.0;
end;

//=============================================================================
//  TrackBar2のOnClickイベント処理
//=============================================================================
procedure TForm1.TrackBar2Change(Sender: TObject);
begin
  if not Assigned(MyPanel) then exit;
  MyPanel.YAddValue :=  TrackBar2.Position / 100.0;
end;

{ TMyPanel }

//-----------------------------------------------------------------------------
//  コンストラクタ
//  各種プロパティの初期化
//-----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
  inherited;

  FXAddValue := 0.0;
  FYAddValue := 0.0;
end;

//-----------------------------------------------------------------------------
//  XAddValueプロパティ設定用メソッド
//  X軸方向の値に加算する値の設定
//-----------------------------------------------------------------------------
procedure TMyPanel.SetXAddValue(const Value: Single);
begin
  if not Assigned(Parent) then exit;

  if FXAddValue <> Value then begin
     FXAddValue := Value;
     Invalidate;
  end;
end;

//-----------------------------------------------------------------------------
//  YAddValueプロパティ設定用メソッド
//  Y軸方向の値に加算する値の設定
//-----------------------------------------------------------------------------
procedure TMyPanel.SetYAddValue(const Value: Single);
begin
  if not Assigned(Parent) then exit;

  if FYAddValue <> Value then begin
     FYAddValue := Value;
     Invalidate;
  end;
end;

//-----------------------------------------------------------------------------
//  TMyPanelクラスのPaintメソッド
//  実際の描画コード
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
  LImageFilePath : String;
  LObjWidth      : Integer;
  LObjHeight     : Integer;
  LXLocation     : Integer;
  LYLocation     : Integer;
  LGPImage       : TGPImage;
  LGPGraphic     : TGPGraphics;
  LGPMatrix     : TGPMatrix;
begin
  inherited;

  LObjWidth  := 192;
  LObjHeight := 144;

  LXLocation := Width  div 2;
  LYLocation := Height div 2;

  LImageFilePath := ExtractFilePath(ParamStr(0)) + 'Hachi.bmp';
  LGPImage      := TGPImage.Create(LImageFilePath);

  LGPGraphic := TGPGraphics.Create(Canvas.Handle);

 LGPMatrix := TGPMatrix.Create;
 LGPMatrix.SetElements(1.0, FYAddValue,
              FXAddValue, 1.0,
              LXLocation, LYLocation);
 LGPGraphic.SetTransform(LGPMatrix);

  LGPGraphic.DrawImage(LGPImage,
                       - LObjWidth  div 2,
                       - LObjHeight div 2,
                       LObjWidth,
                       LObjHeight);

  LGPImage.Free;
  LGPGraphic.Free;
  LGPMatrix.Free;
end;

end.




05_領域を 3 つの点で指定する画像描画


TGPImage と TGPBitmap のオーバーロード関数に,領域指定を 3 点で指定する関数があります.
平行四辺形は,3 点を指定すれば,残りの点は自動的に決まります.これを使用しても,画像を傾斜して描画できます.その確認用のサンプルです.


図15
実行画面

描画座標の指定を変更すると,例えば次のような図となります.
このコードでは,座標値の数値は変えずに,格納する配列の要素だけを変えています.

  LPoints[0] := MakePoint( 30.0,  50.0);
  LPoints[2] := MakePoint(250.0,  20.0);
  LPoints[1] := MakePoint( 90.0, 200.0);


図16
実行画面

リスト5
領域を 3 つの点で指定する画像描画
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls, GDIPAPI, GDIPOBJ, ComCtrls;

type
  TMyPanel = class(TPanel)
  protected
    procedure Paint; override;
  end;

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private 宣言 }
    MyPanel : TMyPanel;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  Caption := 'GDI+  3 点で領域指定した傾斜イメージ';

  //描画するコントロールを生成
  MyPanel := TMyPanel.Create(Self);
  with MyPanel do begin
    Parent := Self;
    SetBounds(5, 5, Self.ClientWidth - 10, Self.ClientHeight - 10);
    DoubleBuffered   := True;
    ControlStyle     := MyPanel.ControlStyle + [csOpaque];
    BevelOuter       := bvNone;
    Visible          := True;
    Color            := clWhite;
    ParentBackground := False;
    Anchors          := [akLeft, akTop, akRight, akBottom];
  end;
end;

{ TMyPanel }

//-----------------------------------------------------------------------------
//  TMyPanelクラスのPaintメソッド
//  実際の描画コード
//
//  DrawImage関数のテスト
//  描画領域に3点を与えると,描画領域は平行四辺形となる
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
  LPoints        : array[0..2] of TGPPointF;
  LImageFilePath : String;
  LGPImage       : TGPImage;
  LGPGraphic     : TGPGraphics;
begin
  inherited;

  LPoints[0] := MakePoint( 30.0,  50.0);
  LPoints[1] := MakePoint(250.0,  20.0);
  LPoints[2] := MakePoint( 90.0, 200.0);

  //画像ファイルを指定.TGPImaageインスタンスを生成して読み込む
  LImageFilePath := ExtractFilePath(ParamStr(0)) + 'Hachi.bmp';
  LGPImage       := TGPImage.Create(LImageFilePath);

  LGPGraphic := TGPGraphics.Create(Canvas.Handle);
  LGPGraphic.DrawImage(LGPImage, PGPPointF(@LPoints), Length(LPoints));

  //Createしたオブジェクトは解放する
  LGPImage.Free;
  LGPGraphic.Free;
end;

end.