今回はガンマ補正です。といっても私はいまいち理解していません。AK さんのホームページでは「中間地を明るくしたり暗くしたりする」といった感じのことがかかれています。
AK's Laboratory
ここで作成するガンマ補正の関数は一般的なものとは異なるのかもしれませんが、私が持っているPhotoshopと同じ感覚で操作できるのでこのタイプのものを使用しています。計算式は以下のようになっています。
Dest := Round(Power(Source / 255, Value / 2.2) * 255);
Source(入力値)は0から255の範囲、Value(補正値)は0.75から3.00の範囲を想定しています。問題は補正値を割る2.2という定数です。この数値は基準となるガンマ値で、一般的なWindowsマシンでは2.2になっているようです。そのため、ここでも2.2を基準値として使用します。基準値はカスタマイズできるようにグローバル変数にしたり、補正値と基準値を受け取る関数を作成するのもいいかもしれませんね。
さて、実際にコードを書くわけですが、上記の計算式はRGB毎に行う必要があります。ただ、入力値も出力値も0から255の範囲内に収まるので、あらかじめ変換テーブルを作成してしまうことにします。これで大幅なスピードアップを行うことができます。
なお、ユニットのusesにMathユニットを追加しておいてください。
procedure Gamma(Bitmap: TBitmap; Value: Double);
//ガンマ補正
var
X, Y: Integer;
pLine: PLine24;
Table: array[Byte]of Byte;
begin
if (Value < 0.75) or (Value = 2.2) or (Value > 3) then
Exit;
Bitmap.PixelFormat := pf24bit;
{ 変換テーブルの作成 }
Value := Value / 2.2;
for Y := 0 to 255 do
begin
X := Round(Power(Y / 255, Value) * 255);
if X > 255 then X := 255 else if X < 0 then X := 0;
Table[Y] := X;
end;
{ ピクセルの変換処理 }
for Y := 0 to Bitmap.Height -1 do
begin
pLine := Bitmap.ScanLine[Y];
for X := 0 to Bitmap.Width -1 do
with pLine^[X] do
begin
R := Table[R];
G := Table[G];
B := Table[B];
end;
end;
if Assigned(Bitmap.OnChange) then
Bitmap.OnChange(Bitmap);
end;
|