Filtres et manipulation d'images en utilisant lockbits et des pointeurs

Soyez le premier à donner votre avis sur cette source.

Vue 15 716 fois - Téléchargée 931 fois


Description

Le but de cet exemple est de montrer comment manipuler une image, en accédant aux données directement en mémoire via la fonction "Lockbits" des Bitmaps.
J'y inclus aussi un filtre d'Eclaircissement (Brightness) comme exemple , à vous de vous servir de votre imagination pour en trouver d'autre ;]
(ou si vous voulez pas chercher envoyez moi un mail ^^")

Source / Exemple :


//namespace
using System.Drawing;
using System.Drawing.Imaging;

//Cette fonction nous retourne une Image eclaircie
private static Image Brightness(Image ImageOrigine)
{
       //On créer donc un nouveau bitmap pour garder notre original intacte
       Bitmap bmp = new Bitmap(ImageOrigine,ImageOrigine.Width,ImageOrigine.Height);
       //C'est dans un BitmapData qu'on utilise Lockbits
       //On fait donc un Lockbits des données de notre Bitmap ....
       BitmapData bmpData = bmp.LockBits(new Rectangle(0,0,bmp.Width,bmp.Height),ImageLockMode.ReadWrite,PixelFormat.Format24bppRgb);
       //Maintenant on collecte certaines informations ...
       int scanline = bmpData.Stride;   //le stride(appelé aussi scanline) est la largeur d'une rangée de pixels dans l'image;
       IntPtr scan0 = bmpData.Scan0; // le Scan0 nous indique où se trouve le 1er pixel en mémoire 

       unsafe // comme on utilise des pointeurs il faut indiquer qu'on code en "unsafe" mode  
       {
                // "p" sera donc notre pointeur 
                byte* p = (byte*)(void*)scan0;
                //on peut aussi écrire  "byte* p = (byte*)scan0.ToPointer();"
                
                //quelques variables nécéssaires
                int val;
                int nOffset = scanline-bmp.Width*3;
                int nWidth = bmp.Width*3;   //*3 parce qu'on travail des couleurs sur3 bytes "RGB"
                
                //C'est durant la prochaine boucle "for" qu'on travail nos pixels
                for(int  y = 0 ; y < bmp.Height ; ++y)
                {
                        for( int x = 0 ; x < nWidth ; ++x)
                        {
                               //on ajoute 50 (par ex.) pour rendre plus claire mais -50 , vous l'aurez deviné rendra l'image plus sombre !
                               val = (int)p[0]+50;
                               //on verifie que les valeurs ne dépasse pas 255 
                               if(val>255)val=255;
                               p[0]=(byte)val;
                               //on a donc augmenté la valeur du premier byte pour ce pixel , on passe au suivant
                               ++p; 
                        }
                         p+=nOffset;
                }
       }
        //notre modif effectuée on "relache" les données
        bmp.UnlockBits(bmpData);

        //On retourne l'image transformée :D
        return (Image)bmp;
}

Conclusion :


note : dans le traitement d'images, la rapidité est très importante , c'est une des raisons pour laquelle les pointeurs sont toujours utilisés dans ce domaine.
(aussi , vous noterez le "++i" au lieu de "i++" , en effet ++i est plus rapide à executer que "i++" en mémoire).

C'est ma premiere source de ce type , il est possible que j'ai fais quelques erreurs , si c'est le cas je m en excuse d'avance !!

Bon courage !

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

billegate2006
Messages postés
2
Date d'inscription
mercredi 17 janvier 2007
Statut
Membre
Dernière intervention
1 avril 2008

Bonjour,
Je veux juste vous poser une question concernant le traitement d'images, bon je veux mettre une bar de zoom sur une image mais il faut quelle soit transparente comme la boussole du google earth, merci de votre reponse.
phoenikz
Messages postés
2
Date d'inscription
mardi 8 janvier 2008
Statut
Membre
Dernière intervention
17 avril 2008

J'ai réalisé un programme de traitement d'image à partir d'une webcam et ton code m'a énormément aidé pour passer en noir et blanc et compté les pixels de certaines couleurs, bref un grand merci (enfin bon là j'ai 4 ans de retard mais c'est pas grave)
olixelle
Messages postés
520
Date d'inscription
vendredi 30 juillet 2004
Statut
Membre
Dernière intervention
3 mars 2008
1
Salut,

je ne connaissais le mode unsage qu'en théorie, j'en ai eu besoin récement donc je me suis très largement inspiré de ton code pour comprendre le principe et le mettre en application donc merci :)

Remarque: Si vous souahitez gérer la transparence des png, passez en Format32bppARgb et remplacez les 3 par des 4 lors de la copie des pixels (une constante aurait été bienvenue)

en tout cas merci :)
farias46
Messages postés
9
Date d'inscription
lundi 29 janvier 2007
Statut
Membre
Dernière intervention
14 octobre 2008

Monstrueusement efficace !!! J'ai commencé le C# il y a 2 semaines environ et j'ai été très déçu par les performances de celui-ci sur les traitements d'images. En effet j'utilisais la méthode "managed" c'est-à-dire avec les GetPixel et SetPixel. J'arrivais à plus de 14sec pour parcourir une image de 800x600... celà uniquement pour passer celle-ci en négatif!
Avec le mode "unsafe", sur une belle image de la lune avec une petite résolution de 5900x3100 siouplé :-) tous mes filtres prennent maxi 3sec !
Un grand merci à toi pour ce joli code qui m'a fait découvrir la puissance des pointeurs ;-)!
Equinox84
Messages postés
63
Date d'inscription
lundi 2 février 2004
Statut
Membre
Dernière intervention
19 mai 2010

Salut !

Merci pour ton code, il m'a permis d'inverser la couleur de mes graphiques avant l'impression, c'est tres pratique pour économiser le noir !

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.