2009-05-03 3 views
2

Je suis en train de créer dynamiquement une image bitmap en utilisant tableau d'octets en utilisant le code suivantC#: Bitmap Création en octets tableau

Bitmap GetImage() 
{ 
    IntPtr ip = Marshal.AllocCoTaskMem(imagesize); 

    //some code to fill ip 

    Image img = new Bitmap(
        w, 
        h, 
        -stride, 
        PixelFormat.Format24bppRgb, 
        (IntPtr)(ip.ToInt32() + imagesize - stride) 
        ); 

    Marshal.FreeCoTaskMem(ip); // Comment this line to work 

    return img; 
} 

void SaveImage() 
{ 
    Image img = GetImage(); 
    img.save("test.bmp"); // This call fails 
    img.Dispose(); 
} 

Maintenant, mon problème est que je veux retourner un Bitmap, mais en même temps je ne » Je ne veux pas que le pointeur IP reste tel que la mémoire allouée fuit. Il n'est jamais libéré. Comment puis-je retourner une image créée avec un tableau bytes et sans déranger l'appelant de la fonction GetImage() pour libérer de la mémoire.

Répondre

4

La façon la plus simple peut être de créer le bitmap (bien que dans similar code j'ai utilisé un bloc normal byte[] puis un fixed, plutôt que d'utiliser directement AllocCoTaskMem), puis créer une secondesBitmap de la même taille. Appelez le Graphics.FromImage sur le second bitmap, puis Graphics.DrawImage en utilisant le bitmap pour copier efficacement le contenu du premier bitmap sur le second. Vous pouvez ensuite appeler le Dispose sur le premier bitmap, libérer la mémoire et utiliser la seconde image bitmap qui est essentiellement une copie.

Il peut y avoir un moyen de faire plus efficace si vous êtes plus compétent avec des trucs d'image, mais si vous êtes à la recherche d'un moyen de le faire fonctionner, il est un point de départ :)

EDIT: commentaire de zachrrs ne fait les choses en utilisant plus facile le constructeur Bitmap(Image):

using (Bitmap original = new Bitmap(...)) 
{ 
    Bitmap copy = new Bitmap(originalImage); 
    // Then return "copy" from your method, and you can free the 
    // memory 
} 
+0

Je reçois les données d'un tampon non géré qui n'est rien d'autre que DirectX SampleGrabber Filter c'est la raison pour laquelle j'utilise AllocCoTaskMem – Ankit

+0

Assez bien :) J'espère que cela fonctionne pour vous. Faites-moi savoir si vous avez besoin d'un échantillon plus complet. –

+2

Vous n'avez pas besoin de créer un objet Graphics intermédiaire, créez simplement une nouvelle instance Bitmap avec l'occurrence Bitmap d'origine dans le constructeur. – bsneeze

0

Si vous connaissez les dimensions à l'avance, pourquoi ne pas créer le bitmap et utiliser la méthode Bitmap.LockBits pour obtenir l'adresse de tampon d'entrée?