Module d'application de filtres graphiques (sur un bitmap)

0/5 (3 avis)

Vue 6 889 fois - Téléchargée 470 fois

Description

Voici un procédure permettant d'appliquer des filtres graphiques sur un Bitmap.
Je me suis basé sur les travaux de Jean-Yves Quéinec en y apportant quelques améliorations, et surtout un code modulaire très facilement incorporable dans n'importe quel projet.
un filtre graphique est constitué d'un matrice "glissante" 3x3 ou plus rarement 5x5.
Chaque point de la matrice est pondéré par un coefficient : le point central est celui à traiter.
un filtre est aussi caractérisé par un diviseur, dont la valeur est en principe égal à la somme des coefficients de la matrice.
Remarquez que la manipulation de l'image s'effectue à un bas niveau, comme dans ma précédente unité sur le redimensionnement par interpolation bilinéaire.

le prototype de la procédure est la suivante :
PROCEDURE APPLY_FILTER(VAR BMP : TBitmap; CONST Filter : ARRAY OF integer; CONST Diviseur : integer; CONST Rect : TRect);

l'image Bitmap est passé par adresse (donc modifié au sein de la procedure)
Filter doit être un tableau de 25 éléments (pour une matrice 5x5 maxi),
Diviseur est caractéristique du filtre
Rect est la zone de l'image sur laquelle le filtre est appliqué

