2009-04-10 36 views
6

Mi tarea es descomprimir un paquete (recibido) usando zlib y luego usar un algoritmo para hacer una imagen de los datoszlib de C++ a C# (Cómo convertir byte [] a stream y stream to byte [])

la buena noticia es que tengo el código en C++, pero la tarea es hacerlo 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; 
      } 
     } 

que estoy tratando de hacer esto con zlib.NET, pero todos los grupos demográficos tener ese código para descomprimir (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(); 
    } 

Mi problema: No quiero guardar el archivo después de la descompresión, porque tengo que usar el algoritmo que se muestra en el código de C++.

Cómo convertir la matriz byte [] en una secuencia similar a la del código C# zlib para descomprimir los datos y luego cómo convertir la secuencia nuevamente en una matriz de bytes?

Además, ¿Cómo cambiar el código de zlib.NET para NO guardar archivos?

+0

necesitaba exactamente lo mismo. ¡Gracias! – lesderid

+0

Quiero darle una recompensa a @JoshStribling - Puedo hacerlo mañana. –

Respuesta

10

sólo tiene que utilizar en lugar de MemoryStreams FileStreams:

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

continuación, puede utilizar output.ToArray() después para obtener una matriz de bytes a cabo.

Tenga en cuenta que generalmente es mejor utilizar sentencias using en lugar de un solo bloque try/finally - de lo contrario, si falla la primera llamada a Close, el resto no se realizará. Puede anidarlos así:

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, admiro el libro que escribió (C# en profundidad). ¿Escribirá otro cuando salga C# v4? –

+1

No hay nada absolutamente concreto aún, pero espero escribir una segunda edición de C# en profundidad para cubrir C# 4, sí. Me alegro de que haya disfrutado de la primera edición :) –

5

Acabo de tropezar con este mismo problema.

para completar ... (ya que esto me perplejo durante varias horas)

En el caso de ZLib.Net también hay que llamar acabado(), que por lo general ocurre durante Close(), antes de llamar retorno output.ToArray()

de lo contrario obtendrá una matriz de bytes vacío/incompleta de su secuencia de memoria, ya que el zStream no ha escrito realmente todos los datos aún:

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(); 
    } 
} 

En este ejemplo I' m también usando el espacio de nombres zlib:

using zlib; 

Originalmente se encuentra en este hilo: ZLib decompression

no tengo suficientes puntos para votar todavía, así que ...

Gracias a Tim Greaves por la punta con respecto meta antes ToArray

y Jon Skeet por la punta con respecto a anidar las instrucciones using para las corrientes (que me gusta mucho mejor que tratar/fin)

+0

¡Muchas gracias! ¡Esto es una pista impresionante! –

+0

¿Qué es inData y outData aquí? – pulkit