views:

5904

answers:

2

Hello,

My task is to decompress a packet(received) using zlib and then use an algoritm to make a picture from the data

The good news is that I have the code in C++,but the task is to do it in 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;
   }
  }

I'm trying to do this with zlib.NET ,but all demos have that code to decompress(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();
 }

My problem:I don't want to save the file after decompression,because I have to use the algoritm shown in the C++ code.

How to convert the byte[] array into a stream similiar to the one in the C# zlib code to decompress the data and then how to convert the stream back into byte array?

Also,How to change the zlib.NET code to NOT save files?

+3  A: 

Just use MemoryStreams instead of FileStreams:

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

Then you can use output.ToArray() afterwards to get a byte array out.

Note that it's generally better to use using statements instead of a single try/finally block - as otherwise if the first call to Close fails, the rest won't be made. You can nest them like this:

using (MemoryStream output = new MemoryStream())
using (Stream outZStream = new zlib.ZOutputStream(output))
using (Stream input = new MemoryStream(bytes))
{
    CopyStream(inFileStream, outZStream);
    return output.ToArray();
}
Jon Skeet
Jon Skeet,I admire the book you wrote(C# in Depth).Will you write another one when C# v4 comes out?
John
There's nothing absolutely concrete yet, but I'm hoping to write a second edition of C# in Depth to cover C# 4, yes. Glad you enjoyed the first edition :)
Jon Skeet
A: 

I just ran into this same issue.

For Completeness... (since this stumped me for several hours)

In the case of ZLib.Net you also have to call finish(), which usually happens during Close(), before you call return output.ToArray()

Otherwise you will get an empty/incomplete byte array from your memory stream, because the ZStream hasn't actually written all of the data yet:

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

In this example I'm also using the zlib namespace:

using zlib;

Originally found in this thread: http://stackoverflow.com/questions/1327412/zlib-decompression

I don't have enough points to vote up yet, so...

Thanks to Tim Greaves for the tip regarding finish before ToArray

And Jon Skeet for the tip regarding nesting the using statements for streams (which I like much better than try/finally)

Josh Stribling