【问题标题】:How to work with anti-alias on delphi firemonkey and android如何在 delphi firemonkey 和 android 上使用抗锯齿
【发布时间】:2015-12-16 12:39:21
【问题描述】:

我使用 firemonkey 在 delphi xe7 上工作并在 android 上进行测试。

当我在正常分辨率为 1 (scene.scale=1) 的设备上工作时,像 TRoundRect、TPie 等组件会产生丑陋的结果,因为它们没有抗锯齿(或者抗锯齿不可见)通过人类的眼睛)。如果我在高清设备上工作(例如scene.scale=2),那么这并不是一个大问题,因为高清弥补了这个问题。


所以第一个问题,他们有没有办法让这些组件产生抗锯齿图形? 还如何直接在画布上绘制抗锯齿光盘(其中包含图像)?


现在,当我在位图和画布上工作时,我注意到 FillText 会产生抗锯齿效果。这在某种程度上对我以前想要的(对于disque)来说是有好处的,但对文本来说有点灾难,因为它使它们“模糊”。 当我首先做 Mybitmap.canvas.FillText => 产生一点抗锯齿然后我做 MyPaintBox.canvas.DrawBitmap(MyBitmap) 它会再次添加更多抗锯齿时,情况更糟!最后的文字会很模糊:(这对我来说听起来很疯狂 在 srcRec 和 destRect 中没有任何失真的 canvas.drawBitmap 不会将确切的像素从位图复制到画布:(

所以这是他们的一种方式:

拨打canvas.FillText不带任何抗锯齿或配置抗锯齿的级别。 致电 canvas.DrawBitmap 根本没有任何抗锯齿功能!从位图到画布的像素完美复制

提前感谢您的帮助!


我今天找到的一些解决方案(以及他们的问题):

我找到了一种使用抗锯齿制作所有视觉控件(troundrect 等)的方法:将 Tform.quality 设置为 highQuality!

但现在我面临另一个我无法理解的非常严重的问题:( 可能是delphi中的一个错误,所以如果有人可以查看它,我将非常感谢他...

当您需要为通过它创建的表单提供画布时

构造函数 TCanvasGpu.CreateFromWindow(...AQuality: TCanvasQuality)

这里的质量取自 MyForm.quality

现在问题出在 TBITMAP 上 :( 与之前我们需要画布作为通过它创建的位图的画布时相同

构造函数 TCanvasGpu.CreateFromBitmap(..AQuality: TCanvasQuality=TCanvasQuality.SystemDefault)

但这里的问题是他们在位图中根本没有属性来设置画布的质量:(

所以我试试这个解决方案:

        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;
          ....

我想我现在在位图上的抗锯齿效果与我直接在表单的画布上绘制时所具有的抗锯齿效果相同吗?绝对没有,没有任何变化,我仍然有丑陋的圆形没有任何抗锯齿:(

我想念什么??


编辑:

我现在发现的唯一删除抗锯齿的选择是使位图更大 2 倍,然后再缩小 2 倍!疯了:(但是reduction的算法去掉了别名……但是所有这些的代价是速度变慢了,尤其是当我们知道所有的图形功能都必须在主线程中完成的时候:(

  • 现在我想多了,我对自己说,拥有一个不支持多线程的图形库真是太疯狂了!我不敢相信这是 openGL 的要求,我现在越来越认为这是 delphi 中的错误或错误概念:(

  • 说到上一点,即使openGL确实要求所有图形例程都必须在主线程中完成(但我真的怀疑),我不明白为什么delphi不在android上提供另一个TcanvasClass(其他比 TcanvasGPU) 支持多线程!更疯狂的是,当您在 Tbitmap 上使用 TCanvasGPU 时,结果无论如何(正如您在我之前的帖子中看到的)与您在视觉组件上使用 TCanvasGPU 的结果都不同!

  • 现在我正在寻找直接在像素网格(老派)上工作的函数,这将使我能够在多线程中工作。但不幸的是,它们与 firemonley/android 不太兼容 :(

  • 完成这是我用来绘制位图的函数。但是由于这个函数必须在主线程中调用,它会减慢我的应用程序(尤其是滚动)......所以如果你有任何想法让它更快或多线程我会采取:)

    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; 
    

【问题讨论】:

    标签: android delphi canvas firemonkey antialiasing


    【解决方案1】:

    如果我们谈论 Firemonkey

    1. TImage 具有属性“DisableInterpolation: boolean”
    2. TForm 具有属性“Quality: TCanvasQuality = (SystemDefault, HighPerformance, HighQuality)”——它在设计时工作

    重要提示:

    1. 抗锯齿是一项非常昂贵的操作,在移动平台上默认禁用此功能。
    2. 设备应支持相同的抗锯齿。要支持多重采样,OpenGL 必须具有 GL_EXT_multisampled_render_to_texture 属性。如果设备硬件不支持多重采样,则 AA 将不支持。

    【讨论】:

      【解决方案2】:

      如果您在某些控件上看到奇怪的抗锯齿,我建议您检查控件没有小数位置和大小值,确保在位置上使用 trunc/round 或 GPU 画布使用一些低- 在任何抗锯齿之上的质量插值效果。

      如果您打算进行逐像素手动调整,我建议您使用优化的颜色转换代码(扫描线 TAlphaColor),因为内置代码是为清晰代码而非性能而设计的: https://github.com/bLightZP/OptimizedDelphiFMXScanline

      至于绘制带有图片的抗锯齿圆,我发现最简单的方法是生成抗锯齿的不透明度贴图并将其应用于 TImage 的 TBitmap。您可以在此处找到生成抗锯齿不透明度贴图的代码: https://github.com/bLightZP/AntiAliasedCircle

      【讨论】:

        【解决方案3】:

        1. 使用 OneChen (Aone) 的 FMXNativeDraw,-非常简单,您甚至不需要更改 Canvas 的标准代码 - 只需添加 2 个线(IFDEF)。它还支持 TPath。 它适用于 4 个平台 - Win、Mac、Android、iOS。但是您只需要在移动平台上使用它,因为抗锯齿功能适用于 Win 和 Mac。 我在我的移动项目中使用 FMXNativeDraw,效果很好!

        先用谷歌翻译阅读这篇关于 FMXNativeDraw 的文章:http://www.cnblogs.com/onechen/p/6350096.html

        下载: https://github.com/OneChen/FMXNativeDraw

        顺便说一句,如果您使用的是 PaintBox Canvas - 照常工作。 如果您需要在 TBitmap Canvas 上绘制 - 先准备 Bitmap:

        if Scene <> nil then
          lScale := Scene.GetSceneScale
        else
          lScale := 1;
        
        fBitmap.BitmapScale := lScale; 
        fBitmap.SetSize(Ceil(Width * lScale), Ceil(Height * lScale) );
        

        2。 (可选) 还可以使用 ZMaterialComponents,它是 FMXNativeDraw(圆形、矩形、线条等)的包装器。您可以将这些组件作为标准 TCircle 和其他组件放置在 FMX 表单上。 https://github.com/rzaripov1990/ZMaterialComponents

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-02-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多