Как раскрасить смесь (раскрасить по указанному Альфа-значению) область холста, используя чистый 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;
для понятия того, что эта функция должна делать, см. Следующее (различение :-) изображения:
и код, который может оказать 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;