Difference between revisions of "BGRABitmap tutorial 5/fr"

From Free Pascal wiki
Jump to navigationJump to search
(→‎Ajout d'un dessin: traduction comment)
 
(9 intermediate revisions by 5 users not shown)
Line 4: Line 4:
  
 
Ce tutoriel montre comment utiliser les couches et les masques.
 
Ce tutoriel montre comment utiliser les couches et les masques.
 +
 +
La première partie montre comment faire sans utiliser d'image multicouche.
 +
 +
La deuxième partie du tutoriel montre comment adapter le code pour utiliser une image multicouche ''TBGRALayeredBitmap'', qui se trouve dans l'unité ''BGRALayers''.
 +
 +
== Sans utiliser les images multicouches ==
  
 
=== Création d'un nouveau projet ===
 
=== Création d'un nouveau projet ===
  
Créez un nouveau projet et ajouter la référence à [[BGRABitmap]], de la même façon que dans [[BGRABitmap tutorial/fr|le premier tutoriel]].
+
Créez un nouveau projet et ajoutez la référence à [[BGRABitmap]], de la même façon que dans [[BGRABitmap tutorial/fr|le premier tutoriel]].
  
 
=== Notions sur les masques ===
 
=== Notions sur les masques ===
  
Un masque est une image en ton de gris. Quand on applique un masque sur une image, les parties de l'image qui se superposent avec les parties noires du masque sont effacées et deviennent transparentes, tandis que les parties qui se superposent avec les parties blanches du masques sont conservées. En d'autres termes, le masque est semblable à un canal alpha définissant une opacité. Si la valeur du masque est à zéro, cela se traduit par une transparence, et si la valeur du masque est à 255, cela se traduit par une opacité.
+
Un masque est une image en ton de gris. Quand on applique un masque sur une image, les parties de l'image qui se superposent avec les parties noires du masque sont effacées et deviennent transparentes, tandis que les parties qui se superposent avec les parties blanches du masque sont conservées. En d'autres termes, le masque est semblable à un canal alpha définissant une opacité. Si la valeur du masque est à zéro, cela se traduit par une transparence alors que si la valeur du masque est à 255, cela se traduit par une opacité.
  
 
[[Image:BGRATutorial5d.png]]
 
[[Image:BGRATutorial5d.png]]
  
Dans cet exemple, l'image de départ est en haut à gauche, le masque est en haut à droite, et le résultat de l'application du masque sur l'image est en bas à gauche.
+
Dans cet exemple, l'image de départ est en haut à gauche, le masque en haut à droite, et le résultat de l'application du masque sur l'image en bas à gauche.
  
Code correspondant dans OnPaint :
+
Code correspondant dans ''OnPaint'' :
<delphi>var temp,tex,mask: TBGRABitmap;
+
<syntaxhighlight lang="pascal">var temp,tex,mask: TBGRABitmap;
 
begin
 
begin
 
   temp:= TBGRABitmap.Create(640,480,ColorToBGRA(ColorToRGB(clBtnFace)));
 
   temp:= TBGRABitmap.Create(640,480,ColorToBGRA(ColorToRGB(clBtnFace)));
Line 49: Line 55:
 
   image.Draw(Canvas,0,0,True);
 
   image.Draw(Canvas,0,0,True);
 
   image.Free;
 
   image.Free;
end;</delphi>
+
end;</syntaxhighlight>
  
 
=== Effacement de parties de l'image ===
 
=== Effacement de parties de l'image ===
  
Certaines fonctions permettent d'effacer une ellipse, un rectangle etc. Cela signifie que la partie concernée de l'image devient transparente. On peut donc dessiner un trou dans une image. Si le paramètre alpha est à 255, le trou est complètement transparent, sinon, la partie devient semi-transparente.
+
Certaines fonctions permettent d'effacer une ellipse, un rectangle, etc. Cela signifie que la partie concernée de l'image devient transparente. On peut donc dessiner un trou dans une image. Si le paramètre alpha est à 255, le trou est complètement transparent, sinon la partie devient semi-transparente.
  
 
[[Image:BGRATutorial5e.png]]
 
[[Image:BGRATutorial5e.png]]
  
Ici une ellipse est effacée à gauche avec un paramètre alpha de 255, et une autre ellipse à droite est effacée avec un paramètre alpha à 128.
+
Ici, une ellipse est effacée à gauche avec un paramètre alpha de 255, et une autre ellipse à droite est effacée avec un paramètre alpha à 128.
  
 
Code correspondant dans OnPaint :
 
Code correspondant dans OnPaint :
<delphi>
+
<syntaxhighlight lang="pascal">
 
var image,tex: TBGRABitmap;
 
var image,tex: TBGRABitmap;
 
begin
 
begin
Line 83: Line 89:
 
   image.Draw(Canvas,0,0,True);
 
   image.Draw(Canvas,0,0,True);
 
   image.Free;
 
   image.Free;
end;</delphi>
+
end;</syntaxhighlight>
  
 
=== Ajout d'un dessin ===
 
=== Ajout d'un dessin ===
  
Avec l'inspecteur de projet, ajouter un gestionnaire OnPaint :
+
Avec l'inspecteur de projet, ajoutez un gestionnaire ''OnPaint'' :
<delphi>procedure TForm1.FormPaint(Sender: TObject);
+
<syntaxhighlight lang="pascal">procedure TForm1.FormPaint(Sender: TObject);
 
var image: TBGRABitmap;
 
var image: TBGRABitmap;
 
     size: single;
 
     size: single;
Line 120: Line 126:
 
   image.Draw(Canvas,0,0,True);
 
   image.Draw(Canvas,0,0,True);
 
   image.free;
 
   image.free;
end; </delphi>
+
end; </syntaxhighlight>
  
La procédure crée un image et la remplit avec un dégradé bleu. Il s'agit de la couche d'arrière-plan.
+
La procédure crée une image et la remplit avec un dégradé bleu. Il s'agit de la couche d'arrière-plan.
  
La procédure DrawMoon crée une couche, dessine une lune dessus. D'abord un disque blanc est dessiné, puis un plus petit disque est soustrait. Finalement, cette couche est fusionnée avec l'arrière-plan.
+
La procédure ''DrawMoon'' crée une couche et dessine une lune dessus. En premier lieu, un disque blanc est dessiné, puis un plus petit disque est soustrait. Finalement, cette couche est fusionnée avec l'arrière-plan.
  
 
=== Exécution du programme ===
 
=== Exécution du programme ===
Line 134: Line 140:
 
=== Ajout d'un soleil ===
 
=== Ajout d'un soleil ===
  
Dans l'événement OnPaint, ajouter la sous-procédure :
+
Dans l'événement ''OnPaint'', ajoutez la sous-procédure :
<delphi>  procedure DrawSun;
+
<syntaxhighlight lang="pascal">  procedure DrawSun;
 
   var layer,mask: TBGRABitmap;
 
   var layer,mask: TBGRABitmap;
 
   begin
 
   begin
Line 149: Line 155:
 
     image.PutImage(0,0,layer,dmDrawWithTransparency);
 
     image.PutImage(0,0,layer,dmDrawWithTransparency);
 
     layer.Free;
 
     layer.Free;
   end;  </delphi>
+
   end;  </syntaxhighlight>
  
 
Cette procédure crée un dégradé radial de rouge et orange et applique un masque circulaire. Cela donne un disque coloré. Finalement, le disque est fusionné avec le fond.
 
Cette procédure crée un dégradé radial de rouge et orange et applique un masque circulaire. Cela donne un disque coloré. Finalement, le disque est fusionné avec le fond.
Line 163: Line 169:
 
=== Ajout d'une lumière ===
 
=== Ajout d'une lumière ===
  
Ajoutez la sous-procédure suivante dans l'événement OnPaint :
+
Ajoutez la sous-procédure suivante dans l'événement ''OnPaint'' :
<delphi>  procedure ApplyLight;
+
<syntaxhighlight lang="pascal">  procedure ApplyLight;
 
   var layer: TBGRABitmap;
 
   var layer: TBGRABitmap;
 
   begin
 
   begin
Line 174: Line 180:
 
     image.BlendImage(0,0,layer,boMultiply);
 
     image.BlendImage(0,0,layer,boMultiply);
 
     layer.Free;
 
     layer.Free;
   end;</delphi>
+
   end;</syntaxhighlight>
  
Cette procédure dessine une couche avec un degradé radial blanc. Elle est ensuite appliqué à l'image par multiplication.
+
Cette procédure dessine une couche avec un dégradé radial blanc. Elle est ensuite appliquée à l'image par multiplication.
  
 
=== Code résultant ===
 
=== Code résultant ===
  
<delphi>procedure TForm1.FormPaint(Sender: TObject);
+
<syntaxhighlight lang="pascal">uses BGRABitmap, BGRABitmapTypes; 
 +
 
 +
...
 +
 
 +
procedure TForm1.FormPaint(Sender: TObject);
 
var image: TBGRABitmap;
 
var image: TBGRABitmap;
 
     size: single;
 
     size: single;
Line 241: Line 251:
 
   image.Draw(Canvas,0,0,True);
 
   image.Draw(Canvas,0,0,True);
 
   image.free;
 
   image.free;
end;</delphi>
+
end;</syntaxhighlight>
  
 
=== Exécution du programme ===
 
=== Exécution du programme ===
Line 249: Line 259:
 
[[Image:Tutorial5c.png]]
 
[[Image:Tutorial5c.png]]
  
[[BGRABitmap tutorial 4/fr|Tutoriel précédent (accès direct aux pixels)]] [[BGRABitmap tutorial 6|Tutoriel suivant (styles de ligne)]]
+
== En utilisant les images multicouches ==
 +
 
 +
L'unité ''BGRALayers'' fournit une classe ''TBGRALayeredBitmap'' qui permet de stocker une image multicouche. Vous allez l'utiliser pour sauvegarder votre dessin au format ''OpenRaster''.
 +
 
 +
=== Quelques adaptations à faire ===
 +
 
 +
Tout d'abord, le résultat sera stocké non pas dans un ''TBGRABitmap'', mais dans un ''TBGRALayeredBitmap'' :
 +
 
 +
<syntaxhighlight lang="pascal">
 +
var image: TBGRALayeredBitmap;
 +
 
 +
...
 +
 
 +
begin
 +
  image := TBGRALayeredBitmap.Create(ClientWidth,ClientHeight);
 +
 
 +
...
 +
 
 +
  image.Draw(Canvas,0,0); //il n'y a pas de paramètre Opaque
 +
  image.free;
 +
end;
 +
</syntaxhighlight>
 +
 
 +
Ensuite, les procédures qui ajoutent des éléments ne doivent pas dessiner directement sur l'image, mais ajouter des calques. Ainsi, le code suivant :
 +
 
 +
<syntaxhighlight lang="pascal">
 +
    image.PutImage(0,0,layer,dmDrawWithTransparency);
 +
    layer.Free;
 +
</syntaxhighlight>
 +
 
 +
devient :
 +
 
 +
<syntaxhighlight lang="pascal">
 +
    image.AddOwnedLayer(layer);
 +
</syntaxhighlight>
 +
 
 +
Et pour l'éclairage, le code suivant :
 +
<syntaxhighlight lang="pascal">
 +
    image.BlendImage(0,0,layer,boMultiply);
 +
    layer.Free;
 +
</syntaxhighlight>
 +
devient :
 +
<syntaxhighlight lang="pascal">
 +
    image.AddOwnedLayer(layer,boMultiply);
 +
</syntaxhighlight>
 +
 
 +
Le fond doit maintenant être aussi un calque. Ajoutez alors une nouvelle procédure :
 +
<syntaxhighlight lang="pascal">
 +
  procedure CreateBackground;
 +
  var layer: TBGRABitmap;
 +
  begin
 +
    layer := TBGRABitmap.Create(image.Width,image.Height);
 +
    layer.GradientFill(0,0,image.Width,image.Height,
 +
                      BGRA(128,192,255),BGRA(0,0,255),
 +
                      gtLinear,PointF(0,0),PointF(0,image.Height),
 +
                      dmSet);
 +
    image.AddOwnedLayer(layer);
 +
  end;
 +
</syntaxhighlight>
 +
 
 +
=== Code résultant avec ''TBGRALayeredBitmap'' ===
 +
 
 +
En déplaçant la création de l'image multicouche dans une fonction à part, ''CreateMyImage'', on obtient :
 +
 
 +
<syntaxhighlight lang="pascal">function CreateMyImage(AWidth,AHeight: integer): TBGRALayeredBitmap;
 +
var image: TBGRALayeredBitmap;
 +
    size: single;
 +
 
 +
  procedure CreateMoon;
 +
  var layer: TBGRABitmap;
 +
  begin
 +
    layer := TBGRABitmap.Create(image.Width,image.Height);
 +
    layer.FillEllipseAntialias(layer.Width/2,layer.Height/2,size*0.4,size*0.4,BGRA(224,224,224,128));
 +
    layer.EraseEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.3,size*0.3,255);
 +
    image.AddOwnedLayer(layer);;
 +
  end;
 +
 
 +
  procedure CreateSun;
 +
  var layer,mask: TBGRABitmap;
 +
  begin
 +
    layer := TBGRABitmap.Create(image.Width,image.Height);
 +
    layer.GradientFill(0,0,layer.Width,layer.Height,
 +
                      BGRA(255,255,0),BGRA(255,0,0),
 +
                      gtRadial,PointF(layer.Width/2,layer.Height/2-size*0.15),PointF(layer.Width/2+size*0.45,layer.Height/2-size*0.15),
 +
                      dmSet);
 +
    mask := TBGRABitmap.Create(layer.Width,layer.Height,BGRABlack);
 +
    mask.FillEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.25,size*0.25,BGRAWhite);
 +
    layer.ApplyMask(mask);
 +
    mask.Free;
 +
    image.AddOwnedLayer(layer);
 +
  end;
 +
 
 +
  procedure CreateLight;
 +
  var layer: TBGRABitmap;
 +
  begin
 +
    layer := TBGRABitmap.Create(image.Width,image.Height);
 +
    layer.GradientFill(0,0,layer.Width,layer.Height,
 +
                      BGRA(255,255,255),BGRA(64,64,64),
 +
                      gtRadial,PointF(layer.Width*5/6,layer.Height/2),PointF(layer.Width*1/3,layer.Height/4),
 +
                      dmSet);
 +
    image.AddOwnedLayer(layer,boMultiply);
 +
  end;
 +
 
 +
  procedure CreateBackground;
 +
  var layer: TBGRABitmap;
 +
  begin
 +
    layer := TBGRABitmap.Create(image.Width,image.Height);
 +
    layer.GradientFill(0,0,image.Width,image.Height,
 +
                      BGRA(128,192,255),BGRA(0,0,255),
 +
                      gtLinear,PointF(0,0),PointF(0,image.Height),
 +
                      dmSet);
 +
    image.AddOwnedLayer(layer);
 +
  end;
 +
 
 +
