2010-12-27 35 views
28

zlibのWebサイトで使用例があります。http://www.zlib.net/zlib_how.htmlzlibでバッファを圧縮するには?

ただし、例ではファイルを圧縮しています。メモリのバッファに格納されているバイナリデータを圧縮したい。私は圧縮されたバッファをディスクに保存したくない。基本的にはここに

は私のバッファです:

fIplImageHeader->imageData = (char*)imageIn->getFrame(); 

私はZLIBとそれを圧縮することができますどのように?

私はそれを行う方法のいくつかのコード例をいただければ幸いです。

+0

あなたが言及した例で何が問題になっていますか?メモリ内のバッファを圧縮しますが、最初にファイルからデータを読み込むだけです。あなたは他の場所からデータを取得しますが、残りは同じです - なぜそうではありませんか? –

答えて

28

これはzlibでバッファをパックし、圧縮された内容をベクトルに保存する例です。compress(またはcompress2)とuncompress

void compress_memory(void *in_data, size_t in_data_size, std::vector<uint8_t> &out_data) 
{ 
std::vector<uint8_t> buffer; 

const size_t BUFSIZE = 128 * 1024; 
uint8_t temp_buffer[BUFSIZE]; 

z_stream strm; 
strm.zalloc = 0; 
strm.zfree = 0; 
strm.next_in = reinterpret_cast<uint8_t *>(in_data); 
strm.avail_in = in_data_size; 
strm.next_out = temp_buffer; 
strm.avail_out = BUFSIZE; 

deflateInit(&strm, Z_BEST_COMPRESSION); 

while (strm.avail_in != 0) 
{ 
    int res = deflate(&strm, Z_NO_FLUSH); 
    assert(res == Z_OK); 
    if (strm.avail_out == 0) 
    { 
    buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE); 
    strm.next_out = temp_buffer; 
    strm.avail_out = BUFSIZE; 
    } 
} 

int deflate_res = Z_OK; 
while (deflate_res == Z_OK) 
{ 
    if (strm.avail_out == 0) 
    { 
    buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE); 
    strm.next_out = temp_buffer; 
    strm.avail_out = BUFSIZE; 
    } 
    deflate_res = deflate(&strm, Z_FINISH); 
} 

assert(deflate_res == Z_STREAM_END); 
buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE - strm.avail_out); 
deflateEnd(&strm); 

out_data.swap(buffer); 
} 
+0

フラグを使用してフラッシュ状態を制御し、それを1つのループで実行する興味深いアプローチを読みました。また、これはvectorの代わりにstd :: stringと同じように機能することに注意する価値があります。これは電線や別の関数を送信するのに適しています。 – Robert

+2

これは非常に複雑に思えます。なぜ単に 'compress'関数を使うのではなく、これをすべて行うのですか? – user673679

+2

Compressでは、出力サイズを知り、十分に大きなバッファを割り当てる必要があります。このメソッドを使用すると、realloc()および動的に拡張されたバッファーを持つことができます。 –

3

これはzlib APIについてのご質問についての直接の回答ではありませんが、boost::iostreamsライブラリとzlibのペアが必要です。

はこれが基本的な「ストリーム」の操作の表記を使用してzlib駆動型梱包アルゴリズムを使用することができ、その後、あなたのデータを簡単にいくつかのメモリストリームを開いて、その上に<< data操作をすることによって圧縮することができます。

boost::iostreamsの場合、ストリームを通過するすべてのデータに対して、対応するパッキングフィルタが自動的に呼び出されます。

+0

ちょうどコメントですが、これは、boost iostreamsライブラリ、boost zlibライブラリ、libz、およびlibzbz2をlibzに比べて含める必要があることを意味します。したがって、これらのライブラリをバンドルするのがサイズの問題である場合は、この場合、ブーストを避けることが最善です。 〜Ben – Ben

10

fread()fwrite()の呼び出しをデータへの直接ポインタで置き換えることで、この例を簡単に変更できます。 (あなたは「あなたのデータのすべての空気を取る」ととしてデフレート呼ぶ)zlib圧縮のためには、z_stream構造を割り当て、その後、deflateInit()を呼び出して:

  1. は、あなたがしたいデータの次のチャンクとnext_inを埋めます
  2. は通常、あなたが
  3. に沿って行くように進み、あなたのバッファ内のポインタである必要があり、圧縮されたデータが書き込まれるべき場所に next_outを設定
  4. next_inで使用可能なバイト数にavail_inを設定圧縮します
  5. deflate
  6. 繰り返し3-5までavail_outが非ゼロであるステップnext_out
  7. 呼び出しで使用可能なバイト数にavail_outを設定する(すなわち、 zlibのニーズよりも、出力バッファ内のより多くの部屋があります - 書き込みにこれ以上のデータ)
  8. はあなたが最終的にあなたがdeflateEnd()を呼び出し、設定が完了し

を圧縮するためのデータを持っている間、繰り返しが1-6を繰り返します。

あなたは入力が終わって出力が切れるまで、基本的に入力と出力のチャンクを与えています。

37

zlib.hはあなたが必要とするすべての機能を持っています。答えはzlibのソースコードを参照してください。

ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)); 
/* 
     Compresses the source buffer into the destination buffer. sourceLen is 
    the byte length of the source buffer. Upon entry, destLen is the total size 
    of the destination buffer, which must be at least the value returned by 
    compressBound(sourceLen). Upon exit, destLen is the actual size of the 
    compressed buffer. 

     compress returns Z_OK if success, Z_MEM_ERROR if there was not 
    enough memory, Z_BUF_ERROR if there was not enough room in the output 
    buffer. 
*/ 

ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)); 
/* 
     Decompresses the source buffer into the destination buffer. sourceLen is 
    the byte length of the source buffer. Upon entry, destLen is the total size 
    of the destination buffer, which must be large enough to hold the entire 
    uncompressed data. (The size of the uncompressed data must have been saved 
    previously by the compressor and transmitted to the decompressor by some 
    mechanism outside the scope of this compression library.) Upon exit, destLen 
    is the actual size of the uncompressed buffer. 

     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not 
    enough memory, Z_BUF_ERROR if there was not enough room in the output 
    buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In 
    the case where there is not enough room, uncompress() will fill the output 
    buffer with the uncompressed data up to that point. 
*/ 
+3

+1。すべてのデフォルト設定が必要な場合は、これはすごく簡単な解決策です。デフォルト設定が不要な場合でも、これらの機能のソースを変更して使用することができます。 – Hossein

関連する問題