Delphi Programming / Object Pascal
[掲載 2012年11月23日] [更新 2017年07月27日] GDI+ 関係サンプル
GDI+ 関係サンプル
G022_カラーマトリックスによる画像の色操作
動作確認等
Windows 7 U64(SP1) + Delphi XE(UP1) Pro
G022_GDIPlus_ColorMatrix.zip [6,360 KB] 2017年07月27日版 (EXE 同梱)
このページのサンプルも,GDI+ のテストプログラムです.
「移動リサイズコントロール」とは直接関係ありませんが,画像を扱う際の参考用です.
GDI+ では,色に対してカラーマトリックス (カラー行例,色行列) を使用することにより,画像の各ピクセルに対して各種の操作を行うことができます.
この行列は,各ピクセルの,赤 (R),緑 (G),青 (B),アルファ値 (α)
に対して,以下の線形演算を実行します.
このマトリックスの各要素の値は,0 から 1.0 の実数値を使用します.0.0 は輝度がないか透明であることを意味し,1.0 は輝度が最大か完全な不透明であることを意味します.要素の値は実数ですが,実際の画素,ピクセルに適用される値は 0 から 255 の範囲となります.
行列の [5, 5] の値は常に 1.0 とします.第 5 例目のその他の要素は 常に 0.0 とします.
第 1 列目は赤 (R) の要素に対する設定
第 2 列目は緑 (G) の要素に対する設定
第 3 列目は青 (B) の要素に対する設定
第 4 列目はアルファ値対する設定
第 5 列目はダミーの列
となっています.同様に各行は,例えば第 1 列目の,
第 1 行目は赤 (R) のピクセルの赤 (R) の割合
第 2 行目は赤 (R) のピクセルの緑 (G) の割合
第 3 行目は赤 (R) のピクセルの青 (B) の割合
第 4 行目は赤 (R) のピクセルのアルファ値の割合
第 5 行目は赤 (R) のピクセルの色の平行移動量の割合
となっています.第 5 行目は色の移動,平行移動のアフィイン変換 (線形変換に続いて平行移動を実行する変換) を可能にしています.マトリックスの行数と列数を同じにするために,第 5 列目をダミーとして追加しています.これによって線形変換と平行移動を任意に組み合わせた変換を実行することができます.
このカラーマトリックスの初期値は,以下の単位行列としますが,TColorMatrix の変数を定義してもこの値とはなりません.利用者が単位行列に初期化する必要があります.
以下は,これカラーマトリックスを使用した簡単なテストプログラムです.
カラーマトリックスは,TGPImageAttributes のオブジェクトを生成して,SetColorMatrix 関数でセットして使用します.
リスト1
カラーマトリックスは,TGPImageAttributes のオブジェクトを生成して,
その TGPImageAttributes
の SetColorMatrix 関数でセットする
copy code
var
LGPGraohc : TGPGraphics;
LGPImgAttr : TGPImageAttributes;
......
begin
LGPImgAttr := TGPImageAttributes.Create;
LGPImgAttr.SetColorMatrix(ColorMatrix);
......
......
リスト2
カラーマトリックスの初期化操作.単位行列を作成する例
copy code
// カラーマトリックスの初期化(単位行列を作成)
FillChar(ColorMatrix, SizeOf(TColorMatrix), #0 );
for i := 0 to 4 do begin
ColorMatrix[i, i] := 1.0 ;
end ;
TGPImageAttributes には,このページで紹介している以外にも次のような関数があります.
[備考]
サンプルの記事とは直線関係ありませんが,FireMonkey フレームワークでは,多くの画像処理関係の機能が実装されています.
FireMonkeyでは,2D 関係のグラフィックス処理は,Direct2D が使用されます.Direct2D が使用できない環境では GDI+ が使用される仕様になっています.RAD Studio 関係のオンラインヘルプも画像付きとなり,筆者が Delphi でプログラミングを始めた頃と較べると,隔世の感があります.
このサンプルでは,あらかじめ値をセットしたカラーマトリックスを,RadioGroup で選択して,そのカラーマトリックスを使用して色を操作します.
図1
設計時画面
図2
オリジナル画像
次図は,次のように,カラーマトリックスの緑の要素だけを 1 とした場合です.
[緑以外は非描画]は,この数値を -1 にする場合ですが,筆者の Windows 7 では 1 の時と同じ結果となりました.Windows XP では描画しない効果がありました.
図3
青以外の輝度が 0 の場合
次の図は,赤,緑,青の輝度の要素の値を,次のように -1 にした場合の結果です.
色が反転して,ネガ画像となります.
図4
色が反転してネガになる
copy code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, ComCtrls, StdCtrls, GDIPOBJ, GDIPAPI;
type
TMyPanel = class (TPanel)
protected
procedure Paint; override ;
end ;
TForm1 = class (TForm)
RadioGroup1: TRadioGroup;
procedure FormCreate(Sender: TObject);
procedure RadioGroup1Click(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
protected
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 := 130 ;
Top := 5 ;
Width := Self.ClientWidth - Left - 5 ;
Height := Self.ClientHeight - Top - 5 ;
Anchors := [akLeft, akTop, akRight, akBottom];
Color := clWhite;
ParentBackground := False;
DoubleBuffered := True;
end ;
// RadioGrou1に選択項目を作成して表示
RadioGroup1.Items.Add('オリジナル' );
RadioGroup1.Items.Add('赤以外は非描画' );
RadioGroup1.Items.Add('赤以外は輝度 0' );
RadioGroup1.Items.Add('緑以外は非描画' );
RadioGroup1.Items.Add('緑以外は輝度 0' );
RadioGroup1.Items.Add('青以外は非描画' );
RadioGroup1.Items.Add('青以外は輝度 0' );
RadioGroup1.Items.Add('反転 (ネガ)' );
// 初期選択項目
RadioGroup1.ItemIndex := 0 ;
end ;
// =============================================================================
// RadioGroup1のOnClickイベン
// RadioGroup1の選択項目を変更したら,MyPanelを再描画
// =============================================================================
procedure TForm1.RadioGroup1Click(Sender: TObject);
begin
MyPanel.Invalidate;
end ;
{ TMyPanel }
// -----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
//
// このPaintメソッドのコードだけをコピペしてのテストも可能
//
// (1) 新規プロジェクトを作成
// (2) usesにGDIPOBJ, GDIPAPIに追加
// (3) Form1のOnPaintイベントハンドラを作成(コードは空のまま)
// (4) このPaintメソッドのコードを,そのイベントハンドラに貼り付け
// (5) inherited; の行を削除(実際には何もしないのであってもかまわない
// (6) コンパイルするとエラーが発生するので修正
// (7) このエラーは,ほとんどプロパティ関係なので,変数のかわりに数値等を書く
//
// 他の,似たような構成のサンプルコードは,全て同じようにテスト可能
// そのために,クラス構成のTMyPanelを定義したサンプルにしている
// -----------------------------------------------------------------------------
procedure TMyPanel.Paint;
// ---------------------------------------------------------------------------
// いろいろなカラーマトリックスを用意しておく
// RadioGroup1の選択項目によって使用するマトリックスを変える
// ---------------------------------------------------------------------------
const
// オリジナル
ColorMatrix_Origin : TColorMatrix = (
( 1.0 , 0.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 1.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 1.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 1.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 0.0 , 1.0 ));
// 赤以外は非描画
ColorMatrix_OnlyRed : TColorMatrix = (
( 1.0 , 0.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , -1.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , -1.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 1.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 0.0 , 1.0 ));
// 赤以外は輝度 0
ColorMatrix_Red : TColorMatrix = (
( 1.0 , 0.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 1.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 0.0 , 1.0 ));
// 緑以外は非描画
ColorMatrix_OnlyGreen : TColorMatrix = (
(-1.0 , 0.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 1.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , -1.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 1.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 0.0 , 1.0 ));
// 緑以外は輝度 0
ColorMatrix_Green : TColorMatrix = (
( 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 1.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 1.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 0.0 , 1.0 ));
// 青以外は非描画
ColorMatrix_OnlyBlue : TColorMatrix = (
(-1.0 , 0.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , -1.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 1.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 1.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 0.0 , 1.0 ));
// 青以外は輝度 0
ColorMatrix_Blue : TColorMatrix = (
( 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 1.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 1.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 0.0 , 1.0 ));
// 色を反転させた画像(ネガティブイメージ)
ColorMatrix_Invers : TColorMatrix = (
(-1.0 , 0.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , -1.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , -1.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 1.0 , 0.0 ),
( 1.0 , 1.0 , 1.0 , 1.0 , 1.0 ));
// --- const部終わり -------------------------------------------------------
var
LGPGraphic : TGPGraphics;
LGPImage : TGPImage;
LGPImageAttr : TGPImageAttributes;
begin
inherited ;
// 画像ファイルを指定して,TGPImageのオブジェクトを生成
LGPImage := TGPImage.Create('dogs018.jpg' );
// TGPImageAttributesのオブジェクトを生成
LGPImageAttr := TGPImageAttributes.Create;
// RadioGroup1の選択項目によって,使用するマトリックスを変える
case Form1.RadioGroup1.ItemIndex of
0 : LGPImageAttr.SetColorMatrix(ColorMatrix_Origin);
1 : LGPImageAttr.SetColorMatrix(ColorMatrix_OnlyRed);
2 : LGPImageAttr.SetColorMatrix(ColorMatrix_Red);
3 : LGPImageAttr.SetColorMatrix(ColorMatrix_OnlyGreen);
4 : LGPImageAttr.SetColorMatrix(ColorMatrix_Green);
5 : LGPImageAttr.SetColorMatrix(ColorMatrix_OnlyBlue);
6 : LGPImageAttr.SetColorMatrix(ColorMatrix_Blue);
7 : LGPImageAttr.SetColorMatrix(ColorMatrix_Invers);
end ;
// TGPGraphicsのオブジェクトを生成
// 描画先はこのTMyPanelのCanvas
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
// GPImageをこのTMyPanelのCanvasに描画
// TCanvasのStretchDrawに相当する
LGPGraphic.DrawImage(
LGPImage,
MakeRect(0 , 0 , ClientWidth, ClientHeight),
0 ,
0 ,
LGPImage.GetWidth,
LGPImage.GetHeight,
UnitPixel,
LGPImageAttr);
// Createしたオブジェクトは解放処理する
LGPImageAttr.Free;
LGPImage.Free;
LGPGraphic.Free;
end ;
end .
半透明画像,つまりアルファブレンドな画像にするには,4 行 4 列目の値を 0 から 1 までの任意の実数値にします.0 は完全な透明,1 は完全な不透明になります.実際に画素に適用されるのは 0 から 255 の範囲となります.
図5
設計時画面
図6
オリジナル画像
図7
半透明にした状態
copy code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, ComCtrls, StdCtrls, GDIPOBJ, GDIPAPI;
type
TMyPanel = class (TPanel)
private
FImageFilePath : String ;
FAlphaValue : Single;
procedure SetAlphaValue(const Value: Single);
procedure SetImageFilePath(const Value: String );
protected
procedure Paint; override ;
public
constructor Create(AOwner: TComponent); override ;
property ImageFilePath : String read FImageFilePath write SetImageFilePath;
property AlphaValue : Single read FAlphaValue write SetAlphaValue;
end ;
TForm1 = class (TForm)
TrackBar1: TTrackBar;
procedure FormCreate(Sender: TObject);
procedure TrackBar1Change(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end ;
var
Form1: TForm1;
implementation
{$R *.dfm}
// =============================================================================
// フォーム生成時の処理
// =============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.Caption := 'GDI+ カラーマトリックス 半透明画像' ;
// 透明度設定用
TrackBar1.ShowSelRange := False;
TrackBar1.Height := 23 ;
TrackBar1.Min := 0 ;
TrackBar1.Max := 100 ;
TrackBar1.Position := TrackBar1.Max;
// TMyPanelを生成して配置
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
Left := 5 ;
Top := 35 ;
Width := Self.ClientWidth - 10 ;
Height := Self.ClientHeight - 40 ;
Anchors := [akLeft, akTop, akRight, akBottom ];
Color := clWhite;
ParentBackground := False;
DoubleBuffered := True;
// TMyPanel固有のプロパティの指定
// 表示する画像ファイル名と画像の透明度
ImageFilePath := 'dogs018.jpg' ;
AlphaValue := 1.00 ;
end ;
end ;
// =============================================================================
// TrackBar1のOnChangeイベント処理
// アルファ値(透明度)を変更したら,TMyPanelクラスのAlphaValueの値を更新する
// カラーマトリックスで指定するアルファ値の範囲は 0 - 1.00 であることに注意
// =============================================================================
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
if not Assigned(MyPanel) then exit;
MyPanel.AlphaValue := TrackBar1.Position / 100 ;
end ;
{ TMyPanel }
// -----------------------------------------------------------------------------
// コンストラクタのCreate処理
// -----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
inherited ;
FAlphaValue := 1.00 ;
end ;
// -----------------------------------------------------------------------------
// AlphaValueプロパティの設定用メソッド
// 画像の透明度であるアルファ値を変更したら,TMyPanelを再描画
// GDI+ のアルファ値の範囲は 0 - 1.00
// -----------------------------------------------------------------------------
procedure TMyPanel.SetAlphaValue(const Value: Single);
begin
if FAlphaValue <> Value then begin
FAlphaValue := Value;
Invalidate;
end ;
end ;
// -----------------------------------------------------------------------------
// ImageFilePathプロパティの設定用メソッド
// 表示する画像を変更したらTMyPanelを再描画
// -----------------------------------------------------------------------------
procedure TMyPanel.SetImageFilePath(const Value: String );
begin
FImageFilePath := Value;
Invalidate;
end ;
// -----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
// -----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LColorMatrix : TColorMatrix;
LGPGraphic : TGPGraphics;
LGPImage : TGPImage;
LGPImageAttr : TGPImageAttributes;
i : Integer;
begin
inherited ;
// 半透明の確認用に,背景に文字列を描画
Canvas.Font.Size := 50 ;
Canvas.Font.Name := 'MS UI Gothic' ;
Canvas.Font.Style := [fsBold];
Canvas.TextOut(20 , 30 , 'DELPHI' );
// カラーマトリックスの初期化(単位行列を作成)
FillChar(LColorMatrix,SizeOf(TColorMatrix), #0 );
for i := 0 to 4 do begin
LColorMatrix[i,i] := 1.0 ;
end ;
// アルファ値を設定
LColorMatrix[3 , 3 ] := FAlphaValue;
// 画像ファイルを指定してTGPImageのオブジェクトを生成
LGPImage := TGPImage.Create(FImageFilePath);
// TGPImageAttributesのオブジェクトを生成してカラーマトリックスをセット
LGPImageAttr := TGPImageAttributes.Create;
LGPImageAttr.SetColorMatrix(LColorMatrix);
// TGPGraphicsのオブジェクトを生成.Canvasを描画先とする
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
// GPImageをこのCanvasに描画
// TCanvasのStretchDrawに相当する
LGPGraphic.DrawImage(
LGPImage,
MakeRect(0 , 0 , ClientWidth, ClientHeight),
0 ,
0 ,
LGPImage.GetWidth,
LGPImage.GetHeight,
UnitPixel,
LGPImageAttr);
// Createしたオブジェクトは解放処理する
LGPImageAttr.Free;
LGPImage.Free;
LGPGraphic.Free;
end ;
end .
カラーマトリックスによる半透明処理は,非常に時間がかかります.
半透明の処理だけであれば,次のように描画先を TGPBitmap にして,そのビットマップのピクセルを直接操作してしまう方が高速です.
copy code
// ----------------------------------------------------------------------------
// TGPBitmapの半透明化処理
// アルファチャンネルに半透明の値を設定する
//
// SrcGDPBmpのビット深さが32bit以上用
// GDI+のTGPImage, TGPBitmapの保持ビット深さは32bit
// ----------------------------------------------------------------------------
function SetOpacitAlphaValue(SrcGDPBmp: TGPBitmap; PixelFmt: TPixelFormat;
Opacity: Byte): Boolean;
var
LBmpData : TBitmapData;
LScanLine : PByte;
LpRGBQuad : PRGBQuad;
LWidth : Integer;
LHeight : Integer;
LDataStride : Integer;
LXPos : integer;
LYPos : Integer;
begin
Result := False;
LWidth := SrcGDPBmp.GetWidth;
LHeight := SrcGDPBmp.GetHeight;
if SrcGDPBmp.LockBits(MakeRect(0 , 0 , LWidth, LHeight),
ImageLockModeWrite,
PixelFmt, LBmpData) <> Ok then exit;
LScanLine := LBmpData.Scan0;
LDataStride := LBmpData.Stride;
for LYPos := 0 to LHeight - 1 do begin
LpRGBQuad := PRGBQuad(LScanLine);
for LXPos := 0 to LWidth - 1 do begin
LpRGBQuad^.rgbReserved := Opacity;
Inc(LpRGBQuad);
end ;
Inc(LScanLine, LDataStride);
end ;
Result := True;
SrcGDPBmp.UnlockBits(LBmpData);
end ;
// -----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
// -----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LGPGraphic : TGPGraphics;
LGDIBitmap : TGPBitmap;
begin
inherited ;
// 半透明の確認用に,背景に文字列を描画
Canvas.Font.Size := 50 ;
Canvas.Font.Name := 'MS UI Gothic' ;
Canvas.Font.Style := [fsBold];
Canvas.TextOut(20 , 30 , 'DELPHI' );
// TGPBitmapのインスタンスを生成
LGDIBitmap := TGPBitmap.Create(FImageFilePath);
// 描画先を指定してTGPGraphicsのインスタンスを生成
LGPGraphic := TGPGraphics.Create(Canvas.Handle); // LBitmap.Canvas.Handle);
// 半透明化処理
SetOpacitAlphaValue(LGDIBitmap, PixelFormat32bppARGB, Trunc(FAlphaValue * 255 ));
// その描画先にTGPBitmapの内容を描画
LGPGraphic.DrawImage(LGDIBitmap,
MakeRect(0 , 0 , Width, Height),
0 ,
0 ,
LGDIBitmap.GetWidth,
LGDIBitmap.GetHeight,
UnitPixel);
LGPGraphic.Free;
LGDIBitmap.Free;
end ;
03_ モノクロ画像への変換 ( グレースケール化 )
カラー画像をモノクロ画像,グレースケール化するには,次のように,カラーマトリックスの各色における R, G, B の要素の値を平均して与える方法が考えられます.
しかし,この設定は実際には使われていません.人の目は,色の違いによって明るさが違って見えるからです.下の図は,左から ( 255 0 0 ) ( 0 255 0 ) ( 0 0 255 ) の色です.これを見ると緑色が一番明るく見えます.
これをそのままの輝度でモノクロの画像に変換すると,次のようになります.この色による輝度の違いは,最初のサンプルでも確認できます.
この,色による視覚的な輝度の違いを考慮して,NTSC (National Television Standards Committee)では,カラー画像を白黒に変換する際に,輝度 Y を以下の式で変換するように規格を定めています.
Y = R × 0.298912 + G × 0.586611 + B × 0.114478
この式を,カラーマトリックスに適用すると,次のようになります.
このサンプルプログラムは,カラーマトリックスに,この値をセットしてグレースケールにしています.透明度も設定できるようにしてみました.AlphaValue がその値です.
図8
設計時画面
図9
実行画面
図10
アルファ値を変更
copy code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, ComCtrls, StdCtrls, GDIPOBJ, GDIPAPI;
type
TMyPanel = class (TPanel)
private
FImageFilePath : String ;
FAlphaValue : Single;
procedure SetImageFilePath(const Value: String );
procedure SetAlphaValue(const Value: Single);
protected
procedure Paint; override ;
public
constructor Create(AOwner: TComponent); override ;
property ImageFilePath : String read FImageFilePath write SetImageFilePath;
property AlphaValue : Single read FAlphaValue write SetAlphaValue;
end ;
TForm1 = class (TForm)
TrackBar1: TTrackBar;
CheckBox1: TCheckBox;
procedure FormCreate(Sender: TObject);
procedure TrackBar1Change(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end ;
var
Form1: TForm1;
implementation
{$R *.dfm}
// =============================================================================
// フォーム生成時の処理
// =============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.Caption := 'GDI+ カラーマトリックス グレースケール化' ;
TrackBar1.ShowSelRange := False;
TrackBar1.Height := 23 ;
TrackBar1.Min := 0 ;
TrackBar1.Max := 100 ;
TrackBar1.Position := TrackBar1.Max;
TrackBar1.Anchors := [akLeft, akBottom];
// TMyPanelを生成して配置
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
Left := 5 ;
Top := 5 ;
Width := Self.ClientWidth - 10 ;
Height := Self.ClientHeight - Top - 35 ;
Anchors := [akLeft, akTop, akRight, akBottom];
Color := clWhite;
ParentBackground := False;
DoubleBuffered := True;
// TMyPanel固有のプロパティの指定
// 表示する画像ファイル名と画像の透明度
AlphaValue := 1.00 ;
ImageFilePath := 'dogs018.jpg' ;
end ;
end ;
// =============================================================================
// TrackBar1のOnChangeイベント処理
// アルファ値(透明度)を変更したら,TMyPanelクラスのAlphaValueの値を更新する
// GDI+ のアルファ値の範囲は 0 - 1.00 であることに注意
// =============================================================================
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
if not Assigned(MyPanel) then exit;
MyPanel.AlphaValue := TrackBar1.Position / 100 ;
MyPanel.Invalidate;
end ;
// =============================================================================
// CheckBox1のOnChangeイベント処理
// TMyPanelを再描画する
// =============================================================================
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
MyPanel.Invalidate;
end ;
{ TMyPanel }
// -----------------------------------------------------------------------------
// コンストラクタのCreate処理
// -----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
inherited ;
FAlphaValue := 1.00 ;
end ;
// -----------------------------------------------------------------------------
// AlphaValueプロパティの設定用メソッド
// 画像の透明度であるアルファ値を変更したら,TMyPanelを再描画
// GDI+ のアルファ値の範囲は 0 - 1.00
// -----------------------------------------------------------------------------
procedure TMyPanel.SetAlphaValue(const Value: Single);
begin
if FAlphaValue <> Value then begin
FAlphaValue := Value;
Invalidate;
end ;
end ;
// -----------------------------------------------------------------------------
// ImageFilePathプロパティの設定用メソッド
// 表示する画像を変更したらTMyPanelを再描画
// -----------------------------------------------------------------------------
procedure TMyPanel.SetImageFilePath(const Value: String );
begin
FImageFilePath := Value;
Invalidate;
end ;
// -----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
// -----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LColorMatrix : TColorMatrix;
LGPGraphic : TGPGraphics;
LGPImage : TGPImage;
LGPImageAttr : TGPImageAttributes;
LRValue : Single;
LGValue : Single;
LBValue : Single;
i : Integer;
begin
inherited ;
if Form1.CheckBox1.Checked then begin
LRValue := 1 / 3 ;
LGValue := 1 / 3 ;
LBValue := 1 / 3 ;
end else begin
LRValue := 0.298912 ;
LGValue := 0.586611 ;
LBValue := 0.114478 ;
end ;
// カラーマトリックスの初期化(単位行列を作成)
FillChar(LColorMatrix,SizeOf(TColorMatrix), #0 );
for i := 0 to 4 do begin
LColorMatrix[i,i] := 1.0 ;
end ;
// 各要素の値を代入
LColorMatrix[0 , 0 ] := LRValue;
LColorMatrix[0 , 1 ] := LRValue;
LColorMatrix[0 , 2 ] := LRValue;
LColorMatrix[1 , 0 ] := LGValue;
LColorMatrix[1 , 1 ] := LGValue;
LColorMatrix[1 , 2 ] := LGValue;
LColorMatrix[2 , 0 ] := LBValue;
LColorMatrix[2 , 1 ] := LBValue;
LColorMatrix[2 , 2 ] := LBValue;
// アルファ値を設定
LColorMatrix[3 , 3 ] := FAlphaValue;
// TGPImageAttributesのオブジェクトを生成してカラーマトリックスをセット
LGPImageAttr := TGPImageAttributes.Create;
LGPImageAttr.SetColorMatrix(LColorMatrix);
// 画像ファイルを指定してTGPImageのオブジェクトを生成
LGPImage := TGPImage.Create(FImageFilePath);
// TGPGraphicsのオブジェクトを生成.Canvasを描画先とする
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
// GPImageをこのCanvasに描画
// TCanvasのStretchDrawに相当する
LGPGraphic.DrawImage(
LGPImage,
MakeRect(0 , 0 , ClientWidth, ClientHeight),
0 ,
0 ,
LGPImage.GetWidth,
LGPImage.GetHeight,
UnitPixel,
LGPImageAttr);
// Createしたオブジェクトは解放処理する
LGPImageAttr.Free;
LGPImage.Free;
LGPGraphic.Free;
end ;
end .
次のように,カラーマトリックスの第 5 行目の値を変えると,「色の平行移動」となります.
このサンプルでは,色ごとに TTrackBar で平行移動値を変えるようにしてみました.上から順番に,赤 (R),緑 (G),青 (B) の設定用となっています.
図11
設計時画面
図12
オリジナル画像
図13
操作例
copy code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, ComCtrls, StdCtrls, GDIPOBJ, GDIPAPI;
type
TMyPanel = class (TPanel)
private
FImageFilePath : String ;
FRTransValue : Single;
FGTransValue : Single;
FBTransValue : Single;
procedure SetTransValue(const Index: Integer; Value: Single);
procedure SetImageFilePath(const Value: String );
protected
procedure Paint; override ;
published
public
constructor Create(AOwner: TComponent); override ;
property ImageFilePath : String read FImageFilePath write SetImageFilePath;
property RTransValue : Single index 0 read FRTransValue write SetTransValue;
property GTransValue : Single index 1 read FGTransValue write SetTransValue;
property BTransValue : Single index 2 read FBTransValue write SetTransValue;
end ;
TForm1 = class (TForm)
Panel1: TPanel;
TrackBar1: TTrackBar;
TrackBar2: TTrackBar;
TrackBar3: TTrackBar;
procedure FormCreate(Sender: TObject);
procedure TrackBar1Change(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end ;
var
Form1: TForm1;
implementation
{$R *.dfm}
// =============================================================================
// フォーム生成時の処理
// 各TTrackBarの以下のプロパティは,オブジェクトインスペクタで設定
// ShowSetRange := False;
// ThumbLenght := 20;
// =============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.Caption := 'GDI+ カラーマトリックス 色の平行移動' ;
// 赤色要素の平行移動量用
TrackBar1.ShowSelRange := False;
TrackBar1.Height := 23 ;
TrackBar1.Min := 0 ;
TrackBar1.Max := 100 ;
TrackBar1.Position := 0 ;
// 緑色要素の平行移動量用
TrackBar2.ShowSelRange := False;
TrackBar2.Height := 23 ;
TrackBar2.Min := 0 ;
TrackBar2.Max := 100 ;
TrackBar2.Position := 0 ;
// 青色要素の平行移動量用
TrackBar3.ShowSelRange := False;
TrackBar3.Height := 23 ;
TrackBar3.Min := 0 ;
TrackBar3.Max := 100 ;
TrackBar3.Position := 0 ;
// TMyPanelを生成して配置
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
Align := alClient;
Color := clWhite;
ParentBackground := False;
DoubleBuffered := True;
end ;
// 表示する画像ファイル名
MyPanel.ImageFilePath := 'dogs018.jpg' ;
TrackBar1Change(nil );
end ;
// =============================================================================
// TrackBarのOnChangeイベント処理
// このイベントは,3つのTTrackBarで共有
// 各色の平行移動量を設定したらTMyPanelクラスを再描画
// 各色の要素の値の範囲は 0 - 1.00 (つまりパーセント)
// =============================================================================
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
if not Assigned(MyPanel) then exit;
MyPanel.RTransValue := TrackBar1.Position / 100.0 ;
MyPanel.GTransValue := TrackBar2.Position / 100.0 ;
MyPanel.BTransValue := TrackBar3.Position / 100.0 ;
MyPanel.Invalidate;
end ;
{ TMyPanel }
// -----------------------------------------------------------------------------
// コンストラクタのCreate処理
// -----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
inherited ;
FRTransValue := 1.00 ;
FGTransValue := 1.00 ;
FBTransValue := 1.00 ;
end ;
// -----------------------------------------------------------------------------
// ImageFilePathプロパティの設定用メソッド
// 表示する画像を変更したらTMyPanelを再描画
// -----------------------------------------------------------------------------
procedure TMyPanel.SetImageFilePath(const Value: String );
begin
FImageFilePath := Value;
Invalidate;
end ;
// -----------------------------------------------------------------------------
// RTransValue
// GTransValue
// BTransValue
// のプロパティ設定用メソッド
// プロパティが変更されたら再描画
// -----------------------------------------------------------------------------
procedure TMyPanel.SetTransValue(const Index: Integer; Value: Single);
begin
case Index of
0 : FRTransValue := Value;
1 : FGTransValue := Value;
2 : FBTransValue := Value;
end ;
end ;
// -----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
// -----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LColorMatrix : TColorMatrix;
LGPGraphic : TGPGraphics;
LGPImage : TGPImage;
LGPImageAttr : TGPImageAttributes;
i : Integer;
begin
inherited ;
// カラーマトリックスの初期化(単位行列を作成)
FillChar(LColorMatrix,SizeOf(TColorMatrix), #0 );
for i := 0 to 4 do begin
LColorMatrix[i,i] := 1.0 ;
end ;
// 各要素の値を代入
LColorMatrix[4 , 0 ] := FRTransValue;
LColorMatrix[4 , 1 ] := FGTransValue;
LColorMatrix[4 , 2 ] := FBTransValue;
// 画像ファイルを指定してTGPImageのオブジェクトを生成
LGPImage := TGPImage.Create(FImageFilePath);
// TGPImageAttributesのオブジェクトを生成してカラーマトリックスをセット
LGPImageAttr := TGPImageAttributes.Create;
LGPImageAttr.SetColorMatrix(LColorMatrix);
// TGPGraphicsのオブジェクトを生成.Canvasを描画先とする
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
// GPImageをこのCanvasに描画
// TCanvasのStretchDrawに相当する
LGPGraphic.DrawImage(
LGPImage,
MakeRect(0 , 0 , ClientWidth, ClientHeight),
0 ,
0 ,
LGPImage.GetWidth,
LGPImage.GetHeight,
UnitPixel,
LGPImageAttr);
// Createしたオブジェクトは解放処理する
LGPImageAttr.Free;
LGPImage.Free;
LGPGraphic.Free;
end ;
end .
前のサンプルでは,第 3 列目までに値をセットしていましたが,次のように,第 4 列目も設定すると輝度調整となります.そのテストプログラムです.
図14
設計時画面
図15
オリジナル画像
図16
正の輝度の値
図17
輝度の値が負の場合
copy code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, ComCtrls, StdCtrls, GDIPOBJ, GDIPAPI;
type
TMyPanel = class (TPanel)
private
FImageFilePath : String ;
FBrightness : Single;
procedure SetBrightness(const Value: Single);
procedure SetImageFilePath(const Value: String );
protected
procedure Paint; override ;
public
constructor Create(AOwner: TComponent); override ;
property ImageFilePath : String read FImageFilePath write SetImageFilePath;
property Brightness : Single read FBrightness write SetBrightness;
end ;
TForm1 = class (TForm)
TrackBar1: TTrackBar;
Label1: TLabel;
procedure FormCreate(Sender: TObject);
procedure TrackBar1Change(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end ;
var
Form1: TForm1;
implementation
{$R *.dfm}
// =============================================================================
// フォーム生成時の処理
// =============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.Caption := 'GDI+ カラーマトリックス 輝度調整' ;
// 輝度の値調整用
TrackBar1.ShowSelRange := False;
TrackBar1.Height := 23 ;
TrackBar1.Min := -50 ;
TrackBar1.Max := 50 ;
TrackBar1.Position := 0 ;
// TMyPanelを生成して配置
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
Left := 5 ;
Top := 35 ;
Width := Self.ClientWidth - 10 ;
Height := Self.ClientHeight - 40 ;
Anchors := [akLeft, akTop, akRight, akBottom];
Color := clWhite;
ParentBackground := False;
DoubleBuffered := True;
// 表示する画像ファイル名
ImageFilePath := 'dogs018.jpg' ;
end ;
TrackBar1Change(nil );
end ;
// =============================================================================
// TrackBarのOnChangeイベント処理
// 各色の平行移動量を設定したらTMyPanelクラスを再描画
// =============================================================================
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
if not Assigned(MyPanel) then exit;
MyPanel.Brightness := TrackBar1.Position / 100.0 ;
Label1.Caption := FormatFloat('##0.00' , MyPanel.Brightness);
end ;
{ TMyPanel }
// -----------------------------------------------------------------------------
// コンストラクタのCreate処理
// -----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
inherited ;
FBrightness := 0.00
end ;
// -----------------------------------------------------------------------------
// ImageFilePathプロパティの設定用メソッド
// 表示する画像を変更したらTMyPanelを再描画
// -----------------------------------------------------------------------------
procedure TMyPanel.SetImageFilePath(const Value: String );
begin
FImageFilePath := Value;
Invalidate;
end ;
// -----------------------------------------------------------------------------
// Brightnessのプロパティ設定用メソッド
// プロパティが変更されたら再描画
// -----------------------------------------------------------------------------
procedure TMyPanel.SetBrightness(const Value: Single);
begin
if FBrightness <> Value then begin
FBrightness := Value;
Invalidate;
end ;
end ;
// -----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
// -----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LColorMatrix : TColorMatrix;
LGPGraphic : TGPGraphics;
LGPImage : TGPImage;
LGPImageAttr : TGPImageAttributes;
i : Integer;
begin
inherited ;
// カラーマトリックスの初期化(単位行列を作成)
FillChar(LColorMatrix,SizeOf(TColorMatrix), #0 );
for i := 0 to 4 do begin
LColorMatrix[i,i] := 1.0 ;
end ;
// 各要素の値を代入
for i := 0 to 3 do begin
LColorMatrix[4 , i] := FBrightness;
end ;
// 画像ファイルを指定してTGPImageのオブジェクトを生成
LGPImage := TGPImage.Create(FImageFilePath);
// TGPImageAttributesのオブジェクトを生成してカラーマトリックスをセット
LGPImageAttr := TGPImageAttributes.Create;
LGPImageAttr.SetColorMatrix(LColorMatrix);
// TGPGraphicsのオブジェクトを生成.Canvasを描画先とする
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
// GPImageをこのCanvasに描画
// TCanvasのStretchDrawに相当する
LGPGraphic.DrawImage(
LGPImage,
MakeRect(0 , 0 , ClientWidth, ClientHeight),
0 ,
0 ,
LGPImage.GetWidth,
LGPImage.GetHeight,
UnitPixel,
LGPImageAttr);
// Createしたオブジェクトは解放処理する
LGPImageAttr.Free;
LGPImage.Free;
LGPGraphic.Free;
end ;
end .
画像のコントラストの設定は少し面倒です.次のように,各色の輝度と同時に,平行移動量も設定しますが,計算処理が必要です.サンプルのコードで確認してください.
図18
設計時画面
図19
オリジナル画像
図20
正のコントラスト
図21
負のコントラスト
copy code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, ComCtrls, StdCtrls, GDIPOBJ, GDIPAPI;
type
TMyPanel = class (TPanel)
private
FImageFilePath : String ;
FContrast : Single;
procedure SetContrastValue(const Value: Single);
procedure SetImageFilePath(const Value: String );
protected
procedure Paint; override ;
public
constructor Create(AOwner: TComponent); override ;
property ImageFilePath : String read FImageFilePath write SetImageFilePath;
property Contrast : Single read FContrast write SetContrastValue;
end ;
TForm1 = class (TForm)
TrackBar1: TTrackBar;
Label1: TLabel;
procedure FormCreate(Sender: TObject);
procedure TrackBar1Change(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end ;
var
Form1: TForm1;
implementation
{$R *.dfm}
// =============================================================================
// フォーム生成時の処理
// =============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.Caption := 'GDI+ コントラスト' ;
// コントラスト調整用
TrackBar1.ShowSelRange := False;
TrackBar1.Height := 23 ;
TrackBar1.Min := -100 ;
TrackBar1.Max := 100 ;
TrackBar1.Position := 0 ;
// TMyPanelを生成して配置
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
Left := 5 ;
Top := 35 ;
Width := Self.ClientWidth - 10 ;
Height := Self.ClientHeight - 40 ;
Anchors := [akLeft, akTop, akRight, akBottom];
Color := clWhite;
ParentBackground := False;
DoubleBuffered := True;
// 表示する画像ファイル名
ImageFilePath := 'dogs018.jpg' ;
end ;
TrackBar1Change(nil );
end ;
// =============================================================================
// TrackBarのOnChangeイベント処理
// 変更したらTMyPanelクラスを再描画
// =============================================================================
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
if not Assigned(MyPanel) then exit;
MyPanel.Contrast := TrackBar1.Position;
Label1.Caption := IntToStr(TrackBar1.Position);
end ;
{ TMyPanel }
// -----------------------------------------------------------------------------
// コンストラクタのCreate処理
// -----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
inherited ;
FContrast := 0 ;
end ;
// -----------------------------------------------------------------------------
// ImageFilePathプロパティの設定用メソッド
// 表示する画像を変更したらTMyPanelを再描画
// -----------------------------------------------------------------------------
procedure TMyPanel.SetImageFilePath(const Value: String );
begin
FImageFilePath := Value;
Invalidate;
end ;
// -----------------------------------------------------------------------------
// Contrastのプロパティ設定用メソッド
// プロパティが変更されたら再描画
// -----------------------------------------------------------------------------
procedure TMyPanel.SetContrastValue(const Value: Single);
begin
if FContrast <> Value then begin
FContrast := Value;
Invalidate;
end ;
end ;
// -----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
// -----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LColorMatrix : TColorMatrix;
LGPGraphic : TGPGraphics;
LGPImageAttr : TGPImageAttributes;
LGPBitmap : TGPBitmap;
LScale : Single;
LAppend : Single;
i : Integer;
begin
inherited ;
// 画像ファイルを指定してTGPBitmapのオブジェクトを生成
// これまでのサンプルと変えて,TGPBitmapにしてみた
LGPBitmap := TGPBitmap.Create(FImageFilePath);
// カラーマトリックスの初期化(単位行列を作成)
FillChar(LColorMatrix,SizeOf(TColorMatrix), #0 );
for i := 0 to 4 do begin
LColorMatrix[i,i] := 1.0 ;
end ;
// 各要素の値を代入
// 計算式はMSDNの記事による
LScale := (100.0 + FContrast) / 100.0 ;
for i := 0 to 2 do begin
LColorMatrix[i, i] := LScale;
end ;
LAppend := 0.5 * (1.0 - LScale);
for i := 0 to 2 do begin
LColorMatrix[4 , i] := LAppend;
end ;
// TGPImageAttributesのオブジェクトを生成してカラーマトリックスをセット
LGPImageAttr := TGPImageAttributes.Create;
LGPImageAttr.SetColorMatrix(LColorMatrix);
// TGPGraphicsのオブジェクトを生成.Canvasを描画先とする
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
// GPBitmapをこのCanvasに描画
// TCanvasのStretchDrawに相当する
LGPGraphic.DrawImage(
LGPBitmap,
MakeRect(0 , 0 , ClientWidth, ClientHeight),
0 ,
0 ,
LGPBitmap.GetWidth,
LGPBitmap.GetHeight,
UnitPixel,
LGPImageAttr);
// Createしたオブジェクトは解放処理する
LGPImageAttr.Free;
LGPBitmap.Free;
LGPGraphic.Free;
end ;
end .
カラーマトリックスを使用するサンプルではありませんが,輝度,コントラストの調整のサンプルを掲載しましたので,ガンマ補正のサンプルも作成しました.
作成したと言っても,カラーマトリックスの設定で使用している TGPImageAttributes の関数に,ガンマ値を設定する SetGamma という関数があります.これの使用例です.
ガンマ補正の機能は,おそらく写真画像の調整用に,よく利用されているかも知れません.
視覚的な意味で,このガンマ補正を「コントラストの調整」と言う場合があります.「コントラストが低いから,(ガンマ曲線) のこの部分を変えてみよう」という言い方をすることがあります.
図22
設計時画面
図23
オリジナル画像
図24
ガンマ値を大きくした場合
図25
ガンマ値が 1 以下の場合
copy code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, ComCtrls, StdCtrls, GDIPOBJ, GDIPAPI;
type
TMyPanel = class (TPanel)
private
FImageFilePath : String ;
FGammaValue : Single;
procedure SetGrammaValue(const Value: Single);
procedure SetImageFilePath(const Value: String );
protected
procedure Paint; override ;
public
constructor Create(AOwner: TComponent); override ;
property ImageFilePath : String read FImageFilePath write SetImageFilePath;
property GammaValue : Single read FGammaValue write SetGrammaValue;
end ;
TForm1 = class (TForm)
TrackBar1: TTrackBar;
Label1: TLabel;
procedure FormCreate(Sender: TObject);
procedure TrackBar1Change(Sender: TObject);
private
{ Private 宣言 }
MyPanel : TMyPanel;
public
{ Public 宣言 }
end ;
var
Form1: TForm1;
implementation
{$R *.dfm}
// =============================================================================
// フォーム生成時の処理
// =============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.Caption := 'GDI+ ガンマ値設定 ( ガンマ補正 )' ;
// ガンマ値設定用
// ガンマ値の設定は,オリジナルが1.0なので少し工夫してみた
TrackBar1.ShowSelRange := False;
TrackBar1.Height := 23 ;
TrackBar1.Min := 0 ;
TrackBar1.Max := 400 ;
TrackBar1.Position := (TrackBar1.Max - TrackBar1.Min) div 2 ;;
// TMyPanelを生成して配置
MyPanel := TMyPanel.Create(Self);
with MyPanel do begin
Parent := Self;
Left := 5 ;
Top := 35 ;
Width := Self.ClientWidth - 10 ;
Height := Self.ClientHeight - 40 ;
Anchors := [akLeft, akTop, akRight, akBottom ];
Color := clWhite;
ParentBackground := False;
DoubleBuffered := True;
// 表示する画像ファイル名
ImageFilePath := 'dogs018.jpg' ;
end ;
TrackBar1Change(nil );
end ;
// =============================================================================
// TrackBarのOnChangeイベント処理
// 変更したらTMyPanelクラスを再描画
// ガンマ値の設定は,オリジナルが1.0なので少し工夫してみた
// TTrackBarの中央と1として,1未満と1以上の場合の処理を分けた
// =============================================================================
procedure TForm1.TrackBar1Change(Sender: TObject);
var
HalfV : Integer;
V : Single;
begin
if not Assigned(MyPanel) then exit;
HalfV := (TrackBar1.Max - TrackBar1.Min) div 2 ;
if TrackBar1.Position < HalfV then begin
V := 1.00 - (HalfV - TrackBar1.Position) / (HalfV - TrackBar1.Min) * 0.8 ;
end else begin
V := (TrackBar1.Position - HalfV) / (TrackBar1.Max - HalfV) * 1.50 + 1.00 ;
end ;
MyPanel.GammaValue := V;
Label1.Caption := FormatFloat('##0.00' , MyPanel.GammaValue);
end ;
{ TMyPanel }
// -----------------------------------------------------------------------------
// コンストラクタのCreate処理
// -----------------------------------------------------------------------------
constructor TMyPanel.Create(AOwner: TComponent);
begin
inherited ;
FGammaValue := 1.0 ;
end ;
// -----------------------------------------------------------------------------
// ImageFilePathプロパティの設定用メソッド
// 表示する画像を変更したらTMyPanelを再描画
// -----------------------------------------------------------------------------
procedure TMyPanel.SetImageFilePath(const Value: String );
begin
FImageFilePath := Value;
Invalidate;
end ;
// -----------------------------------------------------------------------------
// GrammaValueのプロパティ設定用メソッド
// プロパティが変更されたら再描画
// -----------------------------------------------------------------------------
procedure TMyPanel.SetGrammaValue(const Value: Single);
begin
if FGammaValue <> Value then begin
FGammaValue := Value;
Invalidate;
end ;
end ;
// -----------------------------------------------------------------------------
// TMyPanelクラスのPaintメソッド
// 実際の描画コード
// -----------------------------------------------------------------------------
procedure TMyPanel.Paint;
var
LGPGraphic : TGPGraphics;
LGPImage : TGPImage;
LGPImageAttr : TGPImageAttributes;
begin
inherited ;
// 画像ファイルを指定してTGPImageのオブジェクトを生成
LGPImage := TGPImage.Create(FImageFilePath);
// TGPImageAttributesのオブジェクトを生成してガンマ値をセット
LGPImageAttr := TGPImageAttributes.Create;
LGPImageAttr.SetGamma(FGammaValue);
// TGPGraphicsのオブジェクトを生成.Canvasを描画先とする
LGPGraphic := TGPGraphics.Create(Canvas.Handle);
// GPImageをこのCanvasに描画
// TCanvasのStretchDrawに相当する
LGPGraphic.DrawImage(
LGPImage,
MakeRect(0 , 0 , ClientWidth, ClientHeight),
0 ,
0 ,
LGPImage.GetWidth,
LGPImage.GetHeight,
UnitPixel,
LGPImageAttr);
// Createしたオブジェクトは解放処理する
LGPImageAttr.Free;
LGPImage.Free;
LGPGraphic.Free;
end ;
end .
透過色を指定して,TBitmap の Mask メソッドを実行すると,下図のようなビットマップ画像のマスク画像が作成されます.GDI+ で,このモノクロのマスク画像を描画するサンプルです.ただし,このサンプルコードは,アルファチャンネルを処理してくれません.
マスク画像の作成は,画像をアイコン形式の画像に変換する時,あるいはマウスカーソルの画像を作成する時に必要となる処理です.
図26
TBitamp.Mask メソッドによるモノクロのマスク画像
リスト10
TBitamp.Mask メソッドによるモノクロのマスク画像
アルファチャンネルの処理はしない
copy code
procedure TForm1.FormPaint(Sender: TObject);
var
LSrcBitmap : TBitmap;
LDstBitmap : TBitmap;
begin
// 元の画像と処理後の画像用のビットマップを生成
LSrcBitmap := TBitmap.Create;
LDstBitmap := TBitmap.Create;
try
// 画像を読み込む
LSrcBitmap.LoadFromFile('503.bmp' );
LDstBitmap.Assign(LSrcBitmap);
// 透過色を指定してマスク画像を作成
LDstBitmap.TransparentColor := LDstBitmap.Canvas.Pixels[0 , LDstBitmap.Height - 1 ];
LDstBitmap.Mask(LDstBitmap.TransparentColor);
// 元の画像と処理後の画像を表示
Canvas.Draw(10 , 10 , LSrcBitmap);
Canvas.Draw(10 , LSrcBitmap.Height + 20 , LDstBitmap);
finally
FreeAndNil(LDstBitmap);
FreeAndNil(LSrcBitmap);
end ;
end ;
次のマトリックスを使用すると,画像のモノクロマスク画像を描画できます.
このサンプルの場合,TGPBitmap がモノクロのマスク画像になるのではなく,TGPImageAttributes の設定内容で Canvas に描画することになります.
図27
設計時画面
図28
ColorMatrix によるモノクロのマスク画像
リスト11
ColorMatrix によるモノクロのマスク画像を描画
copy code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, GDIPOBJ, GDIPAPI;
type
TForm1 = class (TForm)
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end ;
var
Form1: TForm1;
implementation
{$R *.dfm}
// =============================================================================
// フォーム生成時の処理
// =============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.Caption := 'GDI+ αマスク' ;
DoubleBuffered := True;
end ;
// =============================================================================
// OnPaintイベント
// 実際の描画コード
// =============================================================================
procedure TForm1.FormPaint(Sender: TObject);
const
ColorMatrix : TColorMatrix = (
( 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ),
( 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ),
( -1.0 , -1.0 , -1.0 , 1.0 , 0.0 ),
( 1.0 , 1.0 , 1.0 , 0.0 , 1.0 ));
var
LObjWidth : Integer;
LObjHeight : Integer;
LColor : TGPColor;
LGDPSrcBitmap : TGPBitmap;
LGDPImgAttributes : TGPImageAttributes;
LGDPGraphic : TGPGraphics;
begin
// 画像ファイルをTGPBitmapに読み込み,幅と高さを取得
LGDPSrcBitmap := TGPBitmap.Create('503.bmp' );
LObjWidth := LGDPSrcBitmap.GetWidth;
LObjHeight := LGDPSrcBitmap.GetHeight;
// 透過色を指定して,マトリックスの値を設定
LGDPImgAttributes := TGPImageAttributes.Create;
LGDPSrcBitmap.GetPixel(0 , LObjHeight - 1 , LColor);
LGDPImgAttributes.SetColorKey(LColor, LColor);
LGDPImgAttributes.SetColorMatrix(ColorMatrix,
ColorMatrixFlagsDefault,
ColorAdjustTypeDefault);
// 描画先はこのCanvasとし,処理前の画像を表示
LGDPGraphic := TGPGraphics.Create(Canvas.Handle);
LGDPGraphic.DrawImage(LGDPSrcBitmap, 10 , 10 , LObjWidth, LObjHeight);
// TGPImageAttributesで処理した画像を表示
LGDPGraphic.DrawImage(LGDPSrcBitmap,
MakeRect(10 , LObjHeight + 20 , LObjWidth, LObjHeight),
0 , 0 , LObjWidth, LObjHeight,
UnitPixel,
LGDPImgAttributes);
LGDPSrcBitmap.Free;
LGDPImgAttributes.Free;
LGDPGraphic.Free;
end ;
end .
09_ カラーマトリックスによるアイコン画像の色操作の例
ここまでのサンプルでは,JPEG 形式の写真画像で色操作のテストをしてきました.
本サンプルは PNG 形式のアイコン画像でのテストです.アイコンの画像の色合いを変更したい場合にも利用可能です.上のサンプルと違い,カラーマトリックスの各要素を個別に操作できるようにしてみましたが,半透明度と色の平行移動の設定はありません.
以下に実際の操作例をいくつか掲載しておきます.
以下の記事のサンプルにこのような機能を実装すれば便利かも知れません.
このような機能は多くの画像加工や画像編集のアプリケーションに実装されていますが,その実装内容や操作方法は様々です.
本サンプルでは画像をリサイズして拡大表示していますが,アイコン画像の場合はリサイズはせずに単なる拡大表示とするのが一般的です.
[備考]
本サンプルだけではなく,TGPImageAttributes で属性を指定した描画では,元の TGPBitmap の内容は変化しません.したがって,設定内容は元の TGPBitmap あるいは TGPImage に対するものとなります.表示されているのは,描画先の TCanvas への描画結果です.
図29
設計時の画面
図30
元の画像
図31
ブルー系統の色に変更した例
図32
ゴールド系の色にしてみた例
下図は,以下のサイトからダウンロードした PNG 形式のアイコン画像での操作例です.
図33
元の画像
図34
操作例
下図は,当サイトのサンプルによく登場するヒヨコの例です.
変更した画像を保存して,再度読み込んで操作すると,また別の色合いに変更できます.
図35
元の画像
図36
体が赤っぽいヒヨコに変化
図37
ピンク系統の色に変更
図38
体が緑っぽいヒヨコに変更
図39
体が青っぽいヒヨコに変更
本サンプルには色の平行移動のコードはありません.下図は上の色の平行移動のサンプルコードを実行した結果です.色の平行移動だけでも画像の色合いが変わることが分かります.
図40
元の画像
図41
赤だけを100 % 平行移動した結果
図42
青だけを 100 % 平行移動した結果
リスト12
カラーマトリックスによるアイコン画像の色操作の例
copy code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, GDIPAPI, GDIPOBJ, GDIPUTIL, StdCtrls, Spin, ExtCtrls, ExtDlgs;
type
TForm1 = class (TForm)
Button1: TButton;
Button2: TButton;
Image1: TImage;
OpenPictureDialog1: TOpenPictureDialog;
GroupBox1: TGroupBox;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
SpinEdit_RedInRed: TSpinEdit;
SpinEdit_GreenInRed: TSpinEdit;
SpinEdit_BlueInRed: TSpinEdit;
GroupBox2: TGroupBox;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
SpinEdit_RedInGreen: TSpinEdit;
SpinEdit_GreenInGreen: TSpinEdit;
SpinEdit_BlueInGreen: TSpinEdit;
GroupBox3: TGroupBox;
Label7: TLabel;
Label8: TLabel;
Label9: TLabel;
SpinEdit_RedInBlue: TSpinEdit;
SpinEdit_GreenInBlue: TSpinEdit;
SpinEdit_BlueInBlue: TSpinEdit;
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure SpinEdit_RedInRedChange(Sender: TObject);
procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private 宣言 }
FLoadInitDir : string ;
FImageFilePath : string ;
FMemStream : TBytesStream;
FGPBitmap : TGPBitmap;
FGPImageAttr : TGPImageAttributes;
FImgDispWidth : Integer;
FImgDispHeight : Integer;
procedure DrawGPBitmaToTImage;
public
{ Public 宣言 }
end ;
var
Form1: TForm1;
implementation
{$R *.dfm}
// =============================================================================
// フォーム生成時の処理
// =============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
// ファイルの読み出しの初期ディレクトリ
FLoadInitDir := ExpandFileName('.\Images' );
end ;
// =============================================================================
// フォーム破棄時の処理
// =============================================================================
procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(FGPBitmap) then FreeAndNil(FGPBitmap);
if Assigned(FMemStream) then FreeAndNil(FMemStream);
if Assigned(FGPImageAttr) then FreeAndNil(FGPImageAttr);
end ;
// =============================================================================
// [Load Image]
// 画像ファイルの読み込み
// PNG形式の画像のみ
// =============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LGPGraphic : TGPGraphics;
LGPBitmap : TGPBitmap;
begin
OpenPictureDialog1.Filter := '画像ファイル|*.png' ;
OpenPictureDialog1.InitialDir := FLoadInitDir;
if not OpenPictureDialog1.Execute then exit;
FImageFilePath := OpenPictureDialog1.FileName;
FLoadInitDir := ExtractFileDir(FImageFilePath);
if Assigned(FGPBitmap) then FreeAndNil(FGPBitmap);
if Assigned(FMemStream) then FreeAndNil(FMemStream);
if Assigned(FGPImageAttr) then FreeAndNil(FGPImageAttr);
// メモリストリームに画像ファイルを読み込む
FMemStream := TBytesStream.Create;
FMemStream.LoadFromFile(FImageFilePath);
if ExtractFileExt(FImageFilePath) = '.png' then begin
LGPBitmap := TGPBitmap.Create(TStreamAdapter.Create(FMemStream, soReference));
end else begin
exit;
end ;
// 表示サイズの設定
// 横幅256に固定
FImgDispWidth := 256 ;
FImgDispHeight := Trunc(FImgDispWidth * LGPBitmap.GetHeight / LGPBitmap.GetWidth);
// マウスクリックで色の値を取得したいので表示サイズのTGPBitmapに変換
FGPBitmap := TGPBitmap.Create(FImgDispWidth, FImgDispHeight);
LGPGraphic := TGPGraphics.Create(FGPBitmap);
LGPGraphic.DrawImage(LGPBitmap,
MakeRect(0 , 0 , FImgDispWidth, FImgDispHeight),
0 ,
0 ,
LGPBitmap.GetWidth,
LGPBitmap.GetHeight,
UnitPixel);
// 色調整用の値を設定するTSpinEditの値
SpinEdit_RedInRed.Value := 100 ;
SpinEdit_GreenInRed.Value := 0 ;
SpinEdit_BlueInRed.Value := 0 ;
SpinEdit_RedInGreen.Value := 0 ;
SpinEdit_GreenInGreen.Value := 100 ;
SpinEdit_BlueInGreen.Value := 0 ;
SpinEdit_RedInBlue.Value := 0 ;
SpinEdit_GreenInBlue.Value := 0 ;
SpinEdit_BlueInBlue.Value := 100 ;
Edit1.Text := '' ;
// 描画
DrawGPBitmaToTImage;
LGPBitmap.Free;
LGPGraphic.Free;
end ;
// =============================================================================
// [Reset]
// 読み込んで作成した時の画像に戻す
// =============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
if Assigned(FGPImageAttr) then FreeAndNil(FGPImageAttr);
SpinEdit_RedInRed.Value := 100 ;
SpinEdit_GreenInRed.Value := 0 ;
SpinEdit_BlueInRed.Value := 0 ;
SpinEdit_RedInGreen.Value := 0 ;
SpinEdit_GreenInGreen.Value := 100 ;
SpinEdit_BlueInGreen.Value := 0 ;
SpinEdit_RedInBlue.Value := 0 ;
SpinEdit_GreenInBlue.Value := 0 ;
SpinEdit_BlueInBlue.Value := 100 ;
end ;
// =============================================================================
// 各TSpinEditのOnChangeイベント処理
// =============================================================================
procedure TForm1.SpinEdit_RedInRedChange(Sender: TObject);
var
LColorMatrix : TColorMatrix;
i : Integer;
begin
if not Assigned(FGPBitmap) then exit;
if TSpinEdit(Sender).Value <= 0 then TSpinEdit(Sender).Value := 0 ;
if TSpinEdit(Sender).Value >= 100 then TSpinEdit(Sender).Value := 100 ;
// カラーマトリックスの初期化(単位行列を作成)
FillChar(LColorMatrix, SizeOf(LColorMatrix), #0 );
for i := 0 to 4 do begin
LColorMatrix[i,i] := 1.0 ;
end ;
// 赤
LColorMatrix[0 , 0 ] := SpinEdit_RedInRed.Value / 100 ;
LColorMatrix[1 , 0 ] := SpinEdit_GreenInRed.Value / 100 ;
LColorMatrix[2 , 0 ] := SpinEdit_BlueInRed.Value / 100 ;
// 緑
LColorMatrix[0 , 1 ] := SpinEdit_RedInGreen.Value / 100 ;
LColorMatrix[1 , 1 ] := SpinEdit_GreenInGreen.Value / 100 ;
LColorMatrix[2 , 1 ] := SpinEdit_BlueInGreen.Value / 100 ;
// 青
LColorMatrix[0 , 2 ] := SpinEdit_RedInBlue.Value / 100 ;
LColorMatrix[1 , 2 ] := SpinEdit_GreenInBlue.Value / 100 ;
LColorMatrix[2 , 2 ] := SpinEdit_BlueInBlue.Value / 100 ;
// TGPImageAttributesが生成されていない時だけ生成する
// 既に生成されている場合は他のTGPImageAttributes設定があるかも知れないので
if not Assigned(FGPImageAttr) then begin
FGPImageAttr := TGPImageAttributes.Create;
end ;
// カラーマトリックスの値をTGPImageAttributesに設定
FGPImageAttr.SetColorMatrix(LColorMatrix);
// 描画
DrawGPBitmaToTImage;
end ;
// =============================================================================
// Image1のOnMouseDownイベント処理
// クリックした位置のピクセルの色の値をTEditに表示
// =============================================================================
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
LGPColor : TGPColor;
begin
if not Assigned(FGPBitmap) then exit;
if Button <> mbLeft then exit;
FGPBitmap.GetPixel(X, Y, LGPColor);
Edit1.Text := '$' + IntToHex(LGPColor, 8 );
end ;
// -----------------------------------------------------------------------------
// TImageへの描画ルーチン
// -----------------------------------------------------------------------------
procedure TForm1.DrawGPBitmaToTImage;
var
LGPGraphic : TGPGraphics;
begin
Image1.Picture.Assign(nil );
Image1.Width := FImgDispWidth;
Image1.Height := FImgDispHeight;
LGPGraphic := TGPGraphics.Create(Image1.Canvas.Handle);
LGPGraphic.DrawImage(FGPBitmap,
MakeRect(0 , 0 , FImgDispWidth, FImgDispHeight),
0 ,
0 ,
FGPBitmap.GetWidth,
FGPBitmap.GetHeight,
UnitPixel,
FGPImageAttr);
LGPGraphic.Free;
end ;
end .
本ページの最初の方のサンプルでは主に JPEG 形式の写真画像をテストに使用しています.
前項ではいわゆるアイコンと呼ばれる画像を扱いました.操作していることは同じですが,写真とはまた違う趣があります.ここでガンマ値の効果をアイコン画像で確認してみます.
ガンマ値は一種の明るさの調整ですが,ガンマ値を大きくすると輝度が低い画素は輝度の変化が少なくなりますから,結果的にはコントラスも変化します.
コントラストは,画素間の輝度の相対的な比のことです.輝度 (明るさ),コントラストと共に,このガンマ値の調整も同時に設定する機能を実装すると便利かも知れません.
図43
テスト用の PNG 形式の画像を読み込んで表示
図44
ガンマ値を 2.61 に変更した結果
左上はもとの画像
左の下はガンマ値を変更した画像
右はそれをリサイズして拡大表示した画像
リスト13
アイコン画像におけるガンマ値の効果のテスト
copy code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, GDIPAPI, GDIPOBJ, GDIPUTIL, StdCtrls, Spin, ExtCtrls, ExtDlgs;
type
TForm1 = class (TForm)
Button1: TButton;
Button2: TButton;
Image1: TImage;
OpenPictureDialog1: TOpenPictureDialog;
GroupBox1: TGroupBox;
Label1: TLabel;
SpinEdit_RedInRed: TSpinEdit;
Image2: TImage;
Image3: TImage;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure SpinEdit_RedInRedChange(Sender: TObject);
private
{ Private 宣言 }
FLoadInitDir : string ;
FImageFilePath : string ;
FMemStream : TBytesStream;
FGPBitmap : TGPBitmap;
FGPImageAttr : TGPImageAttributes;
FImgDispWidth : Integer;
FImgDispHeight : Integer;
procedure DrawGPBitmaToTImage;
public
{ Public 宣言 }
end ;
var
Form1: TForm1;
implementation
{$R *.dfm}
// =============================================================================
// フォーム生成時の処理
// =============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
// ファイルの読み出しの初期ディレクトリ
FLoadInitDir := ExpandFileName('.\Images' );
end ;
// =============================================================================
// フォーム破棄時の処理
// =============================================================================
procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(FGPBitmap) then FreeAndNil(FGPBitmap);
if Assigned(FMemStream) then FreeAndNil(FMemStream);
if Assigned(FGPImageAttr) then FreeAndNil(FGPImageAttr);
end ;
// =============================================================================
// [Load Image]
// 画像ファイルの読み込み
// PNG形式の画像のみ
// =============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
OpenPictureDialog1.Filter := '画像ファイル|*.png' ;
OpenPictureDialog1.InitialDir := FLoadInitDir;
if not OpenPictureDialog1.Execute then exit;
FImageFilePath := OpenPictureDialog1.FileName;
FLoadInitDir := ExtractFileDir(FImageFilePath);
if Assigned(FGPBitmap) then FreeAndNil(FGPBitmap);
if Assigned(FMemStream) then FreeAndNil(FMemStream);
if Assigned(FGPImageAttr) then FreeAndNil(FGPImageAttr);
// メモリストリームに画像ファイルを読み込む
FMemStream := TBytesStream.Create;
FMemStream.LoadFromFile(FImageFilePath);
if ExtractFileExt(FImageFilePath) = '.png' then begin
FGPBitmap := TGPBitmap.Create(TStreamAdapter.Create(FMemStream, soReference));
end else begin
exit;
end ;
// 表示サイズの設定
// 横幅256に固定
FImgDispWidth := 128 ;
FImgDispHeight := Trunc(FImgDispWidth * FGPBitmap.GetHeight / FGPBitmap.GetWidth);
// ガンマ値設定用TSpinEditの値
SpinEdit_RedInRed.Value := 100 ;
// 描画
DrawGPBitmaToTImage;
end ;
// =============================================================================
// [Reset]
// 読み込んで作成した時の画像に戻す
// =============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
if Assigned(FGPImageAttr) then FreeAndNil(FGPImageAttr);
SpinEdit_RedInRed.Value := 100 ;
end ;
// =============================================================================
// TSpinEditのOnChangeイベント処理
// =============================================================================
procedure TForm1.SpinEdit_RedInRedChange(Sender: TObject);
var
LGammaValue : Single;
begin
if not Assigned(FGPBitmap) then exit;
// 実際にセットする値はこの値の1/100(0から4.00)
if TSpinEdit(Sender).Value <= 0 then TSpinEdit(Sender).Value := 0 ;
if TSpinEdit(Sender).Value >= 500 then TSpinEdit(Sender).Value := 500 ;
// TGPImageAttributesが生成されていない時だけ生成する
// 既に生成されている場合は他のTGPImageAttributes設定があるかも知れないので
if not Assigned(FGPImageAttr) then begin
FGPImageAttr := TGPImageAttributes.Create;
end ;
// ガンマ値をTGPImageAttributesに設定
LGammaValue := SpinEdit_RedInRed.Value / 100 ;
FGPImageAttr.SetGamma(LGammaValue);
// 描画
DrawGPBitmaToTImage;
end ;
// -----------------------------------------------------------------------------
// TImageへの描画ルーチン
// -----------------------------------------------------------------------------
procedure TForm1.DrawGPBitmaToTImage;
var
LGPGraphic : TGPGraphics;
LWidth : Integer;
LHeight : Integer;
begin
Image1.Picture.Assign(nil );
Image2.Picture.Assign(nil );
Image3.Picture.Assign(nil );
LWidth := FGPBitmap.GetWidth;
LHeight := FGPBitmap.GetHeight;
if LWidth <= 64 then begin
// 元の画像を実サイズ表示
Image2.Width := LWidth;
Image2.Height := LHeight;
LGPGraphic := TGPGraphics.Create(Image2.Canvas.Handle);
LGPGraphic.DrawImage(FGPBitmap, 0 , 0 );
LGPGraphic.Free;
// ガンマ値を変更した画像を実サイズ表示
Image3.Top := Image2.Top + Image2.Height + 10 ;
Image3.Width := LWidth;
Image3.Height := LHeight;
LGPGraphic := TGPGraphics.Create(Image3.Canvas.Handle);
LGPGraphic.DrawImage(FGPBitmap,
MakeRect(0 , 0 , LWidth, LHeight),
0 ,
0 ,
LWidth,
LHeight,
UnitPixel,
FGPImageAttr);
LGPGraphic.Free;
end ;
// 拡大リサイズして表示
Image1.Width := FImgDispWidth;
Image1.Height := FImgDispHeight;
LGPGraphic := TGPGraphics.Create(Image1.Canvas.Handle);
LGPGraphic.DrawImage(FGPBitmap,
MakeRect(0 , 0 , FImgDispWidth, FImgDispHeight),
0 ,
0 ,
LWidth,
LHeight,
UnitPixel,
FGPImageAttr);
LGPGraphic.Free;
end ;
end .
11_ TGPImageAttributes を使用した描画結果の保存
TGPImageAttributes を使用した描画の結果は,指定した Canvas に描画されます.元の TGPBitmap の内容は変化しません.だからこそ設定内容を変化させて描画結果を確認できるわけです.
現在の描画されている状態を画像として保存するには,別の TGPBitmap を用意して,その TGPBitmap に同じ TGPImageAttributes の設定で描画します.
以下はその例です.このコードは,前項のサンプルに保存の機能を追加する例です.
下に示すコードは,保存の際に保存用の TGPBitmap を生成する例です.保存の時は TImage への描画時と描画先を変更する例です.
リスト14
保存の際に保存用のTGPBitmapを作成する例
copy code
// =============================================================================
// 描画内容を保存
// 保存の際に保存用のTGPBitmapを作成する例
// =============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
LGPbitmap : TGPBitmap;
LGPGraphic : TGPGraphics;
LImgGUID : TGUID;
begin
if not Assigned(FGPBitmap) then exit;
// 表示サイズで保存するものとする
// 表示サイズと同じTBPBitmapを作成
LGPbitmap := TGPBitmap.Create(FImgDispWidth, FImgDispHeight);
try
DrawGPBitmaToTImage(LGPbitmap);
// PNG画像として保存
if GetEncoderClsid('image/png' , LImgGUID) >= 0 then begin
LGPBitmap.Save('000.png' , LImgGUID);
end ;
finally
FreeAndNil(LGPbitmap);
end ;
end ;
// -----------------------------------------------------------------------------
// 描画ルーチン
// -----------------------------------------------------------------------------
procedure TForm1.DrawGPBitmaToTImage(AGPBitmap: TGPBitmap = nil );
var
LGPGraphic : TGPGraphics;
begin
Image1.Picture.Assign(nil );
Image1.Width := FImgDispWidth;
Image1.Height := FImgDispHeight;
if AGPBitmap <> nil then begin
LGPGraphic := TGPGraphics. Create(AGPBitmap);
end else begin
LGPGraphic := TGPGraphics.Create(Image1.Canvas.Handle);
end ;
LGPGraphic.DrawImage(FGPBitmap,
MakeRect(0 , 0 , FImgDispWidth, FImgDispHeight),
0 ,
0 ,
FGPBitmap.GetWidth,
FGPBitmap.GetHeight,
UnitPixel,
FGPImageAttr);
LGPGraphic.Free;
end ;
次のコードは TGPBitmap 型のグローバルな変数を用意してそれを使用する方法です.
まず,このグローバル変数の TGPBitmap に描画して,それを TImage に描画しています.
リスト15
グローバルな変数として専用のTGPBitmapを使用する例
copy code
// =============================================================================
// 描画内容を保存
// グローバルな変数として専用のTGPBitmapを使用する例
// =============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
LImgGUID : TGUID;
begin
if not Assigned(FGPSaveBitmap) then exit;
// PNG画像として保存
if GetEncoderClsid('image/png' , LImgGUID) >= 0 then begin
FGPSaveBitmap.Save('000.png' , LImgGUID);
end ;
end ;
// -----------------------------------------------------------------------------
// 描画ルーチン
// -----------------------------------------------------------------------------
procedure TForm1.DrawGPBitmaToTImage;
var
LGPGraphic : TGPGraphics;
begin
Image1.Picture.Assign(nil );
Image1.Width := FImgDispWidth;
Image1.Height := FImgDispHeight;
if not Assigned(FGPSaveBitmap) then begin
// 表示サイズと同じTBPBitmapを作成
FGPSaveBitmap := TGPBitmap.Create(FImgDispWidth, FImgDispHeight);
end ;
// 作成したTGPBitmapに読み込んだ画像を属性を指定して描画する
LGPGraphic := TGPGraphics. Create(FGPSaveBitmap);
LGPGraphic.DrawImage(FGPBitmap,
MakeRect(0 , 0 , FImgDispWidth, FImgDispHeight),
0 ,
0 ,
FGPBitmap.GetWidth,
FGPBitmap.GetHeight,
UnitPixel,
FGPImageAttr);
LGPGraphic.Free;
// 描画の結果をTImageに描画する
LGPGraphic := TGPGraphics.Create(Image1.Canvas.Handle);
LGPGraphic.DrawImage(FGPSaveBitmap, 0 , 0 );
LGPGraphic.Free;
end ;