Delphi Programming / Object Pascal
[掲載 2012年12月02日] [更新 2017年06月25日] GDI+ 関係サンプル |
GDI+ 関係サンプル
G040_各種の画像形式の表示と変換 |
動作確認等 |
Windows 7 U64(SP1) + Delphi XE(UP1) Pro |
|
G040_GDIPlus_SomeImageTypes.zip [1,258 KB] 2017年06月25日版 (EXE 同梱) |
- 2013年05月09日
- GDI+ を使用しない画像形式の変換のサンプルを追加
- 2013年05月15日
- [マルチページ TIFF 画像の作成と表示] を追加
- 2017年05月05日
- GDI+ を使用しない画像形式の変換関係のサンプルを別のページに移動
|
GDI+ では次の形式の画像をディスクから読み込んで表示できます.現在の画像形式を別の形式の画像に変換して保存ができますが,メタファイルと ICON 形式での保存はできません.
下の表の右端の値は,各画像ファイルの先頭バイトからの値です.画像形式を変換して保存した時に,バイナリエディタを使用して,画像の種類をこれらの値で確認できます.
アイコンは,TGPBitmap から ビットマップ (TBitmap) を取得して,そのビットマップをアイコン形式の画像に変換すれば保存できます.
|
拡張子 |
名称 |
保存の可否 |
先頭バイト値 |
BMP |
ビットマップ |
可 |
BM |
GIF |
ジフ |
可 |
GIF89a |
JPEG |
ジェイペグ |
可 |
$FFD8 |
PNG |
ピング |
可 |
$89 + PNG + $0D0A |
TIFF |
ティフ |
可 |
MM または II |
WMF (Windows メタファイル) |
ウィンドウズメタファイル |
不可 |
未確認 |
EMF (拡張メタファイル) |
エンハンスドメタファイル |
不可 |
未確認 |
EMF+ |
エンハンスドメタファイルプラス |
不可 |
未確認 |
ICON |
アイコン |
不可 |
未確認 |
01_TGPBitmap.Save メソッドで画像形式を指定して保存 |
GDI+ で画像を他の形式に変換して保存するには,GetEncoderClsid 関数で,各画像形式に応じた MIME タイプの GUID を取得します.そして,TGPGraphics の Save 関数の引数に,この GUID の値を指定するだけです.
このサンプルでは,変換可能な画像形式全てに変換して保存し,再度読み込んで表示します.結果はフォームの Canvas に表示します.
描画コードは,このフォームの OnPaint イベント内に書いています.描画先を TImage.Canvas にした場合,GDI+ による描画ては AutoSize,Stretch,Transparent は機能しません.また,描画の Canvas をクリアすると,デフォルトの「白」で塗潰されます.Transparent が機能しませんから,画像の白の部分が透過状態になっているのかを確認できません.そこでフォームの Canvas に描画するようにしています. |
[備考]
TBitmap のインスタンスを別に生成しておいて,GDI+ による描画をそのビットマップの Canvas に実行すればそのビットマップを保存できます.
VCL に実装されている JPEG, PNG, GIF 画像処理用の機能を使用すれば,ビットマップを各種の画像形式に変換して保存できます. |
- 図2
- メタファイル画像を他の画像形式に変換して保存
- 保存した画像ファイルを再度表示した結果
- 画像の背景は,アルファ値が 0 のため黒く描画されている,上は元の WMF 画像
|
|
- 図3
- ビットマップ画像を他の画像形式に変換して保存
- 保存した画像ファイルを再度表示した結果.上は元のビットマップ画像
|
|
- 図4
- GIF 画像を他の画像形式に変換して保存
- 保存した画像ファイルを再度表示した結果.上は元の GIF 画像
|
|
- 図5
- JPEG 画像を他の画像形式に変換して保存
- 保存した画像ファイルを再度表示した結果.上は元の JPEG 画像
|
|
- 図6
- PNG 画像を他の画像形式に変換して保存
- 保存した画像ファイルを再度表示した結果.上は元の PNG 画像
|
|
- 図7
- TIFF 画像を他の画像形式に変換して保存
- 保存した画像ファイルを再度表示した結果.上は元の TIFF 画像
|
|
リスト1
TPGImage または TGPBitmap の Save メソッドを使用して画像を他の画像形式で保存 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, GDIPAPI, GDIPOBJ, GDIPUTIL, StdCtrls, ExtCtrls, ExtDlgs;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Label2: TLabel;
OpenDialog1: TOpenDialog;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormPaint(Sender: TObject);
private
{ Private 宣言 }
FImageFilePath : string;
FLoadFilePath : string;
FSaveFilePath : string;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
OpenFileFilter =
'画像ファイル|*.png;*.jpg;*.gif;*.bmp;*.tif;*.emf;*.wmf;*.ico' +
'|*.png|*.png' +
'|*.jpg|*.jpg' +
'|*.gif|*.gif' +
'|*.bmp|*.bmp' +
'|*.tif|*.tif' +
'|*.emf|*.emf' +
'|*.wmf|*.wmf' +
'|*.ico|*.ico';
//=============================================================================
// フォーム生成時の処理
// 画像ファイルの読み出しフォルダと,保存先のフォルダをデリミタ付きで設定
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := 'GDI+ 各種画像形式に変換して保存';
FLoadFilePath := ExtractFilePath(ParamStr(0)) + 'OriginalImages';
FLoadFilePath := IncludeTrailingPathDelimiter(FLoadFilePath);
FSaveFilePath := ExtractFilePath(ParamStr(0)) + 'ChangedImages';
FSaveFilePath := IncludeTrailingPathDelimiter(FSaveFilePath);
end;
//=============================================================================
// 画像ファイルを読み出して,各種形式で保存
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LGPBitmap : TGPBitmap;
LSaveFilePath : string;
LFileName : string;
LImgGUID : TGUID;
begin
if OpenDialog1.InitialDir = '' then begin
OpenDialog1.InitialDir := ExtractFileDir(FLoadFilePath);
end;
OpenDialog1.Filter := OpenFileFilter;
if OpenDialog1.Execute then begin
FImageFilePath := OpenDialog1.FileName;
LGPBitmap := TGPBitmap.Create(FImageFilePath);
LFileName := ExtractFileName(FImageFilePath);
LSaveFilePath := FSaveFilePath + LFileName;
Label1.Caption := LFileName;
Label2.Caption := '左から .bmp, .jpg, .gif, .png, .tif ';
//指定MIMEタイプのGUIDを求め,読み出したファイル名の拡張子を変更して保存
//ビットマップ画像として保存
if GetEncoderClsid('image/bmp', LImgGUID) >= 0 then begin
LGPBitmap.Save(ChangeFileExt(LSaveFilePath, '.bmp'), LImgGUID);
end;
//JPEG画像として保存
if GetEncoderClsid('image/jpeg', LImgGUID) >= 0 then begin
LGPBitmap.Save(ChangeFileExt(LSaveFilePath, '.jpg'), LImgGUID);
end;
//GIF画像として保存
if GetEncoderClsid('image/gif', LImgGUID) >= 0 then begin
LGPBitmap.Save(ChangeFileExt(LSaveFilePath, '.gif'), LImgGUID);
end;
//PNG画像として保存
if GetEncoderClsid('image/png', LImgGUID) >= 0 then begin
LGPBitmap.Save(ChangeFileExt(LSaveFilePath, '.png'), LImgGUID);
end;
//TIFF画像として保存
if GetEncoderClsid('image/tiff', LImgGUID) >= 0 then begin
LGPBitmap.Save(ChangeFileExt(LSaveFilePath, '.tif'), LImgGUID);
end;
LGPBitmap.Free;
Invalidate;
end;
end;
//=============================================================================
// フォームのOnPaintイベント
// 読み出した画像と,保存した画像を読み出して描画
//=============================================================================
// GetImageEncodersSize
procedure TForm1.FormPaint(Sender: TObject);
var
LLoadFilePath : string;
LFileName : string;
LGPGraphic : TGPGraphics;
LGPImage : TGPImage;
LWidth : Integer;
LHeight : Integer;
LLeft : Integer;
LTop : Integer;
begin
if FImageFilePath = '' then exit;
LFileName := ExtractFileName(FImageFilePath);
LLoadFilePath := FSaveFilePath + LFileName;
LWidth := 110;
LHeight := 110;
LLeft := 10;
LTop := 40;
//変換元の画像ファイルからTGPImageを生成
LGPImage := TGPImage.Create(FImageFilePath);
//描画先はこのCanvasとする
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
//元の画像を描画
LGPGraphic.DrawImage(LGPImage, MakeRect(LLeft, LTop, LWidth, LHeight));
LGPImage.Free;
LGPGraphic.Free;
//表示位置を設定して...
LLeft := 10;
LTop := 160;
//画像の形式を変換して保存したファイルを読み出して表示
//ビットマップ画像に変換した画像
LGPImage := TGPImage.Create(ChangeFileExt(LLoadFilePath, '.bmp'));
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
LGPGraphic.DrawImage(LGPImage, MakeRect(LLeft, LTop, LWidth, LHeight));
LGPImage.Free;
LGPGraphic.Free;
LLeft := LLeft + LWidth + 10;
//JPEG画像に変換した画像
LGPImage := TGPImage.Create(ChangeFileExt(LLoadFilePath, '.jpg'));
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
LGPGraphic.DrawImage(LGPImage, MakeRect(LLeft, LTop, LWidth, LHeight));
LGPImage.Free;
LGPGraphic.Free;
LLeft := LLeft + LWidth + 10;
//GIF画像に変換した画像
LGPImage := TGPImage.Create(ChangeFileExt(LLoadFilePath, '.gif'));
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
LGPGraphic.DrawImage(LGPImage, MakeRect(LLeft, LTop, LWidth, LHeight));
LGPImage.Free;
LGPGraphic.Free;
LLeft := LLeft + LWidth + 10;
//PNG画像に変換した画像
LGPImage := TGPImage.Create(ChangeFileExt(LLoadFilePath, '.png'));
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
LGPGraphic.DrawImage(LGPImage, MakeRect(LLeft, LTop, LWidth, LHeight));
LGPImage.Free;
LGPGraphic.Free;
LLeft := LLeft + LWidth + 10;
//TIFF画像に変換した画像
LGPImage := TGPImage.Create(ChangeFileExt(LLoadFilePath, '.tif'));
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
LGPGraphic.DrawImage(LGPImage, MakeRect(LLeft, LTop, LWidth, LHeight));
LGPImage.Free;
LGPGraphic.Free;
end;
end.
02_GDI+ を使用したマルチページ TIFF 画像の作成と表示 |
マルチページ TIFF 画像は主にメタファイルや PDF ファイルを扱うことが多いようですが,ここでは各種画像を TIFF 画像ファイルに保存または読み出して TImage に表示します.JPEG 画像品質等,各種の設定が可能ですが,ここではデフォルトの設定で扱っています.デフォルトでの圧縮形式は LZW となるようです.
既存の TIFF 画像の場合,内部形式によっては読み出しに失敗することがあるようです.そのような場合は,参考リンクにある LibTiffDelphi というライブラリを使用すると読み込めるようですが,筆者は確認していません.
このサンプルでは,TIFF 画像を TImage に表示していますが,TIFF 画像を表示できるのは Delphi 2010 以降の TImage です.また,Windows Vista 以降,.NET Framework 3.0 以降の環境でないと TImage には表示できません.
Delphi 2010 よりも前のバージョン,あるいは,Windows XP 以前の環境でテストする場合は,これまでのサンプルのようにフォームまたは TPanel 等の Canvas に描画してください.
|
|
図8
設計時画面 |
|
図9
操作結果
- [マルチ TIFF 作成] ボタンをクリック
- [マルチ TIFF 表示] ボタンをクリック
- これは最後の画像
サンプルコードでは以下の画像を保存,表示する
503.bmp
ABC.bmp
054709.gif
agt_business.png
|
リスト2
マルチページ TIFF 画像の作成と表示 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, GDIPAPI, GDIPOBJ, GDIPUTIL;
type
TForm1 = class(TForm)
Button1: TButton;
Image1: TImage;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
Math;
{$R *.dfm}
//=============================================================================
// マルチページTIFF画像の作成
// ビットマップ,GIF,PNG画像をTIFFに変換して1つのファイルに格納
// 変換形式は何も設定していないのでデフォルトのまま
//
// このコードは新規作成(上書き)保存としている
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LSaveFilePath : string;
LEncoderParams : TEncoderParameters;
LEncoderParamValue : TEncoderValue;
LclsidTIFF : TGUID;
LGPImage : TGPImage;
LGPImageTIFF : TGPImage;
begin
Button1.Enabled := False;
Button2.Enabled := False;
Sleep(100);
Button2.Refresh;
//保存ファイル名
LSaveFilePath := ExtractFilePath(Application.ExeName) + 'MultiTest.tif';
//ここではTIFFへのエンコードだけ指定
LEncoderParams.Count := 1;
LEncoderParams.Parameter[0].Guid := EncoderSaveFlag;
LEncoderParams.Parameter[0].Type_ := EncoderParameterValueTypeLong;
LEncoderParams.Parameter[0].NumberOfValues := 1;
LEncoderParams.Parameter[0].Value := @LEncoderParamValue;
//TIFFのGUIDを取得
GetEncoderClsid('image/tiff', LclsidTIFF);
//最初の画像をTGPImageに読み込みマルチ画像であることを指定して保存
LGPImage := TGPImage.Create('503.bmp');
LEncoderParamValue := EncoderValueMultiFrame;
LGPImage.Save(LSaveFilePath, LclsidTIFF, @LEncoderParams);
//2番目以降は別のTGPImageを生成して読み込み,それをSaveAddで追加保存する
LGPImageTIFF := TGPImage.Create('ABC.bmp');
try
LEncoderParamValue := EncoderValueFrameDimensionPage;
LGPImage.SaveAdd(LGPImageTIFF, @LEncoderParams);
finally
LGPImageTIFF.Free;
end;
LGPImageTIFF := TGPImage.Create('054709.gif');
try
LEncoderParamValue := EncoderValueFrameDimensionPage;
LGPImage.SaveAdd(LGPImageTIFF, @LEncoderParams);
finally
LGPImageTIFF.Free;
end;
LGPImageTIFF := TGPImage.Create('agt_business.png');
try
LEncoderParamValue := EncoderValueFrameDimensionPage;
LGPImage.SaveAdd(LGPImageTIFF, @LEncoderParams);
finally
LGPImageTIFF.Free;
end;
LGPImage.Free;
Button1.Enabled := True;
Button2.Enabled := True;
end;
//=============================================================================
// マルチページTIFFの表示
// 指定時間間隔で各ページを表示
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LGPGraphic : TGPGraphics;
LGPImage : TGPImage;
LPageGuid : TGUID;
LPageCount : Cardinal;
LPageDimensions : TGPSizeF;
i : Integer;
begin
Button1.Enabled := False;
Sleep(100);
Button1.Refresh;
Button2.Enabled := False;
LGPGraphic := TGPGraphics.Create(Image1.Canvas.Handle);
//TGPImageを生成して画像を読み込み,ページ数を取得
LGPImage := TGPImage.Create('MultiTest.tif');
LPageGuid := FrameDimensionPage;
LPageCount := LGPImage.GetFrameCount(LPageGuid);
//順番に表示
for i := 0 to LPageCount - 1 do begin
LGPImage.SelectActiveFrame(LPageGuid, i);
LGPImage.GetPhysicalDimension(LPageDimensions);
//各ページの画像のサイズが必要なら,以下のコードで取得
//Image1.Width := Trunc(LPageDimensions.Width);
//Image1.Height := Trunc(LPageDimensions.Height);
//TImageのCanvasを現在の色で塗り潰す(画像のクリア)
Image1.Canvas.FillRect(Image1.Canvas.ClipRect);
//表示
LGPGraphic.DrawImage(LGPImage, MakeRect(0, 0, Image1.Width, Image1.Height));
//描画の更新
Image1.Repaint;
Sleep(1000);
end;
LGPGraphic.Free;
LGPImage.Free;
Button1.Enabled := True;
Button2.Enabled := True;
end;
end.
|