begin
 +
  image := TBGRALayeredBitmap.Create(AWidth,AHeight);
 +
 
 +
  if image.Height < image.Width then
 +
    size := image.Height
 +
  else
 +
    size := image.Width;
 +
 
 +
  CreateBackground;
 +
  CreateMoon;
 +
  CreateSun;
 +
  CreateLight;
 +
 
 +
  result := image;
 +
end;
 +
 
 +
{ TForm1 }
 +
 
 +
procedure TForm1.FormPaint(Sender: TObject);
 +
var image: TBGRALayeredBitmap;
 +
begin
 +
  image := CreateMyImage(ClientWidth,ClientHeight);
 +
  image.Draw(Canvas,0,0);
 +
  image.free;
 +
end;    </syntaxhighlight>
 +
 
 +
 
 +
=== Sauvegarder l'image dans un fichier OpenRaster ===
 +
 
 +
A présent, créons un bouton avec le code suivant :
 +
<syntaxhighlight lang="pascal">
 +
procedure TForm1.Button1Click(Sender: TObject);
 +
var image: TBGRALayeredBitmap;
 +
begin
 +
  image := CreateMyImage(ClientWidth,ClientHeight);
 +
  image.SaveToFile('myimage.ora');
 +
  image.free;
 +
end;
 +
