6

私の仕事は、zlibを使用して(受信した)パケットを解凍し、アルゴリズムを使用してデータから画像を作成することです

良いニュースは、私は C++ でコードを持っているということですが、タスクは 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;
            }
        }

私はzlib.NETでこれをやろうとしていますが、すべてのデモには解凍するコードがあります(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();
    }

私の問題: C++ コードに示されているアルゴリズムを使用する必要があるため、解凍後にファイルを保存したくありません。

byte[] 配列を C# zlib コードのストリームに似たストリームに変換してデータを解凍する方法と、ストリームをバイト配列に変換する方法を教えてください。

また、ファイルを保存しないように zlib.NET コードを変更する方法は?

4

2 に答える 2

10

FileStreams の代わりに MemoryStreams を使用するだけです。

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

output.ToArray()その後、バイト配列を取得するために使用できます。

using一般に、単一の try/finally ブロックの代わりにステートメントを使用する方が良いことに注意してください。そうしないと、最初の呼び出しがClose失敗した場合、残りが行われません。次のようにネストできます。

using (MemoryStream output = new MemoryStream())
using (Stream outZStream = new zlib.ZOutputStream(output))
using (Stream input = new MemoryStream(bytes))
{
    CopyStream(inFileStream, outZStream);
    return output.ToArray();
}
于 2009-04-10T10:34:34.490 に答える
6

この同じ問題に遭遇しました。

完全を期すために...(これは数時間私を困惑させたので)

ZLib.Net の場合、return output.ToArray() を呼び出す前に、finish() を呼び出す必要があります。これは通常、Close() 中に発生します。

そうしないと、ZStream が実際にはまだすべてのデータを書き込んでいないため、メモリ ストリームから空の/不完全なバイト配列が取得されます。

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

この例では、zlib 名前空間も使用しています。

using zlib;

このスレッドで最初に見つかりました: ZLib decompression

まだ投票するのに十分なポイントがないので...

ToArray の前の終了に関するヒントを提供してくれた Tim Greaves に感謝します。

そして、Jon Skeet は、ストリームの using ステートメントのネストに関するヒントを提供してくれました (try/finally よりもはるかに気に入っています)。

于 2010-10-02T03:25:46.527 に答える