Delphi Programming / Object Pascal
[掲載 2012年12月28日] [更新 2017年05月18日] GDI+ 関係サンプル |
GDI+ 関係サンプル
G130_イメージのリサイズ |
動作確認等 |
Windows 7 U64(SP1) + Delphi XE(UP1) Pro |
|
G130_GDIPlus_ResizedImage.zip [1,294 KB] 2017年05月18日版 (EXE 同梱) |
TGPGraphic.DrawImag メソッドあるいは TGPMatrix 等で画像を拡大または縮小表示できます.
表示サイズが変化しても,元の画像,イメージの幅と高さが変化するわけではありません.
画像を読み込む時に生成した TGPBitmap あるいは TGPImage のサイズは直接変更できません. |
TGPBitmap や TGPImage のインスタンスに具体的な画像が格納されている状態では,その幅や高さのサイズ等の変更はできないようです.
そこで,このサンプルでは,新しく別の TGPBitmap を新しいサイズで生成します.新しいサイズで生成したこの TGPBitmap を描画先にした TGPGraphics を生成します.そして,元の TGPBitmap の内容を描画すると,新しい TGPBitmap にリサイズした元の画像が格納されます.
操作の確認に,TMyPanel にサイズを変更した TGPBitmap を描画します.更に,保存して実際にサイズが変更されていることを確認できるようにしています.
|
[備考]
本サンプルの保存の機能は TGPBitmap を保存するものです.TMyPanel や TImage に描画している内容を保存したい場合は,新規に作成した TBitmap に対して描画コードを実行すれば,そのビットマップを保存することで実現できます. |
|
図1
設計時の画面 |
|
図2
ビットマップ画像を読み込んで表示
|
|
図3
TSpinEdit でサイズを変更
- 四角形は TGPBitmap に描画しているので,この表示状態がビットマップ画像として保存される
|
リスト1
TGPBitmap のリサイズ
サイズの違う別の TGPBitmap を生成してそれに元の TGPBitmap の内容を描画する |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, ComCtrls, StdCtrls, GDIPOBJ, GDIPAPI, GDIPUTIL, ExtDlgs,
Spin;
type
TMyPanel = class(TPanel)
private
procedure SetDrawWidth(const Value: Integer);
protected
FImageFilePath : string;
FFileStream : TMemoryStream;
FGPGraphic : TGPGraphics;
FOriginGPBitmap : TGPBitmap;
FGPBitmap : TGPBitmap;
FDrawWidth : Integer;
FDrawHeight : Integer;
procedure Paint; override;
procedure DrawImage(ACanvas: TCanvas);
public
procedure LoadImageFromFile(AFileName: string);
procedure SaveImageToFile(AFileName: string);
destructor Destroy; override;
property DrawWidth : Integer read FDrawWidth write SetDrawWidth;
property DrawHeight : Integer read FDrawHeight;
end;
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
OpenPictureDialog1: TOpenPictureDialog;
SpinEdit1: TSpinEdit;
SpinEdit2: TSpinEdit;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure SpinEdit1Change(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.Caption := 'GDI+ イメージのリサイズ';
//TMyPanelを生成して配置
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
Left := 5;
Top := 35;
Width := Self.ClientWidth - 10;
Height := Self.ClientHeight - Top - 5;
Anchors := [akLeft, akTop, akRight, akBottom];
Color := clWhite;
ParentBackground := False;
DoubleBuffered := True;
end;
OpenPictureDialog1.InitialDir := ExpandFileName('..\');
OpenPictureDialog1.FileName := '501.bmp';
end;
//=============================================================================
// 画像の読み込みボタン
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LFileName : String;
begin
if OpenPictureDialog1.Execute then begin
LFileName := OpenPictureDialog1.FileName;
OpenPictureDialog1.InitialDir := ExtractFileDir(LFileName);
MyPanel.LoadImageFromFile(LFileName);
SpinEdit1.Value := MyPanel.DrawWidth;
SpinEdit2.Value := MyPanel.DrawHeight;
end;
end;
//=============================================================================
// 保存ボタン
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LSaveFileName : String;
begin
LSaveFileName := ExpandFileName('..\Save.bmp');
MyPanel.SaveImageToFile(LSaveFileName);
end;
//=============================================================================
// SpinEdit1のChangeイベント処理
// 画像の横サイズを設定する
//=============================================================================
procedure TForm1.SpinEdit1Change(Sender: TObject);
begin
MyPanel.DrawWidth := SpinEdit1.Value;
SpinEdit2.Value := MyPanel.DrawHeight;
end;
{ TMyPanel }
//-----------------------------------------------------------------------------
// TMyPanelクラス破棄時の処理
//-----------------------------------------------------------------------------
destructor TMyPanel.Destroy;
begin
if Assigned(FFileStream) then FreeAndNil(FFileStream);
if Assigned(FGPBitmap) then FreeAndNil(FGPBitmap);
if Assigned(FOriginGPBitmap) then FreeAndNil(FOriginGPBitmap);
if Assigned(FGPGraphic) then FreeAndNil(FGPGraphic);
inherited;
end;
//-----------------------------------------------------------------------------
// TMyPanelのLoadImageFromFileメソッド
//
// 画像表示中に画像ファイルがなくても操作可能なようにメモリストリームに読み込む
// そのメモリストリームからTGPBitmapを生成する
//
// EMF,WMFはこのコードでは正常に読み込めない
//-----------------------------------------------------------------------------
procedure TMyPanel.LoadImageFromFile(AFileName: string);
begin
if Assigned(FOriginGPBitmap) then FreeAndNil(FOriginGPBitmap);
if Assigned(FFileStream) then FreeAndNil(FFileStream);
FFileStream := TMemoryStream.Create;
FFileStream.LoadFromFile(AFileName);
//メモリストリームから読み出してTGPBitmapを生成
//TGPBitmapを使用
//TGPImageだと正常に読み込めないメタファイルがある
FOriginGPBitmap := TGPBitmap.Create(TStreamAdapter.Create(FFileStream, soReference));
FDrawWidth := FOriginGPBitmap.GetWidth;
FDrawHeight := FOriginGPBitmap.GetHeight;
Invalidate;
end;
//-----------------------------------------------------------------------------
// TMyPanelのSaveImageToFileメソッド
// 保存のためのTBitmapを生成して保存
//-----------------------------------------------------------------------------
procedure TMyPanel.SaveImageToFile(AFileName: string);
var
LImgGUID : TGUID;
begin
if not Assigned(FGPBitmap) then exit;
//指定MIMEタイプのGUIDを求め,ビットマップ画像として保存
if GetEncoderClsid('image/bmp', LImgGUID) >= 0 then begin
FGPBitmap.Save(AFileName, LImgGUID);
end;
end;
//-----------------------------------------------------------------------------
// TMyPanelのDrawWidthプロパティの設定用メソッド
//-----------------------------------------------------------------------------
procedure TMyPanel.SetDrawWidth(const Value: Integer);
begin
FDrawWidth := Value;
if FDrawWidth < 10 then exit;
Invalidate;
end;
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
begin
inherited;
DrawImage(Canvas);
end;
//-----------------------------------------------------------------------------
// 描画ルーチン
//
// ACanvas : 描画先のTCanvasオブジェクト
//-----------------------------------------------------------------------------
procedure TMyPanel.DrawImage(ACanvas: TCanvas);
var
LRatio : Double;
LGPPen : TGPPen;
begin
if (FDrawWidth + FDrawHeight) = 0 then exit;
if Assigned(FGPBitmap) then FreeAndNil(FGPBitmap);
if Assigned(FGPGraphic) then FreeAndNil(FGPGraphic);
//---------------------------------------------------------------------------
// TGPBitmapに対する操作
// Paintメソッド内部で実行する必然性はない.描画内容は見えないので
//---------------------------------------------------------------------------
//縦横比を計算
LRatio := FOriginGPBitmap.GetHeight / FOriginGPBitmap.GetWidth;
//描画のサイズを計算
FDrawHeight := Trunc(LRatio * FDrawWidth);
//TGPBitmapオブジェクトを生成
FGPBitmap := TGPBitmap.Create(FDrawWidth, FDrawHeight, PixelFormat32bppARGB);
//生成したTGPBitmapを描画先にしてTGPGraphicsを生成し
//元のTGPBitmapの内容を描画
FGPGraphic := TGPGraphics.Create(FGPBitmap);
FGPGraphic.DrawImage(FOriginGPBitmap, MakeRect(0, 0, FDrawWidth, FDrawHeight));
//ペンのオブジェクトを生成
LGPPen := TGPPen.Create(aclBlue, 5.0);
//四角形を描画
//線の描画関係の関数名はDrawXXXX
FGPGraphic.DrawRectangle(LGPPen, MakeRect(20, 20, 70, 45));
FGPGraphic.Free;
//---------------------------------------------------------------------------
//TGPGraphicsのオブジェクトを生成
//描画先は引数のTCanvas
FGPGraphic := TGPGraphics.Create(ACanvas.Handle);
//TGPBitmapの内容をこのTMyPanelのCanvasに描画
FGPGraphic.DrawImage(FGPBitmap, 0, 0);
//Createしたオブジェクトは解放処理する
if Assigned(FGPGraphic) then FreeAndNil(FGPGraphic);
end;
end.
02_保存の時だけ TGPBitmap をリサイズ |
保存の時だけ TGPBitmap をリサイズするのであれば,描画中のリサイズ処理は不要です.
例えば,保存の時のコードと描画のコードを以下のようにします.
|
//-----------------------------------------------------------------------------
// TMyPanelのSaveImageToFileメソッド
// 保存のためのTBitmapを生成して保存
//-----------------------------------------------------------------------------
procedure TMyPanel.SaveImageToFile(AFileName: string);
var
LImgGUID : TGUID;
begin
if Assigned(FGPBitmap) then FreeAndNil(FGPBitmap);
if Assigned(FGPGraphic) then FreeAndNil(FGPGraphic);
//TGPBitmapオブジェクトを生成
FGPBitmap := TGPBitmap.Create(FDrawWidth, FDrawHeight, PixelFormat32bppARGB);
//生成したTGPBitmapを描画先にしてTGPGraphicsを生成し
//元のTGPBitmapの内容を描画
FGPGraphic := TGPGraphics.Create(FGPBitmap);
FGPGraphic.DrawImage(FOriginGPBitmap, MakeRect(0, 0, FDrawWidth, FDrawHeight));
//指定MIMEタイプのGUIDを求め,ビットマップ画像として保存
if GetEncoderClsid('image/bmp', LImgGUID) >= 0 then begin
FGPBitmap.Save(AFileName, LImgGUID);
end;
if Assigned(FGPGraphic) then FreeAndNil(FGPGraphic);
end;
//-----------------------------------------------------------------------------
// TMyPanelのDrawWidthプロパティの設定用メソッド
//-----------------------------------------------------------------------------
procedure TMyPanel.SetDrawWidth(const Value: Integer);
begin
FDrawWidth := Value;
if FDrawWidth < 10 then exit;
Invalidate;
end;
//-----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
begin
inherited;
DrawImage(Canvas);
end;
//-----------------------------------------------------------------------------
// 描画ルーチン
//
// ACanvas : 描画先のTCanvasオブジェクト
//-----------------------------------------------------------------------------
procedure TMyPanel.DrawImage(ACanvas: TCanvas);
var
LRatio : Double;
begin
if (FDrawWidth + FDrawHeight) = 0 then exit;
if Assigned(FGPGraphic) then FreeAndNil(FGPGraphic);
//縦横比を計算
LRatio := FOriginGPBitmap.GetHeight / FOriginGPBitmap.GetWidth;
//描画のサイズを計算
FDrawHeight := Trunc(LRatio * FDrawWidth);
//TGPGraphicsのオブジェクトを生成
//描画先は引数のTCanvas
FGPGraphic := TGPGraphics.Create(ACanvas.Handle);
//TGPBitmapの内容をこのTMyPanelのCanvasに描画
FGPGraphic.DrawImage(FOriginGPBitmap, 0, 0, FDrawWidth, FDrawHeight);
//Createしたオブジェクトは解放処理する
if Assigned(FGPGraphic) then FreeAndNil(FGPGraphic);
end;
|