Pourquoi AlphaBlend renvoie-t-il toujours false (dessin sur toile) ?
-
12-12-2019 - |
Question
J'essaie de mélanger deux toiles à l'aide de l'appel API Windows alphablend.Je dessine d'abord quelque chose sur le canevas principal (destination), puis j'instancie un autre canevas à l'aide de TBitmap, je dessine dessus, puis je mélange les deux ensemble (en suivant une réponse ici sur SO).
Cependant, je constate que cela renvoie toujours false. Au début, je pensais que cela avait quelque chose à voir avec le passage de mauvais identifiants pour la source et la destination, mais je n'arrive pas à le comprendre.Qu'est ce que ça pourrait être?
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 alphaBlendf(
const in_target : TCanvas;
const in_transperancy : integer;
const in_color : TColor;
const in_rect : TRect;
const in_width : integer;
const in_height : integer);
var
w : integer;
h : integer;
bitmap : TBitmap;
blendFn : BLENDFUNCTION;
ret : boolean;
begin
blendFn.BlendOp := AC_SRC_OVER;
blendFn.SourceConstantAlpha := 80;
try
w := in_rect.Right - in_rect.Left - 1;
h := in_rect.Bottom - in_rect.Top - 1;
bitmap := TBitmap.Create;
bitmap.PixelFormat := pf32bit;
bitmap.Width := w;
bitmap.Height := h;
bitmap.Canvas.Brush.Color := in_color;
bitmap.Canvas.Rectangle(in_rect);
ret := Windows.AlphaBlend(
in_target.Handle,
0,
0,
in_width,
in_height,
bitmap.Canvas.Handle,
0,
0,
in_width,
in_height,
blendFn);
if ret then in_target.TextOut(0, 0, 'ok')
else in_target.TextOut(0, 0, 'fail');
finally
bitmap.Free;
end;
end;
{..............................................................................}
procedure TfrmMain.PaintBox1Paint(Sender: TObject);
var
r: TRect;
begin
PaintBox1.Canvas.Brush.Color := $FCFFB5;
PaintBox1.Canvas.FillRect(r);
r := Rect(0, 0, 100, 100);
alphaBlendf(PaintBox1.Canvas, 0, clLime, r, PaintBox1.ClientWidth, PaintBox1.ClientHeight);
end;
end.
La solution
Vous avez diverses erreurs dans votre code.
Vous ne remplissez pas certains membres de votre BLENDFUNCTION
.Ils ne sont pas facultatifs, fournissent leurs valeurs.
La création de votre objet bitmap doit avoir lieu avant l'instruction try (cela n'a aucun rapport avec la raison pour laquelle AlphaBlend
échoue).
Vous demandez le AlphaBlend
fonction pour mélanger à partir de la source plus qu'elle n'en a, c'est-à-direvotre bitmap est de 99 x 99 mais vous souhaitez que l'API en mélange 105 x 105.
Notez également que dans le gestionnaire de peinture de la paintbox, vous remplissez un rectangle arbitraire (votre r
n’est pas initialisé).
procedure alphaBlendf(
const in_target : TCanvas;
const in_transperancy : integer;
const in_color : TColor;
const in_rect : TRect;
const in_width : integer;
const in_height : integer);
var
w : integer;
h : integer;
bitmap : TBitmap;
blendFn : BLENDFUNCTION;
ret : boolean;
begin
blendFn.BlendOp := AC_SRC_OVER;
blendFn.BlendFlags := 0;
blendFn.SourceConstantAlpha := 80;
blendFn.AlphaFormat := 0;
bitmap := TBitmap.Create;
try
w := in_rect.Right - in_rect.Left - 1;
h := in_rect.Bottom - in_rect.Top - 1;
bitmap.PixelFormat := pf32bit;
bitmap.Width := w;
bitmap.Height := h;
bitmap.Canvas.Brush.Color := in_color;
bitmap.Canvas.Rectangle(in_rect);
ret := Windows.AlphaBlend(
in_target.Handle,
0,
0,
in_width,
in_height,
bitmap.Canvas.Handle,
0,
0,
bitmap.width,
bitmap.height,
blendFn);
if ret then in_target.TextOut(0, 0, 'ok')
else in_target.TextOut(0, 0, 'fail');
finally
bitmap.Free;
end;
end;
{..............................................................................}
procedure TfrmMain.PaintBox1Paint(Sender: TObject);
var
r: TRect;
begin
PaintBox1.Canvas.Brush.Color := $FCFFB5;
r := Rect(0, 0, 100, 100);
PaintBox1.Canvas.FillRect(r);
alphaBlendf(PaintBox1.Canvas, 0, clLime, r,
PaintBox1.ClientWidth, PaintBox1.ClientHeight);
end;