Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
969 connectés 

  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  [C#] Les mystères de la représentation mémoire d'un objet Bitmap

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[C#] Les mystères de la représentation mémoire d'un objet Bitmap

n°1379372
Arjuna
Aircraft Ident.: F-MBSD
Posté le 01-06-2006 à 23:11:09  profilanswer
 

J'en ai chié comme un rat dépressif mort pendant 3 heures pour remplacer "GetPixel()" qui est très lent par le parcours en mémoire d'un array de byte correspondant aux données brutes d'un objet Bitmap...
 
Seulement, j'ai fini par trouver la solution "par l'oppération du saint esprit", et je ne comprends pas :
- pkoi ça plante pas (en toute logique, je devrais avoir un dépassement mémoire)
- pkoi ça marche (que ça plante pas... là la limite... mais que ça donne le bon résultat, là c'est moi qui fait un stack overflow :o)
- pkoi quand je lit n'importe comment de manière anarchique dans le tableau, j'ai que des couleurs grises, alors que par cette oppération foireusement miraculeuse, ça me donne des couleurs...
 
Des suggestions ?
 

Code :
  1. private void PreProcess()
  2.         {
  3.             int nbRows = (ori.Height * nbCols) / ori.Width;
  4.             int width = ori.Width;
  5.             int height = ori.Height;
  6.             int sWidth = width / nbCols;
  7.             int sHeight = height / nbRows;
  8.             int ptr;
  9.             BitmapData bData = ori.LockBits(new Rectangle(new Point(), ori.Size), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
  10.             // number of bytes in the bitmap
  11.             int byteCount = bData.Stride * ori.Height;
  12.             byte[] bmpData = new byte[byteCount];
  13.             // Copy the locked bytes from memory
  14.             Marshal.Copy(bData.Scan0, bmpData, 0, byteCount);
  15.             // don't forget to unlock the bitmap!!
  16.             ori.UnlockBits(bData);
  17.             // Découpe en colonnes
  18.             for (int i = 0; i < nbCols; i++)
  19.             {
  20.                 // Découpe en lignes
  21.                 for (int j = 0; j < nbRows; j++)
  22.                 {
  23.                     this.pictureBox2.Invalidate();
  24.                     long nbPixels = 0;
  25.                     long cR = 0;
  26.                     long cG = 0;
  27.                     long cB = 0;
  28.                     // Parcoure le carré dans l'image originale
  29.                     for (int x = j * sHeight; x < (j + 1) * sHeight; x++)
  30.                     {
  31.                         // 1) Je panne pas pkoi je dois utiliser "height" ici, alors que le stride correspond à une ligne entière
  32.                         // 2) Je panne encore moins pkoi ça ne plante pas, puisque "ptr" est bien plus grand avec "height" qu'avec "width"
  33.                         // 3) Je panne pas non plus pkoi, alors que j'ai interverti x et y par rapport à la méthode "GetPixel()" j'obtiens la bonne miniature...
  34.                         // 4) Pour en revenir au 2, ça me fait des lignes grises, et pas une seule couleur... Même en n'étant pas au bon offset, ça devrait rammener au moins des couleurs dans le désordre...
  35.                         ptr = (bData.Stride - height * 3) * x;
  36.                         for (int y = i * sWidth; y < (i + 1) * sWidth; y++)
  37.                         {
  38.                             // Stocke les couleurs du pixel pour en faire une moyenne
  39.                             cB += (long)bmpData[ptr + (x * height + y) * 3];
  40.                             cG += (long)bmpData[ptr + (x * height + y) * 3 + 1];
  41.                             cR += (long)bmpData[ptr + (x * height + y) * 3 + 2];
  42. //                            cB += (long)ori.GetPixel(x, y).B;
  43.                             nbPixels++;
  44.                         }
  45.                     }
  46.                     g.FillRectangle(new SolidBrush(Color.FromArgb((int)(cR / nbPixels), (int)(cG / nbPixels), (int)(cB / nbPixels))), i * sWidth, j * sHeight, sWidth, sHeight);
  47.                     //pictureBox2.Refresh();
  48.                 }
  49.             }
  50.         }


 
=> Pour le moment, ça ne fait que pixeliser l'image. Je recopie une image d'une picturebox (objet ori) vers l'image d'un autre picture box en passant par un Graphics (objet g). J'en profite pour faire la moyenne des couleurs dans des rectangles de découpe, puis je dessine un rectangle de la même taille avec la couleur moyenne dans la destination (le but après, ça va être de modifier cet affichage des rectangles pour faire autre chose, donc me sortez pas "laMethodePixeliseQuiTue()", elle ne me servira à rien ;)

mood
Publicité
Posté le 01-06-2006 à 23:11:09  profilanswer
 

n°1379381
Arjuna
Aircraft Ident.: F-MBSD
Posté le 01-06-2006 à 23:19:01  profilanswer
 

Pour preuve qu'en faisant "total n'importe quoi" ça marche :
http://magicbuzz.multimania.com/files/pigepas.png

n°1379746
_Mose_
Lonesome coder
Posté le 02-06-2006 à 12:51:36  profilanswer
 

Y'a que toi pour te plaindre quand ça marche   :D

n°1379980
Arjuna
Aircraft Ident.: F-MBSD
Posté le 02-06-2006 à 15:46:04  profilanswer
 

ben ça m'ennuie quand je comprends pas. surtout que là, j'ai besoin de comprendre ce que ça fait, parceque je vais devoir modifier le truc...
et déjà en comprenant ce que je fais, je m'en sors pas, mais alors là, c'est le pompom :D

n°1380029
_Mose_
Lonesome coder
Posté le 02-06-2006 à 16:15:21  profilanswer
 

Je serais toi, je rajouterai des variables pour stocker les valeurs calculées.
Ca peut optimiser un pti peu tes boucles, et ça te permettra sans doute de mieux comprendre.
Paske les for(int x = j * sHeight; x < (j + 1) * sHeight; x++)  c'est assez inbitable :)

n°1380058
Arjuna
Aircraft Ident.: F-MBSD
Posté le 02-06-2006 à 16:45:34  profilanswer
 

Euh... au départ, sHeight n'existait pas, c'était :
 
(j + 1) * (ori.Height / ((ori.Height * nbCols) / ori.Width))
 
Là, ouais, c'était imbittable ;)

n°1383634
Xavier_OM
Monarchiste régicide (fr quoi)
Posté le 08-06-2006 à 12:01:54  profilanswer
 

Voilà un bout de code qui peut ptet t'intéresser :

Code :
  1. unsafe {
  2.                 // on va charcuter bitmap
  3.                 BitmapData bmd = bitmap.LockBits(
  4.                     new Rectangle(0, 0, bitmap.Width, bitmap.Height)
  5.                     , System.Drawing.Imaging.ImageLockMode.WriteOnly
  6.                     , PixelFormat.Format32bppArgb);
  7.                 // on prend un pointeur sur le début du tableau
  8.                 byte* ptr = (byte*) bmd.Scan0;
  9.                 // on fait un super traitement
  10.                 for(int i=0 ; i<bmd.Height ; i++) {
  11.                     for(int j=0 ; j<bmd.Width ; j++) {
  12.                         *ptr++ = 0; //b
  13.                         *ptr++ = 0; //g
  14.                         *ptr++ = 0; //r  
  15.                         *ptr++ = 0; //a
  16.                     }
  17.                     // comme c'est du 32 bits argb, je sais que un pixel = un quadruple blue/green/red/alpha  
  18.                     // en 24 bits un pixel = un triplet blue/green/red
  19.                     // on a fini une ligne, on passe à la ligne suivante
  20.                     // à cause de la structure des bitmaps, on doit encore avancer un peu histoire de bouffer le padding (cf. image plus bas)
  21.                     ptr += bmd.Stride - bmd.Width * 4; // en 24bits ca serait 3 et pas 4...
  22.              
  23.                 }
  24.                 bitmap.UnlockBits(bmd);
  25.             }


 
:o
 
http://www.bobpowell.net/lockin1.gif


Message édité par Xavier_OM le 08-06-2006 à 12:04:14

---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
n°1383635
_darkalt3_
Proctopathe
Posté le 08-06-2006 à 12:03:03  profilanswer
 

[:drapal]

n°1383681
Arjuna
Aircraft Ident.: F-MBSD
Posté le 08-06-2006 à 12:55:14  profilanswer
 

1/ pkoi le +4 ?
2/ ouais, mais justement, si tu regardes mon code, mes interrogations sont en fonction du schéma que tu as posté : à moins que je me sois complètement planté dans le nommage de mes variables (possible) j'ai une incohérence complète : je bouge mon pointeur à partir de la largeur, mais ce sont des colonnes que je récupère, et non ds lignes. du coup, je lis beaucoup trop de fois une taille trop grande (donc ça devrait déborder) et pourtant je récupère bien mon image, alors qu'en toute logique elle devrait être complètement déterriorrée (problèmes d'offsets). hors ça marche :spamafote:

n°1383733
Xavier_OM
Monarchiste régicide (fr quoi)
Posté le 08-06-2006 à 13:58:51  profilanswer
 

1)  :??:  
2) Ya plein de truc que je capte pas trop dans ton code :
Ca par exemple :
int nbRows = (ori.Height * nbCols) / ori.Width;
 
Et ca ? ca te file le nombre de pixels (zone de padding compris, ce qui n'a pas de sens) mais pas le nombre de bytes  :??:  
int byteCount = bData.Stride * ori.Height;


---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
mood
Publicité
Posté le 08-06-2006 à 13:58:51  profilanswer
 

n°1383749
Arjuna
Aircraft Ident.: F-MBSD
Posté le 08-06-2006 à 14:13:17  profilanswer
 

Code :
  1. // on a fini une ligne, on passe à la ligne suivante
  2. // à cause de la structure des bitmaps, on doit encore avancer un peu histoire de bouffer le padding (cf. image plus bas)
  3. ptr += bmd.Stride - bmd.Width * 4;
  4. // en 24bits ca serait 3 et pas 4...


 
Moi je fais pas le +4 et ça marche quand même :sol:
Et pourtant, y'a pas 4 d'écart entre le width et le height de mon image :D
 
:pt1cable:

Message cité 1 fois
Message édité par Arjuna le 08-06-2006 à 14:13:54
n°1383754
Arjuna
Aircraft Ident.: F-MBSD
Posté le 08-06-2006 à 14:17:04  profilanswer
 

Xavier_OM a écrit :


2) Ya plein de truc que je capte pas trop dans ton code :
Ca par exemple :
int nbRows = (ori.Height * nbCols) / ori.Width;


Parceque je découpe mon image en petits rectangles avant le traitement.
(à la base, je vais faire des traîtements sur ces rectangles de découpe).
 
Là, nbCols est mettons 10.
Vu que je veux des rectangles "carrés", je récupère nbRows en fonction de la largeur et de la hauteur (ratio).
 
C'est vrai que mes boucles imbriquées ne sont pas terrible pour aider à la compréhesion...
 
En fait, je recopie l'image par petits rectangles, et non pas de façon séquencielle.

n°1383755
Xavier_OM
Monarchiste régicide (fr quoi)
Posté le 08-06-2006 à 14:17:08  profilanswer
 

Arjuna a écrit :

Code :
  1. // on a fini une ligne, on passe à la ligne suivante
  2. // à cause de la structure des bitmaps, on doit encore avancer un peu histoire de bouffer le padding (cf. image plus bas)
  3. ptr += bmd.Stride - bmd.Width * 4;
  4. // en 24bits ca serait 3 et pas 4...


 
Moi je fais pas le +4 et ça marche quand même :sol:
Et pourtant, y'a pas 4 d'écart entre le width et le height de mon image :D
 
:pt1cable:


 
 
Je fais pas +4 hein  :heink:  
La longueur d'une ligne en bytes c'est stride, la longueur de mon image en pixels c'est width, donc en bytes pour du 32bits c'est 4*width
D'où un padding de stride - 4*width
D'où j'avance de cette quantité pour me placer sur la ligne suivante


---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
n°1383756
Arjuna
Aircraft Ident.: F-MBSD
Posté le 08-06-2006 à 14:18:47  profilanswer
 

Sinon, je ne sais pas d'où tu sors ce padding en fait.
 
Le "bytesCount" (et tout le bloc qui va avec) c'est un copy/paste à partir d'un site style "csharpcorner".
je me demande même si j'ai pas vu le même truc sur la MSDN.
 
PS: je suis en .NET 2.0 ici. Au cas où ça changer d'une version à l'autre (ce serait bien con mais bon :D)

n°1383759
Arjuna
Aircraft Ident.: F-MBSD
Posté le 08-06-2006 à 14:20:30  profilanswer
 

D'ailleurs, en re-regardant ton graph, c'est toi qu'est pas logique.
 
stride = (with * nbBytespp) + padding
 
donc stride * height est bel et bien égal au nombre de bytes correspondant à l'image mémoire entière du bitmap... y'a pas à tortiller à ce niveau...
 
du coup, en bon français : (pour une image 24 bits)
 


pour ligne = 0, tant que ligne < hauteur, incrément de 1
      pour colonne = 0, tant que colonne < largeur, incrément de 1
           pixelCouleurRouge = img[ligne * stride + colonne * 3]
           pixelCouleurVerte = img[ligne * stride + colonne * 3 + 1]
           pixelCouleurBleue = img[ligne * stride + colonne * 3 + 2]
      fin pour
fin pour


Message édité par Arjuna le 08-06-2006 à 14:25:03
n°1383766
Xavier_OM
Monarchiste régicide (fr quoi)
Posté le 08-06-2006 à 14:25:23  profilanswer
 

MSDN :  
"The stride is the width of a single row of pixels (a scan line), rounded up to a four-byte boundary. The stride is always greater than or equal to the actual pixel width. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up."
 
 
désolé mais faut lire la doc hein :o

Message cité 1 fois
Message édité par Xavier_OM le 08-06-2006 à 14:25:51

---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
n°1383767
Arjuna
Aircraft Ident.: F-MBSD
Posté le 08-06-2006 à 14:26:19  profilanswer
 

ben oui, donc les 4 pixels ne sont pas "en plus" du stride, il sont déjà dans le stride...
 
dans ton exemple de code de là-haut, y'a une erreur avec le 4...

n°1383770
Arjuna
Aircraft Ident.: F-MBSD
Posté le 08-06-2006 à 14:27:11  profilanswer
 

correction : nan, y'a pas d'erreur. juste IE 7 béta 2 qui écrit la balise "code" trop petit : je voyais un + 4 et non un * 4
* 4, je suis d'accord :D

n°1383772
Xavier_OM
Monarchiste régicide (fr quoi)
Posté le 08-06-2006 à 14:27:52  profilanswer
 

Arjuna a écrit :

ben oui, donc les 4 pixels ne sont pas "en plus" du stride, il sont déjà dans le stride...
 
dans ton exemple de code de là-haut, y'a une erreur avec le 4...


 
j'abandonne, visiblement tu ne sais pas lire  :o


---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
n°1383775
Arjuna
Aircraft Ident.: F-MBSD
Posté le 08-06-2006 à 14:29:29  profilanswer
 

Xavier_OM a écrit :

MSDN :  
"The stride is the width of a single row of pixels (a scan line), rounded up to a four-byte boundary. The stride is always greater than or equal to the actual pixel width. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up."
 
 
désolé mais faut lire la doc hein :o


up to, ça veut dire "jusqu'à" donc c'est pas forcément 4.
mais vu que c'est pas un + mais un * qu'il y a dans ton code, je suis d'accord. moi je croyais que tu ajoutait la taille du stride + 4 dans l'offset

n°1383776
Arjuna
Aircraft Ident.: F-MBSD
Posté le 08-06-2006 à 14:30:02  profilanswer
 

Xavier_OM a écrit :

j'abandonne, visiblement tu ne sais pas lire  :o


c'est toi qui veut pas comprendre que IE7b2 est trop con pour rendre lisible la balise CODE

n°1383777
Xavier_OM
Monarchiste régicide (fr quoi)
Posté le 08-06-2006 à 14:30:18  profilanswer
 

Arjuna a écrit :

up to, ça veut dire "jusqu'à" donc c'est pas forcément 4.
mais vu que c'est pas un + mais un * qu'il y a dans ton code, je suis d'accord. moi je croyais que tu ajoutait la taille du stride + 4 dans l'offset


 
change de browser alors ;)


---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
n°1383788
Arjuna
Aircraft Ident.: F-MBSD
Posté le 08-06-2006 à 14:37:45  profilanswer
 

bah moz y déconne (c'est une béta 2 aussi :D)

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  [C#] Les mystères de la représentation mémoire d'un objet Bitmap

 

Sujets relatifs
[ASP.NET] Utiliser un objet comme propriété d'un WebControlTester divisibilité d'une adresse mémoire
Erreur d'execution '7' : Mémoire insuffisantecomparaison de fichiers textes avec des tableaux en mémoire.
c# Combobox d'objet qui cause problèmeinstancier un objet a distance
GROS PROBLEME sous VBA word...Memoire insuffisante?API Windows, pointeurs/handles et mémoire locked/unlocked
Créer un objet à partir d'une chaîne de caractèresretrouver la largeur du "border style" d'un objet
Plus de sujets relatifs à : [C#] Les mystères de la représentation mémoire d'un objet Bitmap


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR