begin process at 2012 02 09 00:10:06
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Graphique

 > FILTRES ET MANIPULATION D'IMAGES EN UTILISANT LOCKBITS ET DES POINTEURS

FILTRES ET MANIPULATION D'IMAGES EN UTILISANT LOCKBITS ET DES POINTEURS


 Information sur la source

Note :
7,67 / 10 - par 3 personnes
7,67 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Graphique Source .NET ( DotNet ) Classé sous :filtre, image, lockbit, pointeur Niveau :Initié Date de création :09/12/2004 Date de mise à jour :11/12/2004 09:43:40 Vu / téléchargé :12 639 / 740

Auteur : li9

Ecrire un message privé
Site perso
Commentaire sur cette source (15)
Ajouter un commentaire et/ou une note

 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

  • //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;
  • }
//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 !

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

09 décembre 2004 20:58:12 :
Ajout d'un zip et quelques corrections ^^
11 décembre 2004 09:43:40 :
Ajout des namespaces (et ui ça peut être utile ^^)

 Sources du même auteur

Source avec Zip Source avec une capture Source .NET (Dotnet) CRC32 COMPATIBLE WINRAR ET WINZIP ( BASÉ SUR LE CODE C++ DE ...

 Sources de la même categorie

Source avec Zip Source avec une capture Source .NET (Dotnet) WINDOWSGADGET LIKE par Frelon
Source avec Zip Source avec une capture Source .NET (Dotnet) USERCONTROL PLANNING / SEMAINE / JOURNÉE par yohan49
Source avec Zip Source avec une capture Source .NET (Dotnet) TEMPLATE MATCHING ET RECONNAISSANCE D'OBJETS AVEC OPENCV (EM... par boutemine
Source .NET (Dotnet) CALCULE D'UNE EXPRESSION MATHEMATIQUE PAR COMPILATION par yohan49
Source avec Zip Source avec une capture Source .NET (Dotnet) CALENDRIER TACTILE, SOUS FORME DE ROUES par Robert33

 Sources en rapport avec celle ci

Source avec Zip Source .NET (Dotnet) BALLON, CAREE ET IMAGE QUI TOURNENT, SE GONFLENT ET SE DGONF... par zertyx
Source avec Zip Source .NET (Dotnet) PUZZLE 4X4 par jrscofield
Source avec Zip Source avec une capture Source .NET (Dotnet) IMAGES : FILTRES D'ACCENTUATION par tkfe
Source avec Zip Source avec une capture Source .NET (Dotnet) IMAGES : LE FILTRE MÉDIAN par tkfe
Source avec Zip Source avec une capture Source .NET (Dotnet) X-PRO, ACDSEE LIKE par Arkko

Commentaires et avis

Commentaire de yoannd le 09/12/2004 18:47:56

Alors, les erreurs, il y en a quelques une, en effet, mais rien de bien méchant :

Bitamp bmp = new Bitmap(ImageOrigine,ImageOrigin.Width,ImageOrigin.Height);

on préferrera déclarer un Bitmap plutot qu'un Bitamp et le vairable ImageOrigin n'existe pas, il faut écrire ImageOrigine

Je suppose que tu as voulu écrire ca
int nOffset = scanline-bmp.Width*3;

...à la place de
int nOffset = stride-bmp.Width*3;

Par contre, tu écris aussi ceci :
Image imgOut = Image.FromHBitmap(newBmp.GetHBitmap());
mais mon compilo ne trouve pas les fonction FromHBitmap et GetHBitmap. Est-ce qu'il me manque des using ? Ha non, je viens de voir que FromHbitmap avec un b minuscule fonctionnait, ainsi que GetHbitmap.

D'ailleurs, ce serait pas mal de les indiquer. Il me semble qu'il nous faut ici les using suivants :
using System.Drawing;
using System.Drawing.Imaging;

De plus, il ne me semble jamais avoir entendu que ++x et x++ étaient différents en terme de rapidité, mais la différence, c'est que si j'écris :
x = 3;
Console.WriteLine("" + (x++));
Ca m'affiche 3, puis ca incrémente de 1 la valeur x, alors que si j'écris :
Console.WriteLine("" + (++x));
ben ca incrémente de un la valeur x puis ca affiche 3+1, soit 4.

Bon, passons sur ceci, ce qui m'embète un peu plus, c'est que j'ai testé ce code, et ca me donne une image qui ne contient que des bandes grises et noires, bref, donc voila, heuuu, je crois qu'il y a un bug. En tout cas, c'est tout de même un contribution et ca peut peut-être aider quelqu'un, c'est le point positif de la chose. Mais c'est vrai qu'un petit zip, ca aurait été cool.

Commentaire de yoannd le 09/12/2004 18:52:31

Ha oui, dernier truc, tu écris ceci dans ton code:
byte* p = (byte*)(void*)scan0;
                //on peut aussi écrire  "byte* p = (byte*)scan0.ToPointer();"
                
Ben moi, il y a que
byte* p = (byte*)scan0.ToPointer();
... qui passe à la compilation.

Commentaire de li9 le 09/12/2004 21:18:05

Merci pour ton commentaire.
Effectivement , y avait quelques fautes mdr ....
J'ai tout corrigé (je pense .... ) et j'ai rajouté un zip avec quelques filtres supplémentaires pour me faire pardonner v( ^_^ )v .

J'ai voulu faire le chaud et tout taper de tête en postant ma source , c'est à cause de ça qu'y avait autant de fautes ....j'aurais dû faire un vieux copier/coller xD

C'est vrai que j'aurais dû parler des namespaces ,
Je m'en excuse !!

Pour "++i" ou "i++" t'as peut être raison, je pensait avoir vu ça dans la version de msdn fournit dans vs.net ... à vérifier ...
et pour la déclar. du pointeur moi les 2 passent niquel o_O , mais je me sert que de "(byte*)(void*)scan0"
Réessayes avec la source de mon zip. : /
on sait jamais ...

Ciao

Commentaire de yoannd le 10/12/2004 09:32:02

Putain là ouais, ca marche, et c'est nikel !
tu viens de donner pas mal de valeur à ta source là, d'un coup ! ben bravo, je trouve ca extra !

Commentaire de galinace le 11/12/2004 00:15:00

Bonjour,

Je viens de lire ton poste et ta methode me parrait effectivement intéressante.

J'aurais aimé avoir une sorte de comparatif ou tout du moins d'ordre d'idée concernant la différence de rapidité d'exécution entre le principe que tu décris (parcourt par pointeur etc) et le fait de rester en mode managé et dessiner la bitmap en passant par un objet "graphics".

Effectivement je ne parle pas là de modification de luminosité ou autre mais bien de dessin à proprement parler d'une bitmap. Je sais que ce n'est pas directement le sujet mais un rapport tout de même étroit m'a poussé a écrire ce poste.

Merci d'avance pour ta réponse

Commentaire de galinace le 11/12/2004 00:53:23

Re ....

Je viens de réaliser quelques tests entre ta methode et celle consistant à extraire le graphics du bitmap et travailler directement dessus.

Je me suis permis de modifier un peu ton source afin de laisser la possibilité d'importer une image et par suite remplacer celle par défaut. J'importe une bitmap de taille importante (105 Mo) afin de voir les temps de calculs et la mémoire prise (je suis sur un XP2000+ à 512 DDR).

L'application d'un filtre selon ta methode prend environ 6 à 7 secondes à pleine puissance (je parle ici de travail sans effet mémoire pour la possibilité d'annulation afin de ne pas être inflencé par des éventuel swappages).

La même opération effectuée sur une bitmap par extraction du graphics prends exactement le même temps.

Tout ceci pour pauser la question de l'utilité du mode "unsafe". C'est effectivement une question qui me tracasse pas mal car d'une part, le mode managé permet une certaine "sécurité" du code mais est sensé ralentir quelque peut l'exécution. Malheureusement pour moi, chaque exemple que je peux tester ne me permet pas réellement de trancher sur un mode plutôt que l'autre.

Pourrais tu m'éclarrer sur ton choix (travail en mode unsafe) et ton avis général sur la question ???

D'avance encore merci

Commentaire de li9 le 11/12/2004 09:41:43

Salut galinace,
on peut aussi utiliser les fonction "GetPixel()" et "SetPixel()" de la classe Bitmap pour travailler les pixels.
mais ces méthodes sont "très" lentes par rapport à l'utilisation de pointeurs.
Sur MSDN il y a un article interressant là dessus.
l'auteur y écrit qu'en Managed Code (getpixel,setpixel) son filtre Grayscale s'applique en 14sec. (enormement long mdr) , en Unmanaged (pointeurs) : 0.52sec  ; )

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp11152001.asp

par contre je vois pas trop ce que tu as fais pour ton test entre Managed et Unmanaged , tu extraits ton bitmap de 2 manieres differente et tu lui appliques mon filtre ? o_o

Sinon mon avis général sur la question c'est que l'étude des pointeurs va me permettre beaucoup de choses impossible à faire en managed code ^^"

wallou

++

Commentaire de kamal101 le 17/11/2005 21:44:16

Est-ce qu'il y a quelqu'un qui sait comment faire en c# la reconnaissance de forme. Je veux trouver des mini-cercles ronds dans une image et les mettre par exemple en noir. Est-ce qu'il y a une librairie pour ça ?

Commentaire de Warny le 26/03/2006 18:00:48

pour le fonction(i++) et le fonction(++i) le dotnet le compile en...
fonction(i); i = i+1;
et
i=i+1; fonction(i);
respectivement,
donc pour la vitesse, j'ai un doute ;)

Commentaire de Warny le 26/03/2006 19:20:54

Salut à nouveau,
Je me suis inspiré de ton code pour optimiser une déformation d'image (pour faire de l'assemblage horizontal de photo). C'est vrai que c'est nettement plus efficace. Merci beaucoup.

Commentaire de Equinox84 le 21/07/2006 10:33:25

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 !

Commentaire de farias46 le 13/02/2007 10:37:24

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 ;-)!

