Comment réaliser un 'effet de loupe' ?

Laurent LE BRUN (LLB)

Dans ce tutoriel, je vais essayer de vous expliquer comment capturer l'écran et y effectuer un agrandissement (ou un rétrécissement). ♪

- Titre : Comment réaliser un 'effet de loupe' ?

- Auteur : Laurent LE BRUN (LLB)

- Parution : 25 mai 2002

- Mise à jour : 25 mai 2002

- Licence : Ce document est issu de https://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.

Sommaire

- I. Comment réaliser un 'effet de loupe'

I - Comment réaliser un 'effet de loupe'

L'astuce consiste à utiliser la procédure CopyRect d'un Canvas.

procedure CopyRect(Dest: TRect; Canvas: TCanvas; Source: TRect);

Elle permet de copier dans le canevas une partie de l'image d'un autre canevas. Dest spécifie le rectangle du canevas où l'image source doit être copiée. Le paramètre Canvas spécifie le canevas contenant l'image source. Source spécifie le rectangle délimitant la partie du canevas source à copier. Si les paramètres Dest et Source ont les mêmes dimensions, l'image est juste copiée. Alors que s'ils sont de tailles différentes, l'image est redimensionnée. Cela permet donc d'agrandir ou de rétrécir tout ou partie d'une image.

Dans notre exemple, on va se baser sur l'écran. On va récupérer une partie de l'écran, centrée sur la souris. Pour plus de clarté, on va créer une procédure, avec pour paramètre la position de la souris.

procedure Loupe(x,y: Integer);

L'idéal serait d'appeler cette méthode dès que la souris bouge, ce qui est simple quand elle reste sur notre fiche. Mais, c'est un peu plus compliqué lorsqu'elle en sort. Dans notre exemple, on va utiliser un Timer, avec un faible Intervalle, soit 1. Et on appelle la procédure :

procedure TForm1.Timer1Timer(Sender: TObject);
begin
Loupe(Mouse.CursorPos.x, Mouse.CursorPos.y);
end;

On peut maintenant se concentrer sur notre procédure. On va zoomer sur un carré, de côté 40 pixels et de centre la position de la souris, c'est-à-dire (x,y). On définit la zone par un TRect, appelé ici Cadre1 :

procedure Loupe(x,y: Integer);
var
Cadre1: TRect;
begin
// définition d'un carré de 40x40 pixels centré sur la position de la souris
Cadre1.Top := y - 20 - Form1.Top;
Cadre1.Left := x - 20 - Form1.Left;
Cadre1.Right := x + 20 - Form1.Left;
Cadre1.Bottom := y + 20 -Form1.Top;
end;

Vous aurez remarqué qu'il faut retrancher la position de la fiche à la position de Cadre1. Il ne faut pas l'oublier, car ce rectangle est défini par rapport à l'ÉCRAN (son coin supérieur gauche). Et, quand on l'affichera sur la fiche, les positions se feront par rapport au coin supérieur gauche de la FICHE. Cela provoquerait un décalage assez important.

On doit maintenant définir un second carré : celui que l'on affichera sur la fiche. Il doit donc être de dimension supérieure pour provoquer un agrandissement.

procedure Loupe(x,y: Integer);
var
Cadre1, Cadre2: TRect;
begin
// définition d'un carré de 40x40 pixels centré sur la position de la souris
Cadre1.Top := y - 20 - Form1.Top;
Cadre1.Left := x - 20 - Form1.Left;
Cadre1.Right := x + 20 - Form1.Left;>
Cadre1.Bottom := y + 20 -Form1.Top;

// définition d'un carré de 100x100 pixels pour l'affichage
Cadre2.Top:=10;
Cadre2.Left:=10;
Cadre2.Right:=110;
Cadre2.Bottom:=110;
end;

Il nous reste maintenant à copier le Cadre1 vers le Cadre2 au moyen de la méthode CopyRect.

Form1.Canvas.CopyRect(Cadre2, Form1.Canvas, Cadre1);

Le programme est maintenant opérationnel. On peut l'améliorer, en mettant la possibilité de régler le zoom. On rajoute le paramètre Size dans notre procédure, qui déterminera la taille du rectangle à copier. Donc, plus le rectangle sera petit, plus le zoom sera puissant.

procedure Loupe(x, y, Size: Integer);
var
Cadre1, Cadre2: TRect;
begin
// définition d'un carré centré sur la position de la souris
Cadre1.Top := y - Size - Form1.Top;
Cadre1.Left := x - Size - Form1.Left;
Cadre1.Right := x + Size - Form1.Left;
Cadre1.Bottom := y + Size -Form1.Top;
{...}
end;

On ajoute un TTrackBar sur la fiche, pour pouvoir régler le zoom. Je l'ai appelé TBar (c'est plus court ;-). On modifie l'événement OnTimer du Timer, en ajoutant le nouveau paramètre :

Loupe(Mouse.CursorPos.x, Mouse.CursorPos.y, TBar.Position);

On ajoute maintenant un TLabel pour afficher le grossissement :

Label1.Caption := IntToStr(100 * 100 div (TBar.Position * 2))+' %';

On multiplie d'abord par 100 pour avoir un pourcentage, sinon on aurait toujours 0, puisqu'on travaille avec des entiers (Delphi arrondirait la valeur). On a un deuxième 100, car c'est la taille de l'image qui est affichée (sur la fiche). On a presque fini notre programme. Si on veut enregistrer l'image agrandie, il serait préférable de l'afficher dans un TImage (que j'ai appelé Img). On a juste quelques modifications à effectuer. À la fin, vous devriez avoir un source, ressemblant à ça :

unit LoupeUnit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, ComCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Timer1: TTimer;
tbar: TTrackBar;
img: TImage;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure tbarChange(Sender: TObject);
private
{ Déclarations privées }
public
{ Déclarations publiques }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
close;
end;

procedure Loupe(x, y, Size: Integer);
var
Cadre1, Cadre2: TRect;
begin
// définition d'un carré centré sur la position de la souris
Cadre1.Top := y - Size - Form1.Top;
Cadre1.Left := x - Size - Form1.Left;
Cadre1.Right := x + Size - Form1.Left;
Cadre1.Bottom := y + Size -Form1.Top;

// On récupère la taille de l'image pour afficher dedans l'image agrandie.
Cadre2.Top := 0;
Cadre2.Left := 0;
Cadre2.Right := Form1.Img.Width;
Cadre2.Bottom := Form1.img.Height;

Form1.Img.Canvas.CopyRect(Cadre2, Form1.Canvas, Cadre1);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
Loupe(Mouse.CursorPos.x, Mouse.CursorPos.y, TBar.Position);
end;

procedure TForm1.tbarChange(Sender: TObject);
begin
Label1.Caption := IntToStr(100 * 100 div (TBar.Position * 2))+' %';
end;
end.

Nous voici à la fin de ce tutoriel. Vous pouvez adapter l'exemple à vos propres besoins. Vous devez être capable de réaliser un logiciel de capture d'écran. Vous pouvez télécharger le programme d'exemple ici. J'ai réalisé ce cours grâce à un exemple de Lionel Rouvarel. N'hésitez surtout pas à me dire ce que vous pensez, ou si vous avez des problèmes.
Tout commentaire, suggestion, remarque ou question sont les bienvenus.
Si vous avez le temps, visitez mon site Le Temple de la Programmation !

Un mot d'encouragement ou un compliment fait toujours plaisir.

LLB/DeuSSuM