</syntaxhighlight>
 +
 
 +
Ce code est relativement évident : il crée une image de la taille de la fenêtre et la sauvegarde au format ''OpenRaster'' (.ora). Vous pouvez ensuite importer cette image dans Krita, Gimp ou Paint.NET.
 +
 
  
[[Category:Graphics]]
+
[[BGRABitmap tutorial 4/fr|Tutoriel précédent (accès direct aux pixels)]] [[BGRABitmap tutorial 6/fr|Tutoriel suivant (styles de ligne)]]

Latest revision as of 09:56, 15 February 2024

Deutsch (de) English (en) español (es) français (fr)


Accueil | Tutoriel 1 | Tutoriel 2 | Tutoriel 3 | Tutoriel 4 | Tutoriel 5 | Tutoriel 6 | Tutoriel 7 | Tutoriel 8 | Tutoriel 9 | Tutoriel 10 | Tutoriel 11 | Tutoriel 12 | Edit

Ce tutoriel montre comment utiliser les couches et les masques.

La première partie montre comment faire sans utiliser d'image multicouche.

La deuxième partie du tutoriel montre comment adapter le code pour utiliser une image multicouche TBGRALayeredBitmap, qui se trouve dans l'unité BGRALayers.

Sans utiliser les images multicouches

Création d'un nouveau projet

