Delphi Programming / Object Pascal
[掲載 2012年12月02日] [更新 2017年07月02日] GDI+ 関係サンプル |
GDI+ 関係サンプル
G042_GDI+ を使用しない画像形式の変換 |
動作確認等 |
Windows 7 U64(SP1) + Delphi XE(UP1) Pro |
|
G042_GDIPlus_ChangeImageTypes.zip [1,891 KB] 2017年07月02日版 (EXE 同梱) |
GDI+ を使用しない画像形式の変換テストです.
原理は単純です.画像をディスクから読み込み,保存する時に目的の画像形式で保存します.必要であれば,圧縮レベルの設定や透明処理を行ってから保存します.本サンプルでは,画像を TImage に表示していますが,画像を表示する必要がなければ,TImage を使用する必要はありません.
JPEG 画像は Delphi 3 から,GIF 画像は Delphi 2007 から,PNG 画素は Delphi 2009 からサポートされています.TPngImage はアルファチャンネルもサポートしています.
ビットマップを他の画像形式に変換するこれらのコードは,GDI+ を使用する場合にも必要となることがあります.例えば,表示サイズで画像を保存したい場合にも利用できます. |
|
図1
設計時画面 |
|
図2
24 bit ビットマップの変換
- 24 ビットのビットマップ画像を読み込んで,変換して保存
|
|
図3
32 ビットの α チャンネル付きビットマップの変換
- 32 ビットのビットマップ画像を読み込んで,変換して保存
- 元の画像が 24 ビットの時の違いは,保存した画像を表示した時の目の部分と背景色に注目
|
リスト1
GDI+ を使用しない画像形式の変換.変換元の画像がビットマップの例 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, GDIPAPI, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Image1: TImage;
Button1: TButton;
Button2: TButton;
Button3: TButton;
RadioGroup1: TRadioGroup;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
Jpeg,
GifImg,
PNGImage;
{$R *.dfm}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.Caption := '画像形式の変換テスト';
RadioGroup1.ItemIndex := 0;
end;
//=============================================================================
// BMP画像をJPEG画像形式に変換して保存
// 添付の32ビットビットマップはアルファチャンネル付
//
// usesにJpegが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LFileName : string;
LFilePath : string;
LSavePath : string;
LBitmap : TBitmap;
LJpegImg : TJPEGImage;
begin
if RadioGroup1.ItemIndex = 0 then begin
LFileName := '503_24bit.bmp';
end else begin
//アルファチャンネル付32bitビットマップ
LFileName := '502_32bit.bmp';
end;
LFilePath := ExtractFilePath(Application.ExeName) + LFileName;
LSavePath := ExtractFilePath(Application.ExeName) + 'Changed_' + LFileName;
LBitmap := TBitmap.Create;
try
if RadioGroup1.ItemIndex = 1 then begin
LBitmap.PixelFormat := pf32bit;
LBitmap.AlphaFormat := afDefined;
end;
//変換元のビットマップ画像を読み込んでTImageに表示
//TImageへの表示は確認用.表示しなくてもよい
LBitmap.LoadFromFile(LFilePath);
Image1.Picture.Bitmap.Assign(LBitmap);
LJpegImg := TJPEGImage.Create;
try
LJpegImg.Assign(LBitmap);
//JPEG画像品質の設定(デフォルト値は90)
LJpegImg.CompressionQuality := 75;
//拡張子を変更してJPEG画像保存
LSavePath := ChangeFileExt(LSavePath, '.jpg');
LJpegImg.SaveToFile(LSavePath);
finally
FreeAndNil(LJpegImg);
end;
finally
FreeAndNil(LBitmap);
end;
end;
//=============================================================================
// BMP画像をGIF画像形式に変換して保存
// 添付の32ビットビットマップはアルファチャンネル付
//
// usesにGifimgが必要
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LFileName : string;
LFilePath : string;
LSavePath : string;
LBitmap : TBitmap;
LGifImage : TGIFImage;
LGifExtent : TGIFGraphicControlExtension;
LColor : TColor;
begin
if RadioGroup1.ItemIndex = 0 then begin
LFileName := '503_24bit.bmp';
end else begin
//アルファチャンネル付32bitビットマップ
LFileName := '502_32bit.bmp';
end;
LFilePath := ExtractFilePath(Application.ExeName) + LFileName;
LSavePath := ExtractFilePath(Application.ExeName) + 'Changed_' + LFileName;
LBitmap := TBitmap.Create;
try
if RadioGroup1.ItemIndex = 1 then begin
LBitmap.PixelFormat := pf32bit;
LBitmap.AlphaFormat := afDefined;
end;
//変換元のビットマップ画像を読み込んでTImageに表示
//TImageへの表示は確認用.表示しなくてもよい
LBitmap.LoadFromFile(LFilePath);
Image1.Picture.Bitmap.Assign(LBitmap);
LGifImage := TGIFImage.Create;
try
LGifImage.Assign(LBitmap);
//カラーマップの最適化
LGifImage.OptimizeColorMap;
//GIFイメージの透明化処理
LColor := LGifImage.Bitmap.Canvas.Pixels[0, LGifImage.Bitmap.Height - 1];
LGifExtent := TGIFGraphicControlExtension.Create(LGifImage.Images[0]);
LGifExtent.Transparent := True;
LGifExtent.TransparentColor := LColor;
//拡張子を変更してGIF画像保存
LSavePath := ChangeFileExt(LSavePath, '.gif');
LGifImage.SaveToFile(LSavePath);
finally
FreeAndNil(LGifImage);
end;
finally
FreeAndNil(LBitmap);
end;
end;
//=============================================================================
// BMP画像をPNG画像形式に変換して保存
// 添付の32ビットビットマップはアルファチャンネル付
//
// usesにPNGImageが必要
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
LFileName : string;
LFilePath : string;
LSavePath : string;
LBitmap : TBitmap;
LPNGImag : TPngImage;
LColor : TColor;
begin
if RadioGroup1.ItemIndex = 0 then begin
LFileName := '503_24bit.bmp';
end else begin
//アルファチャンネル付32bitビットマップ
LFileName := '502_32bit.bmp';
end;
LFilePath := ExtractFilePath(Application.ExeName) + LFileName;
LSavePath := ExtractFilePath(Application.ExeName) + 'Changed_' + LFileName;
LBitmap := TBitmap.Create;
try
if RadioGroup1.ItemIndex = 1 then begin
LBitmap.PixelFormat := pf32bit;
LBitmap.AlphaFormat := afDefined;
end;
//変換元のビットマップ画像を読み込んでTImageに表示
//TImageへの表示は確認用.表示しなくてもよい
LBitmap.LoadFromFile(LFilePath);
Image1.Picture.Bitmap.Assign(LBitmap);
LPNGImag := TPngImage.Create;
try
//元のビットマップがアルファ値をもっていてもアルファ値はコピーされない
LPNGImag.Assign(LBitmap);
//圧縮レベルの設定(デフォルト値は7)
LPNGImag.CompressionLevel := 7;
//PNGイメージの透明化処理
LColor := LPNGImag.Canvas.Pixels[0, LPNGImag.Height - 1];
LPNGImag.Transparent := True;
LPNGImag.TransparentColor := LColor;
//拡張子を変更してPNG画像保存
LSavePath := ChangeFileExt(LSavePath, '.png');
LPNGImag.SaveToFile(LSavePath);
finally
FreeAndNil(LPNGImag);
end;
finally
FreeAndNil(LBitmap);
end;
end;
end.
02_半透明のビットマップ画像を TPngImage 形式の画像に変換 |
上のコードでもアルファチャンネル付きのビットマップ画像を TPngImage 形式の画像に変換はできますが,半透明のビットマップを変換すると正常な色になりません.
ピクセルの操作が必要です.参考リンクの記事にもありますが,こちらにも掲載しておきます. |
リスト2
半透明のビットマップ画像も TPngImage 形式の画像に変換するコード例 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, GDIPAPI, StdCtrls, ExtCtrls, ExtDlgs, pngimage;
type
TForm1 = class(TForm)
Image1: TImage;
Button1: TButton;
OpenPictureDialog1: TOpenPictureDialog;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
FLoadInitDir : string;
FImageFilePath : string;
function ChangeBitmapToPngimage(SrcBitmap: TBitmap;
DstPngImage: TPngImage): Boolean;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
FLoadInitDir := ExpandFileName('.\');
end;
//=============================================================================
// BMP画像をPNG画像形式に変換して保存
// 半透明のビットマップもPNG形式の画像に変換
//
// usesにPNGImageが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LBitmap : TBitmap;
LPngImage : TPngImage;
LSavePath : string;
begin
Image1.Picture.Assign(nil);
OpenPictureDialog1.Filter := '画像ファイル|*.bmp';
OpenPictureDialog1.InitialDir := FLoadInitDir;
if not OpenPictureDialog1.Execute then exit;
FImageFilePath := OpenPictureDialog1.FileName;
FLoadInitDir := ExtractFileDir(FImageFilePath);
LBitmap := TBitmap.Create;
try
LBitmap.LoadFromFile(FImageFilePath);
if LBitmap.PixelFormat = pf32bit then begin
//ここで以下にしないこと
//afDefinedにしてしまうとPNG画像の色がおかしくなる
//LBitmap.AlphaFormat := afDefined;
Image1.Picture.Bitmap.Assign(LBitmap);
//TPngImage生成
LPngImage := TPngImage.CreateBlank(COLOR_RGBALPHA,
8,
LBitmap.Width,
LBitmap.Height);
try
//TBitmapをTPngImageに変換
ChangeBitmapToPngimage(LBitmap, LPngImage);
//保存
LSavePath := ChangeFileExt(FImageFilePath, '.png');
LPngImage.SaveToFile(LSavePath);
//ビットマップをアルファチャンネル付で表示したい場合
//TPngImageに変換してからafDefinedにして描画する
LBitmap.AlphaFormat := afDefined;
Image1.Picture.Bitmap.Assign(LBitmap);
finally
FreeAndNil(LPngImage);
end;
end;
finally
FreeAndNil(LBitmap);
end;
end;
//-----------------------------------------------------------------------------
// TBitmapをアルファチャンネルの情報を保持してTPngImageに変換
//-----------------------------------------------------------------------------
function TForm1.ChangeBitmapToPngimage(SrcBitmap: TBitmap;
DstPngImage: TPngImage): Boolean;
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
LBmpScanLine : PRGBQArray;
LPngScanLine : PRGBTArray;
LpPngARGBQuad : RGBQUAD;
LpBmpRGBTriple : RGBTRIPLE;
LYPos : Integer;
LXPos : Integer;
begin
Result := True;
for LYPos := 0 to SrcBitmap.Height - 1 do begin
LBmpScanLine := SrcBitmap.ScanLine[LYPos];
LPngScanLine := DstPngImage.ScanLine[LYPos];
for LXPos := 0 to SrcBitmap.Width - 1 do begin
LpPngARGBQuad := LBmpScanLine[LXPos];
LpBmpRGBTriple.rgbtBlue := LpPngARGBQuad.rgbBlue;
LpBmpRGBTriple.rgbtGreen := LpPngARGBQuad.rgbGreen;
LpBmpRGBTriple.rgbtRed := LpPngARGBQuad.rgbRed;
LPngScanLine[LXPos] := LpBmpRGBTriple;
DstPngImage.AlphaScanline[LYPos]^[LXPos] := LpPngARGBQuad.rgbReserved;
end;
end;
end;
end.
TPngImage を TBitmap 画像に変換するにはは,単純に Assign メソッドで可能です. |
TBitmap.Assign(TPngImage);
03_TImage に描画している画像の形式と保存 |
TImage に描画している画像の形式の確認方法と,その画像を TBitmap 形式の画像に変換する例です.
本サンプルでは TImage に TJPEGImage 形式の画像を描画してテストしています. |
リスト3
TImage に描画している画像の形式の確認の方法と,ビットマップ画像への変換
TBitmap に変換できれば,前項の方法で他の形式にも変換できる |
implementation
uses
Jpeg,
GifImg,
PNGImage;
{$R *.dfm}
//=============================================================================
// TImageに描画している画像形式が何であるかを確認する方法
// TImageに描画している画像を同じ画像形式で別の名前で保存する例
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
Image1.Picture.LoadFromFile('503.jpg');
//TImageに描画されているのがTJPegImaageの画像形式の場合
if (Image1.Picture.Graphic is TJPEGImage) then begin
//別名で保存
//拡張子を変更しても別の画像形式にはならない
Image1.Picture.SaveToFile('000.jpg');
end;
end;
//=============================================================================
// TImageに描画している画像形式が何であるかを確認する方法
// TImageに描画している画像を別の画像形式で保存する例
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LBitmap : TBitmap;
begin
Image1.Picture.LoadFromFile('503.jpg');
//TImageに描画されているのがTJPegImaageの画像形式の場合
if (Image1.Picture.Graphic is TJPEGImage) then begin
LBitmap := TBitmap.Create;
try
//ビットマップにして保存
//ビットマップを他の画像形式に変換すれば他の画像形式での保存が可能
LBitmap.Assign(Image1.Picture.Graphic);
LBitmap.SaveToFile('000.bmp');
finally
FreeAndNil(LBitmap);
end;
end;
end;
04_JPEG 形式等の画像を TBitmap 形式の画像に変換 |
TImage には表示していない TJPEGImage 形式の画像を TBitmap 形式の画像に変換する例です.この方法は,JPEG 画像以外でも利用できます.
最初の方法は TBitamap.Assign メソッドを使用しています.次のコードは,TBitmap.Canvas に描画する方法です.
|
リスト4
JPEG 形式の画像をビットマップ画像に変換する例
同じ方法で,他の画像形式もビットマップ画像に変換できる |
implementation
uses
Jpeg,
GifImg,
PNGImage;
{$R *.dfm}
//=============================================================================
// JPEG形式の画像をTBitmap形式の画像に変換
// Assignメソッドを使用する方法
// 他の加増形式も同じ方法でTBitmapに変換できる
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LJpegImage : TJPEGImage;
LBitmap : TBitmap;
begin
LJpegImage := TJPEGImage.Create;
LBitmap := TBitmap.Create;
try
//JPEG画像を読み込む
LJpegImage.LoadFromFile('503.jpg');
//ビットマップに代入
LBitmap.Assign(LJpegImage);
//ビットマップを保存
LBitmap.SaveToFile('000.bmp');
finally
FreeAndNil(LJpegImage);
FreeAndNil(LBitmap);
end;
end;
//=============================================================================
// JPEG形式の画像をTBitmap形式の画像に変換
// TBitmap.Canvasに描画する方法
// 他の加増形式も同じ方法でTBitmapに変換できる
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
LJpegImage : TJPEGImage;
LBitmap : TBitmap;
begin
LJpegImage := TJPEGImage.Create;
LBitmap := TBitmap.Create;
try
//JPEG画像を読み込む
LJpegImage.LoadFromFile('503.jpg');
//ビットマップのサイズを設定してCanvaaに描画
LBitmap.Width := LJpegImage.Width;
LBitmap.Height := LJpegImage.Height;
LBitmap.Canvas.Draw(0, 0, LJpegImage);
//ビットマップを保存
LBitmap.SaveToFile('000.bmp');
finally
FreeAndNil(LJpegImage);
FreeAndNil(LBitmap);
end;
end;
05_TWICImage を使用した TIFF 画像への変換 |
シングルの TIFF 画像であれば,Delphi 2010 で実装された TWICImage クラスを使用して以下のように表示できます.
画像形式の確認または,画像形式の変換は,TWICImage.ImageFormat プロパティを使用します.このプロパティの値を使用すれば,TWICImage がサポートしている画像形式に変換して保存できます.たとえ TWICImage を使用しても,画像の読み込みの時とは違い,拡張子を変えるだけでは画像の形式は変わりません.拡張子を変えただけだと,中身は元の画像形式のままです.
各種画像形式の詳細な設定はできません.
TWICImage は,Windows Vista 以降,.NET Framework 3.0 以降の環境で使用可能です.
|
リスト5
TWICImage クラスを使用した TIFF 画像の表示と変換
TWICImage.ImageFormat プロパティを変更すれば,他の画像形式に変換できる |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ExtDlgs;
type
TForm1 = class(TForm)
Button1: TButton;
Image1: TImage;
Button2: TButton;
OpenPictureDialog1: TOpenPictureDialog;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
OpenPictureDialog1.InitialDir := ExpandFileName('..\');
end;
//=============================================================================
// TWICImageを使用して,画像をTImageに表示
// Image1.Repaint; あるいはUpdate等を表示確認のために入れておいた方が良い
//
// アルファチャンネル付の画像の場合
// TImage.Picture.Bitmap.AlphaFormat := afDefined;
// でアルファチャンネルの描画が有効となるのだが,以下のコードでは無効
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LFilePath : string;
LWICImage : TWICImage;
begin
if not OpenPictureDialog1.Execute then exit;
LFilePath := OpenPictureDialog1.FileName;
OpenPictureDialog1.InitialDir := ExtractFileDir(LFilePath);
LWICImage := TWICImage.Create;
try
LWICImage.LoadFromFile(LFilePath);
Image1.Picture.Assign(LWICImage);
Image1.Repaint;
finally
FreeAndNil(LWICImage);
end;
end;
//=============================================================================
// TWICImageを使用して,ビットマップ画像をTIFF画像に変換して保存
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LBitmap : TBitmap;
LWICImage : TWICImage;
begin
LBitmap := TBitmap.Create;
LWICImage := TWICImage.Create;
try
LBitmap.LoadFromFile('503.bmp');
LWICImage.Assign(LBitmap);
LWICImage.ImageFormat := wifTiff;
LWICImage.SaveToFile('503.tif');
finally
FreeAndNil(LWICImage);
FreeAndNil(LBitmap);
end;
end;
end.
|