0
votes

I am trying to make a kind of bitmap editor so I just want to draw a line on a bitmap with no anti-aliasing effect in Firemonkey. Something like this:

var
  Bmp: TBitmap;

Bmp := TBitmap.Create(2000, 2000);
if (Bmp.Canvas.BeginScene) then 
begin
  Bmp.Canvas.Stroke.Color := TAlphaColors.Aquamarine;
  Bmp.Canvas.DrawLine(PointF(5, 5), PointF(100, 100), 1);
  Bmp.Canvas.EndScene;
  Bmp.SaveToFile('c:\temp\result.bmp');
end;
FreeAndNil(Bmp);

But it doesn't work. I am trying for a while with several ideas with no luck:

  • Using Map/Unmap to access the bitmap data directly is very slow with big bitmaps according to my coworkers.
  • Using a TImage with DisableInterpolation=true and even GlobalUseGPUCanvas=False doesn't work.
  • Using a TPaintBox component doesn't fit our needs.
  • The solution would be the use of Canvas.Quality=HighPerformance but it's a read-only property. I tried to change the bitmap Canvas.Quality in different ways but it doesn't work.

So how can I simply draw a line with no anti-aliasing effect at all in Firemonkey?

PS: I am using Delphi 10.2.3 (Tokyo)

2

2 Answers

1
votes

FireMonkey paints lines on the grid between the pixels and not on the pixels. So you have to add 0.5 to each coordinate in order to paint on the pixels:

Bmp.Canvas.DrawLine(PointF(5.5, 5.5), PointF(100.5, 100.5), 1);

This does not disable anti-aliasing, but avoids the excessive anti-aliasing that happens otherwise. I'm not aware of a FireMonkey function that disables anti-alisiasing. You would have to call a native OS function, for example CGContextSetAllowsAntialiasing on MacOS, but usually it is not needed anymore as soon as you figure out how to paint on the pixels.

1
votes

Finally I found a way to do this. It's so simple that I am wondering if there is some hidden poison in the solution (LOL). TCanvasManager allows the creation of a HighPerformance Canvas from a given bitmap. It draws with no antialiasing according to my tests. Here the code:

var
  Bmp: TBitmap;
  TmpCanvas: TCanvas;
begin
  Bmp := TBitmap.Create(2000, 2000);
  TmpCanvas := TCanvasManager.CreateFromBitmap(Bmp, TCanvasQuality.HighPerformance);
  if (TmpCanvas.BeginScene) then
  begin
    TmpCanvas.Stroke.Color := TAlphaColors.Aquamarine;
    TmpCanvas.DrawLine(PointF(5, 5), PointF(100, 100), 1);
    TmpCanvas.EndScene;
    Bmp.SaveToFile('c:\temp\result.bmp');
  end;
  FreeAndNil(TmpCanvas);
  FreeAndNil(Bmp);

I also found that it doesn't work with the method to write text on Canvas (Canvas.FillText).

I hope this helps many others with the same problem.