Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2013年01月06日] [更新 2013年01月06日] GDI+ 関係サンプル
GDI+ 関係サンプル 
G150_JPEG 画像保存時の品質設定
動作確認等 Windows 7 U64(SP1) + Delphi XE(UP1) Pro
G150_GDIPlus_JPEGQuality.zip [841 KB] 2013年01月06日版 (EXE 同梱)







TGPImage ( TGPBitmap ) 保存時の TEncoderParameter


画像の保存用の TGPImage.Save または TGPBitmap.Save メソッドには,エンコードパラメータと呼ばれる,TEncoderParameter レコード型の値を引数にもつオーバーロード関数があります.
このエンコードパラメータには,次の表の値を使用します.


表1 
TEncoderParameter (EncoderParameter レコード型) のメンバー

GUID 変換の種別を意味する TGUID 値で,表2 の値
NumberOfValues Value に設定する値の数で 符号なし32ビット整数値 (ULONG, Cardinal)
Value に設定する要素数
Type_ Value の型で,表3 のいずれかの値
Value 実際に設定する値のポインタ.表4 の値のいずれか,または実際の値


表2 
EncoderParameter の GUID の値
GUID の値に応じて Value の値を取得または設定する種類.その Value の値の型を Type_ で指定

EncoderCompression 圧縮率
EncoderColorDepth 色のビット深さ.image/tiff 用
EncoderScanMethod スキャン方式 (インターレスまたはノンインターレス)
事実上 GDI+ 1.0 では使用不可
EncoderVersion バージョン
EncoderRenderMethod レンダリングのプログレッシブモードの設定
事実上 GDI+ 1.0 では使用不可
EncoderQuality 画質・品質
EncoderTransformation 画像の回転,反転の状態.image/jpeg 用
EncoderLuminanceTable 要素数 64 (ShorInt) の輝度テーブル.image/jpeg 用
クロミナンスとルミナンスの両方のテーブルの指定が必要
EncoderChrominanceTable 要素数 64 (ShortInt) の彩度ステーブル.image/jpeg 用
クロミナンスとルミナンスの両方のテーブルの指定が必要
EncoderSaveFlag フラグ保存.形式の異なる複数の画像を単一の画像に保存
MSDN の Creating and Saving a Multiple-Frame Image 参照
(複数の画像形式を 1 つの TIFF ファイルに保存するサンプル)
CodecIImageBytes メモリ設定 (?).詳細は不明


表3 
EncoderParameter の Type_ の値

EncoderParameterValueTypeByte 符号なし 8bit整数形式 (Byte, PByte)
EncoderParameterValueTypeASCII 1 つの文字が 8bit の ASCII Null 終端文字
EncoderParameterValueTypeShort 16 ビット符号なし整数 (Word, PWord)
EncoderParameterValueTypeLong 32 ビット符号なし整数 (LongWord, PLongWord)
EncoderParameterValueTypeRational 分数形式の 2 つの 32bit整数
EncoderParameterValueTypeLongRange 整数の範囲を意味する 2 つの 32bit 整数値
EncoderParameterValueTypeUndefined 8 ビット整数と解釈する (ShortInt, PShortInt)
EncoderParameterValueTypeRationalRange 2 つの分数形式で,32bit 整数値


表4 
EncoderParameter の Value の値
回転した画像は,幅と高さはそのままで,その領域内での回転となる