ex d'utilisation :
ApplyFilter(MyBMP, [0,0,0,0,0, 0,1,2,1,0, 0,2,20,2,0, 0,1,2,1,0, 0,0,0,0,0], 32, Rect(0,0,MyBMP.Width-1,MyBMP.Height-1);
//Application d'un filtre d'adoucissement

ApplyFilter(MyBMP, [0,0,0,0,0, 0,-1,-2,-1,0, 0,-2,28,-2,0, 0,-1,-2,-1,0, 0,0,0,0,0], 16, Rect(0,0,MyBMP.Width-1,MyBMP.Height-1);
//Application d'un filtre de durcissement

A vous de jouer avec les coefficients de la matrice pour définir vos propres filtres
Attention, la valeur du Diviseur doit être adéquat pour que le filtre soit fonctionnel.
Et n'oubliez pas de libérer la ressource Bitmap après l'appel de cette procédure.

Source / Exemple :


//Module : MOTEUR D'APPLICATION DE FILTRES GRAPHIQUES BASES SUR DES //MATRICES BIDIMENSIONNELLES 3x3 OU 5x5 DE PIXELS PONDERES PAR DES COEFFICIENTS.
//Créé par MORLET Alexandre en Avril/Mai 2002
//Basé sur les travaux de Jean-Yves Quéinec
//La fonction principale "Apply_Filter" reçoit en entrée les paramètres suivant :
//1.Image Bitmap sur lequel agira le filtre
//2.Filtre à appliquer sur le Bitmap
//3.Rectangle de Sélection permettant d'appliquer le filtre sur une zone uniquement

//Exemple de Filtres (la dernière valeur représente le Diviseur
//[0,0,0,0,0, 0,1,2,1,0, 0,2,20,2,0, 0,1,2,1,0, 0,0,0,0,0], 32; Adoucir
//[0,0,0,0,0, 0,-1,-2,-1,0, 0,-2,28,-2,0, 0,-1,-2,-1,0, 0,0,0,0,0], 16; Durcir
//Trouvez vos propres filtres :-P

UNIT U_ApplyFilter;

INTERFACE

USES
  Windows, Graphics;

//L'API Windows fournit la structure TRGBtriple (3 bytes), qui décrit
//les trois couleurs :  .Rgbtred, .Rgbtgreen, .Rgbtblue dans un bitmap.
//Tbitmap.pixelformat = pf24bit pour n'avoir qu'à traiter ce cas (en 16 millions de couleurs)

//Un Filtre est caractérisé par une Matrice 5*5 ou 3*3 de coefficient ainsi qu'un Diviseur
//Le Point Central de la Matrice est le pixel à traiter
//En principe : Somme(coefficients de la Matrice) / Diviseur = 1

TYPE
    TRGB = RECORD
         R : integer;
         G : integer;
         B : integer;
END;

CONST

     //La Matrice de Référence permet de savoir si le Filtre utilisé
     //repose sur une Matrice 5x5 ou 3x3
     MatrixModel : ARRAY[0..24] OF integer = (1,1,1,1,1,
                                              1,0,0,0,1,
                                              1,0,0,0,1,
                                              1,0,0,0,1,
                                              1,1,1,1,1);

PROCEDURE APPLY_FILTER(VAR BMP : TBitmap; CONST Filter : ARRAY OF integer; CONST Diviseur : integer; CONST Rect : TRect);

IMPLEMENTATION

PROCEDURE APPLY_FILTER(VAR BMP : TBitmap; CONST Filter : ARRAY OF integer; CONST Diviseur : integer; CONST Rect : TRect);
TYPE
//Tableau de Triplet RGB (RGBTRed,RGBTGreen,RGBTBlue) où chaque composante est de type BYTE
TRGBArray = ARRAY[0..0] OF TRGBTriple;
//Pointeur vers un Tableau de Triplet
PRGBArray = ^TRGBArray;
VAR
RGB : TRGB;
New_RGB : TRGB;
IM : integer; //Indice Matriciel pour l'indexage des coefficients
mX, mY, dX, dY : integer; //Position de et dans la Matrice Glissante
D : integer; //Décalage par rapport au centre de la Matrice
cpt : integer;
//Déclaration des tableaux de pointeur
//Chaque pointeur pointe sur une ligne
//Limitation dans le nombre de lignes à 2048
TabScanlineBMP : ARRAY OF PRGBArray; //Tableau Dynamique de Pointeurs sur Lignes
TabScanlineFinalBMP : ARRAY OF PRGBArray; //Tableau Dynamique de Pointeurs sur Lignes
//Position PosX et PosY dans l'image
PosX, PosY : integer;
//Image Bitmap avec Filtre
FinalBMP : TBitmap;
BEGIN

//D=1 si Matrice 3x3
//D=2 si Matrice 5x5
D := 1;
FOR cpt:=0 TO 24 DO
    IF ((Filter[cpt] AND MatrixModel[cpt]) <> 0) THEN
       BEGIN
       D := 2;
       Break;
       END;

   FinalBMP := TBitmap.Create;

   TRY
      FinalBMP.Assign(BMP);

      setLength(TabScanlineBMP, BMP.Height);
      setLength(TabScanlineFinalBMP, BMP.Height);

      //Stockage des Pointeurs de Scanlines
      FOR cpt := 0 TO BMP.Height-1 DO
          BEGIN
          TabScanlineBMP[cpt] := BMP.Scanline[cpt];
          TabScanlineFinalBMP[cpt] := FinalBMP.Scanline[cpt];
          END;

      FOR PosY := Rect.Top TO Rect.Bottom - 1 DO
          FOR PosX := Rect.Left TO Rect.Right - 1 DO
              BEGIN
              New_RGB.R :=0; New_RGB.G :=0; New_RGB.B :=0;
              //dX et dY pour le déplacement de la matrice glissante sur l'image
              FOR dY := -D TO D DO
                  FOR dX := -D TO D DO
                      BEGIN
                      //iX et iY pour la position du pixel à traiter
                      mY := PosY + dY;
                      mX := PosX + dX;

                      //Vérification des limites pour éviter les effets de bord
                      //Lecture des composantes RGB de chaque pixel
                      IF  (mY >= 1) AND (mY <= BMP.Height - 1)
                      AND (mX >= 1) AND (mX <= BMP.Width - 1) THEN
                          BEGIN
                          RGB.R := TabScanlineBMP[mY,mX].RGBTRed;
                          RGB.G := TabScanlineBMP[mY,mX].RGBTGreen;
                          RGB.B := TabScanlineBMP[mY,mX].RGBTBlue;
                          END
                      ELSE
                          BEGIN
                          RGB.R := TabScanlineBMP[PosY,PosX].RGBTRed;
                          RGB.G := TabScanlineBMP[PosY,PosX].RGBTGreen;
                          RGB.B := TabScanlineBMP[PosY,PosX].RGBTBlue;
                          END;

                      //Calcul de l'Indice Matriciel
                      //Si dX et dY varie entre -2 et 2, Alors IM varie entre 0 et 24
                      IM := 12 + dY * 5 + dX;

                      //Définition des nouvelles valeurs des composantes RGB en fonction du Filtre choisi
                      New_RGB.R := New_RGB.R + RGB.R * Filter[IM]; //Multiplier par le Coefficient Matriciel
                      New_RGB.G := New_RGB.G + RGB.G * Filter[IM];
                      New_RGB.B := New_RGB.B + RGB.B * Filter[IM];
                      END;

              New_RGB.R := New_RGB.R DIV Diviseur;
              New_RGB.G := New_RGB.G DIV Diviseur;
              New_RGB.B := New_RGB.B DIV Diviseur;

              //Vérification des limites sur le domaine de définition du type BYTE
              IF New_RGB.R > 255 THEN New_RGB.R := 255 ELSE IF New_RGB.R < 0 THEN New_RGB.R := 0;
              IF New_RGB.G > 255 THEN New_RGB.G := 255 ELSE IF New_RGB.G < 0 THEN New_RGB.G := 0;
              IF New_RGB.B > 255 THEN New_RGB.B := 255 ELSE IF New_RGB.B < 0 THEN New_RGB.B := 0;

              //Ecriture des nouvelles valeurs RGB dans l'image de destination
              TabScanlineFinalBMP[PosY,PosX].RGBTRed   := New_RGB.R;
              TabScanlineFinalBMP[PosY,PosX].RGBTGreen := New_RGB.G;
              TabScanlineFinalBMP[PosY,PosX].RGBTBlue  := New_RGB.B;
              END;

      BMP.Assign(FinalBMP);
      FINALLY
      FinalBMP.Free;
      END;

END;

END.

Conclusion :


Je suis ouvert à tout commentaire, toute critique : bonne ou mauvaise, toute optimisation
w413x@free.fr

Codes Sources

A voir également

Ajouter un commentaire Commentaires
abis007 Messages postés 17 Date d'inscription jeudi 10 avril 2003 Statut Membre Dernière intervention 13 décembre 2006
3 nov. 2004 à 12:51
je voudrai avoir(télecharger ) cette source en zip en delphi pas en vb!
merci d'avance
fabiin Messages postés 329 Date d'inscription mercredi 4 avril 2001 Statut Membre Dernière intervention 8 décembre 2009 6
29 mai 2003 à 10:10
comprend pas tous comment on peut faire son filtre,...
mais g essayé avec tes exemples et ca marche,
balaise,...
BlackWizzard Messages postés 1258 Date d'inscription mercredi 21 mars 2001 Statut Membre Dernière intervention 21 juin 2009 2
6 juil. 2002 à 19:11
C plus compliqué qu'en C et VB!
G pas essayé mais ça a l'air cool mais vachement compliqué!
tu peux faire plus simple avec gdi ou setpixel() getpixel()

si tu vx t'inspirer, http://www.vbfrance.com/article.aspx?Val=4800

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.