Comparaison de bytes d images

Résolu
cs_danyclassique Messages postés 94 Date d'inscription samedi 1 décembre 2007 Statut Membre Dernière intervention 7 novembre 2010 - 14 mars 2008 à 13:22
cs_danyclassique Messages postés 94 Date d'inscription samedi 1 décembre 2007 Statut Membre Dernière intervention 7 novembre 2010 - 3 juin 2009 à 16:57
Bonjour a tous.
J aurai voulu savoir si quelqu un connait une methode  pour comparer 2 tableaux de bytes contenant chacun
les paquets de bytes d une image
exemple:
byte[]b //contient une image;
byte[]b2 //contient une autre image;
puis en extraire la difference  qui ensuite sera affichee  dans une picturebox
Je pense que vous avez compris son sens;

Merci d avance;
A voir également:

25 réponses

taupe4 Messages postés 91 Date d'inscription dimanche 16 avril 2006 Statut Membre Dernière intervention 17 avril 2008 1
16 mars 2008 à 17:32
Pour clarifier le code manquant avec les différences (en pseudo-code):

SI difference ÉGALE 0 ALORS
 SI il y a des données dans notre tampon ALORS
  ON ENVOIE LE X,Y DU DÉBUT DES DONNÉES
  ON ENVOIE LA TAILLE DU TAMPON DE DONNÉES
  ON ENVOIE LE TAMPON DE DONNÉES
 FIN SI
SINON
 ON ENREGISTRE difference DANS NOTRE TAMPON
FIN SI

À la réception
VERROU IMAGE A EN LECTURE / ÉCRITURE
TANT QU'IL Y A DES DONNÉES À LIRE
 ON LIT UN X,Y
 ON LIT LA TAILLE DU TAMPON
 ON LIT LE TAMPON
 ON SE POSITIONNE AU PIXEL X,Y VOULU ( en byte pour 24bpp -> y * bitmapData.Stride + x*3, en int pour 32bpp-> y* bitmapData.Stride>>2 + x)
 POUR CHAQUE DONNEE DU TAMPON
  LE PIXEL DE A = LE PIXEL DE A + difference (LA DONNÉE DU TAMPON)
 FIN POUR CHAQUE
FIN TANT QUE
DÉVERROUILLE IMAGE A

Et, je suis désolé, dans mes deux méthodes il manque ceci à la toute fin. Il faut les mettre dans les codes, surtout si on est en lecture/écriture. Car sinon le bitmap reste ouvert et inaccessible.:
a.UnlockBits(bmpA);
b.UnlockBits(bmpB);
 
 
<hr size="2" width="100%" />«L'erreur est humaine mais un véritable désastre nécessite un ordinateur.»
«Selon les derniers chiffres, 43 % des statistiques sont fausses»
3
ShareVB Messages postés 2676 Date d'inscription vendredi 28 juin 2002 Statut Membre Dernière intervention 13 janvier 2016 26
14 mars 2008 à 17:46
salut,

ca dépend du format de l'image....si tu peux recréer un Bitmap à partir de ton tableau, il y a une solution sinon, il te faut le bon décodeur et ensuite, comparer le résultat "bitmap"...

ShareVB
0
cs_danyclassique Messages postés 94 Date d'inscription samedi 1 décembre 2007 Statut Membre Dernière intervention 7 novembre 2010
15 mars 2008 à 18:50
En fait j utilise un webservices pour le transport d  images entre 2 ordi distants
Ces images sont la capture du  bureau d un des ordi .

Jusqu a la tout fonctionne mais il y a une repetition  de chaque images envoyees y compris ce qu il y avait dans la picturebox de l ordi no2 ce qui est logique puisque le thread de l ordi no1 prend sans arret des captures d images sur lui meme   

Le but est qu a l arrivee il y est une comparaison entre l image qui est deja dans la picture box et la nouvelle qui arrive et c est cette differnce que l on afficherai  en suivant et si il n y a pas de difference majeure on afficherai rien

