概述
从GR32库中,我使用TImgView32渲染网格,这将是我的透明背景,如下所示:
放在TImgView32内部我有一个常规的TImage,我将在画布上画画,如下所示:
任务
我想要达到的是能够设置画笔的不透明度,从而为我的程序中的图像编辑提供了更多的可能性。而不是绘制一个平面颜色,设置画笔的不透明度允许不同级别的颜色深度等。
我在搜索时发现了这个问题:Draw opacity ellipse in Delphi 2010 - Andreas Rejbrand在回答这个问题时提供了一些例子。
我已经看过安德烈亚斯做了什么,并提出了我自己的简化尝试,但我遇到了问题。看看下面这两个图像,第一个是透明背景,第二个是黑色背景,以显示问题更清晰:
正如你所看到的,在画笔(圆圈)周围是一个非常讨厌的广场,我无法摆脱。所有应该可见的是刷子。这是我用来产生这些结果的代码:
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
,则仍然有一个白框,但不再有不透明度。只是一个坚实的白色方块和坚实的红色圆圈。
答案 0 :(得分:14)
TCanvas.Draw()
的不透明度功能不支持您尝试执行的操作,至少不支持您尝试使用它的方式。为了实现您想要的效果,您需要创建一个32位TBitmap
,这样您就拥有了每像素的Alpha通道,然后为每个像素填充alpha,将alpha设置为0,用于您不需要的像素; t想要,并将alpha设置为所需像素的所需不透明度。然后,在调用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;