Créez un nouveau projet et ajoutez la référence à BGRABitmap, de la même façon que dans le premier tutoriel.

Notions sur les masques

Un masque est une image en ton de gris. Quand on applique un masque sur une image, les parties de l'image qui se superposent avec les parties noires du masque sont effacées et deviennent transparentes, tandis que les parties qui se superposent avec les parties blanches du masque sont conservées. En d'autres termes, le masque est semblable à un canal alpha définissant une opacité. Si la valeur du masque est à zéro, cela se traduit par une transparence alors que si la valeur du masque est à 255, cela se traduit par une opacité.

BGRATutorial5d.png

Dans cet exemple, l'image de départ est en haut à gauche, le masque en haut à droite, et le résultat de l'application du masque sur l'image en bas à gauche.

Code correspondant dans OnPaint :

var temp,tex,mask: TBGRABitmap;
begin
  temp:= TBGRABitmap.Create(640,480,ColorToBGRA(ColorToRGB(clBtnFace)));

  //chargement d'une texture et redimensionnement
  tex := TBGRABitmap.Create('texture.png');
  BGRAReplace(tex,tex.Resample(128,80));

  //on affiche l'image en haut à gauche
  temp.PutImage(10,10,tex,dmDrawWithTransparency);

  //création d'un masque avec une ellipse et un rectangle
  mask := TBGRABitmap.Create(128,80,BGRABlack);
  mask.FillEllipseAntialias(40,40,30,30,BGRAWhite);
  mask.FillRectAntialias(60,40,100,70,BGRAWhite);

  //on affiche le masque en haut à droite
  temp.PutImage(150,10,mask,dmDrawWithTransparency);

  //on applique le masque à l'image
  tex.ApplyMask(mask);

  //on affiche l'image résultante en bas à gauche
  temp.PutImage(10,100,tex,dmDrawWithTransparency);

  mask.Free;
  tex.Free;

  //on affiche le tout à l'écran
  image.Draw(Canvas,0,0,True);
  image.Free;