A chaque envoies d images  j utilise une fonction de convertion d images qui renvoie un tableau de bytes pour chaque transport







private



byte
[] Convert(

Image
i,

ImageFormat
f)



{



MemoryStream
ms =

new



MemoryStream
();



i.Save(ms, f);



byte
[] bytes = ms.ToArray();




return
bytes;



}




et pour chaque reception d  images  j utilise une fonction qui reconstitue le  flux de bytes en bitmap
et c est ce bitmap que j affiche dans le picturebox



private



Image
Convert(

byte
[] b)



{



MemoryStream
ms =

new



MemoryStream
(b);




Bitmap
bm =

new



Bitmap
(ms);




return
bm;



}

Apres reflexion je pense qu il serai mieux pour le programme et plus rapide pour celui ci que le travail de comparaison ce passe a l envoie et non a la recption .

J adapterai cela par la suite.

Desole pour les explications un peut farfelus  mais ce bug est difficile a expliquer

Je pense de  toute facon que tu as deja compris le problemme.

Merci pour ton aide.
0
ShareVB Messages postés 2676 Date d'inscription vendredi 28 juin 2002 Statut Membre Dernière intervention 13 janvier 2016 26
15 mars 2008 à 21:16
salut,

donc ce que tu cherches à faire est une sorte de VNC....donc ce ne serait pas qu'une simple comparaison mais plutot un delta dans le genre de ce que font les codecs mpeg4...l'idée est de n'envoyer que les parties de l'image qui changent...

Côté serveur :
Tu gardes deux images la précédente et celle en cours
Tu fais une comparaison et tu récupéres les zones de différences (sous la forme [(x,y début) (données) (x,y fin)])
Ensuite, tu envois toutes ces zones
Côté client :
Enfin, dans ton image de destination, tu recopies toutes tes zones...

donc maintenant comment faire tout cela et de préférence rapidement : par le code unsafe...sinon tu as GetPixel mais alors là ca va prendre un moment...

quelque chose comme :
            BitmapData bmpA = x.LockBits(new Rectangle(Point.Empty, x.Size), ImageLockMode.ReadOnly, x.PixelFormat);
            BitmapData bmpB = y.LockBits(new Rectangle(Point.Empty, y.Size), ImageLockMode.ReadOnly, y.PixelFormat);

            bool ret = true;
            unsafe
            {
                UnmanagedMemoryStream umsA = new UnmanagedMemoryStream((byte*)bmpA.Scan0, (long)bmpA.Stride * bmpA.Height);
                UnmanagedMemoryStream umsB = new UnmanagedMemoryStream((byte*)bmpB.Scan0, (long)bmpB.Stride * bmpB.Height);

                for (int i = 0; i < bmpA.Height;i++)
                {
                    int s = ((bmpA.Width*3 + 7) / 8);
                    for (int j = 0; j < s; j++)
                    {
                        int bA = umsA.ReadByte() >> 2 + umsA.ReadByte() >> 1 + umsA.ReadByte();
                        int bB = umsB.ReadByte() >> 2 + umsB.ReadByte() >> 1 + umsB.ReadByte();
                        //récuérer les zones de différences
                    }
                }
            }
            x.UnlockBits(bmpA);
            y.UnlockBits(bmpB);

ShareVB
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_danyclassique Messages postés 94 Date d'inscription samedi 1 décembre 2007 Statut Membre Dernière intervention 7 novembre 2010
15 mars 2008 à 21:47
Exactement .


Merci d avoir repondu si vite je vais essayer de mettre ca en route et je te recontact des que je ne recoit que ce qu il faut et pas une repetition d image

A bientot ou peut etre a tout a l heure.
0
cs_danyclassique Messages postés 94 Date d'inscription samedi 1 décembre 2007 Statut Membre Dernière intervention 7 novembre 2010
15 mars 2008 à 22:20
Je t avoue que je comprend a moitie ton code
mais je pense que je n est pas le niveau encore de l adapter sur le mien
tu na pas l air d un petit joueur bien au contraire

