【问题标题】:Draw a transparent Ellipse in a layer在图层中绘制透明椭圆
【发布时间】:2023-11-09 21:14:01
【问题描述】:

我的表单上有一个TImgView32(名为 CityMap),并在其上加载了一张图片。现在我创建一个图层(TBitmapLayer)并使用TBitmap32 变量的Canvas.Ellipse 绘制一个圆圈,如下所示:

procedure TfrmMain.Button1Click(Sender: TObject);
var
  tmpBmp: TBitmap32;
  tmpBL: TBitmapLayer;  
begin
  tmpBL:= TBitmapLayer.Create(CityMap.Layers);

  tmpBmp:= TBitmap32.Create;

  with tmpBmp do
  begin
    //Clear;
    SetSize(50, 50);
    Canvas.Brush.Color := clYellow;
    Canvas.Brush.Style:= bsSolid;
    Canvas.Pen.Color := clBlue;
    Canvas.Pen.Width := 2;
    Canvas.Ellipse(Rect(0, 0, 50, 50));
  end;  

  with tmpBL do
  begin
    Scaled:=true;
    Bitmap.DrawMode:=dmBlend;
    tmpBL.Bitmap:=(tmpBmp);
    //tmpBmp.DrawTo(tmpBL.Bitmap, 0, 0); This line doesn't work! So using above line instead
  end;

  //...

end;

结果是这样的:

如您所见,问题在于烦人的黑色矩形。如何创建这样的结果:

【问题讨论】:

    标签: delphi layer graphics32


    【解决方案1】:

    TBitmap32 图像的DrawMode 属性使用dmTransparent 绘制模式:

    procedure TForm1.Button1Click(Sender: TObject);
    var
      Bitmap: TBitmap32;
      Layer: TBitmapLayer;
    begin
      Layer := TBitmapLayer.Create(CityMap.Layers);
    
      Bitmap := TBitmap32.Create;
      Bitmap.DrawMode := dmTransparent;
      Bitmap.SetSize(50, 50);
      Bitmap.Canvas.Brush.Color := clYellow;
      Bitmap.Canvas.Brush.Style:= bsSolid;
      Bitmap.Canvas.Pen.Color := clBlue;
      Bitmap.Canvas.Pen.Width := 2;
      Bitmap.Canvas.Ellipse(Rect(0, 0, 50, 50));
    
      Layer.Scaled := True;
      Layer.Bitmap := Bitmap;
      ...
    end;
    

    【讨论】:

    • 无论如何,如果您正在寻找抗锯齿矢量绘图引擎,我建议您使用 Anti Grain Geometry Library (AGG)。我试过了,例如当我决定在地图控件中使用什么时,GR32_Lines 扩展,我正在研究,但结果不如 AGG。而且,出于好奇,AGG 被用作 Mapnik 的主要渲染器,例如用于渲染 OpenStreetMaps 瓦片。
    • 感谢您的信息。和你一样,我已经尝试过 GR32_Lines 来产生抗锯齿结果。但是在缩放地图时效果很差。无论如何,GR32 有很好的特性(例如图层和转换)。我可以将 AGG 与 GR32 一起使用(IDK 关于 AGG 的任何事情)吗?
    • 我个人使用AggPasMod 包装器,它带有GR32 demo。我没有尝试过该演示,但可以肯定的是,我可以告诉您,您可以像使用 TGraphic 对象 (TAgg2DGraphics) 一样使用 AGG,因此您可以渲染矢量结果,例如使用TCanvas.Draw 方法。
    • 它是否可以自己绘制,所以当 Bimap32 图像被缩放时(通过例如 ImgView32)它会产生反纹理结果(Layer.Scaled := True;)?
    • 我认为有办法做到这一点,但从未使用过。我们更多地使用 AGG 作为光栅渲染器,因为当我们的地图被缩放时(我们只使用我们的 OSM 瓦片服务器渲染器给出的固定缩放值),路线高亮和所有相关的自定义点被重新渲染,因为点得到如果放大或缩小,地图上的位置会更准确。我知道这不是你的情况,但我不能在这里服务。