2015-11-20 1 views
0

Je veux copier BitmapData dans byte [], mais j'obtiens des zéros non existants au milieu du tableau (index 6 et 7). Qu'est ce que je fais mal?Comment puis-je copier BitmapData dans le tableau Byte en utilisant C#?

 Bitmap bt = new Bitmap(2, 2, System.Drawing.Imaging.PixelFormat.Format24bppRgb); 
     for(int ii = 0; ii < bt.Width; ii++) 
      for(int jj = 0; jj < bt.Height; jj++) 
     { 
      int tempVal = (ii + jj * 2)*85; 
      bt.SetPixel(ii, jj, System.Drawing.Color.FromArgb(tempVal, tempVal, tempVal)); 
     } 
     Rectangle rect = new Rectangle(0,0,bt.Width, bt.Height); 
     System.Drawing.Imaging.BitmapData btData = bt.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, bt.PixelFormat); 
     IntPtr ptr = btData.Scan0; 
     int bytes = bt.Width * bt.Height * 3; 
     byte[] rgbValues = new byte[bytes]; 
     System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes); 
     bt.UnlockBits(btData); 

     for (var ii = 0; ii < bytes; ii++) 
      System.Diagnostics.Debug.WriteLine(rgbValues[ii]); 

     //bt.Save("test.png"); 

Répondre

2

Ces zéros sont rembourrages parce que vous utilisez un format Format24bppRgb, qui est de 3 octets par pixel donc il y a un rembourrage à la fin de chaque ligne dans l'image. La propriété BitmapData.Stride renvoie la taille d'une ligne en mémoire. Pour les images descendantes, c'est une valeur positive, pour les images ascendantes une valeur négative. Le stride peut toujours être divisé par 4 pour les bitmaps de mémoire .NET.

Donc, si vous voulez utiliser un tableau d'octets géré, vous pouvez le faire comme ceci:

byte[] data = new byte[Math.Abs(bitmapData.Stride * bitmapData.Height)]; 
Marshal.Copy(bitmapData.Scan0, data, 0, data.Length); 

Ou, si vous utilisez le code dangereux, vous pouvez parcourir les lignes comme celle-ci:

unsafe 
{ 
    byte* line = (byte*)bitmapData.Scan0; 
    for (int y = 0; y < data.Height; y++) 
    { 
     for (int x = 0; x < data.Width; x++) 
     { 
      byte* pos = line + x * 3; 
      int pixel = Color.FromArgb(pos[0], pos[1], pos[2]).ToArgb(); 
      // do whatever 
     } 

     line += data.Stride; 
    } 
} 
0

C'est par la conception comme format de matrice de pixels bitmap nécessite au pad chaque ligne offset de départ pour pointer vers une adresse qui est un multiple de 4.

de Wikipedia Aux fins du stockage de fichiers, seule la taille de chaque ligne doit être un multiple de 4 octets alors que le décalage de fichier peut être arbitraire. [5] Un bitmap 24 bits avec Width = 1, aurait 3 octets de données par ligne (bleu, vert, rouge) et 1 octet de remplissage, tandis que Width = 2 aurait 2 octets de remplissage, Largeur = 3 avoir 3 octets de remplissage, et Width = 4 n'aurait aucun padding du tout.

Par ailleurs, votre numéro de calcul d'octets semble être incorrect, et selon the documentation, devrait plutôt être:

bytes = Math.Abs(btData.Stride) * bt.Height;