Delphi 2009ではTBitmapの32ビット形式サポート、PNGサポート、TCanvas.Drawメソッドの拡張、TImageListの拡張など、グラフィック機能の強化も行われています。今回は新しいグラフィック機能についてできるだけ網羅的に解説を行います。
新たに追加されたTPNGImage
Delphi 2009からはついにPNGが標準でサポートされました。これでようやくビットマップ、JPEG、GIF、PNGの標準的なライブラリが全て揃ったことになります。
PNGを扱うクラスはTPNGImageです。使用するにはまずuses節にPNGImageを追加します
※JPEG、PNG、GIFのユニット名
困ったことに、JPEG、GIF、PNGのユニット名は命名規則が統一されていません。
JPEG:JPEG.pas(Delphi 3から)
GIF:GIFImg.pas(Delphi 2007から)
PNG:PNGImage.pas(Delphi 2009から)
これは、元々GIFがAnders Melander氏制作のライブラリ、PNGがGustavo Huffenbacher Daud氏制作のライブラリであるからです。
※JPEG、PNG、GIFのヘルプはどこに?
極めて残念なことですが、Delphi 2009 Help Update 1の時点では、JPEG、PNG、GIFのドキュメントは収録されていません。
JPEGについての使用方法は流石に周知されているとは思いますが、PNG、GIFについての情報が付属のヘルプから得られないのは大変不便です。
○JPEGのドキュメント
少なくともDelphi 2006のヘルプには収録されているので、
Turbo Delphi Explorerを導入すればTJPEGImageについてのリファレンスを無料で入手できます。
当然ですがDelphi 3~2006をお持ちであればそれらに収録されているドキュメントを参照すればOKです。
○PNGのドキュメント
もし、旧バージョン等でTPNGImageを導入していたのであれば、
付属しているヘルプを参照すればかなり参考になりますが、残念なことに現状では新規に入手する方法がありません。
○GIFのドキュメント
TGIFImageの作者のページは閉鎖されていますが、ライブラリ自体は配布されているサイトがあります。
http://www.tolderlund.eu/delphi/
ヘルプも同時に配布されているので、それを利用すればなんとかなるでしょう。
(ただし、多少の読み替えが必要な場合があります)
PNGの作成・読み込み・保存
TPNGImageの使い方は非常に簡単で、TJPEGImageのようなグラフィッククラスを使ったことがあればすぐに使いこなせるように出来ています。
ここではまず、ビットマップをPNGに変換してファイルに保存する例を見てみます。
Code#004:BitmapからPNGへの変換
uses
・・・・, PNGImage;
var
BMP: TBitmap;
PNG: TPNGImage;
begin
BMP := TBitmap.Create;
PNG := TPNGImage.Create;
try
BMP.LoadFromFile('hogehoge.bmp');
PNG.Assign(BMP);
PNG.CompressionLevel := 5;
PNG.Filters := [pfNone,pfSub,pfUp,pfAverage,pfPaeth];
PNG.SaveToFile('HogeHoge.png');
finally
BMP.Free;
PNG.Free
end;
end;
ビットマップを変換してPNGを生成するのもJPEGと同じ要領で、極めて簡単です。AssignするだけでOKです。ただし、Assignの引数に指定するビットマップが32ビット形式の場合はエラーを起こしてしまいます。32ビット形式から変換をする際には別の変換方法を採用しなければなりません。
PNGの圧縮レベルはCompressionLevelプロパティで指定します。JPEGの際は1~100の整数値を指定し、数値が大きいほど高品質(=ファイルサイズは大きい)でした。PNGの場合は、0~9の整数値を指定し、数値が小さいほど速度重視(=ファイルサイズは大きい)、数値が大きいほど圧縮率重視(=ファイルサイズは小さい)になります。
PNGのフィルターはFiltersプロパティで指定します。Filtersプロパティには複数のフィルターを指定することが可能です。フィルターはpfNone、pfSub、pfUp、pfAverage、pfPaethの5種類を指定できます。特段の理由がなければ上記コードのように全てのフィルターを指定することが推奨されています。
ファイルの読み込みについてはLoadFromFile、ファイルへの保存についてはSaveToFileメソッドが使えます。つまり、TBitmapやTJPEGImageと全く同じ要領でPNGファイルの読み書きが可能です。
アルファチャンネル
TPNGImageはアルファチャネルもサポートしています。ここでは、既存の24ビットPNG画像に対して新たにアルファチャンネルを設定する例を紹介します。アルファチャネルを設定するには、AlphaScanlineを使うと便利です。
Code#005:アルファチャンネルの作成
var
i,ii: Integer;
PNG: TPNGImage;
begin
PNG := TPngImage.Create;
try
PNG.LoadFromFile('alpha.png');
PNG.CreateAlpha;
for i := 0 to PNG.Height - 1 do
begin
for ii := 0 to PNG.Width - 1 do
begin
PNG.AlphaScanline[i]^[ii] := 128;
end;
end;
PNG.SaveToFile('alpha.png');
finally
PNG.Free;
end;
end;
まずTPNGImageのインスタンスを生成し、ファイルを読み込みます。次にCreateAlphaメソッドを実行します。32ビット形式でないPNG画像の場合はCreateAlphaメソッドを実行してからではないとアルファチャンネルの設定が出来ません。CreateAlphaメソッドを実行したら、1ピクセルずつAlphaScanlineを使ってアルファチャンネルの値を設定していきます。
実行結果は以下の通りです。
実行結果

