I'd like to color blend (colorize by specified alpha value) the area of a canvas using pure Windows GDI
(so without GDI+, DirectX or similar, no OpenGL, no assembler or a 3rd party libraries).
I've created the following function and I'd like to know if there is a more efficient or easier way to do this:
procedure ColorBlend(const ACanvas: HDC; const ARect: TRect;
const ABlendColor: TColor; const ABlendValue: Integer);
var
DC: HDC;
Brush: HBRUSH;
Bitmap: HBITMAP;
BlendFunction: TBlendFunction;
begin
DC := CreateCompatibleDC(ACanvas);
Bitmap := CreateCompatibleBitmap(ACanvas, ARect.Right - ARect.Left,
ARect.Bottom - ARect.Top);
Brush := CreateSolidBrush(ColorToRGB(ABlendColor));
try
SelectObject(DC, Bitmap);
Windows.FillRect(DC, Rect(0, 0, ARect.Right - ARect.Left,
ARect.Bottom - ARect.Top), Brush);
BlendFunction.BlendOp := AC_SRC_OVER;
BlendFunction.BlendFlags := 0;
BlendFunction.AlphaFormat := 0;
BlendFunction.SourceConstantAlpha := ABlendValue;
Windows.AlphaBlend(ACanvas, ARect.Left, ARect.Top,
ARect.Right - ARect.Left, ARect.Bottom - ARect.Top, DC, 0, 0,
ARect.Right - ARect.Left, ARect.Bottom - ARect.Top, BlendFunction);
finally
DeleteObject(Brush);
DeleteObject(Bitmap);
DeleteDC(DC);
end;
end;
For the notion of what this function should do see the following (discriminating :-) images:
And the code that can render this image
to the top left side of the form in the way shown above:
uses
PNGImage;
procedure TForm1.Button1Click(Sender: TObject);
var
Image: TPNGImage;
begin
Image := TPNGImage.Create;
try
Image.LoadFromFile('d:\6G3Eg.png');
ColorBlend(Image.Canvas.Handle, Image.Canvas.ClipRect, $0000FF80, 175);
Canvas.Draw(0, 0, Image);
finally
Image.Free;
end;
end;
Is there a more efficient way to do this using pure GDI or Delphi VCL ?
Have you tried the Canvas Drawing with AlphaBlend?
something like
Canvas.Draw(Arect.Left, ARect.Top, ABitmap, AAlphaBlendValue);
combined with a FillRect for the blend color
Update: And here's some code, as close as possible to your interface, but pure VCL.
Might not be as efficient, but much simpler (and somewhat portable).
As Remy said, to paint on a Form in a pseudo persistent way, you'd have to use OnPaint...
procedure ColorBlend(const ACanvas: TCanvas; const ARect: TRect;
const ABlendColor: TColor; const ABlendValue: Integer);
var
bmp: TBitmap;
begin
bmp := TBitmap.Create;
try
bmp.Canvas.Brush.Color := ABlendColor;
bmp.Width := ARect.Right - ARect.Left;
bmp.Height := ARect.Bottom - ARect.Top;
bmp.Canvas.FillRect(Rect(0,0,bmp.Width, bmp.Height));
ACanvas.Draw(ARect.Left, ARect.Top, bmp, ABlendValue);
finally
bmp.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Image: TPNGImage;
begin
Image := TPNGImage.Create;
try
Image.LoadFromFile('d:\6G3Eg.png');
ColorBlend(Image.Canvas, Image.Canvas.ClipRect, $0000FF80, 175);
Canvas.Draw(0, 0, Image);
// then for fun do it to the Form itself
ColorBlend(Canvas, ClientRect, clYellow, 15);
finally
Image.Free;
end;
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With