end;

Effacement de parties de l'image

Certaines fonctions permettent d'effacer une ellipse, un rectangle, etc. Cela signifie que la partie concernée de l'image devient transparente. On peut donc dessiner un trou dans une image. Si le paramètre alpha est à 255, le trou est complètement transparent, sinon la partie devient semi-transparente.

BGRATutorial5e.png

Ici, une ellipse est effacée à gauche avec un paramètre alpha de 255, et une autre ellipse à droite est effacée avec un paramètre alpha à 128.

Code correspondant dans OnPaint :

var image,tex: TBGRABitmap;
begin
  image := TBGRABitmap.Create(640,480,ColorToBGRA(ColorToRGB(clBtnFace)));

  //chargement d'une texture et redimensionnement
  tex := TBGRABitmap.Create('texture.png');
  BGRAReplace(tex,tex.Resample(128,80));

  //on affiche l'image en haut à gauche
  image.PutImage(10,10,tex,dmDrawWithTransparency);

  tex.EraseEllipseAntialias(40,40,30,30,255);
  tex.EraseEllipseAntialias(80,40,30,30,128);

  //on affiche l'image modifiée en bas à gauche
  image.PutImage(10,100,tex,dmDrawWithTransparency);

  tex.Free;

  //on affiche le tout à l'écran
  image.Draw(Canvas,0,0,True);
  image.Free;
