How to color blend (colorize by specified alpha value) the canvas area using pure GDI?

江枫思渺然 提交于 2019-12-03 17:50:36

问题


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 ?


回答1:


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;


来源:https://stackoverflow.com/questions/10541811/how-to-color-blend-colorize-by-specified-alpha-value-the-canvas-area-using-pur

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!