Esta pregunta está relacionada con mi earlier question en SO.Alphablend y TransparentBlt
Quiero combinar dos capas con alfa aplicado solo a una parte específica de la capa fuente. Una forma de hacerlo fue configurar SourceConstantAlpha en $ ff (y hacer que la función use el canal alfa en la capa fuente).
Este tipo de trabajo -aunque lento (supongo que puedo acelerarlo usando ScanLines), el tipo de parte es que no puedo averiguar a qué configurar el canal alfa. La documentación indica que el cálculo es:
st.Red = Src.Red + (1 - Src.Alpha) * Dst.Red
me han tratado algunos valores diferentes de trabajo de la conjetura, pero mi primera pregunta es: ¿Cómo calculo el valor alfa?
Después de leer algunas otras preguntas de SO, me encontré con la función TransparentBlt, que hace bien el enmascaramiento (y rápido) pero no la transparencia, ¿hay alguna forma de combinar estas dos llamadas juntas (tal vez usando una tercera capa)?
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.
Usted multiplica y r de cada píxel, g, b con su alfa deseada y dividido por 255 para 'AlphaBlend', por supuesto, también establece el alfa del píxel en el valor alfa. No entiendo la pregunta sobre 'TransparentBlt', ¿cómo es que la transparencia no está bien? –
@Sertac OP tiene un mapa de bits que se compone parcialmente de un color transparente. Las partes transparentes deben permanecer intactas en el lienzo de destino, las partes dibujadas se deben alfabetizar al lienzo de destino. – NGLN