EncoderValueColorTypeCMYK CMYK カラー形式.GDI+ 1.0 は未実装
EncoderValueColorTypeYCCK YCCK カラー形式.GDI+ 1.0 は未実装
EncoderValueCompressionLZW LZW 圧縮スキーム (TIFF)
EncoderValueCompressionCCITT3 CCITT3 圧縮スキーム (TIFF)
EncoderValueCompressionCCITT4 CCITT4 圧縮スキーム (TIFF)
EncoderValueCompressionRle RLE 圧縮スキーム (TIFF)
EncoderValueCompressionNone 無圧縮 (TIFF)
EncoderValueScanMethodInterlaced インターレス.GDI+ 1.0 は未実装
EncoderValueScanMethodNonInterlaced ノンインターレス.GDI+ 1.0 は未実装
EncoderValueVersionGif87 GIF87 ファイル形式.GDI+ 1.0 は未実装
EncoderValueVersionGif89 GIF89 ファイル形式.GDI+ 1.0 は未実装
EncoderValueRenderProgressive プログレッシブレンダリング.GDI+ 1.0 は未実装
EncoderValueRenderNonProgressive ノンプログレッシブレンダリング.GDI+ 1.0 は未実装
EncoderValueTransformRotate90 時計回りに 90 度回転した画像 (JPEG)
EncoderValueTransformRotate180 時計回りに 180 度回転した画像 (JPEG)
EncoderValueTransformRotate270 時計回りに 270 度回転した画像 (JPEG)
EncoderValueTransformFlipHorizontal 左右反転画像 (JPEG)
EncoderValueTransformFlipVertical 上下反転画像 (JPEG)
EncoderValueMultiFrame マルチフレーム画像 (TIFF)
EncoderValueLastFrame マルチフレームの最後のフレーム (TIFF)
EncoderValueFlush 複数フレームのファイルやストリームを閉じる (TIFF)
EncoderValueFrameDimensionTime フレームの時間設定 (TIFF).GDI+ 1.0 は未実装
EncoderValueFrameDimensionResolution フレームの解像度 (TIFF).GDI+ 1.0 は未実装
EncoderValueFrameDimensionPage フレームのページ設定 (TIFF).GDI+ 1.0 は未実装




01_JPEG 画像の保存時の品質設定


エンコードパラメータを使用して,JPEG 画像の品質を設定して保存するサンプルです.
ディスクには保存していません.メモリストリームに保存し,比較のために,元の画像と並べて表示するようにしています.
複数のパラメータの同時設定もできるようですが,実際には,TEncoderParameters を再定義して,メモリ領域を確保してやる必要があるようです.

値の設定にトラックバーを使用していますが,サンプル画像のサイズが小さいので,連続的に変化できますが,大きなサイズの画像では,レスポンスが悪くなります.


図1
設計時画面
図2
実行例

リスト1
JPEG 画像保存時の品質設定
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, ComCtrls, StdCtrls, GDIPOBJ, GDIPAPI,  GDIPUTIL, ExtDlgs,
  ActiveX;

type
  TMyPanel = class(TCustomPanel)
  private
    FImageFilePath : String;
    FJPEGQuality   : Cardinal;
    procedure SetImageFilePath(const Value: String);
    procedure SetJPEGQuality(const Value: Cardinal);
  protected
    procedure Paint; override;
  public
    constructor Create(AOwner: TComponent); override;
    property ImageFilePath : String   read FImageFilePath write SetImageFilePath;
    property JPEGQuality   : Cardinal read FJPEGQuality   write SetJPEGQuality;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    OpenPictureDialog1: TOpenPictureDialog;
    TrackBar1: TTrackBar;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure TrackBar1Change(Sender: TObject);
  private
    { Private 宣言 }
    MyPanel : TMyPanel;
  protected

  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses
  JPEG,
  GifImg,
  pngimage;

{$R *.dfm}

//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  Self.Caption := 'GDI+  JPEG 画像の品質設定';

  //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;

    BevelOuter       := bvNone;
    ParentBackground := False;
    DoubleBuffered   := True;
  end;

  //品質の設定用
  with TrackBar1 do begin
    ShowSelRange := False;
    TickStyle    := tsNone;
    Height   := 26;
    Min      := 0;
    Max      := 100;
    Position := 100;
  end;
end;

//=============================================================================
//  [画像ファイル]ボタン
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
  if not Assigned(MyPanel) then exit;

  if OpenPictureDialog1.InitialDir = '' then begin
    OpenPictureDialog1.InitialDir := ExtractFileDir(ParamStr(0));
  end;

  OpenPictureDialog1.Filter := '画像ファイル|*.png;*.jpg;*.jpeg;*.bmp;*.gif';
  if OpenPictureDialog1.Execute then begin
    OpenPictureDialog1.InitialDir := ExtractFileDir(MyPanel.ImageFilePath);
    MyPanel.ImageFilePath         := OpenPictureDialog1.FileName;
  end;
end;

//=============================================================================
//  TrackBar1のOnChangeイベント処理
//=============================================================================
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
  if not Assigned(MyPanel) then exit;
  MyPanel.JPEGQuality := TrackBar1.Position;
  Label1.Caption := IntToStr(TrackBar1.Position);
end;

{ TMyPanel }

//-----------------------------------------------------------------------------
//  コンストラクタ
//-----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
  inherited;
  FImageFilePath := '';
  FJPEGQuality   := 100;
end;

