简体   繁体   中英

Delphi drawing part of png file on another image

I am using this function to draw a png over a TImage on a specific location:

procedure TForm1.PlacePNG(nam: string; px, py: Integer);
var
  vPic: TPicture;
  vSrc: TGraphic;
begin
  vPic := TPicture.Create;
  try
    vPic.LoadFromFile(Nam);
    vSrc := vPic.Graphic;
    Image1.Canvas.Draw(px, py, vSrc);
  finally
    vPic.Free;
  end;
end;

My question: what is the best way to do this with part of the png file, without losing its transparency?

This is an interesting question!

Of course, drawing the entire PNG is trivial:

procedure TForm1.FormCreate(Sender: TObject);
var
  bg, fg: TPngImage;
begin

  bg := TPngImage.Create;
  try
    bg.LoadFromFile('K:\bg.png');
    fg := TPngImage.Create;
    try
      fg.LoadFromFile('K:\fg.png');
      Image1.Picture.Graphic := bg;
      Image2.Picture.Graphic := fg;
      fg.Draw(bg.Canvas, Rect(0, 0, fg.Width, fg.Height));
      Image3.Picture.Graphic := bg;
    finally
      fg.Free;
    end;
  finally
    bg.Free;
  end;

end;

输出

To draw only a part, one possible solution is to obtain the images as 32-bpp RGBA bitmaps and then use the Windows API, specifically, the AlphaBlend function:

procedure TForm1.FormCreate(Sender: TObject);
var
  bg, fg: TPngImage;
  bgbm, fgbm: TBitmap;
  BlendFunction: TBlendFunction;
begin

  // Load background PNG
  bg := TPngImage.Create;
  try

    bg.LoadFromFile('K:\bg.png');

    // Load foreground PNG
    fg := TPngImage.Create;
    try

      fg.LoadFromFile('K:\fg.png');

      // Preview background and foreground
      Image1.Picture.Graphic := bg;
      Image2.Picture.Graphic := fg;

      // Create background BMP
      bgbm := TBitmap.Create;
      try

        bgbm.Assign(bg);

        // Create foreground BMP
        fgbm := TBitmap.Create;
        try

          fgbm.Assign(fg);

          // Blend PART OF foreground BMP onto background BMP
          BlendFunction.BlendOp := AC_SRC_OVER;
          BlendFunction.BlendFlags := 0;
          BlendFunction.SourceConstantAlpha := 255;
          BlendFunction.AlphaFormat := AC_SRC_ALPHA;
          if not Winapi.Windows.AlphaBlend(
            bgbm.Canvas.Handle,
            100,
            100,
            200,
            200,
            fgbm.Canvas.Handle,
            200,
            200,
            200,
            200,
            BlendFunction
          ) then
            RaiseLastOSError;

          // Preview result
          Image3.Picture.Graphic := bgbm;

        finally
          fgbm.Free;
        end;

      finally
        bgbm.Free;
      end;

    finally
      fg.Free;
    end;

  finally
    bg.Free;
  end;

end;

输出

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