12

概要

GR32 ライブラリから、TImgView32 を使用して、次のように透明な背景となるグリッドをレンダリングしています。

ここに画像の説明を入力

TImgView32 内に配置すると、次のようなキャンバスに描画する通常の TImage があります。

ここに画像の説明を入力

仕事

私が達成したいのは、ブラシの不透明度を設定する機能であり、プログラムでの画像編集の可能性をさらに広げます。1 つの単色を描画するのではなく、ブラシの不透明度を設定することで、さまざまなレベルの色深度などが可能になります。

Delphi 2010 で不透明な楕円を描く- Andreas Rejbrandは、その質問に対する回答でいくつかの例を提供しています。

私はアンドレアスが何をしたかを見て、私自身の単純化された試みを思いつきましたが、私は問題に悩まされています. 次の 2 つの画像を見てください。最初の画像は背景が透明で、2 番目の画像は背景が黒で、問題がより明確に示されています。

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

ご覧のとおり、ブラシ (円) の周りは、私が取り除くことができない非常に厄介な四角形です。目に見えるのはブラシだけです。これは、これらの結果を生成するために使用される私のコードです:

procedure DrawOpacityBrush(ACanvasBitmap: TBitmap; X, Y: Integer;
  AColor: TColor; ASize: Integer; Opacity: Integer);
var
  Bmp: TBitmap;
begin
  Bmp := TBitmap.Create;
  try
    Bmp.SetSize(ASize, ASize);
    Bmp.Transparent := False;

    with Bmp.Canvas do
    begin
      Pen.Color := AColor;
      Pen.Style := psSolid;
      Pen.Width := ASize;
      MoveTo(ASize div 2, ASize div 2);
      LineTo(ASize div 2, ASize div 2);
    end;

    ACanvasBitmap.Canvas.Draw(X, Y, Bmp, Opacity);
  finally
    Bmp.Free;
  end;
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  DrawOpacityBrush(Image1.Picture.Bitmap, X, Y, clRed, 50, 85);
end;

通常のビットマップでこれを生成します:

ここに画像の説明を入力

私が持っていたアイデア (不透明な楕円を作成する Andreas の方法に基づく) は、典型的なブラシをキャンバスにレンダリングし、それをオフスクリーン ビットマップに割り当ててから、不透明なメイン ビットマップに再描画することでした。エッジの周りの迷惑な四角形を除いて、これは機能します。

スクリーンショットに示されているように、不透明度のあるブラシをレンダリングするにはどうすればよいですか?ただし、ブラシの円の周りに四角形はありません。

設定Bmp.Transparent := Trueすると、まだ白いボックスがありますが、不透明度はなくなりました。塗りつぶされた白い四角と塗りつぶされた赤い円だけです。

4

1 に答える 1

17

の不透明度機能は、TCanvas.Draw()あなたがやろうとしていること、少なくともあなたがそれを使おうとしている方法をサポートしていません。必要な効果を実現するには、32 ビットを作成してTBitmapピクセルごとのアルファ チャネルを作成し、各ピクセルのアルファを入力して、不要なピクセルのアルファを 0 に設定し、アルファを、必要なピクセルの希望する不透明度に変更します。次に、 を呼び出すときにTCanvas.Draw()、不透明度を 255 に設定して、ピクセルごとの不透明度のみを使用するように指示します。

procedure DrawOpacityBrush(ACanvas: TCanvas; X, Y: Integer; AColor: TColor; ASize: Integer; Opacity: Byte);
var
  Bmp: TBitmap;
  I, J: Integer;
  Pixels: PRGBQuad;
  ColorRgb: Integer;
  ColorR, ColorG, ColorB: Byte;
begin
  Bmp := TBitmap.Create;
  try
    Bmp.PixelFormat := pf32Bit; // needed for an alpha channel
    Bmp.SetSize(ASize, ASize);

    with Bmp.Canvas do
    begin
      Brush.Color := clFuchsia; // background color to mask out
      ColorRgb := ColorToRGB(Brush.Color);
      FillRect(Rect(0, 0, ASize, ASize));
      Pen.Color := AColor;
      Pen.Style := psSolid;
      Pen.Width := ASize;
      MoveTo(ASize div 2, ASize div 2);
      LineTo(ASize div 2, ASize div 2);
    end;

    ColorR := GetRValue(ColorRgb);
    ColorG := GetGValue(ColorRgb);
    ColorB := GetBValue(ColorRgb);

    for I := 0 to Bmp.Height-1 do
    begin
      Pixels := PRGBQuad(Bmp.ScanLine[I]);
      for J := 0 to Bmp.Width-1 do
      begin
        with Pixels^ do
        begin
          if (rgbRed = ColorR) and (rgbGreen = ColorG) and (rgbBlue = ColorB) then
            rgbReserved := 0
          else
            rgbReserved := Opacity; 
          // must pre-multiply the pixel with its alpha channel before drawing
          rgbRed := (rgbRed * rgbReserved) div $FF;
          rgbGreen := (rgbGreen * rgbReserved) div $FF;
          rgbBlue := (rgbBlue * rgbReserved) div $FF;
        end;
        Inc(Pixels);
      end;
    end;

    ACanvas.Draw(X, Y, Bmp, 255);
  finally
    Bmp.Free;
  end;
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;  
  Shift: TShiftState; X, Y: Integer);  
begin  
  DrawOpacityBrush(Image1.Picture.Bitmap.Canvas, X, Y, clRed, 50, 85);  
end;  
于 2012-04-27T00:39:10.900 に答える