Как раскрасить смесь (раскрасить по указанному Альфа-значению) область холста, используя чистый GDI?

Я хотел бы смешать цвет (раскрасить по указанному Альфа-значению) область холста, используя pure Windows GDI (поэтому без GDI+, DirectX или подобных, без OpenGL, без ассемблера или сторонних библиотек).

Я создал следующую функцию, и я хотел бы знать, есть ли более эффективный или простой способ сделать это:

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;

для понятия того, что эта функция должна делать, см. Следующее (различение :-) изображения:

enter image description hereenter image description here

и код, который может оказать this image в верхней левой части формы, как это показано выше:

uses
  PNGImage;

procedure TForm1.Button1Click(Sender: TObject);
var
  Image: TPNGImage;
begin
  Image := TPNGImage.Create;
  try
    Image.LoadFromFile('d:G3Eg.png');
    ColorBlend(Image.Canvas.Handle, Image.Canvas.ClipRect, 00FF80, 175);
    Canvas.Draw(0, 0, Image);
  finally
    Image.Free;
  end;
end;

есть ли более эффективный способ сделать это с помощью чистого GDI или Delphi VCL ?

1 ответов


вы пробовали рисунок холста с AlphaBlend?

что-то вроде

Canvas.Draw(Arect.Left, ARect.Top, ABitmap, AAlphaBlendValue);

в сочетании с FillRect для цвета смеси

обновление: и вот какой-то код, как можно ближе к вашему интерфейсу, но чистый VCL.
Может быть, не так эффективно, но намного проще (и несколько портативно).
Как сказал Реми, чтобы рисовать на форме псевдо настойчивым способом, вам нужно будет использовать 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:G3Eg.png');
    ColorBlend(Image.Canvas, Image.Canvas.ClipRect, 00FF80, 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;