Sign in Join
Wiki copytemporary

BGRABitmap tutorial 5/fr: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: BGRABitmap tutorial 5/fr

OldNewLine
1+Ce tutoriel montre comment utiliser les couches et les masques.
2+
3+La première partie montre comment faire sans utiliser d'image multicouche.
4+
5+La deuxième partie du tutoriel montre comment adapter le code pour utiliser une image multicouche *TBGRALayeredBitmap*, qui se trouve dans l'unité *BGRALayers*.
6+
7+## Sans utiliser les images multicouches
8+
9+### Création d'un nouveau projet
10+
11+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]].
12+
13+### Notions sur les masques
14+
15+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é.
16+
17+<figure>
18+<img src="BGRATutorial5d.png" title="BGRATutorial5d.png" />
19+<figcaption>BGRATutorial5d.png</figcaption>
20+</figure>
21+
22+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.
23+
24+Code correspondant dans *OnPaint* :
25+
26+``` pascal
27+var temp,tex,mask: TBGRABitmap;
28+begin
29+ temp:= TBGRABitmap.Create(640,480,ColorToBGRA(ColorToRGB(clBtnFace)));
30+
31+ //chargement d'une texture et redimensionnement
32+ tex := TBGRABitmap.Create('texture.png');
33+ BGRAReplace(tex,tex.Resample(128,80));
34+
35+ //on affiche l'image en haut à gauche
36+ temp.PutImage(10,10,tex,dmDrawWithTransparency);
37+
38+ //création d'un masque avec une ellipse et un rectangle
39+ mask := TBGRABitmap.Create(128,80,BGRABlack);
40+ mask.FillEllipseAntialias(40,40,30,30,BGRAWhite);
41+ mask.FillRectAntialias(60,40,100,70,BGRAWhite);
42+
43+ //on affiche le masque en haut à droite
44+ temp.PutImage(150,10,mask,dmDrawWithTransparency);
45+
46+ //on applique le masque à l'image
47+ tex.ApplyMask(mask);
48+
49+ //on affiche l'image résultante en bas à gauche
50+ temp.PutImage(10,100,tex,dmDrawWithTransparency);
51+
52+ mask.Free;
53+ tex.Free;
54+
55+ //on affiche le tout à l'écran
56+ image.Draw(Canvas,0,0,True);
57+ image.Free;
58+end;
59+```
60+
61+### Effacement de parties de l'image
62+
63+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.
64+
65+<figure>
66+<img src="BGRATutorial5e.png" title="BGRATutorial5e.png" />
67+<figcaption>BGRATutorial5e.png</figcaption>
68+</figure>
69+
70+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.
71+
72+Code correspondant dans OnPaint :
73+
74+``` pascal
75+var image,tex: TBGRABitmap;
76+begin
77+ image := TBGRABitmap.Create(640,480,ColorToBGRA(ColorToRGB(clBtnFace)));
78+
79+ //chargement d'une texture et redimensionnement
80+ tex := TBGRABitmap.Create('texture.png');
81+ BGRAReplace(tex,tex.Resample(128,80));
82+
83+ //on affiche l'image en haut à gauche
84+ image.PutImage(10,10,tex,dmDrawWithTransparency);
85+
86+ tex.EraseEllipseAntialias(40,40,30,30,255);
87+ tex.EraseEllipseAntialias(80,40,30,30,128);
88+
89+ //on affiche l'image modifiée en bas à gauche
90+ image.PutImage(10,100,tex,dmDrawWithTransparency);
91+
92+ tex.Free;
93+
94+ //on affiche le tout à l'écran
95+ image.Draw(Canvas,0,0,True);
96+ image.Free;
97+end;
98+```
99+
100+### Ajout d'un dessin
101+
102+Avec l'inspecteur de projet, ajoutez un gestionnaire *OnPaint* :
103+
104+``` pascal
105+procedure TForm1.FormPaint(Sender: TObject);
106+var image: TBGRABitmap;
107+ size: single;
108+
109+ procedure DrawMoon;
110+ var layer: TBGRABitmap;
111+ begin
112+ layer := TBGRABitmap.Create(image.Width,image.Height);
113+ layer.FillEllipseAntialias(layer.Width/2,layer.Height/2,size*0.4,size*0.4,BGRA(224,224,224,128));
114+ layer.EraseEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.3,size*0.3,255);
115+ image.PutImage(0,0,layer,dmDrawWithTransparency);
116+ layer.Free;
117+ end;
118+
119+begin
120+ image := TBGRABitmap.Create(ClientWidth,ClientHeight);
121+
122+ //calcul la place disponible dans les deux directions
123+ if image.Height < image.Width then
124+ size := image.Height
125+ else
126+ size := image.Width;
127+
128+ image.GradientFill(0,0,image.Width,image.Height,
129+ BGRA(128,192,255),BGRA(0,0,255),
130+ gtLinear,PointF(0,0),PointF(0,image.Height),
131+ dmSet);
132+
133+ DrawMoon;
134+
135+ image.Draw(Canvas,0,0,True);
136+ image.free;
137+end;
138+```
139+
140+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.
141+
142+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.
143+
144+### Exécution du programme
145+
146+Vous devriez voir un ciel bleu avec une lune. Quand vous redimensionnez la fenêtre, l'image est aussi redimensionnée.
147+
148+<figure>
149+<img src="Tutorial5a.png" title="Tutorial5a.png" />
150+<figcaption>Tutorial5a.png</figcaption>
151+</figure>
152+
153+### Ajout d'un soleil
154+
155+Dans l'événement *OnPaint*, ajoutez la sous-procédure :
156+
157+``` pascal
158+ procedure DrawSun;
159+ var layer,mask: TBGRABitmap;
160+ begin
161+ layer := TBGRABitmap.Create(image.Width,image.Height);
162+ layer.GradientFill(0,0,layer.Width,layer.Height,
163+ BGRA(255,255,0),BGRA(255,0,0),
164+ gtRadial,PointF(layer.Width/2,layer.Height/2-size*0.15),PointF(layer.Width/2+size*0.45,layer.Height/2-size*0.15),
165+ dmSet);
166+ mask := TBGRABitmap.Create(layer.Width,layer.Height,BGRABlack);
167+ mask.FillEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.25,size*0.25,BGRAWhite);
168+ layer.ApplyMask(mask);
169+ mask.Free;
170+ image.PutImage(0,0,layer,dmDrawWithTransparency);
171+ layer.Free;
172+ end;
173+```
174+
175+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.
176+
177+Ajoutez un appel à cette procédure après la lune.
178+
179+### Exécution du programme
180+
181+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.
182+
183+<figure>
184+<img src="BGRATutorial5b.png" title="BGRATutorial5b.png" />
185+<figcaption>BGRATutorial5b.png</figcaption>
186+</figure>
187+
188+### Ajout d'une lumière
189+
190+Ajoutez la sous-procédure suivante dans l'événement *OnPaint* :
191+
192+``` pascal
193+ procedure ApplyLight;
194+ var layer: TBGRABitmap;
195+ begin
196+ layer := TBGRABitmap.Create(image.Width,image.Height);
197+ layer.GradientFill(0,0,layer.Width,layer.Height,
198+ BGRA(255,255,255),BGRA(64,64,64),
199+ gtRadial,PointF(layer.Width*5/6,layer.Height/2),PointF(layer.Width*1/3,layer.Height/4),
200+ dmSet);
201+ image.BlendImage(0,0,layer,boMultiply);
202+ layer.Free;
203+ end;
204+```
205+
206+Cette procédure dessine une couche avec un dégradé radial blanc. Elle est ensuite appliquée à l'image par multiplication.
207+
208+### Code résultant
209+
210+``` pascal
211+uses BGRABitmap, BGRABitmapTypes;
212+
213+...
214+
215+procedure TForm1.FormPaint(Sender: TObject);
216+var image: TBGRABitmap;
217+ size: single;
218+
219+ procedure DrawMoon;
220+ var layer: TBGRABitmap;
221+ begin
222+ layer := TBGRABitmap.Create(image.Width,image.Height);
223+ layer.FillEllipseAntialias(layer.Width/2,layer.Height/2,size*0.4,size*0.4,BGRA(224,224,224,128));
224+ layer.EraseEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.3,size*0.3,255);
225+ image.PutImage(0,0,layer,dmDrawWithTransparency);
226+ layer.Free;
227+ end;
228+
229+ procedure DrawSun;
230+ var layer,mask: TBGRABitmap;
231+ begin
232+ layer := TBGRABitmap.Create(image.Width,image.Height);
233+ layer.GradientFill(0,0,layer.Width,layer.Height,
234+ BGRA(255,255,0),BGRA(255,0,0),
235+ gtRadial,PointF(layer.Width/2,layer.Height/2-size*0.15),PointF(layer.Width/2+size*0.45,layer.Height/2-size*0.15),
236+ dmSet);
237+ mask := TBGRABitmap.Create(layer.Width,layer.Height,BGRABlack);
238+ mask.FillEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.25,size*0.25,BGRAWhite);
239+ layer.ApplyMask(mask);
240+ mask.Free;
241+ image.PutImage(0,0,layer,dmDrawWithTransparency);
242+ layer.Free;
243+ end;
244+
245+ procedure ApplyLight;
246+ var layer: TBGRABitmap;
247+ begin
248+ layer := TBGRABitmap.Create(image.Width,image.Height);
249+ layer.GradientFill(0,0,layer.Width,layer.Height,
250+ BGRA(255,255,255),BGRA(64,64,64),
251+ gtRadial,PointF(layer.Width*5/6,layer.Height/2),PointF(layer.Width*1/3,layer.Height/4),
252+ dmSet);
253+ image.BlendImage(0,0,layer,boMultiply);
254+ layer.Free;
255+ end;
256+
257+begin
258+ image := TBGRABitmap.Create(ClientWidth,ClientHeight);
259+
260+ if image.Height < image.Width then
261+ size := image.Height
262+ else
263+ size := image.Width;
264+
265+ image.GradientFill(0,0,image.Width,image.Height,
266+ BGRA(128,192,255),BGRA(0,0,255),
267+ gtLinear,PointF(0,0),PointF(0,image.Height),
268+ dmSet);
269+
270+ DrawMoon;
271+ DrawSun;
272+ ApplyLight;
273+
274+ image.Draw(Canvas,0,0,True);
275+ image.free;
276+end;
277+```
278+
279+### Exécution du programme
280+
281+Vous devriez voir un ciel bleu avec une lune et un soleil, avec un effet de lumière.
282+
283+<figure>
284+<img src="Tutorial5c.png" title="Tutorial5c.png" />
285+<figcaption>Tutorial5c.png</figcaption>
286+</figure>
287+
288+## En utilisant les images multicouches
289+
290+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*.
291+
292+### Quelques adaptations à faire
293+
294+Tout d'abord, le résultat sera stocké non pas dans un *TBGRABitmap*, mais dans un *TBGRALayeredBitmap* :
295+
296+``` pascal
297+var image: TBGRALayeredBitmap;
298+
299+...
300+
301+begin
302+ image := TBGRALayeredBitmap.Create(ClientWidth,ClientHeight);
303+
304+...
305+
306+ image.Draw(Canvas,0,0); //il n'y a pas de paramètre Opaque
307+ image.free;
308+end;
309+```
310+
311+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 :
312+
313+``` pascal
314+ image.PutImage(0,0,layer,dmDrawWithTransparency);
315+ layer.Free;
316+```
317+
318+devient :
319+
320+``` pascal
321+ image.AddOwnedLayer(layer);
322+```
323+
324+Et pour l'éclairage, le code suivant :
325+
326+``` pascal
327+ image.BlendImage(0,0,layer,boMultiply);
328+ layer.Free;
329+```
330+
331+devient :
332+
333+``` pascal
334+ image.AddOwnedLayer(layer,boMultiply);
335+```
336+
337+Le fond doit maintenant être aussi un calque. Ajoutez alors une nouvelle procédure :
338+
339+``` pascal
340+ procedure CreateBackground;
341+ var layer: TBGRABitmap;
342+ begin
343+ layer := TBGRABitmap.Create(image.Width,image.Height);
344+ layer.GradientFill(0,0,image.Width,image.Height,
345+ BGRA(128,192,255),BGRA(0,0,255),
346+ gtLinear,PointF(0,0),PointF(0,image.Height),
347+ dmSet);
348+ image.AddOwnedLayer(layer);
349+ end;
350+```
351+
352+### Code résultant avec *TBGRALayeredBitmap*
353+
354+En déplaçant la création de l'image multicouche dans une fonction à part, *CreateMyImage*, on obtient :
355+
356+``` pascal
357+function CreateMyImage(AWidth,AHeight: integer): TBGRALayeredBitmap;
358+var image: TBGRALayeredBitmap;
359+ size: single;
360+
361+ procedure CreateMoon;
362+ var layer: TBGRABitmap;
363+ begin
364+ layer := TBGRABitmap.Create(image.Width,image.Height);
365+ layer.FillEllipseAntialias(layer.Width/2,layer.Height/2,size*0.4,size*0.4,BGRA(224,224,224,128));
366+ layer.EraseEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.3,size*0.3,255);
367+ image.AddOwnedLayer(layer);;
368+ end;
369+
370+ procedure CreateSun;
371+ var layer,mask: TBGRABitmap;
372+ begin
373+ layer := TBGRABitmap.Create(image.Width,image.Height);
374+ layer.GradientFill(0,0,layer.Width,layer.Height,
375+ BGRA(255,255,0),BGRA(255,0,0),
376+ gtRadial,PointF(layer.Width/2,layer.Height/2-size*0.15),PointF(layer.Width/2+size*0.45,layer.Height/2-size*0.15),
377+ dmSet);
378+ mask := TBGRABitmap.Create(layer.Width,layer.Height,BGRABlack);
379+ mask.FillEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.25,size*0.25,BGRAWhite);
380+ layer.ApplyMask(mask);
381+ mask.Free;
382+ image.AddOwnedLayer(layer);
383+ end;
384+
385+ procedure CreateLight;
386+ var layer: TBGRABitmap;
387+ begin
388+ layer := TBGRABitmap.Create(image.Width,image.Height);
389+ layer.GradientFill(0,0,layer.Width,layer.Height,
390+ BGRA(255,255,255),BGRA(64,64,64),
391+ gtRadial,PointF(layer.Width*5/6,layer.Height/2),PointF(layer.Width*1/3,layer.Height/4),
392+ dmSet);
393+ image.AddOwnedLayer(layer,boMultiply);
394+ end;
395+
396+ procedure CreateBackground;
397+ var layer: TBGRABitmap;
398+ begin
399+ layer := TBGRABitmap.Create(image.Width,image.Height);
400+ layer.GradientFill(0,0,image.Width,image.Height,
401+ BGRA(128,192,255),BGRA(0,0,255),
402+ gtLinear,PointF(0,0),PointF(0,image.Height),
403+ dmSet);
404+ image.AddOwnedLayer(layer);
405+ end;
406+
407+begin
408+ image := TBGRALayeredBitmap.Create(AWidth,AHeight);
409+
410+ if image.Height < image.Width then
411+ size := image.Height
412+ else
413+ size := image.Width;
414+
415+ CreateBackground;
416+ CreateMoon;
417+ CreateSun;
418+ CreateLight;
419+
420+ result := image;
421+end;
422+
423+{ TForm1 }
424+
425+procedure TForm1.FormPaint(Sender: TObject);
426+var image: TBGRALayeredBitmap;
427+begin
428+ image := CreateMyImage(ClientWidth,ClientHeight);
429+ image.Draw(Canvas,0,0);
430+ image.free;
431+end;
432+```
433+
434+### Sauvegarder l'image dans un fichier OpenRaster
435+
436+A présent, créons un bouton avec le code suivant :
437+
438+``` pascal
439+procedure TForm1.Button1Click(Sender: TObject);
440+var image: TBGRALayeredBitmap;
441+begin
442+ image := CreateMyImage(ClientWidth,ClientHeight);
443+ image.SaveToFile('myimage.ora');
444+ image.free;
445+end;
446+```
447+
448+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.
449+
450+[[BGRABitmap tutorial 4/fr|Tutoriel précédent (accès direct aux pixels)]] [[BGRABitmap tutorial 6/fr|Tutoriel suivant (styles de ligne)]]
451+
452+---
453+*From the Free Pascal wiki, page "BGRABitmap tutorial 5/fr", as it stood on 2024-02-15 after a change by Circular, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history