Shannon Matthews
Shannon Matthews

Reputation: 10378

How to draw a bitmap with per-pixel alpha onto a control's Canvas?

Question

What's the best way to draw a bitmap with a per-pixel alpha onto a control's Canvas?

My bitmap data is stored in a 2d array of 32-bit pixel values.

T32BitPixel = packed record
    Blue  : byte;
    Green : byte;
    Red   : byte;
    Alpha : byte;
end;

My control is a descendent of TCustomTransparentControl.

Background

For a GUI I'm building I need to draw semi-transparent controls over other controls and textured backgrounds. The control graphics are created using AggPasMod (a port of Anti-Grain Geometry).

TCustomTransparentControl.Canvas.Handle provides access to the device context for drawing but I'm not sure how to blit the pixel data from there.

Upvotes: 4

Views: 1122

Answers (1)

TLama
TLama

Reputation: 76733

Assuming, you have your pixel array composed like the image rows and pixels in them, I would do it this way. The Canvas parameter is a target canvas, the X and Y are coordinates, where the bitmap will be rendered in the target canvas and the Pixels is the pixel array:

type
  TPixel = packed record
    B: Byte;
    G: Byte;
    R: Byte;
    A: Byte;
  end;
  TPixelArray = array of array of TPixel;

procedure RenderBitmap(Canvas: TCanvas; X, Y: Integer; Pixels: TPixelArray);
var
  I: Integer;
  Size: Integer;
  Bitmap: TBitmap;
  BlendFunction: TBlendFunction;
begin
  Bitmap := TBitmap.Create;
  try
    Bitmap.PixelFormat := pf32bit;
    Bitmap.Width := Length(Pixels[0]);
    Bitmap.Height := Length(Pixels);
    Size := Bitmap.Width * SizeOf(TPixel);

    for I := 0 to Bitmap.Height - 1 do
      Move(Pixels[I][0], Bitmap.ScanLine[I]^, Size);

    BlendFunction.BlendOp := AC_SRC_OVER;
    BlendFunction.BlendFlags := 0;
    BlendFunction.SourceConstantAlpha := 255;
    BlendFunction.AlphaFormat := AC_SRC_ALPHA;
    AlphaBlend(Canvas.Handle, X, Y, Bitmap.Width, Bitmap.Height,
      Bitmap.Canvas.Handle, 0, 0, Bitmap.Width, Bitmap.Height, BlendFunction);
  finally
    Bitmap.Free;
  end;
end;

Upvotes: 7

Related Questions