Diese Frage bezieht sich auf meine earlier question auf SO.Alphablend und TransparentBlt
Ich möchte zwei Schichten mit Alpha kombinieren, die nur auf einen bestimmten Teil der Quellschicht angewendet werden. Eine Möglichkeit, die ich versuchte, war, SourceConstantAlpha auf $ ff zu setzen (und die Funktion den Alphakanal in der Quellschicht verwenden zu lassen).
Diese Art von Arbeiten - obwohl langsam (ich glaube, ich kann es beschleunigen mit ScanLines), die Art von Teil ist, dass ich nicht herausfinden, was den Alpha-Kanal zu setzen. Die Dokumentation schlägt vor, dass die Berechnung ist:
st.Red = Src.Red + (1 - Src.Alpha) * Dst.Red
ich ein paar verschiedenen Werte von Mutmaßungen versucht, aber meine erste Frage ist: Wie kann ich den Alpha-Wert zu berechnen?
Nachdem ich ein paar andere SO-Fragen gelesen hatte, stieß ich auf die TransparentBlt-Funktion, die die Maskierung gut (und schnell), aber nicht die Transparenz, gibt es eine Möglichkeit diese beiden Aufrufe zusammen zu kombinieren (vielleicht mit einer dritten Schicht))
unit MainWnd;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, ControlsEx;
type
{------------------------------------------------------------------------------}
TfrmMain = class(TForm)
PaintBox1: TPaintBox;
procedure PaintBox1Paint(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
{..............................................................................}
procedure copyToAlpha(const in_bitmap : TBitmap; const in_transparentColor : TColor;
const in_transparency : integer);
var
x : integer;
y : integer;
p : integer;
begin
ASSERT(in_bitmap.PixelFormat = pf32bit);
for x := 0 to in_bitmap.Width - 1 do
begin
for y := 0 to in_bitmap.Height - 1 do
begin
p := in_bitmap.Canvas.Pixels[x, y];
if TColor(p) <> in_transparentColor then
begin
in_bitmap.Canvas.Pixels[x, y] := p or (in_transparency shl 24);
end
else
in_bitmap.Canvas.Pixels[x, y] := p or ($ff shl 24);
end;
end;
end;
{..............................................................................}
procedure alphaBlendTest(
const in_target : TCanvas;
const in_width : integer;
const in_height : integer);
const
BARSIZE = 30;
var
bitmap : TBitmap;
r : TRect;
blendFn : BLENDFUNCTION;
ret : Boolean;
begin
blendFn.BlendOp := AC_SRC_OVER;
blendFn.SourceConstantAlpha := $ff;
blendFn.BlendFlags := 0;
blendFn.alphaFormat := AC_SRC_ALPHA;
bitmap := TBitmap.Create;
try
bitmap.Width := in_width;
bitmap.Height := in_height;
bitmap.PixelFormat := pf32bit;
bitmap.HandleType := bmDIB;
bitmap.TransparentColor := clFuchsia;
bitmap.Transparent := true;
bitmap.Canvas.Brush.Color := clFuchsia;
bitmap.Canvas.FillRect(Bounds(0, 0, in_width, in_height));
bitmap.Canvas.Brush.Color := clGreen;
r := Bounds(
in_width div 2 - (in_width div 3) div 2,
0,
(in_width div 3) + 1,
BARSIZE + 1);
bitmap.Canvas.Rectangle(r);
// done drawing
//copyToAlpha(bitmap, clFuchsia, 1);
ret := Windows.TransparentBlt(
in_target.Handle,
0,
0,
in_width,
in_height,
bitmap.Canvas.Handle,
0,
0,
in_width,
in_height,
clFuchsia);
//blendFn);
ASSERT(ret);
finally
bitmap.Free;
end;
end;
{..............................................................................}
procedure TfrmMain.PaintBox1Paint(Sender: TObject);
var
r: TRect;
begin
PaintBox1.Canvas.Brush.Color := clBlue;
r := Bounds(0, 0, PaintBox1.ClientWidth, PaintBox1.ClientHeight);
PaintBox1.Canvas.FillRect(r);
PaintBox1.Canvas.Brush.Color := clRed;
PaintBox1.Canvas.Ellipse(0, 0, PaintBox1.ClientWidth, PaintBox1.ClientHeight);
alphaBlendTest(PaintBox1.Canvas, PaintBox1.ClientWidth, PaintBox1.ClientHeight);
end;
end.
Sie multiplizieren y jedes Pixel r, g, b mit dem gewünschten Alpha und dividiere durch 255 für 'AlphaBlend', setze natürlich auch das Alpha des Pixels auf den Alpha-Wert. Ich verstehe die Frage nach TransparentBlt nicht, wie ist die Transparenz nicht gut? –
@Sertac OP hat eine Bitmap, die teilweise aus einer transparenten Farbe besteht. Die transparenten Teile sollen auf dem Ziel-Canvas intakt bleiben, die gezeichneten Teile werden zum Ziel-Canvas geblendet. – NGLN