如何使图像的一部分透明?

时间:2017-08-09 22:37:41

标签: android delphi opengl-es firemonkey

在delphi(Firmonkey)下,在android下如果重要,我需要使位图的特定部分透明,即位图的圆角,如下图所示:

Example of the picture, I want the red part to be transparent

位图是通过Control.MakeScreenShot生成的。

我尝试用透明像素替换所有左上角的红色像素,如下所示:

    if fScreenShot.Map(TMapAccess.ReadWrite, M) then
    try

      //make the top left corner transparent
      for x := 0 to fScreenShot.Width - 1 do begin
        aContinue := False;
        for y := 0 to fScreenShot.Height - 1 do begin
          if M.GetPixel(X,Y) = _FrameBGColor then begin
            aContinue := True;
            M.SetPixel(X,Y,TalphaColorRec.Null);
          end
          else break;
        end;
        if not aContinue then break;
      end;

    finally
      fScreenShot.Unmap(M);
    end;

但指令fScreenShot.Map(TMapAccess.ReadWrite,M)非常慢(大约200毫秒)所以我不能这样做:(有没有其他方法我可以用透明替换这个红色颜色?

注意:现在(我只关注android / ios,所以在 OpenGL )我发现在画布中清除某个区域的唯一方法就是< / p>

Canvas.SaveState;
Canvas.IntersectClipRect(TRectF.create());
Canvas.Clear(TalphaColorRec.Null);
canvas.RestoreState

然而,这只适用于矩形区域,不能应用于我的问题:(

注意2 我即将使用blending := False找到可行的解决方案:

Canvas.blending := False;
Canvas.Fill.Color := $00000000;
Canvas.Fill.Kind := TbrushKind.Solid;
canvas.FillRect(TRectF.create(100,100,200,200), //const ARect: TRectF;
                0, 0, //const XRadius, YRadius: Single;
                [], //const ACorners: TCorners;
                1, // const AOpacity: Single;
                TCornerType.round);
Canvas.blending := true;

此代码实际上清除了矩形。看起来不错,这就是我想要的角落。所以我尝试将FillRect替换为fillpath,我很不走运,这与fillpath无关:(任何想法?它适用于fillEllipseFillRect等等,但只是fillpath它不起作用:(

1 个答案:

答案 0 :(得分:1)

如果有人发现这个并且也想要解决方案,这就是我最终做到的。最后,我可以说,做这样一个琐碎的想法,它的缝很复杂:(

{************************************}
{$IF defined(IOS) or defined(android)}
type
  _TcustomCanvasGPUProtectedAccess = class(TcustomCanvasGPU);
{$ENDIF}

{************************************}
{$IF defined(IOS) or defined(android)}
procedure ClearRoundCorner(const aCanvas: Tcanvas; const ARect: TRectF; const ACorner: TCorner);

const
  MinFlatDistance = 4;

var
  Vertices: TCanvasHelper.TVertexArray;
  Colors: TCanvasHelper.TAlphaColorArray;
  Indices: TCanvasHelper.TIndexArray;
  Index, SubdivCount, VertexCount: Integer;
  Offset: integer;
  Angle: Single;
  Radius: TPointF;
  Center, CurPt, OriPt: TPointF;

begin
  Radius.X := ARect.Width;
  Radius.Y := ARect.Height;

  SubdivCount := (Max(Ceil(2 * Pi * Max(Radius.X, Radius.Y) / MinFlatDistance), 40) div 4) * 4; // https://quality.embarcadero.com/browse/RSP-15206
  VertexCount := (SubdivCount div 4) + 1;

  case ACorner of
    TCorner.BottomRight: begin
                           Offset := 0;
                           Center.X := ARect.left;
                           Center.Y := ARect.top;
                           OriPt.X := ARect.left + aRect.width;
                           OriPt.Y := ARect.bottom + aRect.height;
                         end;
    TCorner.BottomLeft: begin
                          Offset := (SubdivCount div 4);
                          Center.X := ARect.Right;
                          Center.Y := ARect.top;
                          OriPt.X := ARect.left - aRect.width;
                          OriPt.Y := ARect.bottom + aRect.height;
                        end;
    TCorner.TopLeft: begin
                       Offset := (SubdivCount div 4) * 2;
                       Center.X := ARect.right;
                       Center.Y := ARect.bottom;
                       OriPt.X := ARect.left - ARect.width;
                       OriPt.Y := ARect.top - aRect.height;
                     end;
    TCorner.TopRight: begin
                        Offset := (SubdivCount div 4) * 3;
                        Center.X := ARect.left;
                        Center.Y := ARect.Bottom;
                        OriPt.X := ARect.right + aRect.width;
                        OriPt.Y := ARect.top - aRect.height;
                      end;
  end;

  SetLength(Vertices, 1 + VertexCount);
  SetLength(Colors, 1 + VertexCount);
  SetLength(Indices, VertexCount * 3);

  CurPt := OriPt;

  //if Assigned(TransformCallback) then
  //  TransformCallback(CurPt);
  CurPt := _TcustomCanvasGPUProtectedAccess(aCanvas).TransformPoint(CurPt);
  //if FAlignToPixels then
  //  AlignToPixel(Result);

  Vertices[0] := CurPt;
  Colors[0] := TalphaColorRec.null;

  for Index := 0 to VertexCount - 1 do
  begin

    if index = VertexCount - 1 then CurPt := OriPt
    else begin

      Angle := (Offset + Index) * 2 * Pi / SubdivCount;

      CurPt.X := Cos(Angle) * Radius.X;
      CurPt.Y := Sin(Angle) * Radius.Y;

      CurPt.Offset(Center);

    end;

    //if Assigned(TransformCallback) then
    //  TransformCallback(CurPt);
    CurPt := _TcustomCanvasGPUProtectedAccess(aCanvas).TransformPoint(CurPt);
    //if FAlignToPixels then
    //  AlignToPixel(Result);

    Vertices[1 + Index] := CurPt;
    Colors[1 + Index] := TalphaColorRec.null;

    Indices[(Index * 3) + 0] := 0;
    Indices[(Index * 3) + 1] := 1 + Index;
    Indices[(Index * 3) + 2] := 1 + ((1 + Index) mod VertexCount);
  end;

  CanvasHelper.FillTriangles(Vertices, Colors, Indices, Length(Vertices), VertexCount);
end;
{$ENDIF}