Reputation: 10378
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
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