在图像上绘制文本

Rep*_*til 3 delphi android firemonkey delphi-10-seattle

我正在尝试使用以下代码在图像上绘制文本:

procedure TfMain.TextToImage(const AText: string; const AImage: TImage);
begin
  if NOT Assigned(AImage) then Exit;    
  AImage.Canvas.BeginScene;
  AImage.Canvas.Font.Size    := 18;
  AImage.Canvas.Font.Family  := 'Arial';
  AImage.Canvas.Fill.Color   := TAlphaColorRec.Dodgerblue;
  AImage.Canvas.Font.Style   := [TFontStyle.fsbold];
  AImage.Canvas.FillText( AImage.AbsoluteRect,
                          AText,
                          False,
                          1,
                          [TFillTextFlag.RightToLeft],
                          TTextAlign.taCenter,
                          TTextAlign.taCenter);
  AImage.Canvas.EndScene;
end;
Run Code Online (Sandbox Code Playgroud)

问:为什么上面的步骤在 Windows 上可以运行,但在 Android 上却不行?

小智 5

尝试直接在TBitmaptimage 的画布上绘制,而不是在 TImage 的 Canvas 上绘制。

在尝试访问图像之前,您还需要创建图像的位图:

AImage.Bitmap := TBitmap.Create(Round(AImage.Width), Round(AImage.Height));
Run Code Online (Sandbox Code Playgroud)

所以正确的代码应该是这样的:

procedure TfMain.TextToImage(const AText: string; const AImage: TImage);
begin
  if NOT Assigned(AImage) then Exit;
  AImage.Bitmap := TBitmap.Create(Round(AImage.Width), Round(AImage.Height));
  AImage.Bitmap.Canvas.BeginScene;
  try
    //....
    // Use AImage.Bitmap.Canvas as needed
    AImage.Bitmap.Canvas.FillText( AImage.AbsoluteRect,
                            AText,
                            False,
                            1,
                            [],
                            TTextAlign.Center,
                            TTextAlign.Center);
  finally
    AImage.Bitmap.Canvas.EndScene;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

TImage.Paint事件代码中您将看到:

procedure TImage.Paint;
var
  R: TRectF;
begin
  if (csDesigning in ComponentState) and not Locked and not FInPaintTo then
  begin
    R := LocalRect;
    InflateRect(R, -0.5, -0.5);
    Canvas.DrawDashRect(R, 0, 0, AllCorners, AbsoluteOpacity, $A0909090);
  end;

  UpdateCurrentBitmap;
  if FCurrentBitmap <> nil then
    DrawBitmap(Canvas, LocalRect, FCurrentBitmap, AbsoluteOpacity);
end;
Run Code Online (Sandbox Code Playgroud)

因此,无论您要在画布上绘制什么,在下一次重新绘制时,它都会再次绘制完整的位图,从而擦除您已经完成的内容。

如果您不想触摸位图,则需要覆盖和 调用OnPaint的事件TImagefunction TextToImage(const AText: string; const AImage: TImage);