Direct2Dのキャンバス(TDirect2DCanvas)を使ってTBitmapに描画を行う ~Delphiでお手軽プログラミング

Direct2Dのキャンバス(TDirect2DCanvas)を使ってTBitmapに描画を行う ~Delphiでお手軽プログラミング

Direct2Dは描画操作をCPUではなくGPUに転送します。よって多くの場合、高速に処理できます。
またDirect2Dのキャンバス(TDirect2DCanvas)を使うと、半透明色が使用でき、アンチエイリアスを有効にすることも出来ます。
ただし、Windows7以降、かつDelphi2010以降でなければ使用できません。

プロジェクトの作成と画面設計

プロジェクトを新規作成(VCLアプリケーション)し、フォーム(Form1)にTButtonを1個、TImageを1個を配置する。
TDirect2DCanvas

ソースコードの記述

TButton1をダブルクリックして、以下ソースコードを記述する。
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Image1: TImage;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses Vcl.Direct2D, Winapi.D2D1, System.Math, Vcl.Imaging.jpeg;

procedure TForm1.Button1Click(Sender: TObject);
var D2Canvas:TDirect2DCanvas;
    ptf:TD2DPoint2f;
    jpg:TJpegImage;
    D2D1SolidColorBrush:ID2D1SolidColorBrush;
    D2D1StrokeStyle:ID2D1StrokeStyle;
