简体   繁体   中英

How to work with anti-alias on delphi firemonkey and android

I work on delphi xe7 with firemonkey and testing on android.

When i work on a device that have a normal resolution of 1 (scene.scale=1) then component like TRoundRect, TPie, etc produce ugly result because they are not anti-aliased (or the anti-alias is not visible by humain eyes). if i work on high definition device (scene.scale=2 for exemple), then it's not really a big problem because high definition compensate the problem.


So first question, is their any way to make theses component produce anti-alias graphic ? also how to draw directly on the canvas an anti-aliased disque (with an image in it) ?


Now when i work on bitmap and on canvas, i notice that the FillText produce anti-aliasing result. this is in someway good for what i want previously (for disque) but a little disaster for text because it's make them "blur". it's even worse when i do first Mybitmap.canvas.FillText => produce a little of antialias and then later i do MyPaintBox.canvas.DrawBitmap(MyBitmap) it's will add AGAIN more anti-alias ! the text will be very blur at the end :( it's sound crazy for me that doing canvas.drawBitmap without any distorsion in the srcRec and destRect not copy the exact pixel from bitmap to the canvas :(

so it's their a way to :

Call canvas.FillText without any anti-alias or to configure the level of anti-alias. Call c anvas.DrawBitmap without any anti-alias at all ! pixel perfect copy from bitmap to the canvas

thanks by advance for your help !


some solutions i found todays (and theirs problems) :

I found a way how to make all the visual controls (troundrect, etc) with anti-aliasing : set Tform.quality to highQuality !

But now im facing another very strong problem that i can not understand :( maybe a bug in delphi so if someone can look at it i will be very thanks to him ...

when you need a canvas for the form it's created via

constructor TCanvasGpu.CreateFromWindow(...AQuality: TCanvasQuality)

and here the quality is taken from the MyForm.quality

now the problem is with TBITMAP :( same as previous when we need the canvas for the bitmap it's created via

constructor TCanvasGpu.CreateFromBitmap(....AQuality: TCanvasQuality=TCanvasQuality.SystemDefault)

but here the problem their is NO PROPERTY at all in the bitmap to setup the quality of the canvas :(

so i try this solution :

        aBitmap := Tbitmap.Create(w,h);
        try

          aCanvas := TCanvasManager.CreateFromBitmap(ABitmap, TCanvasQuality.HighQuality);
          Try

            aCanvas.BeginScene;
            try
              aCanvas.Fill.Kind := TbrushKind.solid;
              acanvas.Fill.Color := $ff000000;
              aCanvas.FillRect(TRectF.Create(0, 0, w, h), w / 2,  h / 2, ALLcorners, 1);

            finally
              aCanvas.EndScene;
            end;

          Finally
            aCanvas.Free;
          End;
          ....

and i was thinking i will have now on my bitmap the same antialiasing effect of what i have when i draw directly on the canvas of the form ? absolutely not, nothing change and i still have ugly round without any anti-aliasing :(

what i miss ??


EDIT:

The only option i found for now to remove the antialias is to make the bitmap 2x more bigger and reduce it after by 2x! crazy :( but the algorithme of reduction remove the aliased ... but the cost of all of this is that the speed become slow, especially when we know that all the graphic function must be done in the main thread :(

  • Now more i think more i say to myself that it's crazy to have a graphic library that not support multi-thread ! i can not believe that it's a requirement of openGL and i think now more and more that it's a bug or bad conception in delphi :(

  • Speaking about the previous point, even if openGL really required that all graphic routines must be done in the main thread (but really i doubt), i don't understand why delphi not offer on android another TcanvasClass (other than TcanvasGPU) that support multithread ! more crazy is that when you work with TCanvasGPU on Tbitmap, the result will be in any case (as you can see in my previous post) different from what you will have working with TCanvasGPU on the visual component !

  • now im looking for function to work directly on pixels grids (old school), that will make me possible to work in multi-thread. but unfortunately their is not to much compatible with firemonley/android :(

  • to finish this is the function i use to draw my bitmap. but as this function must be call in the main thread, it's slow down my application (especially the scroll) ... so if you have any idea to make this more fast or multithread i take :)

     function DrawAdvertBitmap: Tbitmap; var aBitmapAliased: Tbitmap; begin aBitmapAliased := Tbitmap.Create(trunc(FWidth * fScreenScale) * 2, trunc(FHeight * fScreenScale) * 2); try aBitmapAliased.Canvas.BeginScene; try aBitmapAliased.canvas.Clear(0); aBitmapAliased.canvas.Fill.Color := $ff000000; aBitmapAliased.Canvas.Fill.Kind := TbrushKind.Solid; aBitmapAliased.Canvas.FillRect(...); aBitmapAliased.Canvas.Fill.Color := $ff333844; aBitmapAliased.Canvas.Font.Family := 'Roboto-Bold'; aBitmapAliased.Canvas.Font.Size := 12 * fScreenScale * 2; aBitmapAliased.Canvas.Font.Style := [TFontStyle.fsBold]; aBitmapAliased.Canvas.FillText(...); finally aBitmapAliased.Canvas.EndScene; end; //reduce by 2 to make antialiased result := Tbitmap.Create(trunc(FWidth * fScreenScale), trunc(FHeight * fScreenScale)); try result.Canvas.BeginScene; try result.Canvas.Clear(0); result.Canvas.DrawBitmap(aBitmapAliased,...); finally result.Canvas.EndScene; end; except result.Free; raise; end; result.BitmapScale := fScreenScale; finally aBitmapAliased.free; end; end; 

If we talk about Firemonkey :

  1. TImage has the property "DisableInterpolation: boolean"
  2. TForm has the property "Quality: TCanvasQuality = (SystemDefault, HighPerformance, HighQuality)" — it is works in design-time

Important to know:

  1. Anti-aliasing is very expensive operation, this is disabled by default on mobile platforms.
  2. The same anti-aliasing should be supported by the device. To Support multisampling the OpenGL must have GL_EXT_multisampled_render_to_texture property. If the device hardware does not support multisampling, the AA will not be.

If you are seeing weird anti-aliasing on some controls, I would recommend that you check that the controls do not have fractional position and size values, make sure to use trunc/round on the position or the GPU canvas uses some low-quality interpolation effect on top of any anti-aliasing.

If you plan to do per-pixel manual adjustments, I recommend that you use optimized color-conversion code (scanline <> TAlphaColor) as the built-in code is designed for clear code and not performance: https://github.com/bLightZP/OptimizedDelphiFMXScanline

As for drawing anti-aliased circles with pictures in them, I found the easiest way is to generate an anti-aliased opacity map and apply it to a TImage's TBitmap. You can find code for generating an anti-aliased opacity map here: https://github.com/bLightZP/AntiAliasedCircle

1. Use FMXNativeDraw by OneChen (Aone), - it's very simple , you even do not need to change your standard code for Canvas - need to add only 2 lines (IFDEF). It also supports TPath. It works on 4 platoforms - Win, Mac, Android, iOS. But you need it only on mobile platforms, because antialiasing works on Win and Mac. I use FMXNativeDraw in my mobile projects and it works very well!

Read this article first with google translate about FMXNativeDraw: http://www.cnblogs.com/onechen/p/6350096.html

Download: https://github.com/OneChen/FMXNativeDraw

Btw if you're using PaintBox Canvas - work as usual. If you need to draw on TBitmap Canvas - prepare Bitmap first:

if Scene <> nil then
  lScale := Scene.GetSceneScale
else
  lScale := 1;

fBitmap.BitmapScale := lScale; 
fBitmap.SetSize(Ceil(Width * lScale), Ceil(Height * lScale) );

2. (optional) Also use ZMaterialComponents, that is a wrapper for FMXNativeDraw (circle, rectangle, line etc). You can place these components on a FMX Form as standard TCircle and others. https://github.com/rzaripov1990/ZMaterialComponents

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM