IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Voir le flux RSS

Blog de Gilles Vasseur - Pascal et compagnie

Rotation d'une image - bibliothèque BGRABitmap avec Lazarus (2/2)

Noter ce billet
par , 14/02/2017 à 07h39 (1505 Affichages)
Dans le billet précédent, j'ai proposé une petite application utilisant PutImageAngle, mais mettant volontairement de côté deux des paramètres possibles de cette méthode : AOutputBounds qui délimite la zone d'affichage de l'image traitée et AResampleFilter qui permet de choisir le filtre utilisé lors de la modification de la même image.

AOutputBounds est du type TRect, ce qui signifie qu'il contient au choix deux points définissant le point supérieur gauche et le point inférieur droit, ou quatre coordonnées représentant les mêmes points.

En déposant sur la fiche un composant TCheckBox à renommer cbRect et en modifiant la méthode associée à l'événement OnPaint de la TPaintBox, il devient possible de prendre en compte ou non la restriction de la surface à dessiner :

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
procedure TMainForm.PaintBoxPaint(Sender: TObject);
// *** la PaintBox est repeinte ***
var
  LBmp: TBGRABitmap;
  LRect: TRect;
begin
  if cbRect.Checked then
  begin
    // Rectangle restreint choisi pour le dessin
    LRect.Bottom:=150;
    LRect.Left:=10;
    LRect.Right:=150;
    LRect.Top:=10;
  end
  else
    // surface complète de la surface de dessin
    LRect := PaintBox.ClientRect;
  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, LRect,
      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;

La nouvelle TCheckBox voit son événement OnChange relié comme les autres contrôles à la méthode tckbAngleChange qui centralise ainsi tout changement. À présent, l'image traitée n'apparaîtra que si elle est incluse dans le rectangle prédéfini :

Nom : 2017-02-13_195747.png
Affichages : 309
Taille : 28,2 Ko

Pour tester l'influence de AResampleFilter, il faut revoir l'interface, car le nouveau paramètre remplace le drapeau concernant le flou. Le type utilisé devient alors TResampleFilter déclaré ainsi :

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
TResampleFilter = (
    {** Equivalent of simple stretch with high quality and pixel-centered coordinates }
    rfBox,
    {** Linear interpolation giving slow transition between pixels }
    rfLinear,
    {** Mix of ''rfLinear'' and ''rfCosine'' giving medium speed stransition between pixels }
    rfHalfCosine,
    {** Cosine-like interpolation giving fast transition between pixels }
    rfCosine,
    {** Simple bi-cubic filter (blurry) }
    rfBicubic,
    {** Mitchell filter, good for downsizing interpolation }
    rfMitchell,
    {** Spline filter, good for upsizing interpolation, however slightly blurry }
    rfSpline,
    {** Lanczos with radius 2, blur is corrected }
    rfLanczos2,
    {** Lanczos with radius 3, high contrast }
    rfLanczos3,
    {** Lanczos with radius 4, high contrast }
    rfLanczos4,
    {** Best quality using rfMitchell or rfSpline }
    rfBestQuality);

Quand bien même les différentes options ne seront pas toujours visibles avec une image en rotation, la création de onze boutons radio dans un TRadioGroup s'impose :


Nom : 2017-02-13_195953.png
Affichages : 370
Taille : 26,9 Ko

Il faut ensuite déclarer une variable rsFilter dans la classe TMainForm :

Code Pascal : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
 procedure RadioButton1Change(Sender: TObject);
    procedure tckbAngleChange(Sender: TObject);
  private
    { private declarations }
    rsFilter: TResampleFilter;
  public
    { public declarations }
    bmpWork: TBGRABitmap;
  end;

Chaque bouton radio voit alors son gestionnaire d'événement OnChange lié à une méthode centralisée qui se sert du transtypage du paramètre Sender en TRadioButton et de la propriété TabOrder pour discriminer les boutons :

Code Pascal : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
procedure TMainForm.RadioButton1Change(Sender: TObject);
// *** nouveau filtre actif ***
begin
  rsFilter := TResampleFilter((Sender as TRadioButton).TabOrder);
  PaintBox.Invalidate; // force le réaffichage
end;

Enfin, la méthode pour l'événement OnPaint de la TPainBox doit tenir compte du changement de la nouvelle variante de PutImageAngle utilisée :

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
procedure TMainForm.PaintBoxPaint(Sender: TObject);
// *** la PaintBox est repainte ***
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, rsFilter,
      bmpWork.Width * tckbRotCenter.Position / 100 - 0.5,
      bmpWork.Height * tckbRotCenter.Position / 100 - 0.5,
      seOpacity.Value, cbOffset.Checked);
    LBmp.Draw(PaintBox.Canvas, 0, 0, False);
  finally
    LBmp.Free;
  end;
end;

L'exécution du programme permet de tester les différents filtres, en particulier lorsque l'image subit une rotation qui ne correspond pas à un multiple de l'angle droit :


Nom : 2017-02-13_200024.png
Affichages : 334
Taille : 53,0 Ko

Encore une fois, à vous de jouer et de transformer ce programme comme bon vous semble : l'objectif est de comprendre comment fonctionne la méthode PutImageAngle .

Liens pour les codes source des deux exemples : rotateimage3.7z et rotateimage2.7z

Envoyer le billet « Rotation d'une image - bibliothèque BGRABitmap avec Lazarus (2/2) » dans le blog Viadeo Envoyer le billet « Rotation d'une image - bibliothèque BGRABitmap avec Lazarus (2/2) » dans le blog Twitter Envoyer le billet « Rotation d'une image - bibliothèque BGRABitmap avec Lazarus (2/2) » dans le blog Google Envoyer le billet « Rotation d'une image - bibliothèque BGRABitmap avec Lazarus (2/2) » dans le blog Facebook Envoyer le billet « Rotation d'une image - bibliothèque BGRABitmap avec Lazarus (2/2) » dans le blog Digg Envoyer le billet « Rotation d'une image - bibliothèque BGRABitmap avec Lazarus (2/2) » dans le blog Delicious Envoyer le billet « Rotation d'une image - bibliothèque BGRABitmap avec Lazarus (2/2) » dans le blog MySpace Envoyer le billet « Rotation d'une image - bibliothèque BGRABitmap avec Lazarus (2/2) » dans le blog Yahoo

Mis à jour 15/02/2017 à 11h36 par gvasseur58

Catégories
Programmation , Free Pascal , Lazarus , Graphisme

Commentaires