begin
  if not TDirect2DCanvas.Supported then
  begin
    ShowMessage('Direct2Dは使えません');
    exit;
  end;

  //サイズの設定
  Image1.Width:=320;
  Image1.Height:=320;
  Image1.Picture.Bitmap.Width:=Image1.Width;
  Image1.Picture.Bitmap.Height:=Image1.Height;
  Image1.Picture.Bitmap.PixelFormat:=pf24bit;

  //Direct2Dキャンバスの作成
  D2Canvas:=
    TDirect2DCanvas.Create(
      Image1.Picture.Bitmap.Canvas,
      Rect(
        0,0,
        Image1.Picture.Bitmap.Width,
        Image1.Picture.Bitmap.Height
      )
    );

  //描画の開始
  D2Canvas.BeginDraw;


  //ブラシの設定
  D2Canvas.Brush.Color:=clWhite;
  D2Canvas.Brush.Style:=bsSolid;
  D2Canvas.Brush.Handle.SetOpacity(1);//不透明度100%
  //ペンの設定
  D2Canvas.Pen.Color:=clBlue;
  D2Canvas.Pen.Style:=psSolid;
  D2Canvas.Pen.Width:=4;

  //アンチエイリアスを無効にする
  D2Canvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);


  //■矩形の描画
  D2Canvas.Rectangle(
    0,0,
    Image1.Picture.Bitmap.Width,
    Image1.Picture.Bitmap.Height
  );


  //ブラシの設定
  D2Canvas.Brush.Color:=clYellow;
  D2Canvas.Brush.Handle.SetOpacity(0.5);//不透明度50%
  //ペンの設定
  D2Canvas.Pen.Brush.Handle.SetOpacity(0.5);//不透明度50%
  D2Canvas.Pen.Width:=12;


  //■線の描画
  //アンチエイリアスを有効に戻す
  D2Canvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
  //直線を描画
  D2Canvas.MoveTo(0,0);
  D2Canvas.LineTo(
    100,
    Image1.Picture.Bitmap.Height-1
  );
  //アンチエイリアスを無効にする
  D2Canvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
  //直線を描画
  D2Canvas.MoveTo(20,0);
  D2Canvas.LineTo(
    120,
    Image1.Picture.Bitmap.Height-1
  );


  //■RenderTarget.DrawLineで線を描画
  //青色の不透明度50%のブラシを「D2D1SolidColorBrush」に作成
  D2Canvas.RenderTarget.CreateSolidColorBrush(
    D2D1ColorF(clBlue, 0.5), nil, D2D1SolidColorBrush);
  //線の形状を「D2D1StrokeStyle」に作成
  D2DFactory.CreateStrokeStyle(
    D2D1StrokeStyleProperties(
      D2D1_CAP_STYLE_ROUND,   //開始点の形状(丸くする)
      D2D1_CAP_STYLE_ROUND,   //終了点の形状(丸くする)
      D2D1_CAP_STYLE_TRIANGLE,//破線の形状(三角形に)
      D2D1_LINE_JOIN_ROUND,   //線の接続点の形状(丸くする)
      10.0,                   //マイター(線の接合点の尖った部分)の限界値
      D2D1_DASH_STYLE_DASH,   //破線を指定
      0
    ),
    nil,
    0,
    D2D1StrokeStyle
  );
  //直線を描画
  D2Canvas.RenderTarget.DrawLine(
    D2D1PointF(50,20),
    D2D1PointF(130,Image1.Picture.Bitmap.Height-56),
    D2D1SolidColorBrush,
    12,
    D2D1StrokeStyle
  );


  //■角丸矩形を描画
  //アンチエイリアスを有効に戻す
  D2Canvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
  //角丸矩形を描画
  D2Canvas.RoundRect(
    Rect(180,100,280,140),
    8,8
  );
  //アンチエイリアスを無効にする
  D2Canvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
  //角丸矩形を描画
  D2Canvas.RoundRect(
    Rect(200,120,300,160),
    8,8
  );


  //■楕円を描画
  //アンチエイリアスを有効に戻す
  D2Canvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
  //楕円の描画
  D2Canvas.Ellipse(180,180,260,280);
  //アンチエイリアスを無効にする
  D2Canvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
  //楕円の描画
  D2Canvas.Ellipse(200,200,280,300);


  //■テキストを描画
  //テキスト出力時にアンチエイリアスを有効にする
  D2Canvas.RenderTarget.SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
  //ブラシを透明にする
  D2Canvas.Brush.Style:=bsClear;
  //フォントの設定
  D2Canvas.Font.Brush.Handle.SetOpacity(0.7);
  D2Canvas.Font.Size:=24;  //(pt)
  ptf.x:=40;
  ptf.y:=160;
  //変換を30度回転に設定する
  D2Canvas.RenderTarget.SetTransform(TD2DMatrix3x2F.Rotation(30,ptf));
  //文字の描画
  D2Canvas.TextOut(trunc(ptf.x),trunc(ptf.y),'文字列');
  //テキスト出力時にアンチエイリアスを無効にする
  D2Canvas.RenderTarget.SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
  //変換を元に戻す
  D2Canvas.RenderTarget.SetTransform(TD2DMatrix3x2F.Rotation(0,ptf));
  //文字の描画
  D2Canvas.TextOut(trunc(ptf.x),trunc(ptf.y),'文字列');


  //JPEG画像を描画 (test.jpg画像を用意してください)
  //アンチエイリアスを有効に戻す
  D2Canvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
  jpg:=TJPEGImage.Create;
  try
    jpg.LoadFromFile('..\..\test.jpg');
    ptf.x:=200;
    ptf.y:=10;
    //変換を20度回転に設定する
    D2Canvas.RenderTarget.SetTransform(TD2DMatrix3x2F.Rotation(20,ptf));
    D2Canvas.StretchDraw(
      Rect(
        trunc(ptf.x),trunc(ptf.y),
        trunc(ptf.x)+80,trunc(ptf.y+80*jpg.Height/jpg.Width)
      ),
      jpg,
      180 //不透明度(0~255)
    );
    //変換を元に戻す
    D2Canvas.RenderTarget.SetTransform(TD2DMatrix3x2F.Rotation(0,ptf));

  finally
    jpg.Free;
  end;


  //描画の終了
  D2Canvas.EndDraw;

  //Direct2Dキャンバスの破棄
  D2Canvas.Free;
end;

end.

実行する

実行ボタンを押して実行します。(デバッグ実行でもOK)

Button1をクリックすると、Image1.picture.bitmapの背景を塗りつぶし、線、角丸矩形、楕円、文字、jpg画像を描画します。
アンチエイリアスの有無で境界がギザギザだったり滑らかだったりしています。
TDirect2DCanvas