Modification rapide d'un Bitmap

Les méthodes GetPixel et SetPixel de l'objet Bitmap ont la particularité d'être à la fois très simples d'utilisation, et très lentes.
Voici donc une petite classe qui encapsule un Bitmap pour optimiser tout ça.
Vu 2872  fois

 

Le principe de fonctionnement

 

Il existe une méthode de l'objet Bitmap appelée LockBits, qui permet de récupérer un objet BitmapData, lequel est d'un formalisme très simple. Il se présente ainsi :

 

Structure de la matrice du Bitmap

 

Pour travailler l'image, il nous suffit donc d'aller lire et écrire dans cette matrice.
Pour ce faire, nous allons créer un objet BitmapRapide implémentant les méthodes suivantes :

  • Un constructeur prenant en paramètre un Bitmap
  • Des méthodes GetPixel et SetPixel identiques à celles de l'objet Bitmap
  • Un accesseur Image renvoyant un objet Bitmap

 

Construction de l'objet BitmapRapide

 

Le principe est ici de récupérer et de stocker la matrice correspondant au Bitmap passé en paramètre du constructeur :

 

private int largeur = 0;
private int decalage = 0;
private int hauteur = 0;
private byte[] matrice;






public BitmapRapide(Bitmap image)
{
   this.largeur = image.Width;
   this.decalage = (this.largeur * 3) + this.largeur%4;
   this.hauteur = image.Height;
         
   Rectangle bounds = new Rectangle(0, 0, this.largeur, this.hauteur);
   BitmapData bitmapData = image.LockBits(bounds, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

   this.matrice = new byte[this.hauteur * bitmapData.Stride];
      System.Runtime.InteropServices.Marshal.Copy(bitmapData.Scan0, matrice, 0, matrice.Length - 1);
         
   image.UnlockBits(bitmapData);
}

 

La variable "decalage" va permettre de passer d'une ligne à l'autre, en tenant compte des éventuels octets inutilisés en fin de ligne.

 

Récupération et mise à jour des Pixels

 

L'objet Bitmap est à présent conservé dans notre matrice, et c'est donc sur cette matrice que nous allons travailler directement.

 

Récupération de la couleur d'un Pixel dans la matrice :

 

public Color GetPixel(int x, int y) 
{
   byte bleu = matrice[(x * 3) + (y * this.decalage)];
   byte vert = matrice[((x * 3) + 1) + (y * this.decalage)];
   byte rouge = matrice[((x * 3) + 2) + (y * this.decalage)];

   return Color.FromArgb(rouge, vert, bleu);
}

 

Mise à jour de la couleur d'un pixel dans la matrice :

 

public void SetPixel(int x, int y, Color couleur) 
{
   matrice[(x * 3) + (y * this.decalage)] = couleur.B;
   matrice[((x * 3) + 1) + (y * this.decalage)] = couleur.G;
   matrice[((x * 3) + 2) + (y * this.decalage)] = couleur.R;
}

Reconstruction du Bitmap

 

Et pour finir, il nous faut un accesseur sur notre objet Bitmap modifié.
Il suffit pour cela de reconvertir notre BitmapData en Bitmap :

 

public Bitmap Image
{
   get
   {
      Bitmap image = new Bitmap(this.largeur, this.hauteur, PixelFormat.Format24bppRgb);

      Rectangle bounds = new Rectangle(0, 0, this.largeur, this.hauteur);
      BitmapData bitmapData = image.LockBits(bounds, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

      System.Runtime.InteropServices.Marshal.Copy(matrice, 0, bitmapData.Scan0, matrice.Length - 1);
            image.UnlockBits(bitmapData);
      return image;
   }
}

Comparaison des performances

 

Pour comparer les performances, nous allons effectuer des copies intégrales de Bitmaps de différentes tailles. Le temps de construction de l'objet BitmapRapide et de reconstruction de l'objet Bitmap est évidemment à prendre en compte.

 

Comparaison des performances

 

On constate que BitmapRapide permet de modifier les objets Bitmap environ 3,5 fois plus vite qu'en utilisant l'objet Bitmap standard, et ce quelque soit la taille de l'image.

 

On constate également qu'une durée de plus de 6 secondes pour le traitement d'une image complète de 10 millions de Pixel implique de toujours utiliser ces méthodes avec parcimonie.


 

Publié le  20/05/2007
Auteur:  Patrick A

 

Commentaires

Pas de commentaires

Si vous souhaitez ajouter un commentaire vous devez être authentifié.

 

ASP MAGAZINE  ASP-PHP.NET  C²I  CodePPC  CodeS-SourceS  Dotnet-News.com  Tech Head Brothers 

Dotnet-Project.com© tous droits réservés
Webmaster Aleks. Ont collaboré à l'aboutissement de ce projet :
CodeS-SourceS.com, ASP-PHP.Net, DotNet-FR.org, C2i.fr, Newsletter ASP.NET.