画像全体が半透明で表示されています。TBitmapと違い、表示前にAlphaFormatプロパティを設定するといったような作業は不要です。
32ビット形式のビットマップからの変換
PixelFormat = pf32bitのTBitmapから直にAssignするとエラーになるので、若干面倒なコードを書かなければなりません。
Code#006:32ビット形式のビットマップからの変換
type
TRGBQArray = array [0..High(Integer) div 4 - 1] of RGBQUAD;
PRGBQArray = ^TRGBQArray;
TRGBTArray = array [0..High(Integer) div 3 - 1] of RGBTRIPLE;
PRGBTArray = ^TRGBTArray;
var
PNG: TPngImage;
i,ii: Integer;
BPQ: PRGBQArray;
CQ: RGBQUAD;
PPT: PRGBTArray;
CT: RGBTRIPLE;
BMP: TBitmap;
begin
BMP := TBitmap.Create;
PNG := TPngImage.CreateBlank(COLOR_RGBALPHA,8,100,100);
try
BMP.LoadFromFile('original.bmp');
for i := 0 to BMP.Height - 1 do
begin
BPQ := BMP.ScanLine[i];
PPT := PNG.ScanLine[i];
for ii := 0 to BMP.Width - 1 do
begin
CQ := BPQ[ii];
CT.rgbtBlue := CQ.rgbBlue;
CT.rgbtGreen := CQ.rgbGreen;
CT.rgbtRed := CQ.rgbRed;
PPT[ii] := CT;
PNG.AlphaScanline[i]^[ii] := CQ.rgbReserved;
end;
end;
PNG.SaveToFile('result.png');
finally
BMP.Free;
PNG.Free;
end;
end;
まず、TPNGImageのインスタンスをCreateメソッドではなくCreateBlankメソッドで作成します。なぜなら、TPNGImageのWidthとHeightはReadOnlyなので、新しい値を代入できません。今回のコードでは空のPNGにビットマップの情報を1ピクセルずつ移植するという処理なので、WidthとHeightを設定しないままTPNGImageのインスタンスを生成するCreateは役に立ちません。
CreateBlankメソッドの第1引数にはCOLOR_RGBALPHAを指定します。これで32ビット形式のPNGとなるので、別途CreateAlphaメソッドを実行する必要がなくなります。第2引数は8をセットしておけば1ピクセルあたりの情報量はRGBAの4バイトになります。第3,4引数には新しいイメージの幅と高さ(今回の例では両方ともビットマップ画像の幅と高さである100)をセットします。
変換はビットマップの各ピクセルの情報のうち、RGBをRGBTripleの変数を経由してScanlineで、Alpha値をAlphaScanlineで渡しています。
半透明描画が可能なDrawメソッド
TCanvas.Drawメソッドに新しくオーバーロードが追加されました。従来は引数が3つでしたが、新たなオーバーロードは4つめの引数にOpacityというバイト型をとる物が追加されています。これは描画時にOpacityに値を指定することによって、Graphicで指定した画像を半透明で描画することが出来るという機能です。
Code#007:TCanvas.Drawのオーバーロード
var
BMP: TBitmap;
begin
BMP := TBitmap.Create;
try
BMP.LoadFromFile('original.bmp');
PaintBox1.Canvas.Draw(0,0,BMP);
PaintBox2.Canvas.Draw(0,0,BMP,64);
finally
BMP.Free;
end;
end;
実行結果

左側が従来のメソッド、右側が新しいオーバーロードされたメソッドで描画したものです。
右側はOpacityに64を指定しているため、画像全体が半透明になって描画されています。