end;

Ajout d'un dessin

Avec l'inspecteur de projet, ajoutez un gestionnaire OnPaint :

procedure TForm1.FormPaint(Sender: TObject);
var image: TBGRABitmap;
    size: single;

  procedure DrawMoon;
  var layer: TBGRABitmap;
  begin
    layer := TBGRABitmap.Create(image.Width,image.Height);
    layer.FillEllipseAntialias(layer.Width/2,layer.Height/2,size*0.4,size*0.4,BGRA(224,224,224,128));
    layer.EraseEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.3,size*0.3,255);
    image.PutImage(0,0,layer,dmDrawWithTransparency);
    layer.Free;
  end;

begin
  image := TBGRABitmap.Create(ClientWidth,ClientHeight);

  //calcul la place disponible dans les deux directions
  if image.Height < image.Width then
    size := image.Height
  else
    size := image.Width;

  image.GradientFill(0,0,image.Width,image.Height,
                     BGRA(128,192,255),BGRA(0,0,255),
                     gtLinear,PointF(0,0),PointF(0,image.Height),
                     dmSet);

  DrawMoon;

  image.Draw(Canvas,0,0,True);
  image.free;
end;

La procédure crée une image et la remplit avec un dégradé bleu. Il s'agit de la couche d'arrière-plan.

La procédure DrawMoon crée une couche et dessine une lune dessus. En premier lieu, un disque blanc est dessiné, puis un plus petit disque est soustrait. Finalement, cette couche est fusionnée avec l'arrière-plan.

Exécution du programme

Vous devriez voir un ciel bleu avec une lune. Quand vous redimensionnez la fenêtre, l'image est aussi redimensionnée.

Tutorial5a.png

Ajout d'un soleil

Dans l'événement OnPaint, ajoutez la sous-procédure :

  procedure DrawSun;
  var layer,mask: TBGRABitmap;
  begin
    layer := TBGRABitmap.Create(image.Width,image.Height);
    layer.GradientFill(0,0,layer.Width,layer.Height,
                       BGRA(255,255,0),BGRA(255,0,0),
                       gtRadial,PointF(layer.Width/2,layer.Height/2-size*0.15),PointF(layer.Width/2+size*0.45,layer.Height/2-size*0.15),
                       dmSet);
    mask := TBGRABitmap.Create(layer.Width,layer.Height,BGRABlack);
    mask.FillEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.25,size*0.25,BGRAWhite);
    layer.ApplyMask(mask);
    mask.Free;
    image.PutImage(0,0,layer,dmDrawWithTransparency);
    layer.Free;
  end;

Cette procédure crée un dégradé radial de rouge et orange et applique un masque circulaire. Cela donne un disque coloré. Finalement, le disque est fusionné avec le fond.

Ajoutez un appel à cette procédure après la lune.

Exécution du programme

Vous devriez voir un ciel bleu avec une lune et un soleil. Quand la fenêtre est redimensionnée, l'image est aussi redimensionnée.

BGRATutorial5b.png

Ajout d'une lumière