Bravo pour  ces competences

Mais pour en revenir a mon petit niveau je vais t envoyer mon code et peut etre tu pourras me diriger su la direction que j ai deja prise

cote serveur


using System;



using



System.Collections.Generic;


using



System.ComponentModel;


using



System.Data;


using



System.Drawing;


using



System.Text;


using



System.Windows.Forms;


using



System.Runtime.InteropServices;


using



System.Collections;


using



System.Runtime.Serialization.Formatters.Binary;


using



System.IO;


using



System.Diagnostics ;


namespace



CAPTURE{


using
dany;


using
System.Threading;


using
System.Drawing.Imaging;


public



partial



class



Form1
:

Form

{







public
Form1(){

InitializeComponent();

}



#region



Declarationsdany.


Service
s =

new
CAPTURE.dany.

Service
();


ImageFormat
imageformat =

ImageFormat
.Png;


Thread
t;


//Thread t2;






IntPtr
handle2 =

new



IntPtr
();


IntPtr
handle =

new



IntPtr
();


#endregion



Declarations


#region



Dll and Constantes[


DllImport
(

"user32.dll"
)]


private



static



extern



IntPtr
GetDesktopWindow();[


DllImport
(

"gdi32.dll"
)]


private



static



extern



bool
BitBlt(


IntPtr
hdcDest,


int
nXDest,


int
nYDest,


int
nWidth,


int
nHeight,


IntPtr
hdcSrc,


int
nXSrc,


int
nYSrc,


int
dwRop);


private



const



int
SRCCOPY = 0xCC0020;


#endregion



Dll and Constantes 


public



void
CaptureTotale(){


while
(

true
){

handle = GetDesktopWindow();


Graphics
gScreen =

Graphics
.FromHwnd(handle);


Rectangle
r =

Screen
.PrimaryScreen.Bounds;


Bitmap
bmpScreen =

new



Bitmap
(r.Width, r.Height);


Graphics
gBmp =

Graphics
.FromImage(bmpScreen);


IntPtr
hDCScreen = gScreen.GetHdc();


IntPtr
hDCBmp = gBmp.GetHdc();BitBlt(hDCBmp,

0,

0,

r.Width,

r.Height,

hDCScreen,

0,

0,

SRCCOPY);

gScreen.ReleaseHdc(hDCScreen);

gBmp.ReleaseHdc(hDCBmp);


byte
[] b = Convert(bmpScreen, imageformat);s.setimage(b);


Thread
.Sleep(100);}

}

 


private



byte
[] Convert(

Image
i,

ImageFormat
f){


MemoryStream
ms =

new



MemoryStream
();i.Save(ms, f);


byte
[] bytes = ms.ToArray();


return
bytes;}


private



void
button1Capture_Click(

object
sender,

EventArgs
e){


ThreadStart
ts =

new



ThreadStart
(CaptureTotale);t =


new



Thread
(ts);t.Start();

 

 

 

}


private



void
Form1_FormClosed(

object
sender,

FormClosedEventArgs
e){


//t2.Abort();//no run if project clientreceive îåøä work just test.

t.Abort();


}


}


}

cote web service


[



WebMethod
]


public



void
setimage(

byte
[] b){

Application[


"b"
] = b;}

[


WebMethod
]


public



byte
[] getimage(){


byte
[] b = (

byte
[])Application[

"b"
];


return
b;}

cote client

using


System;


using



System.Collections.Generic;


using



System.ComponentModel;


using



System.Data;


using



System.Drawing;


using



System.Text;


using



System.Windows.Forms;


using



System.Runtime.Serialization.Formatters.Binary;


using



System.IO;


using



System.Collections;


using



System.Threading;


using



System.Drawing.Imaging;


namespace



