2011-06-28 3 views
0

J'ai quelques stations sur un site au moment et ils vient d'annoncer que l'un d'entre eux affiche l'erreur suivante:Ouvrir CV GUI erreur Gestionnaire - Mémoire insuffisante

Ouvrir CV GUI erreur Gestionnaire

insuffisante mémoire (de mémoire) en fonction cvAlloc, .cvalloc.cpp (111)

Ces machines font très peu, ils se connectent à un lecteur d'empreintes digitales Suprema RealScan biométrique: http://www.supremainc.com/eng/product/ls_20.php?mark=52

Je soupçonne que le problème provient de ce qui suit:

Dans le cadre de ce SDK de périphériques, vous avez la possibilité d'enregistrer un 'rappel de rappel'. Cela signifie que lorsque le périphérique est démarré, ce rappel se déclenchera et fournira un pointeur vers une image, cette image est l'image réelle provenant du scanner. Ceci est utilisé de sorte que vous pouvez afficher une image en direct des doigts des utilisateurs comme ils les placent sur l'appareil. Le callBack se déclenche toutes les quelques millisecondes pendant que l'appareil est en mode de capture. Lorsque l'appareil arrête de capturer les appels callback arrête. Lorsque nous avons commencé à intégrer le SDK, nous nous sommes rendus compte que la seule façon de nous permettre de convertir ce pointeur d'image en un type d'image C# était d'utiliser une fonction qui enregistrait les données du pointeur dans un fichier. Nous avons ensuite dû lire l'image à partir de ce fichier qui a été créé, et supprimer le fichier. Nous avons pensé que c'était un peu fou et nous avons envoyé un e-mail à leur support demandant s'il y avait un moyen de convertir le pointeur Image en une image C# dans le code sans avoir à le sauvegarder dans un fichier en utilisant leur SDK.

Ils nous ont fourni la fonction suivante (qui ils ont dit n'a pas été testé, quelqu'un avait littéralement écrit), et je crois que c'est là cette erreur vient comme tout le reste est très basique:

public void ProcessNewPreviewImage(IntPtr imageData, int imageWidth, int imageHeight) 
    { 
     try 
     { 
      if (realScanCapturing) 
      { 
       //______________________________________ 
       // Create byte[] to store the image data 
       byte[] templateRawData; 

       //________________________________________ 
       // Init the array to the size of this image 
       templateRawData = new byte[imageWidth * imageHeight]; 

       //____________________________________ 
       // Get the size of the image as a UINT 
       uint size = Convert.ToUInt32(imageWidth * imageHeight); 

       //__________________________________________________________ 
       // Copy the pointer image data to the byte[] we just created 
       CopyMemory(templateRawData, imageData, size); 

       //_____________________________________________________________________ 
       //Create a new bitmap object usign this preview images height and width 
       Bitmap tmpBmp = new Bitmap(imageWidth, imageHeight, System.Drawing.Imaging.PixelFormat.Format8bppIndexed); 

       //_________________________________________ 
       // Create the color palette for this bitmap 
       System.Drawing.Imaging.ColorPalette cp = tmpBmp.Palette; 
       for (int i = 0; i <= 255; i++) 
       { 
        cp.Entries[i] = Color.FromArgb(i, i, i); 
       } 

       //________________________________________ 
       // Assign this color palette to the bitmap 
       tmpBmp.Palette = cp; 

       //_________________________________________________________________ 
       // Create a new rectangle object using the dimensions of our bitmap 
       Rectangle rect = new Rectangle(0, 0, tmpBmp.Width, tmpBmp.Height); 

       //_____________________________________________________________________________ 
       // Create a BitmapData object (which will be used to modify the preview image?) 
       System.Drawing.Imaging.BitmapData tmpBMPData = null; 

       //________________________________________________________________________________________________ 
       // Locks the bitmap holding the preview image into memory so that we can change it programatically 
       tmpBMPData = tmpBmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, tmpBmp.PixelFormat); 

       //__________________________________________________________________________ 
       // Create new pointer pointing at the start of the image data we just locked 
       IntPtr ptr = tmpBMPData.Scan0; 

       //__________________________________________________________ 
       // Copy the raw template data to the pointer we just created 
       System.Runtime.InteropServices.Marshal.Copy(templateRawData, 0, ptr, imageWidth * imageHeight); 

       //__________________ 
       // Unlock the bitmap 
       tmpBmp.UnlockBits(tmpBMPData); 

       System.IO.MemoryStream msImage = new System.IO.MemoryStream(); 
       tmpBmp.Save(msImage, ImageFormat.Bmp); 

       byte[] byteImage = Util.ImageToByteArray(tmpBmp); 

       //______________________________ 
       // Send the extracted image data back to the client for display 
       thisClientServer.GetStreamingWcf(activeClientStation.VtServerDetails.ServerIpAddress, (int)activeClientStation.StreamingPort).StreamImage(byteImage); 


       tmpBmp.Dispose(); 
      } 
     } 
     catch (Exception ex) 
     { 
      ShowDebugMessage("Error in ProcessNewPreviewImage: " + ex.Message); 
     } 
    } 

Les commentaires ont été ajoutés par moi-même comme je l'ai essayé de donner un sens à ce qui se passe réellement ici, je ne pense toujours pas que je comprends pleinement ce qu'ils font. Cela fonctionne, et je n'ai pas rencontré l'erreur lors de mes tests, mais évidemment, après une utilisation intensive prolongée, cette erreur apparaît.

J'espère que quelqu'un pourra mieux comprendre le code qu'il m'a fourni et mettre en évidence les zones qui pourraient causer un problème?

Toute aide est appréciée! Cordialement Adrian

+0

Vous avez obtenu ce que vous avez demandé, vous utilisez maintenant beaucoup de mémoire non gérée au lieu de ces jolis fichiers mappés en mémoire. Le fait de ne pas appeler Dispose() sur les images bitmap est l'abréviation typique lorsque le garbage collector ne fonctionne pas assez fréquemment. Utilisez l'explorateur de processus de SysInternals et observez les octets privés de votre processus. –

Répondre

0

J'ai trouvé la fuite de mémoire, finalement.

Questions connexes