Rotation d'une image - bibliothèque BGRABitmap avec Lazarus (1/2)
par
, 13/02/2017 à 14h46 (1566 Affichages)
La bibliothèque de graphisme BGRABitmap a fait l’objet de tutoriels de qualité réalisés par son auteur Johann Elsass. Cependant, de nombreuses fonctionnalités de ce produit restent inexploitées et je me propose de les faire découvrir au fur et à mesure de mes propres travaux.
Aujourd’hui, c’est la méthode PutImageAngle de la classe principale TBGRABitmap qui a retenu mon attention. Ainsi que l’indique son nom, cette méthode permet de procéder à une rotation d’une image.
Comme souvent avec BGRABitmap, la méthode se décline selon plusieurs déclarations surchargées :
Code Pascal : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; AOutputBounds: TRect; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255; ARestoreOffsetAfterRotation: boolean = false; ACorrectBlur: Boolean = false); overload; procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255; ARestoreOffsetAfterRotation: boolean = false; ACorrectBlur: Boolean = false); overload; procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; AOutputBounds: TRect; AResampleFilter: TResampleFilter; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255; ARestoreOffsetAfterRotation: boolean = false); overload; procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; AResampleFilter: TResampleFilter; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255; ARestoreOffsetAfterRotation: boolean = false); overload;
Dans un premier temps, je vous propose ci-après une petite application qui la met en œuvre dans sa forme la plus simple, à savoir :
Code Pascal : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255; ARestoreOffsetAfterRotation: boolean = false; ACorrectBlur: Boolean = false); overload;
Les paramètres essentiels de la méthode sont les suivants :
- X et Y désignent les coordonnées du point supérieur gauche de l’image qui sera retournée ;
- Source est l’image de type TBGRABitmap à traiter ;
- imageCenterX et imageCenterY désignent les coordonnées du centre de symétrie fixé par défaut au coin supérieur gauche de l’image.
Les autres paramètres n’ont pas besoin d’être modifiés souvent si bien qu’une valeur par défaut leur est attribuée :
- AOpacity indique le degré d’opacité de l’image (de 0 à 255) ;
- ARestoreOffsetAfterRotation indique si l’image doit être décalée en fonction de l’axe de rotation ;
- ACorrectBlur filtre l’effet de flou selon des transitions rapides (False) ou lentes (True) entre pixels.
Afin de se rendre compte en action ce que signifient exactement ces paramètres, voici l’interface de l’application d’exemple :
Le fichier lfm qui permet de connaître les composants utilisés et leurs propriétés modifiées est le suivant :
Code Pascal : Sélectionner tout - Visualiser dans une fenêtre à part
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137 object MainForm: TMainForm Left = 376 Height = 516 Top = 159 Width = 563 Caption = 'Test de PUTIMAGEANGLE - BGRABitmap' ClientHeight = 516 ClientWidth = 563 OnCreate = FormCreate OnDestroy = FormDestroy Position = poScreenCenter LCLVersion = '1.6.2.0' object tckbAngle: TTrackBar Left = 16 Height = 25 Top = 320 Width = 320 Frequency = 30 Max = 360 OnChange = tckbAngleChange PageSize = 30 Position = 0 TabOrder = 0 end object tckbX: TTrackBar Left = 16 Height = 25 Top = 360 Width = 320 Max = 100 OnChange = tckbAngleChange Position = 50 TabOrder = 1 end object tckbY: TTrackBar Left = 16 Height = 25 Top = 416 Width = 320 Max = 100 OnChange = tckbAngleChange Position = 50 TabOrder = 2 end object lblAngle: TLabel Left = 344 Height = 15 Top = 320 Width = 31 Caption = 'Angle' FocusControl = tckbAngle ParentColor = False end object lblX: TLabel Left = 344 Height = 15 Top = 360 Width = 7 Caption = 'X' FocusControl = tckbX ParentColor = False end object lblY: TLabel Left = 344 Height = 15 Top = 416 Width = 7 Caption = 'Y' FocusControl = tckbY ParentColor = False end object PaintBox: TPaintBox Left = 16 Height = 280 Top = 24 Width = 320 OnPaint = PaintBoxPaint end object tckbRotCenter: TTrackBar Left = 16 Height = 25 Top = 470 Width = 320 Max = 100 OnChange = tckbAngleChange Position = 50 TabOrder = 3 end object lbRotCenter: TLabel Left = 344 Height = 15 Top = 470 Width = 19 Caption = 'Axe' ParentColor = False end object cbOffset: TCheckBox Left = 360 Height = 19 Top = 32 Width = 68 Caption = 'Décalage' Checked = True OnChange = tckbAngleChange State = cbChecked TabOrder = 4 end object cbBlur: TCheckBox Left = 360 Height = 19 Top = 64 Width = 43 Caption = 'Flou' Checked = True State = cbChecked TabOrder = 5 end object seOpacity: TSpinEdit Left = 432 Height = 23 Top = 96 Width = 98 MaxValue = 255 OnChange = tckbAngleChange TabOrder = 6 Value = 255 end object lblOpacity: TLabel Left = 360 Height = 15 Top = 104 Width = 47 Caption = 'Opacité :' FocusControl = seOpacity ParentColor = False end end
Les composants mis en œuvre sont tous présents par défaut dans Lazarus. Il s’agit essentiellement d’une zone de dessin (TPaintBox) et de différents contrôles pour modifier les propriétés de l’image. On remarquera en particulier les TTrackBar toujours très utiles lorsque des intervalles de valeurs raisonnables sont en jeu.
Le principe de l’application est simple : à chaque fois qu’un contrôle voit sa valeur modifiée, il est fait appel à la méthode OnPaint de la TPaintBox. C'est elle qui est chargée de redessiner la surface du canevas de la TPaintBox. Cette méthode OnPaint contient essentiellement un appel à la méthode PutImageAngle appliquée à un objet de type TBGRABitmap provisoire, créé et libéré en lien avec une section try… finally qui assure une gestion sécurisée des ressources allouées pour l’image.
Voici le listing complet de l’application :
Code Pascal : Sélectionner tout - Visualiser dans une fenêtre à part
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 { |========================================================================| | | | Projet : découverte de BGRABITMAP | | Description : Programme exemple 01 PUTIMAGEANGLE | | Unité : main.pas | | Site : www.developpez.com | | Copyright : © Gilles VASSEUR 2017 | | | | Date: 13/02/2017 13:16:10 | | Version : 1.0.0 | | | |========================================================================| } unit main; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ComCtrls, StdCtrls, ExtCtrls, Spin, BGRABitmap, BGRABitmapTypes; type { TMainForm } TMainForm = class(TForm) cbOffset: TCheckBox; cbBlur: TCheckBox; lblOpacity: TLabel; lbRotCenter: TLabel; lblY: TLabel; lblX: TLabel; lblAngle: TLabel; PaintBox: TPaintBox; seOpacity: TSpinEdit; tckbX: TTrackBar; tckbAngle: TTrackBar; tckbY: TTrackBar; tckbRotCenter: TTrackBar; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure PaintBoxPaint(Sender: TObject); procedure tckbAngleChange(Sender: TObject); private { private declarations } public { public declarations } bmpWork: TBGRABitmap; end; var MainForm: TMainForm; implementation {$R *.lfm} { TMainForm } procedure TMainForm.FormCreate(Sender: TObject); // *** chargement de l'image à la création *** begin bmpWork := TBGRABitmap.Create('logoFPC.png'); end; procedure TMainForm.FormDestroy(Sender: TObject); // *** libération des ressources *** begin bmpWork.Free; end; procedure TMainForm.PaintBoxPaint(Sender: TObject); // *** la PaintBox est repeinte *** var LBmp: TBGRABitmap; begin LBmp := TBGRABitmap.Create(PaintBox.Width, PaintBox.Height, BGRABlack); try LBmp.PutImageAngle((PaintBox.Width - bmpWork.Width) * tckbX.Position / 100 - 0.5, (PaintBox.Height - bmpWork.Height) * tckbY.Position / 100 - 0.5, bmpWork, tckbAngle.Position, bmpWork.Width * tckbRotCenter.Position / 100 - 0.5, bmpWork.Height * tckbRotCenter.Position / 100 - 0.5, seOpacity.Value, cbOffset.Checked, cbBlur.Checked); LBmp.Draw(PaintBox.Canvas, 0, 0, False); finally LBmp.Free; end; end; procedure TMainForm.tckbAngleChange(Sender: TObject); // *** une valeur a été modifiée *** begin PaintBox.Invalidate; end; end.
En dehors des angles en degrés, les autres mesures sont exprimées en pourcentage de leur valeur maximale. L’abscisse et l’ordonnée de l’image tiennent compte de ses dimensions afin d’assurer, lorsque la correction du décalage est actif et que l’angle de rotation est nul, le maintien de l’image dans les limites définies par la TPaintBox.
Voici enfin un instantané de l’application en action :
À vous de jouer !
Lien pour le code source : rotateimage.7z