ScanLineの2次配列化 (Delphi)


Delphiで画像をご存知と思いますが、BitmapのPixelsプロパティを使ってのピクセル色の取得・設定は画像処理などでループ作業をする場合、非常に時間がかかります。

そこで通常はScanLineを使うわけですが、横一ライン分の画素しか持てません。対象ピクセルから数ドット上のピクセルを参照、なんて場合は無駄に面倒なルーチンを組まないといけません。
そこで、ポインタを使って2次配列化するやり方を載せていたサイトがあったのですが、どうも数年経つ間にサイトが消えてしまったようです。

{RGB構造体定義}
type TRGB     = record B,G,R:Byte end;
     PRGB     =^TRGB;
     TLine    = array[0..0]of TRGB;
     PLine    =^TLine;
     TPLines  = array[0..0]of PLine;
     PPLines  =^TPLines;

{2次配列に変換}
function GetPixelArray(Bitmap:TBitmap):PPLines;
var
  i  :integer;
  h  :integer;
begin
 Result:=nil;
 if Bitmap.Empty then exit;
 
 h := Bitmap.Height;
 Result := Allocmem(sizeof(PLine)*h);

 for i:=0 to h-1 do
   Result^[i] := Bitmap.ScanLine[i];
end;

{メモリ解放}
procedure FreePixelArray(var PixelArray:PPLines);
begin
  if PixelArray <> nil then begin
    Freemem(PixelArray);
    PixelArray := nil;
  end;
end;

{使用例:画像のネガポジ反転コピー}
procedure Invert(SrcBitmap,DstBitmap:TBitmap);
var
  Src      :PPLines;
  Dst      :PPLines;
  i,j      :integer;
begin
  Src := GetPixelArray(SrcBitmap);
  Dst := GetPixelArray(DstBitmap);

  for i := 0 to SrcBitmap.Height - 1 do
  for j := 0 to SrcBitmap.Width  - 1 do
  begin
    Dst[i,j].R := 255 - Src[i,j].R; //座標は[Y,X]となります
     Dst[i,j].G := 255 - Src[i,j].G;
    Dst[i,j].B := 255 - Src[i,j].B;
  end;

  FreePixelArray(Dst); //メモリを解放してください
  FreePixelArray(Src);
end;

24Bit同サイズのビットマップ前提です。

参考リンク


MemoNyanDum Delphi(Graphics) : ScanLine --> TBmpData24


最終更新:2006年12月17日 00:10