clientreceive{


public



partial



class



Form1
:

Form

{







public
Form1(){

InitializeComponent();

}



#region



Declarationsdanyrecoit.


Service
se =

new
clientreceive.danyrecoit.

Service
();


Thread
t2;


#endregion



Declarations


private



void
button1receive_Click(

object
sender,

EventArgs
e){


ThreadStart
ts2 =

new



ThreadStart
(Display);t2 =


new



Thread
(ts2);t2.Start();

}


void
Display(){


while
(

true
){


try

{







byte
[] b = se.getimage();


Image
bmp Convert(b);pictureBox1.Image bmp;

 

 

}


catch
(

Exception
ex){


string
text =

string
.Format(

"Eception Type:{0}\n\n"

+




"Message: {1}\n\n"

+




"Stack Trace: {2}"
,ex.GetType(), ex.Message, ex.StackTrace);


//MessageBox.Show(text);--->no run this one bug

}


 


}


}


 


 


 







private



Image
Convert(

byte
[] b){


MemoryStream
ms =

new



MemoryStream
(b);


Bitmap
bm =

new



Bitmap
(ms);


return
bm;}


private



void
Form1_FormClosed(

object
sender,

FormClosedEventArgs
e){

t2.Abort();


//no run ->this new instance just test.

}


 


 


 


}


}

Desole pour tout ca mais je suis coince a une repetion de la meme image avec la nouvelle

et notre prof veut que nous employons   la technique du bitblt

En tout cas merci et chapeau pour cet algorithme extra
0
ShareVB Messages postés 2676 Date d'inscription vendredi 28 juin 2002 Statut Membre Dernière intervention 13 janvier 2016 26
15 mars 2008 à 22:43
salut,

euh, il y a plusieurs choses qui me surprennent relativement :
-> pourquoi un webservice ? dans ce cas, un service WCF ou plus simplement un socket...
-> (plus de l'ordre du détail) le serveur pourrait être une appli console ou un service (bon pour tester c'est un peu moins facile)

pour le reste tu peux intégrer mon code avec le bitmap que tu crées depuis bitblt...

ShareVB
0
cs_danyclassique Messages postés 94 Date d'inscription samedi 1 décembre 2007 Statut Membre Dernière intervention 7 novembre 2010
15 mars 2008 à 22:48
Je comprend bien ce que tu dis


moi j avais suggere au prof par tcp ip comme un chat que nous avions deja mis au point mais il etait pas daccord alors bon!!!


ok donc je vais essayer de my mettre


merci encore
0
cs_danyclassique Messages postés 94 Date d'inscription samedi 1 décembre 2007 Statut Membre Dernière intervention 7 novembre 2010
15 mars 2008 à 23:40
Ou la la

Je t avoue que je suis en plein cassement de tete je n arrive pas tres bien a adapter ton code au mien
pour mieux dire je n est jamais utilise la technique dangereuse qui elle meme utilise les pointeurs

Je suis completement coince mais le pire c est qu il n y a pas beaucoup de monde qui arrivent a me repondre a par toi pour l instant

