Delphi: FMX ビットマップのRGB値のスキャン

Delphi活用

VCLの ScanLine は FMX でどうする的な話

TBitmapData の GetScanline を使う

例としてTImageにこの画像のpngファイルを読み込み、画像をスキャンします。
画像のスキャンには、TBitmapData の GetScanline を使います。

TBitmap の Mapメソッド で TBitmapData にマッピング

まず、TBitmap の Map メソッドで TBitmap のビットマップ データを TBitmapData にマップします。

TBitmapData の GetScanline メソッドを使い画像を横方向にスキャンして、TAlphaColor の配列を指すポインタを取得します。得られた TAlphaColor を TAlphaColorRec に入れると、TAlphaColorRec の機能を利用してRGB値を取得することができます。

最後に TBitmap の Unmap メソッドで ビットマップのカスタマイズ セッションをファイナライズします。

MemoにRGB値を書き込む例

以下の例では、Memoに、画像と同じ向きのRGB値を書き込んでいます。
この例では、値を読むだけなので、Mapメソッドでアクセスのタイプを TMapAccess.Read にしています。書き込む場合は、TMapAccess.Write または TMapAccess.ReadWrite を使います。

procedure TForm1.CornerButton1Click(Sender: TObject);
var
FileName: String;
bd1: TBitmapData;
x, y, w, h: Integer;
p1: FMX.Utils.PAlphaColorArray;
AC: TAlphaColor;
rec : TAlphaColorRec;
S:String;
Blue:byte;
begin
FileName:= System.IOUtils.TPath.Combine(FTestPath, 'Paste1.png');
try
Image2.Bitmap.LoadFromFile(FileName);
w := Image2.Bitmap.Width;
h := Image2.Bitmap.Height;
try
Image2.Bitmap.Map(TMapAccess.Read, bd1);
for y := 0 to h -1 do
begin
p1 := PAlphaColorArray(bd1.GetScanline(y));
S:='';
for x := 0 to w -1 do
begin
AC:= TAlphaColor(p1[x]);
rec.Color:= AC;
Blue:= rec.B; { RとGは省略 }
S:= S + IntToStr(Blue) + #9;
end;
Memo1.Lines.Add(S);
end;
finally
Image2.Bitmap.Unmap(bd1);
end;
except
end;
end;

結果をエクセルのカラースケールで見る

Memoの内容をエクセルにコピーし、カラースケールを適用するとこうなりました。

画像の(x,y)と出力の(x,y)が一致しています。

RGB値を右側から縦方向に書き込む例

procedure TForm1.CornerButton2Click(Sender: TObject);
var
  FileName: String;
  bd1: TBitmapData;
  x, y, w, h: Integer;
  p1: FMX.Utils.PAlphaColorArray;
  AC: TAlphaColor;
  rec : TAlphaColorRec;
  S:String;
  Blue:byte;
begin
  FileName:= System.IOUtils.TPath.Combine(FTestPath, 'Paste1.png');
  try
    Image2.Bitmap.LoadFromFile(FileName);
    w := Image2.Bitmap.Width;
    h := Image2.Bitmap.Height;
    try
      Image2.Bitmap.Map(TMapAccess.Read, bd1);
      S:= '';
      for y := 0 to h -1 do
      begin
        p1 := PAlphaColorArray(bd1.GetScanline(y));
        for x := 0 to w -1 do
        begin
          if y = 0 then
            Memo1.Lines.Add(S);
          AC:= TAlphaColor(p1[x]);
          rec.Color:=  AC;
          Blue:= rec.B;   { RとGは省略  }
          S:= IntToStr(Blue) + #9;
          Memo1.Lines[x]:= Memo1.Lines[x] + S;
        end;
      end;
    finally
      Image2.Bitmap.Unmap(bd1);
    end;
  except
  end;
end;

Memoの内容をエクセルにコピーし、カラースケールを適用するとこうなります。

画像の(x,y)と出力の(x,y)では、xとyが入れ替わっています。

参考:Excelのカラースケール

ちなみにExcelのカラースケールは「ホーム」タブの「条件付き書式」の中にあります。

値の分布をレビューするのに重宝しています。

値を操作するにもエクセルは便利です。下図は上下、左右の値を引いたり足したりして境界の検出方法を検討した例です

RGBすべての結果

RGBをそれぞれカラースケールで示すとこうなります。(上からR,G,B)

TMapAccess.Read と TMapAccess.Write を使って画像を複製する例

こちらで紹介されています。

How to manipulate pixels on a bitmap by scanline property(Ma Xiaoguang and Ma Xiaoming) - findumars - 博客园
We have been developing image processing software for above 14 years with old versions of Delphi, such as Delphi 6 and D...
タイトルとURLをコピーしました