4

別の「下」の画像の上に透明な画像を表示しています。

この場合、下の (ソリッド) 画像はチェス盤のグリッドで、上の画像はライオン (透明) です。

ここに画像の説明を入力

ここに画像の説明を入力=ここに画像の説明を入力

その理由は、通常、どの領域が透明であるかを確認できないため、透明領域をより適切に表示するためです。

問題は、ビットマップのサイズは任意であるため、グリッドもビットマップと同じサイズにする必要があることです。

2000x2000 などのサイズのチェス盤グリッドのより大きなバージョンを作成し、作業しているビットマップのサイズに応じて、グリッドのキャンバスのサイズを変更して一致させることができます。これは理想的ではありません。これは、大きなチェス盤のグリッド ビットマップをアプリケーションに格納することを意味し、サイズを変更することを意味し、アスペクト比などによっては正しい結果が得られない可能性があるためです。

私が感じる正しいアプローチは、チェス盤のグリッドをプログラムで次のようにレンダリングすることです。

procedure RenderGrid(Source: TBitmap; Height, Width: Integer;
  Size: Integer; Color1, Color2: TColor);
begin

end;

これにより、グリッドをさまざまなサイズと色でカスタマイズできるようになり、大きなチェス盤グリッド ビットマップを格納してサイズを変更するオーバーヘッドについて心配する必要がなくなります。

ただし、グリッドをビットマップに描画する方法がわかりませんか? 私が考えていたのは、ビットマップの交互の各行をループして、そのように色を付ける必要があるということでしたか? 私はわかりません。

これには、私が苦手な数学と計算が含まれます。グリッドをビットマップにレンダリングする最も効果的な方法を教えていただければ幸いです。

4

4 に答える 4

5
procedure RenderGrid(Source: TBitmap; Height, Width: Integer;
  Size: Integer; Color1, Color2: TColor);
var
  y: Integer;
  x: Integer;
begin
  Source.SetSize(Width, Height);
  for y := 0 to Height div Size do
    for x := 0 to Width div Size do
    begin
      if Odd(x) xor Odd(y) then
        Source.Canvas.Brush.Color := Color1
      else
        Source.Canvas.Brush.Color := Color2;
      Source.Canvas.FillRect(Rect(x*Size, y*Size, (x+1)*Size, (y+1)*Size));
    end;
end;
于 2012-07-17T20:07:07.890 に答える
3

むかしむかし、私はこの特定の必要性をプロファイリングしました。RenderGrid署名を考慮するBitmapと、ビットマップが描画された後にパラメーターの画像が描画される可能性があります。次に、 でビットマップ全体をColor1ペイントし、 の正方形のみをペイントすると、最高のパフォーマンスが得られColor2ます。

procedure RenderGrid(Target: TBitmap; Height, Width: Integer; Size: Integer;
  Color1, Color2: TColor);
var
  Col: Integer;
  Row: Integer;
begin
  Target.SetSize(Width, Height)
  Target.Canvas.Brush.Color := Color1;
  Target.Canvas.FillRect(Rect(0, 0, Width, Height));
  Target.Canvas.Brush.Color := Color2;
  for Col := 0 to Width div Size do
    for Row := 0 to Height div Size do
      if Odd(Col + Row) then
        Target.Canvas.FillRect(Bounds(Col * Size, Row * Size, Size, Size));
end;

アップデート

しかし、大きなビットマップについて話しているので、以下に示すルーチンはさらに 20% 高速です。2 x 2 のチェス盤など、4 つの正方形のみの小さなビットマップを作成し、ターゲットのブラシ プロパティによって自動的に展開されます。*)

procedure RenderGrid(Target: TBitmap; Height, Width: Integer; Size: Integer;
  Color1, Color2: TColor);
var
  Tmp: TBitmap;
begin
  Tmp := TBitmap.Create;
  try
    Tmp.Canvas.Brush.Color := Color1;
    Tmp.Width := 2 * Size;
    Tmp.Height := 2 * Size;
    Tmp.Canvas.Brush.Color := Color2;
    Tmp.Canvas.FillRect(Rect(0, 0, Size, Size));
    Tmp.Canvas.FillRect(Bounds(Size, Size, Size, Size));
    Target.Canvas.Brush.Bitmap := Tmp;
    if Target.Width * Target.Height = 0 then
      Target.SetSize(Width, Height)
    else
    begin
      Target.SetSize(Width, Height)
      Target.Canvas.FillRect(Rect(0, 0, Width, Height));
    end;
  finally
    Tmp.Free;
  end;
end;

これをさらに最適化するには、この小さなビットマップ ( Tmp) をキャッシュし、サイズが変更されていないときに再利用します。

*)も参照してください:を呼び出さずにビットマップに色を付けるにはFillRect()? .

于 2012-07-17T22:31:56.553 に答える
-1

このアプローチにより、パフォーマンスが向上します。CellSize = 0 を渡さないでください。

// Color1, Color2 in RRGGBB format (i.e. Red = $00FF0000)
procedure RenderGrid(Source: TBitmap; CellSize: Integer; Color1, Color2: TColorRef);
var
  I, J: Integer;
  Pixel: ^TColorRef;
  UseColor1: Boolean;
begin
  Source.PixelFormat := pf32bit;
  Pixel := Source.ScanLine[Source.Height - 1];
  for I := 0 to Source.Height - 1 do
  begin
    UseColor1 := (I div CellSize) mod 2 = 0;
    for J := 0 to Source.Width - 1 do
    begin
      if J mod CellSize = 0 then UseColor1 := not UseColor1;

      if UseColor1 then
        Pixel^ := Color1
      else
        Pixel^ := Color2;
      Inc(Pixel);
    end;
  end;
end;
于 2012-07-17T20:24:15.953 に答える