Ajoutez la sous-procédure suivante dans l'événement OnPaint :

  procedure ApplyLight;
  var layer: TBGRABitmap;
  begin
    layer := TBGRABitmap.Create(image.Width,image.Height);
    layer.GradientFill(0,0,layer.Width,layer.Height,
                       BGRA(255,255,255),BGRA(64,64,64),
                       gtRadial,PointF(layer.Width*5/6,layer.Height/2),PointF(layer.Width*1/3,layer.Height/4),
                       dmSet);
    image.BlendImage(0,0,layer,boMultiply);
    layer.Free;
  end;

Cette procédure dessine une couche avec un dégradé radial blanc. Elle est ensuite appliquée à l'image par multiplication.

Code résultant

uses BGRABitmap, BGRABitmapTypes;  

...

procedure TForm1.FormPaint(Sender: TObject);
var image: TBGRABitmap;
    size: single;

  procedure DrawMoon;
  var layer: TBGRABitmap;
  begin
    layer := TBGRABitmap.Create(image.Width,image.Height);
    layer.FillEllipseAntialias(layer.Width/2,layer.Height/2,size*0.4,size*0.4,BGRA(224,224,224,128));
    layer.EraseEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.3,size*0.3,255);
    image.PutImage(0,0,layer,dmDrawWithTransparency);
    layer.Free;
  end;

  procedure DrawSun;
  var layer,mask: TBGRABitmap;
  begin
    layer := TBGRABitmap.Create(image.Width,image.Height);
    layer.GradientFill(0,0,layer.Width,layer.Height,
                       BGRA(255,255,0),BGRA(255,0,0),
                       gtRadial,PointF(layer.Width/2,layer.Height/2-size*0.15),PointF(layer.Width/2+size*0.45,layer.Height/2-size*0.15),
                       dmSet);
    mask := TBGRABitmap.Create(layer.Width,layer.Height,BGRABlack);
    mask.FillEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.25,size*0.25,BGRAWhite);
    layer.ApplyMask(mask);
    mask.Free;
    image.PutImage(0,0,layer,dmDrawWithTransparency);
    layer.Free;
  end;

  procedure ApplyLight;
  var layer: TBGRABitmap;
  begin
    layer := TBGRABitmap.Create(image.Width,image.Height);
    layer.GradientFill(0,0,layer.Width,layer.Height,
                       BGRA(255,255,255),BGRA(64,64,64),
                       gtRadial,PointF(layer.Width*5/6,layer.Height/2),PointF(layer.Width*1/3,layer.Height/4),
                       dmSet);
    image.BlendImage(0,0,layer,boMultiply);
    layer.Free;
  end;

begin
  image := TBGRABitmap.Create(ClientWidth,ClientHeight);

  if image.Height < image.Width then
    size := image.Height
  else
    size := image.Width;

  image.GradientFill(0,0,image.Width,image.Height,
                     BGRA(128,192,255),BGRA(0,0,255),
                     gtLinear,PointF(0,0),PointF(0,image.Height),
                     dmSet);

  DrawMoon;
  DrawSun;
  ApplyLight;

  image.Draw(Canvas,0,0,True);
  image.free;
end;

Exécution du programme

Vous devriez voir un ciel bleu avec une lune et un soleil, avec un effet de lumière.

Tutorial5c.png

En utilisant les images multicouches

L'unité BGRALayers fournit une classe TBGRALayeredBitmap qui permet de stocker une image multicouche. Vous allez l'utiliser pour sauvegarder votre dessin au format OpenRaster.

Quelques adaptations à faire

Tout d'abord, le résultat sera stocké non pas dans un TBGRABitmap, mais dans un TBGRALayeredBitmap :

var image: TBGRALayeredBitmap;

...

begin
  image := TBGRALayeredBitmap.Create(ClientWidth,ClientHeight);

...

  image.Draw(Canvas,0,0); //il n'y a pas de paramètre Opaque
  image.free;
end;

Ensuite, les procédures qui ajoutent des éléments ne doivent pas dessiner directement sur l'image, mais ajouter des calques. Ainsi, le code suivant :

    image.PutImage(0,0,layer,dmDrawWithTransparency);
    layer.Free;

devient :

    image.AddOwnedLayer(layer);

Et pour l'éclairage, le code suivant :

    image.BlendImage(0,0,layer,boMultiply);
    layer.Free;