Commentaire de olixelle le 13/12/2007 13:04:45

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 :)

Commentaire de phoenikz le 05/03/2008 08:37:57 10/10

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)

Commentaire de billegate2006 le 01/04/2008 16:31:34

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.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Filtre imagelist [ par Monico9385 ] Bonjour tout le monde, j'ai un soucis sur le filtrage d'image. En fait, j'ai un ImageList associ&#233; &#224; un ListView, et j'aimerai lister que l traitement d'image en c [ par noussadk84 ] Svp jai un projet en c qui permet de faire des opérations de base sur les images de changer la luminosité ,le contraste appliquer le filtre uniforme e pointeur rawdata bitmap [ par gearmat ] Bonjour Bonjour j'aurais besoin de votre aide pour la classe bitmap :) j'ai une dll coder en c++ de traitement d'image qui me demande en paramètre u coordonée clique souris [ par chasseurdedemon ] bonjour, J'ai besoin pour mon programme de connétre les coordoné de la souris lor d'un clique . exemple : j'ai une image lors d'un clique sur l'imag Bandeau d'image(cliquable) dans un formulaire Winform [ par partales ] bonjour, Je cherche à faire une sorte de bandeau d'image cliquable dans un formulaire. Seulement, j'aurais souhaité pouvoir le courber (le bandeau) d Découper une image en WPF [ par xmox667 ] Salut à tous, Qui saurait comment on découpe une image comme un puzzle en wpf ? Merci Handle d'un objet Image [ par ellandebasque ] Bonjour, je vous remercie de prendre le temps lire mon message. Je vous expose mon problème. Je dispose de 2 caméras. Je cherche à faire un petit l WebClient OpenRead Time out [ par keikun59 ] Bonjour à tous, En faisant un test avec WebClient, je suis tombé sur un comportement très étrange. Pour cela, il vous suffit de tester le code suivan imprimer une image en filigrame [ par tatronic ] Bonjour a vous développeur! je viens de me lancer sur le c# et du coup, avec des amis je me suis lance dans le développement d'une application de ges


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 5,959 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales