2009-04-10 11 views
6

Ma tâche est de décompresser un paquet (reçu) en utilisant zlib puis d'utiliser un algoritm pour faire une image à partir des donnéeszlib de C++ vers C# (Comment convertir octet [] pour streamer et streamer vers octet [])

les bonnes nouvelles sont que j'ai le code en C++, mais la tâche est de le faire en C#

C++

 //Read the first values of the packet received 

     DWORD image[200 * 64] = {0}; //used for algoritm(width always = 200 and height always == 64) 
     int imgIndex = 0; //used for algoritm 
     unsigned char rawbytes_[131072] = {0}; //read below 
     unsigned char * rawbytes = rawbytes_; //destrination parameter for decompression(ptr) 
     compressed = r.Read<WORD>(); //the length of the compressed bytes(picture) 
     uncompressed = r.Read<WORD>(); //the length that should be after decompression 
     width = r.Read<WORD>(); //the width of the picture 
     height = r.Read<WORD>(); //the height of the picture 

     LPBYTE ptr = r.GetCurrentStream(); //the bytes(file that must be decompressed) 

     outLen = uncompressed; //copy the len into another variable 

     //Decompress 

     if(uncompress((Bytef*)rawbytes, &outLen, ptr, compressed) != Z_OK) 
     { 
      printf("Could not uncompress the image code.\n"); 
      Disconnect(); 
      return; 
     } 

     //Algoritm to make up the picture 
     // Loop through the data 
     for(int c = 0; c < (int)height; ++c) 
     { 
      for(int r = 0; r < (int)width; ++r) 
      { 
       imgIndex = (height - 1 - c) * width + r; 
       image[imgIndex] = 0xFF000000; 
       if(-((1 << (0xFF & (r & 0x80000007))) & rawbytes[((c * width + r) >> 3)])) 
        image[imgIndex] = 0xFFFFFFFF; 
      } 
     } 

Je suis en train de le faire avec zlib.NET, mais toutes les démos avoir ce code pour décompresser (C#)

private void decompressFile(string inFile, string outFile) 
    { 
     System.IO.FileStream outFileStream = new System.IO.FileStream(outFile, System.IO.FileMode.Create); 
     zlib.ZOutputStream outZStream = new zlib.ZOutputStream(outFileStream); 
     System.IO.FileStream inFileStream = new System.IO.FileStream(inFile, System.IO.FileMode.Open);   
     try 
     { 
      CopyStream(inFileStream, outZStream); 
     } 
     finally 
     { 
      outZStream.Close(); 
      outFileStream.Close(); 
      inFileStream.Close(); 
     } 
    } 

    public static void CopyStream(System.IO.Stream input, System.IO.Stream output) 
    { 
     byte[] buffer = new byte[2000]; 
     int len; 
     while ((len = input.Read(buffer, 0, 2000)) > 0) 
     { 
      output.Write(buffer, 0, len); 
     } 
     output.Flush(); 
    } 

Mon problème: Je ne veux pas enregistrer le fichier après la décompression, car je dois utiliser l'algoritm affiché dans le code C++. Comment convertir le tableau byte [] en un flux similaire à celui du code zlib C# pour décompresser les données et ensuite comment convertir le flux en tableau byte?

De même, comment modifier le code zlib.NET pour ne pas enregistrer les fichiers?

+0

nécessaires exactement la même chose. Merci! – lesderid

+0

Je veux donner une prime à @JoshStribling - Je peux le faire demain. –

Répondre

10

utiliser juste MemoryStreams au lieu de FileStreams:

// Assuming inputData is a byte[] 
MemoryStream input = new MemoryStream(inputData); 
MemoryStream output = new MemoryStream(); 

Ensuite, vous pouvez utiliser output.ToArray() ensuite pour obtenir un tableau d'octets sur.

Notez qu'il est généralement préférable d'utiliser les instructions using au lieu d'un seul bloc try/finally - sinon, si le premier appel à Close échoue, le reste ne sera pas effectué. Vous pouvez les imbriquer comme ceci:

using (MemoryStream output = new MemoryStream()) 
using (Stream outZStream = new zlib.ZOutputStream(output)) 
using (Stream input = new MemoryStream(bytes)) 
{ 
    CopyStream(inFileStream, outZStream); 
    return output.ToArray(); 
} 
+1

Jon Skeet, j'admire le livre que tu as écrit (C# en Profondeur). En écriras-tu un autre quand C# v4 sortira? –

+1

Il n'y a rien encore de concret, mais j'espère écrire une deuxième édition de C# en profondeur pour couvrir C# 4, oui. Je suis content que vous ayez apprécié la première édition :) –

5

Je viens de rencontrer ce même problème.

Pour ... Exhaustivité (puisque cela me déconcerté pendant plusieurs heures)

Dans le cas de ZLib.Net vous devez également appeler finish(), qui se produit habituellement pendant Close(), avant d'appeler le retour output.ToArray()

Sinon, vous obtiendrez un tableau d'octets vide/incomplet de votre flux de mémoire, parce que le zStream n'a pas encore réellement toutes les données encore:

public static void CompressData(byte[] inData, out byte[] outData) 
{ 
    using (MemoryStream outMemoryStream = new MemoryStream()) 
    using (ZOutputStream outZStream = new ZOutputStream(outMemoryStream, zlibConst.Z_DEFAULT_COMPRESSION)) 
    using (Stream inMemoryStream = new MemoryStream(inData)) 
    { 
     CopyStream(inMemoryStream, outZStream); 
     outZStream.finish(); 
     outData = outMemoryStream.ToArray(); 
    } 
} 

public static void DecompressData(byte[] inData, out byte[] outData) 
{ 
    using (MemoryStream outMemoryStream = new MemoryStream()) 
    using (ZOutputStream outZStream = new ZOutputStream(outMemoryStream)) 
    using (Stream inMemoryStream = new MemoryStream(inData)) 
    { 
     CopyStream(inMemoryStream, outZStream); 
     outZStream.finish(); 
     outData = outMemoryStream.ToArray(); 
    } 
} 

Dans cet exemple, je m utilise également l'espace de noms zlib:

using zlib; 

à l'origine dans cette discussion: ZLib decompression

Je n'ai pas assez de points pour voter encore, donc ...

Merci à Tim Greaves pour la pointe en ce qui concerne la finition avant ToArray

Et Jon Skeet pour la pointe en ce qui concerne l'imbrication des états à l'aide des cours d'eau (ce qui me plaît beaucoup mieux que d'essayer/enfin)

+0

Merci beaucoup! C'est un indice impressionnant! –

+0

qu'est-ce que inData et outData ici ??? – pulkit

Questions connexes