//-----------------------------------------------------------------------------
//  ImageFilePathプロパティの設定メソッド
//  表示する画像ファイルを指定する
//-----------------------------------------------------------------------------
procedure TMyPanel.SetImageFilePath(const Value: String);
begin
  if not FileExists(Value) then exit;

  FImageFilePath := Value;
  Invalidate;
end;

//-----------------------------------------------------------------------------
//  JPEGQualityプロパティの設定メソッド
//-----------------------------------------------------------------------------
procedure TMyPanel.SetJPEGQuality(const Value: Cardinal);
begin
  if FImageFilePath = '' then exit;
  if FJPEGQuality <> Value then begin
    FJPEGQuality := Value;
    Invalidate;
  end;
end;

//-----------------------------------------------------------------------------
//  TMyPanelクラスのPaintメソッド
//  実際の描画コード
//-----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
  LObjWidth      : Integer;
  LObjHeight     : Integer;
  LGPImage       : TGPImage;
  LGPGraphic     : TGPGraphics;
  LEncoderParams : TEncoderParameters;
  LMemoryStream  : TMemoryStream;
  LIStrema       : IStream;
  LImageGUID     : TGUID;
begin
  inherited;
  if FImageFilePath = '' then exit;

  //画像ファイルからTGPImageのインスタンスを生成.幅と高さを取得
  LGPImage   := TGPImage.Create(FImageFilePath);
  LObjWidth   := LGPImage.GetWidth;
  LObjHeight  := LGPImage.GetHeight;

  //画像をTMyPanelのCanvasに描画
  LGPGraphic := TGPGraphics.Create(Canvas.Handle);
  LGPGraphic.DrawImage(LGPImage, 0, 0, LObjWidth, LObjHeight);

  //JPEGの品質関係の値をTEncoderParametersレコード型の各メンバーにセット
  LEncoderParams.Count := 1;
  LEncoderParams.Parameter[0].Guid           := EncoderQuality;
  LEncoderParams.Parameter[0].Type_          := EncoderParameterValueTypeLong;
  LEncoderParams.Parameter[0].NumberOfValues := 1;
  LEncoderParams.Parameter[0].Value := @FJPEGQuality;

  LMemoryStream := TMemoryStream.Create;
  try
    //メモリストリームを生成して,そこに保存
    GetEncoderClsid('image/jpeg', LImageGUID);
    LGPImage.Save(TStreamAdapter.Create(LMemoryStream), LImageGUID, @LEncoderParams);

    LGPImage.Free;
    //保存したJPEG画像を読み出して描画
    LIStrema := TStreamAdapter.Create(LMemoryStream);
    LGPImage := TGPBitmap.Create(LIStrema);
    LGPGraphic.DrawImage(LGPImage, LObjWidth + 10, 0, LObjWidth, LObjHeight);
  finally
    LMemoryStream.Free;
  end;

  LGPImage.Free;
  LGPGraphic.Free;
end;

end.




02_画像処理のテスト用画像とレナ ( Lenna ) の画像


GDI+ 関係のサンプルプログラムでは使用していませんが,画像処理の研究等によく利用される「標準画像」と言われるテスト用画像があります.その一部が下図の画像類です.
画像処理の関係者以外でも,画像処理関係の参考書を読んだことがある方は,おそくら見たことがあるかも知れません.特に,最後のレナと呼ばれている画像は,
  • フォーカス合っている人物像と,フォーカスが外れた背景領域の両方がある
  • 背景も単調な壁ではなく,鏡や斜めの「構造」が含まれている
  • 高周波 (帽子の飾りや髪) 領域と,低周波 (腕や背景) 領域の両方を含んでいる
等の理由で使用されています.また,グレイスケール化した画像もよく使われているようです.
これらの元画像は,提供元の Signal and Image Processing Institute のサイトからダウンロードできます.
他の方,あるいは,別の処理方法と処理結果を比較する必要がある場合は,これらの標準画像を使用するといいでしょう.


[注意]
下図の画像も含めて,当サイトの画像は,拡張子を除いたファイル名で管理している都合上,極一部を除いて全て 256 色の gif 画像となっています.したがって,画像処理のサンプル画像としては決して適切とは言えません.
下図の画像が必要な場合は,参考リンクから入手してください.ただし,参考リンクから入手した医用画像には,グレースケール (白黒・モノクロ) の 256, 512, 1024 等の階調の画像もあります.これはセンサーの分解能による違いです.


図3
ガール (Girl)
図4
マンドリル (Mandrill)
図5
パロッツ (Parrots)
図6
レナ (lenna)