【问题标题】:Draw on TeeChart directly with GDI+直接使用 GDI+ 在 TeeChart 上绘图
【发布时间】:2019-02-01 18:17:25
【问题描述】:

如何在 TChart 上直接使用 GDI+ 旋转和绘制透明的 PNG 图像?

目前我将 PNG 图像加载到位图并使用两个位图进行 GDI+ 旋转(它工作得非常快),然后使目标位图透明并在 TChart 的画布上绘制它(打开透明度时它工作得很慢)。

procedure TPitchDisplay._chartAfterDraw(Sender: TObject);
var
  c: TCanvas3D;
  pw, ph: Integer;
  r: TRect;
  bmp: TBitmap;
  rotAngle: Integer;
begin
  _setKnobBounds();
  c := _chart.Canvas;
  _drawCircle(c, _knob.CenterPoint.X, _knob.CenterPoint.Y, Round(_knob.YRadius * 0.9));
  c.StretchDrawQuality := sqHigh;
  pw := 450;
  ph := Round((pw / _shipBitmap.Width) * _shipBitmap.Height);
  r.Left := _chart.ChartXCenter - pw div 2;
  r.Top := Round(_chart.Height / 3);
  r.Width := pw;
  r.Height := ph;

  //Draw water
  c.StretchDraw(Rect(0, r.Top + Round(ph / 1.5), _chart.Width, _chart.Height), _waterBitmap);

  //Draw rotated ship over it
  bmp := TBitmap.Create();
  try
    bmp.Width := Round(_shipBitmap.Width * 1.2);
    bmp.Height := Round(_shipBitmap.Height * 1.7);
    bmp.TransparentColor := clBlack;
    bmp.Transparent := True;
    bmp.TransparentMode := TTransparentMode.tmFixed;
    if VarIsNumeric(_pitchBox.Value) then
      rotAngle := _pitchBox.Value
    else
      rotAngle := 0;
    TGraphUtils.RotateBitmap(_shipBitmap, bmp, 0.5, 0.7, rotAngle, False, clBlack);
    c.StretchDraw(r, bmp);
  finally
    bmp.Free();
  end;
end;

轮换套路:

class procedure TGraphUtils.RotateBitmap(srcBmp, tgtBmp: TBitmap; rotateAtX, rotateAtY: Single; Degs: Integer; AdjustSize: Boolean;
  BkColor: TColor = clNone);
var
  Tmp: TGPBitmap;
  Matrix: TGPMatrix;
  C: Single;
  S: Single;
  NewSize: TSize;
  Graphs: TGPGraphics;
  P: TGPPointF;
  attr: TGPImageAttributes;
begin
  Tmp := TGPBitmap.Create(srcBmp.Handle, srcBmp.Palette);
  Matrix := TGPMatrix.Create();
  try
    Matrix.RotateAt(Degs, MakePoint(rotateAtX * srcBmp.Width, rotateAtY * srcBmp.Height));
    if AdjustSize then begin
      C := Cos(DegToRad(Degs));
      S := Sin(DegToRad(Degs));
      NewSize.cx := Round(srcBmp.Width * Abs(C) + srcBmp.Height * Abs(S));
      NewSize.cy := Round(srcBmp.Width * Abs(S) + srcBmp.Height * Abs(C));
      tgtBmp.Width := NewSize.cx;
      tgtBmp.Height := NewSize.cy;
    end;
    Graphs := TGPGraphics.Create(tgtBmp.Canvas.Handle);
    attr := TGPImageAttributes.Create;
    try
      Graphs.Clear(ColorRefToARGB(ColorToRGB(BkColor)));
      Graphs.SetTransform(Matrix);
      //attr.SetColorKey($FFFFFF {TGPColor.Blue}, $FFFFFF {TGPColor.Blue}, ColorAdjustTypeBitmap);
      Graphs.DrawImage(Tmp, (Cardinal(tgtBmp.Width) - Tmp.GetWidth) div 2,
        (Cardinal(tgtBmp.Height) - Tmp.GetHeight) div 2);
    finally
      attr.Free();
      Graphs.Free();
    end;
  finally
    Matrix.Free();
    Tmp.Free();
  end;
end;

【问题讨论】:

    标签: delphi gdi+ teechart


    【解决方案1】:

    procedure TForm1.Chart1AfterDraw(Sender: TObject);
    var
      GPImage: TGPImage;
      GPGraphics: TGPGraphics;
      Matrix: TGPMatrix;
      c: TCanvas3d;
     begin
      c := Chart1.Canvas;
      GPImage := TGPImage.Create('e:\2.png');
      GPGraphics :=  TGPGraphics.Create(C.Handle);
      Matrix := TGPMatrix.Create;
      Matrix.Rotate(30);
      Matrix.Scale(0.5, 0.5);
      GPGraphics.SetTransform(Matrix);
      GPGraphics.DrawImage(GPImage, 150, 0);
      Matrix.Free;
      GPGraphics.Free;
      GPimage.Free;
    end;
    

    输出到表单中心的不精确示例:

      IM := TGPMatrix.Create;
      IM := Matrix.Clone;
      IM.Invert;
      pc := MakePoint(Width div 2 - GPImage.GetWidth() div 2, 
                      Height div 2 - Integer(GPImage.GetHeight) div 2);
      Im.TransformPoints(pgppoINT(@pc));
      GPGraphics.DrawImage(GPImage, pc);
    

    【讨论】:

    • 它有效,而且速度非常快!谢谢你。也许你可以告诉我如何从 PNG 资源加载 TGPImage?我正在使用 TPNGImage 将其加载到位图。
    • 我将您的示例中的Matrix.Rotate(30) 更改为Matrix.RotateAt(rotAngle, MakePoint(GPImage.GetWidth() div 2, GPImage.GetHeight() div 2)) 以围绕图像中心旋转,并且它可以正确旋转,但是当我将GPGraphics.DrawImage(GPImage, 150, 0) 更改为150_chart.ChartXCenter 时,它会旋转再次绕过图像角落。我不知道为什么。
    • ResourceStream/StreamAdapter/IStream/TGPImage.FromStream 方法是否适用于 png?
    • 它围绕图像中心旋转,但输出发生在旋转坐标系中(尝试使用 y=0 和不同 x 的 drawimage,您会看到图像按斜线移动)。您必须在新坐标系中找到图表中心的坐标(使用逆矩阵)。我添加了粗略的例子
    • 感谢您的提示。在 RotateAt 之前使用 Matrix.Translate(x,y) 来移动图像很有帮助。
    猜你喜欢
    • 2013-02-01
    • 2020-02-16
    • 2015-12-29
    • 2017-05-28
    • 1970-01-01
    • 1970-01-01
    • 2011-03-04
    • 2022-08-17
    • 1970-01-01
    相关资源
    最近更新 更多