pourrai tu peut etre me dirriger dans l insertion de ton code ce qui pourrai m aider pour mieux le comprendre quand je le ferai tourner pas a pas
0
taupe4 Messages postés 91 Date d'inscription dimanche 16 avril 2006 Statut Membre Dernière intervention 17 avril 2008 1
16 mars 2008 à 15:17
Je ne te conseille pas les images PNG. Dans ton cas, et avec la méthode que tu désires utiliser (la méthode des différences), utiliser des PNG ralentira le processus (bah oui coder une image en PNG c'est forcément plus long qu'en BMP.

Pour une performance optimale, j'irais même à te recommander les BMP 32 bit, si tu utilises la méthode des différences. Car, dans ce cas, tout peut se faire très rapidement et efficacement.

Et le code donné par ShareVB ne fonctionnera pas. En premier lieu, l'utilisation de SHR (>>) au lieu de SHL (<<), qui créera un truc incohérenct. En second lieu, le non-respect de l'endianness.

Le code suivant contient des commentaires pour t'aider à comprendre comment faire l'opération relativement efficacement. Car les logiciels de type VNC utilisent une méthode encore plus efficace: ils créent un pilote de carte vidéo virtuel (qui sous-traite la production au vrai pilote) et peuvent donc obtenir tout changement en temps réel, et ce sans avoir à obtenir une image complète continuellement.
//Modifier le VOID.
static unsafe void GetDifferences(Bitmap a, Bitmap b)
        {
            //On obtient la surface de travail des Bitmaps. Cela permet de traiter directement leurs pixels.
            //On prétend ici que les deux images ont la même taille.
            Rectangle surfaceTravail = new Rectangle(Point.Empty, a.Size);
            BitmapData bmpA = a.LockBits(surfaceTravail, ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
            BitmapData bmpB = b.LockBits(surfaceTravail, ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
          
            //Nous permet de "voir" deux couleurs.
            int* couleurA, couleurB;
            int difference;
            //Ici on dit que notre pointeur (visionneur) est au début des deux bitmaps
            couleurA = (int*)bmpA.Scan0;
            couleurB = (int*)bmpB.Scan0;

            for(int y = 0; y < surfaceTravail.Height; y++) {
                for(int x = 0; x < surfaceTravail.Width; x++) {
                    //On calcul la différence entre la couleur B et la couleur A. Pour récupérer la couleur B, il faudra donc ajouter la couleur A.
                    //De plus, on passe à la couleur suivante grâce au ++. C'est l'arithmétique des pointeurs qui fait que cela fonctionne.
                    difference = (*couleurB++) - (*couleurA++);
                    //Faire quelque chose avec cette différence. Par exemple, enregistrer (x,y, difference) et l'envoyer.
                    throw new NotImplementedException("Il ne se passe rien avec la différence");
                }
            }
        }
Ce code est fonctionnel à trois conditions:
1. Les deux images doivent avoir la même taille
2. Les deux images doivent avoir un format 32 bpp X8R8G8B8 (soit 8 bit par canal de couleur plus un canal 8bit inutilisé). Cela permet d'utiliser l'arithmétique de pointeur sur les entiers (int*) qui est plus efficace que celle sur les images 24bit R8G8B8 (de plus il n'y a pas de stride trop grand et le processeur est optimisé pour un traitement 32bit). Pour que ça prenne moins de place tu pourais prendre le 16 bit R5G6B5 ou X1R5G5B5. Mais là tu serais limité à 65536 couleurs pour le R5G6B5 et 32768 couleurs pour le X1R5G5B5.

Mais il manque à ce code la partie qui gère les différences. On l'obtient, oui, mais on ne fait strictement rien avec.

Le truc le moins compréhensible du code est (*couleurB++). Cela veut dire "Je veux voir la couleur où est couleurB puis je veux que couleurB représente la couleur du pixel suivant". Ce code est strictement équivalent à:
difference = *couleurB - *couleurA;
couleurB++; couleurA++;

Si tu as des questions, pose-les . Pour quelqu'un du monde C# les pointeurs ça peut venir compliquer d'un cran les codes.

<hr size="2" width="100%" />«L'erreur est humaine mais un véritable désastre nécessite un ordinateur.»
«Selon les derniers chiffres, 43 % des statistiques sont fausses»
0
taupe4 Messages postés 91 Date d'inscription dimanche 16 avril 2006 Statut Membre Dernière intervention 17 avril 2008 1
16 mars 2008 à 15:17
Je ne te conseille pas les images PNG. Dans ton cas, et avec la méthode que tu désires utiliser (la méthode des différences), utiliser des PNG ralentira le processus (bah oui coder une image en PNG c'est forcément plus long qu'en BMP.

Pour une performance optimale, j'irais même à te recommander les BMP 32 bit, si tu utilises la méthode des différences. Car, dans ce cas, tout peut se faire très rapidement et efficacement.

Et le code donné par ShareVB ne fonctionnera pas. En premier lieu, l'utilisation de SHR (>>) au lieu de SHL (<<), qui créera un truc incohérenct. En second lieu, le non-respect de l'endianness.

Le code suivant contient des commentaires pour t'aider à comprendre comment faire l'opération relativement efficacement. Car les logiciels de type VNC utilisent une méthode encore plus efficace: ils créent un pilote de carte vidéo virtuel (qui sous-traite la production au vrai pilote) et peuvent donc obtenir tout changement en temps réel, et ce sans avoir à obtenir une image complète continuellement.
//Modifier le VOID.
static unsafe void GetDifferences(Bitmap a, Bitmap b)
        {
            //On obtient la surface de travail des Bitmaps. Cela permet de traiter directement leurs pixels.
            //On prétend ici que les deux images ont la même taille.
            Rectangle surfaceTravail = new Rectangle(Point.Empty, a.Size);
            BitmapData bmpA = a.LockBits(surfaceTravail, ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
            BitmapData bmpB = b.LockBits(surfaceTravail, ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
          
            //Nous permet de "voir" deux couleurs.
            int* couleurA, couleurB;
            int difference;
            //Ici on dit que notre pointeur (visionneur) est au début des deux bitmaps
            couleurA = (int*)bmpA.Scan0;
            couleurB = (int*)bmpB.Scan0;

            for(int y = 0; y < surfaceTravail.Height; y++) {
                for(int x = 0; x < surfaceTravail.Width; x++) {
                    //On calcul la différence entre la couleur B et la couleur A. Pour récupérer la couleur B, il faudra donc ajouter la couleur A.
                    //De plus, on passe à la couleur suivante grâce au ++. C'est l'arithmétique des pointeurs qui fait que cela fonctionne.
                    difference = (*couleurB++) - (*couleurA++);
                    //Faire quelque chose avec cette différence. Par exemple, enregistrer (x,y, difference) et l'envoyer.
                    throw new NotImplementedException("Il ne se passe rien avec la différence");
                }
            }
        }
Ce code est fonctionnel à trois conditions:
1. Les deux images doivent avoir la même taille
2. Les deux images doivent avoir un format 32 bpp X8R8G8B8 (soit 8 bit par canal de couleur plus un canal 8bit inutilisé). Cela permet d'utiliser l'arithmétique de pointeur sur les entiers (int*) qui est plus efficace que celle sur les images 24bit R8G8B8 (de plus il n'y a pas de stride trop grand et le processeur est optimisé pour un traitement 32bit). Pour que ça prenne moins de place tu pourais prendre le 16 bit R5G6B5 ou X1R5G5B5. Mais là tu serais limité à 65536 couleurs pour le R5G6B5 et 32768 couleurs pour le X1R5G5B5.

Mais il manque à ce code la partie qui gère les différences. On l'obtient, oui, mais on ne fait strictement rien avec.

Le truc le moins compréhensible du code est (*couleurB++). Cela veut dire "Je veux voir la couleur où est couleurB puis je veux que couleurB représente la couleur du pixel suivant". Ce code est strictement équivalent à:
difference = *couleurB - *couleurA;
couleurB++; couleurA++;

Si tu as des questions, pose-les . Pour quelqu'un du monde C# les pointeurs ça peut venir compliquer d'un cran les codes.

<hr size="2" width="100%" />«L'erreur est humaine mais un véritable désastre nécessite un ordinateur.»
«Selon les derniers chiffres, 43 % des statistiques sont fausses»
0
ShareVB Messages postés 2676 Date d'inscription vendredi 28 juin 2002 Statut Membre Dernière intervention 13 janvier 2016 26
16 mars 2008 à 15:48
salut,

euh, moi, j'ai deux questions :
-> l'endianess pour une bitmap dépend de l'architecture ? donc on ne pourrait pas passer un bmp d'une archi à une autre ? ou alors c'est seulement LockBits qui fait ca ?
-> je n'ai jamais réussi à forcer un PixelFormat autre que celui de la Bitmap dans LockBits, il y a un moyen de convertir de 24 à 32 bits ?

sinon, euh, oui, effectivement, dans mon code, ca devrait être << et pas >>...

ShareVB
0
cs_danyclassique Messages postés 94 Date d'inscription samedi 1 décembre 2007 Statut Membre Dernière intervention 7 novembre 2010
16 mars 2008 à 16:23
Avant tout merci a vous deux de prendre part a mon probleme

je vais essayer de comprendre tout ca et en parallele continuer ce que j ai en cour avec sharevb bien que les deux idees se rejoignent

je me met au travail de suite et je vous tient au courrant
0
cs_danyclassique Messages postés 94 Date d'inscription samedi 1 décembre 2007 Statut Membre Dernière intervention 7 novembre 2010
16 mars 2008 à 16:48
taupe4 grace a toi et a sharevb j ai parfetement bien compris ton code et ainssi maintenant que celui de sharevb assez rapidement 
tout ca est tres bien explique je dierai meme mieux que mon prof mais bon ne le crions pas trop fort .

J ai reussi a envoyer mes 2 images du bureau prise l une a la suite des autres et apres ces 2 prises les inserer dans la fonction unsafe tout ce passe bien jusqu a l action qui doit etre menee pour reccuperer les differences x ,y, et difference je suis desole d etre si null mais je ne vois pas du tout ou je peut les envoyees et les reutilisees sachant qu a l autre bout c est a dire l odi n02 il devrai recuperer cette difference et l affiche dans son picturebox mais  je pense qu on tient le bon bout car toutes ces idees sont en coherences avec les directives 
que le prof avait donne sauf que lui voulait photographier une parti de l ecran et faire un 
update ce qui ne m a  pas beaucoup aide

dans l attente encore merci a vous deux 

 
0
taupe4 Messages postés 91 Date d'inscription dimanche 16 avril 2006 Statut Membre Dernière intervention 17 avril 2008 1
16 mars 2008 à 17:11
La plupart des formats d'images utilisent le little-endian pour coder leurs pixels (entre autres, le bmp). L'image .NET est donc codée ainsi et qu'il faut donc, en 24 bit, faire byte | byte2<<8| byte3<<16 pour obtenir une couleur réelle.

Si le bitmap obtenu n'est pas du bon format(24bpp au lieu de 32), alors il est plus avantageux d'utiliser le format de base. Je supposais qu'on pouvait la modifier à la source. (car oui on peut convertir une image mais c'est coûteux en performance).

Si on doit travailler en 24bpp, c'est cette méthode qu'il faut prendre:
static unsafe void GetDifferences(Bitmap a, Bitmap b)
        {
            //On obtient la surface de travail des Bitmaps. Cela permet de traiter directement leurs pixels.
            //On prétend ici que les deux images ont la même taille.
            Rectangle surfaceTravail = new Rectangle(Point.Empty, a.Size);
            BitmapData bmpA = a.LockBits(surfaceTravail, ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
            BitmapData bmpB = b.LockBits(surfaceTravail, ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);

            //Nous permet de "voir" deux couleurs.
            byte* couleurA, couleurB;
            int difference;

            //Ici l'espace supplémentaire à la fin de chaque ligne.
            int padding = bmpA.Stride - surfaceTravail.Width * 3;

            //Ici on dit que notre pointeur (visionneur) est au début des deux bitmaps
            couleurA = (int*)bmpA.Scan0;
            couleurB = (int*)bmpB.Scan0;

            for(int y = 0; y < surfaceTravail.Height; y++) {
                for(int x = 0; x < surfaceTravail.Width; x++) {
                    //On calcul la différence entre la couleur B et la couleur A. Pour récupérer la couleur B, il faudra donc ajouter la couleur A.
                    //De plus, on passe à la couleur suivante grâce au ++. C'est l'arithmétique des pointeurs qui fait que cela fonctionne.
                    difference = ((*couleurB++) | (*couleurB++)<<8 | (*couleurB++)<<16) - ((*couleurA++) | (*couleurA++)<<8 | (*couleurA++)<<16);
                    //Faire quelque chose avec cette différence. Par exemple, enregistrer (x,y, difference) et l'envoyer.
                    throw new NotImplementedException("Il ne se passe rien avec la différence");
                }
                couleurA += padding;
                couleurB += padding;
            }
        }

Et les deux codes que j'ai fourni ne fonctionne que sur les architectures little-endian. Sur des big-endian, des conversions supplémentaires sont requises, tant en 32 qu'en 24 bpp. Mais .NET ne fonctionne que sur des machines little-endian.

<hr size="2" width="100%" />«L'erreur est humaine mais un véritable désastre nécessite un ordinateur.»
«Selon les derniers chiffres, 43 % des statistiques sont fausses»
0
taupe4 Messages postés 91 Date d'inscription dimanche 16 avril 2006 Statut Membre Dernière intervention 17 avril 2008 1
16 mars 2008 à 17:19
Ma différence est en fait la valeur qu'il faut ajouter à la couleur initiale pour obtenir la couleur finale. Lorsque celle-ci vaut zéro, c'est que le pixel est identique. Ce qu'il faudrait faire, c'est de créer des blocs qui correspondent à une suite de différences n'égalant pas zéro et une coordonnée X,Y. par exemple: Les 16 pixels suivant (4,3) sont différents: voici leur différence. Ce qu'il reste à faire, c'est:
 1. Créer ces blocs
 2. Les envoyer
--->machine distante
 3. Les recevoir
 4. modifier l'image source pour que les différences s'appliquent. (ici une autre méthode unsafe sera nécessaire)

Mais, il va falloir que, éventuellement, tu décides de renvoyer une image complète de temps en temps pour assurer une synchronisation parfaite et corriger la perte de données.  Par exemple, une image clé à toutes les 100 frames ou 15 secondes.

Mais j'aimerais savoir, avons-nous affaire à une image 32 bit ou 24 bit ? Car les méthodes de traitement doivent être ajustées en conséquence.

<hr size="2" width="100%" />«L'erreur est humaine mais un véritable désastre nécessite un ordinateur.»
«Selon les derniers chiffres, 43 % des statistiques sont fausses»
0
cs_danyclassique Messages postés 94 Date d'inscription samedi 1 décembre 2007 Statut Membre Dernière intervention 7 novembre 2010
16 mars 2008 à 17:36
Je vais essayer d appliquer tout ca ,je voudrais ajouter au passage que c est pour moi des techniques archi nouvelles alors desole si je suis un peu lent a la detente

merci taupe4
0
cs_danyclassique Messages postés 94 Date d'inscription samedi 1 décembre 2007 Statut Membre Dernière intervention 7 novembre 2010
17 mars 2008 à 01:56
Salut taupe4 j ai essayer pendant pas mal de temps d adapter ta fonction sur mon code mais a la compilation j ai un msg du style
Error 1 Unsafe code may only appear if compiling with /unsafe 
et donc je n arrvive pas a demarer la compilation pour analyser mes valeurs

peut etre que tu a deja eu cette erreur
0
cs_danyclassique Messages postés 94 Date d'inscription samedi 1 décembre 2007 Statut Membre Dernière intervention 7 novembre 2010
17 mars 2008 à 02:49
J ai trouve la raison de ce msg il faut configurer le unsafe dans les proprietes de mon projet

J ai essayer mais ca ne marche pas et j ai remarque qu il fallait faire un casting byte* au lieu de int* dan
0
cs_danyclassique Messages postés 94 Date d'inscription samedi 1 décembre 2007 Statut Membre Dernière intervention 7 novembre 2010
17 mars 2008 à 02:56
le casting etait
couleurA = (int*)bmpA.Scan0;
            couleurB = (int*)bmpB.Scan0;

Je vais continuer ma recherche mais je te remercie a toi et a sharevb pour votre aide
0
Rejoignez-nous