par , 23/03/2018 à 08h29 (855 Affichages)
Un élément que nous aimerions déterminer est sans doute l'opacité des images, car cette fonctionnalité nous permettrait de les dessiner avec une transparence plus ou moins forte. La bibliothèque BGRABitmap propose de nombreuses routines dont un des paramètres est justement l'opacité.
Introduction de l'opacité
Le degré de transparence est fourni dans la composition d'une couleur par un entier de 0 à 255 appelé canal alpha. La valeur 255 rend un pixel totalement opaque tandis que la valeur 0 le rend totalement transparent. Les valeurs intermédiaires permettent de nuancer cette transparence.
Toujours dans un souci d'une meilleure lisibilité de notre code, nous allons donc définir une constante fixant la valeur maximale de l'opacité :
1 2 3 4 5 6 7 8
|
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
StdCtrls, ComCtrls, BGRABitmapTypes, BGRABitmap;
const
C_DefaultSpeed = 80;
C_MaxOpacity = 255; // opacité maximale |
Plutôt que de calculer à la main l'opacité pour un pourcentage donné de transition réalisée, nous allons créer une fonction qui la calculera automatiquement selon une fonction linéaire tout en offrant à l'utilisateur la possibilité d'activer ou de désactiver ce traitement particulier.
Il nous faut par conséquent un champ de type booléen pour l'activation de l'opacité, une propriété manipulant ce champ et une fonction renvoyant la valeur de l'opacité suivant l'état du système à un temps déterminé. Ces éléments sont déclarés dans la classe abritant la fiche principale :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| { TMainForm }
TMainForm = class(TForm)
btnGo: TButton;
cbOpacity: TCheckBox;
imgFrom: TImage;
imgTo: TImage;
imgResult: TImage;
lblSpeed: TLabel;
tbarSpeed: TTrackBar;
procedure btnGoClick(Sender: TObject);
procedure cbOpacityChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure tbarSpeedChange(Sender: TObject);
private
fBGRAFrom, fBGRATo: TBGRABitmap;
fStep: Byte;
fSpeed: Byte;
fWithOpacity: Boolean; // opacité
procedure SetWithOpacity(AValue: Boolean);
procedure SetSpeed(AValue: Byte);
public
function Opacity(Up: Boolean = True): Byte; // opacité à utiliser
property Speed: Byte read fSpeed write SetSpeed default C_DefaultSpeed;
property WithOpacity: Boolean read fWithOpacity write SetWithOpacity;
end; |
Le traitement de la propriété WithOpacity est similaire à celui correspondant à la propriété Speed :
1 2 3 4 5 6 7
| procedure TMainForm.SetWithOpacity(AValue: Boolean);
// *** détermination de l'opacité ***
begin
if fWithOpacity = AValue then
Exit;
fWithOpacity := AValue;
end; |
La propriété WithOpacity appelle la même remarque que sa consœur : en l'état, une simple écriture de la valeur du champ interne aurait été possible, mais l'écriture d'une méthode particulière prépare des extensions comme un gestionnaire d'événement dédié.
D'ores et déjà, nous pouvons réagir au changement de la case à cocher chargée de gérer la prise en compte ou non de l'opacité. En double-cliquant sur cette case à cocher, Lazarus crée un gestionnaire que nous renseignerons ainsi :
1 2 3 4 5
| procedure TMainForm.cbOpacityChange(Sender: TObject);
// *** gestion de la transparence ***
begin
WithOpacity := cbOpacity.Checked;
end; |
L'opacité sera dorénavant active si la case est cochée. Par défaut, nous savons que le champ sera initialisé à False lors de la création de la fiche : il n'est donc pas nécessaire de lui donner cette valeur dans la méthode OnCreate.
Reste bien sûr la fonction Opacity introduite par nos soins. Son paramètre fixé par défaut à True indiquera si l'opacité doit augmenter avec le pourcentage réalisé de transition ou si elle doit au contraire diminuer. Cette possibilité nous permettra par exemple de faire apparaître une image tout en faisant disparaître l'autre.
Il nous faut donc distinguer plusieurs cas, suivant si la prise en compte de l'opacité est activée ou non, et suivant la valeur du paramètre Up. Voici le code proposé :
1 2 3 4 5 6 7 8 9 10 11 12 13
| function TMainForm.Opacity(Up: Boolean): Byte;
// *** calcul de l'opacité en fonction du pourcentage effectué ***
begin
if fWithOpacity then
begin
if Up then
Result := fStep * C_MaxOpacity div 100
else
Result := C_MaxOpacity - fStep * C_MaxOpacity div 100;
end
else
Result := C_MaxOpacity;
end; |
La méthode ne pose pas de problèmes insurmontables. Il s'agit de ramener un pourcentage à une valeur comprise entre 0 et 255, c'est-à-dire dans l'intervalle autorisé des valeurs de l'opacité. Si l'opacité est inactive, l'image sera totalement opaque. Si le paramètre de la fonction est à False, une soustraction permet de faire décroître l'opacité.
Pour que tout cela fonctionne, il faut encore modifier les paramètres des méthodes de BGRABitmap qui gèrent la transparence. Le gestionnaire du clic sur le bouton devient alors :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| procedure TMainForm.btnGoClick(Sender: TObject);
// *** dessin ***
var
LBGRATemp: TBGRABitmap;
LY, LX: Integer;
begin
btnGo.Enabled := False;
LBGRATemp := TBGRABitmap.Create(imgResult.ClientWidth, imgResult.ClientHeight, BGRABlack);
try
LX := 0;
LY := 0;
fStep := 0;
repeat
Inc(fStep);
LBGRATemp.FillRect(ClientRect, BGRABlack);
LBGRATemp.PutImage(0, 0, fBGRAFrom, dmSet, Opacity(False)); // opacité !
// traitement ici...
LY := - imgResult.ClientHeight + imgResult.ClientHeight * fStep div
100; // OVERDOWN
LBGRATemp.PutImage(LX, LY, fBGRATo, dmDrawWithTransparency, Opacity); // opacité !
LBGRATemp.Draw(imgResult.Canvas, 0, 0);
imgResult.Repaint;
sleep(100 - fSpeed);
until fStep = 100;
finally
LBGRATemp.Free;
btnGo.Enabled := True;
end;
end; |
Nous avons choisi de faire disparaître peu à peu l'image d'origine tandis que l'image qui la recouvre voit sa visibilité s'accroître dans les mêmes proportions. Il suffit de lancer notre application qui servira de modèle avec l'unique transition que nous connaissons et de cocher la case marqué « Transparence » pour obtenir des images comme celle-ci :
On voit que le rouge-gorge commence à se dessiner alors que la mésange et le chardonneret s'évanouissent déjà.
La première partie de notre travail s'achève ici : nous avons installé la bibliothèque BGRABitmap et réalisé l'application qui nous servira de modèle pour les tests. Grâce à elle, nous aurons deux images pour travailler et de quoi gérer l'opacité et la vitesse d'affichage de la résultante du traitement par nos transitions. Le billet suivant concernera bien évidemment les transitions elles-mêmes.