devient :

    image.AddOwnedLayer(layer,boMultiply);

Le fond doit maintenant être aussi un calque. Ajoutez alors une nouvelle procédure :

  procedure CreateBackground;
  var layer: TBGRABitmap;
  begin
    layer := TBGRABitmap.Create(image.Width,image.Height);
    layer.GradientFill(0,0,image.Width,image.Height,
                       BGRA(128,192,255),BGRA(0,0,255),
                       gtLinear,PointF(0,0),PointF(0,image.Height),
                       dmSet);
    image.AddOwnedLayer(layer);
  end;

Code résultant avec TBGRALayeredBitmap

En déplaçant la création de l'image multicouche dans une fonction à part, CreateMyImage, on obtient :

function CreateMyImage(AWidth,AHeight: integer): TBGRALayeredBitmap;
var image: TBGRALayeredBitmap;
    size: single;

  procedure CreateMoon;
  var layer: TBGRABitmap;
  begin
    layer := TBGRABitmap.Create(image.Width,image.Height);
    layer.FillEllipseAntialias(layer.Width/2,layer.Height/2,size*0.4,size*0.4,BGRA(224,224,224,128));
    layer.EraseEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.3,size*0.3,255);
    image.AddOwnedLayer(layer);;
  end;

  procedure CreateSun;
  var layer,mask: TBGRABitmap;
  begin
    layer := TBGRABitmap.Create(image.Width,image.Height);
    layer.GradientFill(0,0,layer.Width,layer.Height,
                       BGRA(255,255,0),BGRA(255,0,0),
                       gtRadial,PointF(layer.Width/2,layer.Height/2-size*0.15),PointF(layer.Width/2+size*0.45,layer.Height/2-size*0.15),
                       dmSet);
    mask := TBGRABitmap.Create(layer.Width,layer.Height,BGRABlack);
    mask.FillEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.25,size*0.25,BGRAWhite);
    layer.ApplyMask(mask);
    mask.Free;
    image.AddOwnedLayer(layer);
  end;

  procedure CreateLight;
  var layer: TBGRABitmap;
  begin
    layer := TBGRABitmap.Create(image.Width,image.Height);
    layer.GradientFill(0,0,layer.Width,layer.Height,
                       BGRA(255,255,255),BGRA(64,64,64),
                       gtRadial,PointF(layer.Width*5/6,layer.Height/2),PointF(layer.Width*1/3,layer.Height/4),
                       dmSet);
    image.AddOwnedLayer(layer,boMultiply);
  end;

  procedure CreateBackground;
  var layer: TBGRABitmap;
  begin
    layer := TBGRABitmap.Create(image.Width,image.Height);
    layer.GradientFill(0,0,image.Width,image.Height,
                       BGRA(128,192,255),BGRA(0,0,255),
                       gtLinear,PointF(0,0),PointF(0,image.Height),
                       dmSet);
    image.AddOwnedLayer(layer);
  end;

begin
  image := TBGRALayeredBitmap.Create(AWidth,AHeight);

  if image.Height < image.Width then
    size := image.Height
  else
    size := image.Width;

  CreateBackground;
  CreateMoon;
  CreateSun;
  CreateLight;

  result := image;
end;

{ TForm1 }

procedure TForm1.FormPaint(Sender: TObject);
var image: TBGRALayeredBitmap;
begin
  image := CreateMyImage(ClientWidth,ClientHeight);
  image.Draw(Canvas,0,0);
  image.free;
end;


Sauvegarder l'image dans un fichier OpenRaster

A présent, créons un bouton avec le code suivant :

procedure TForm1.Button1Click(Sender: TObject);
var image: TBGRALayeredBitmap;
begin
  image := CreateMyImage(ClientWidth,ClientHeight);
  image.SaveToFile('myimage.ora');
  image.free;
end;

Ce code est relativement évident : il crée une image de la taille de la fenêtre et la sauvegarde au format OpenRaster (.ora). Vous pouvez ensuite importer cette image dans Krita, Gimp ou Paint.NET.


Tutoriel précédent (accès direct aux pixels) Tutoriel suivant (styles de ligne)